1cc66365588f94a3339ddf6c039db58d8e0a7e95
[livewp] / applet / src / livewp-actor.c
1 /*vim: set sw=4 ts=4 et: */
2 /*
3  * This file is part of Live Wallpaper (livewp)
4  * 
5  * Copyright (C) 2010 Vlad Vasiliev
6  * Copyright (C) 2010 Tanya Makova
7  *       for the code
8  * 
9  * This software is free software; you can redistribute it and/or
10  * modify it under the terms of the GNU Lesser General Public License
11  * as published by the Free Software Foundation; either version 2.1 of
12  * the License, or (at your option) any later version.
13  * 
14  * This software is distributed in the hope that it will be useful, but
15  * WITHOUT ANY WARRANTY; without even the implied warranty of
16  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
17  * Lesser General Public License for more details.
18  * 
19  * You should have received a copy of the GNU Lesser General Public
20  * License along with this software; if not, write to the Free Software
21  * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
22  * 02110-1301 USA
23 */
24 /*******************************************************************************/
25 #include "livewp-actor.h"
26 #include <sys/time.h>
27 #include "livewp-rules.h"
28
29 Actor* 
30 init_object(AWallpaperPlugin *desktop_plugin, 
31             gchar * name, 
32             gchar * filename, 
33             gint x, 
34             gint y, 
35             gint z, 
36             gint width, 
37             gint height, 
38             gboolean visible, 
39             gboolean load_image,
40             gint scale, 
41             gint opacity, 
42             void (*pfunc_change)(Actor*),
43             void (*pfunc_probability)(Actor*),
44             GPtrArray *child
45            )
46 {
47     Actor *actor = NULL;
48     actor = g_new0(Actor, 1);
49     actor->x = x;
50     actor->y = y;
51     actor->z = z;
52     actor->width = width;
53     actor->height = height;
54     actor->visible = visible;
55     actor->scale = scale;
56     actor->opacity = opacity;
57     actor->filename = g_strdup(filename);
58     actor->name = g_strdup(name);
59     actor->func_change = (gpointer)pfunc_change; 
60     actor->func_probability = (gpointer)pfunc_probability;
61     actor->child = child;
62     if (load_image)
63         create_hildon_actor(actor, desktop_plugin);
64     else 
65          actor->widget = NULL;
66     actor->time_start_animation = 0;
67     actor->duration_animation = 0;
68     return actor;
69 }
70
71 void 
72 destroy_actor(Actor *actor)
73 {
74     if (actor){
75         if (actor->child){
76             g_ptr_array_free(actor->child, TRUE);
77         }
78         if (actor->filename)
79             g_free(actor->filename);
80         if (actor->name)
81             g_free(actor->name);
82         gtk_widget_destroy(actor->widget);
83         //actor->widget = NULL;
84         g_free(actor);
85     }
86 }
87 static gint 
88 path_line(gint x0, gint x1, double t)
89 {
90     // уравниение прямой
91     return ((x1 - x0) * t + x0);
92 }
93 void
94 set_actor_scale(Actor *actor, double scalex, double scaley)
95 {
96     hildon_animation_actor_set_scale(
97             HILDON_ANIMATION_ACTOR(actor->widget), 
98             scalex, 
99             scaley
100     );
101
102 }
103
104 void 
105 set_actor_visible(Actor *actor, gboolean visible)
106 {
107     hildon_animation_actor_set_show(HILDON_ANIMATION_ACTOR(actor->widget), visible);
108 }
109
110 void
111 set_actor_position(Actor *actor, gint x, gint y, gint z, AWallpaperPlugin *desktop_plugin)
112 {
113     hildon_animation_actor_set_position_full(HILDON_ANIMATION_ACTOR (actor->widget), 
114                                              x-desktop_plugin->priv->xapplet, 
115                                              y-desktop_plugin->priv->yapplet, 
116                                              z);
117 }
118
119 void 
120 change_moon(Actor * actor, AWallpaperPlugin *desktop_plugin)
121 {
122     gint phase;
123     char *newfile;
124     gint x0 = 150,
125          x1 = 650, 
126          x, y;
127     struct timeval tvb;     
128     suseconds_t ms;
129     long sec;
130     double t;
131 #if 0
132     gint y0, y1, x2, y2;
133     double a, b, c;
134     a = (double)(y2 - (double)(x2*(y1-y0) + x1*y0 - x0*y1)/(x1-x0))/(x2*(x2-x0-x1)+x0*x1);
135     b = (double)(y1-y0)/(x1-x0) - (double)a*(x0+x1);
136     c = (double)(x1*y0 - x0*y1)/(x1-x0) + (double)a*x0*x1;
137     fprintf(stderr, "a=%f, b=%f, c=%f\n", a, b, c);
138 #endif
139     gettimeofday(&tvb, NULL);
140     
141     ms = tvb.tv_usec;
142     sec = tvb.tv_sec;
143
144     if (actor){
145         if (desktop_plugin->priv->scene->daytime == TIME_NIGHT){
146             if (!actor->visible){
147                 actor->visible = TRUE;
148                 phase = get_moon_phase();
149                 newfile = g_strdup_printf( "%s%d.png", actor->name, phase);
150                 if (actor->filename)
151                     g_free(actor->filename);
152                 actor->filename = newfile;
153                 actor->time_start_animation = sec - fast_rnd(60 * 60);
154                 actor->duration_animation = 1 * 60 * 60;
155                 create_hildon_actor(actor, desktop_plugin);
156
157             }
158             t = (double)((double)sec+(double)ms/1000000 - actor->time_start_animation) / actor->duration_animation;
159             if (t <= 1)
160                 x = path_line(x0, x1, t);
161             else 
162                 x = path_line(x1, x0, t-1);
163             y = 0.001920*x*x - 1.536*x + 337.2;
164             //y = a*x*x + b*x + c;
165
166             set_actor_position(actor, x, y, actor->z, desktop_plugin);
167
168             if (t>=2){
169                 actor->time_start_animation = sec;
170             }
171
172          }else if (actor->visible){
173             actor->visible = FALSE;
174             fprintf(stderr, "destroy moon \n");
175             destroy_hildon_actor(actor);
176             actor->time_start_animation = 0;
177         } 
178     }
179     
180 }
181
182 void 
183 change_sun(Actor * actor, AWallpaperPlugin *desktop_plugin)
184 {
185     double alt, azm;
186     gint x, y;
187
188     //fprintf(stderr, "change sun\n");
189     if (actor){
190         if (desktop_plugin->priv->scene->daytime != TIME_NIGHT){
191             if (!actor->visible){
192                 actor->visible = TRUE;
193                 create_hildon_actor(actor, desktop_plugin);
194             }
195             get_sun_pos(&alt, &azm);
196             get_sun_screen_pos(alt, azm, &x, &y);
197             actor->x = x;
198             actor->y = y;
199             set_actor_position(actor, x, y, actor->z, desktop_plugin);
200             actor->time_start_animation = time(NULL) + 60;
201          }else if (actor->visible){
202             actor->visible = FALSE;
203             destroy_hildon_actor(actor);
204             actor->time_start_animation = 0;
205         } 
206     }
207     
208 }
209
210 void 
211 change_tram(Actor * actor, AWallpaperPlugin *desktop_plugin)
212 {
213     gint x0 = -300, y0 = 225, scale0 = 100,
214          x1 = 800, y1 = 162, scale1 = 130, 
215          x, y, scale;
216     struct timeval tvb;     
217     suseconds_t ms;
218     long sec;
219     double t;
220
221     //fprintf(stderr, "change tram\n");
222     gettimeofday(&tvb, NULL);
223     
224     ms = tvb.tv_usec;
225     sec = tvb.tv_sec;
226     
227     if (!actor->visible){
228         actor->visible = TRUE;
229         if (desktop_plugin->priv->scene->daytime == TIME_NIGHT){
230             if (actor->filename)
231                 g_free(actor->filename);
232             actor->filename = g_strdup("tram_dark.png");
233         } else{
234             if (actor->filename)
235                 g_free(actor->filename);
236             actor->filename = g_strdup("tram.png");
237         }
238         create_hildon_actor(actor, desktop_plugin);
239     }
240     t = (double)((double)sec+(double)ms/1000000 - actor->time_start_animation) / actor->duration_animation;
241     x = path_line(x0, x1, t);
242     y = path_line(y0, y1, t);
243     scale = path_line(scale0, scale1, t);
244     set_actor_position(actor, x, y, actor->z, desktop_plugin);
245     set_actor_scale(actor, (double)scale/100, (double)scale/100);
246     if (t >= 1){
247         /* stop animation */
248         actor->visible = FALSE;
249         destroy_hildon_actor(actor);
250         actor->time_start_animation = sec + fast_rnd(60);
251     }
252 }
253
254 void
255 change_plane1(Actor *actor, AWallpaperPlugin *desktop_plugin)
256 {
257     gint x0 = 620, y0 = 233,
258          x1 = 79, y1 = -146, 
259          x, y;
260     struct timeval tvb;     
261     suseconds_t ms;
262     long sec;
263     double t;
264
265     gettimeofday(&tvb, NULL);
266     
267     ms = tvb.tv_usec;
268     sec = tvb.tv_sec;
269 //    fprintf(stderr, "1 %f - %d\n", sec+(double)ms/100000, now);
270    
271     if (desktop_plugin->priv->scene->daytime != TIME_NIGHT){
272         if (actor->time_start_animation == 0){
273             actor->time_start_animation = sec + fast_rnd(180);
274             return;
275         }
276     }
277     if (!actor->visible){
278         actor->visible = TRUE;
279         create_hildon_actor(actor, desktop_plugin);
280     }
281     t = (double)((double)sec+(double)ms/1000000 - actor->time_start_animation) / actor->duration_animation;
282     x = path_line(x0, x1, t);
283     y = path_line(y0, y1, t);
284     //scale = path_line(scale0, scale1, t);
285     set_actor_position(actor, x, y, actor->z, desktop_plugin);
286     if (t >= 1){
287         /* stop animation */
288         actor->visible = FALSE;
289         destroy_hildon_actor(actor);
290         if (desktop_plugin->priv->scene->daytime == TIME_NIGHT) 
291             actor->time_start_animation = 0;
292         else 
293             actor->time_start_animation = sec + fast_rnd(180);
294     }
295
296 }
297
298 void
299 change_plane2(Actor *actor, AWallpaperPlugin *desktop_plugin)
300 {
301     gint x0 = -actor->width, y0 = 45,
302          x1 = 800, y1 = 20, 
303          x, y;
304     struct timeval tvb;     
305     suseconds_t ms;
306     long sec;
307     double t;
308
309     gettimeofday(&tvb, NULL);
310     
311     ms = tvb.tv_usec;
312     sec = tvb.tv_sec;
313 //    fprintf(stderr, "1 %f - %d\n", sec+(double)ms/100000, now);
314     if (desktop_plugin->priv->scene->daytime != TIME_NIGHT){
315         if (actor->time_start_animation == 0){
316             actor->time_start_animation = sec + fast_rnd(180);
317             return;
318         }
319     }
320     if (!actor->visible){
321         actor->visible = TRUE;
322         create_hildon_actor(actor, desktop_plugin);
323     }
324
325     t = (double)((double)sec+(double)ms/1000000 - actor->time_start_animation) / actor->duration_animation;
326     x = path_line(x0, x1, t);
327     y = path_line(y0, y1, t);
328     //scale = path_line(scale0, scale1, t);
329     set_actor_position(actor, x, y, actor->z, desktop_plugin);
330     if (t >= 1){
331         /* stop animation */
332         actor->visible = FALSE;
333         destroy_hildon_actor(actor);
334         if (desktop_plugin->priv->scene->daytime == TIME_NIGHT) 
335             actor->time_start_animation = 0;
336         else 
337             actor->time_start_animation = sec + fast_rnd(180);
338     }
339
340 }
341
342 void
343 change_cloud(Actor *actor, AWallpaperPlugin *desktop_plugin)
344 {
345     gint x0, y0 = 300, scale0 = 100,
346          x1, y1 = -actor->height, scale1 = 150, 
347          x, y, scale;
348     struct timeval tvb;     
349     suseconds_t ms;
350     long sec;
351     double t;
352     gchar *newfile;
353
354     //fprintf(stderr, "change cloud\n");
355     gettimeofday(&tvb, NULL);
356     
357     ms = tvb.tv_usec;
358     sec = tvb.tv_sec;
359    
360     if (!actor->visible){
361         actor->visible = TRUE;
362         if (desktop_plugin->priv->scene->daytime == TIME_NIGHT){
363             newfile = g_strdup_printf("%s_dark.png", actor->name);
364         }else{
365             newfile = g_strdup_printf("%s.png", actor->name);
366         } 
367         if (actor->filename)
368             g_free(actor->filename);
369         actor->filename = newfile;
370          
371         create_hildon_actor(actor, desktop_plugin);
372     }
373     t = (double)((double)sec+(double)ms/1000000 - actor->time_start_animation) / actor->duration_animation;
374     
375     if (desktop_plugin->priv->scene->wind_orientation == 1){
376         x0 = -actor->width;
377         x1 = 800;
378     }
379     else {
380         x0 = 800;
381         x1 = -actor->width;
382     }
383
384     x = path_line(x0, x1, t);    
385     y = -desktop_plugin->priv->scene->wind_angle * (x - x0) + actor->y;
386     scale = path_line(scale0, scale1, (double)(y - y0)/(y1 - y0));
387
388     set_actor_position(actor, x, y, actor->z, desktop_plugin);
389     set_actor_scale(actor, (double)scale/100, (double)scale/100);
390     if ((y < y1 || y > y0) || t >= 1){
391         /* stop animation */
392         actor->visible = FALSE;
393         destroy_hildon_actor(actor);
394         actor->time_start_animation = sec + fast_rnd(300);
395         actor->y = fast_rnd(300);
396     }
397
398 }
399
400 void
401 change_wind(Actor *actor, AWallpaperPlugin *desktop_plugin)
402 {
403     desktop_plugin->priv->scene->wind_orientation = fast_rnd(2);
404     if (desktop_plugin->priv->scene->wind_orientation == 0) desktop_plugin->priv->scene->wind_orientation = -1;
405     desktop_plugin->priv->scene->wind_angle = (double)(fast_rnd(200) - 100) / 100;
406     actor->time_start_animation = time(NULL) + (fast_rnd(10) + 10) * 60;
407     //fprintf(stderr, "change wind orient = %d angle = %f after = %d\n", scene.wind_orientation, scene.wind_angle, actor->time_start_animation-time(NULL));
408 }
409
410 void 
411 change_window1(Actor * actor, AWallpaperPlugin *desktop_plugin)
412 {
413     gint now = time(NULL);
414     if (desktop_plugin->priv->scene->daytime == TIME_DAY){
415         if (actor->widget){
416             actor->visible = FALSE;
417             destroy_hildon_actor(actor);
418         }
419         actor->time_start_animation = 0;
420         return;
421     }else {
422         if (!actor->widget)
423             create_hildon_actor(actor, desktop_plugin);
424         if (actor->time_start_animation == 0){
425             actor->time_start_animation = now + fast_rnd(30);
426             return;
427         }
428     }
429
430     if (!actor->visible)
431         actor->visible = TRUE;
432     else 
433         actor->visible = FALSE;
434     set_actor_visible(actor, actor->visible);
435     actor->time_start_animation = now + fast_rnd(60) + 10;
436
437 }
438
439 void 
440 change_signal(Actor * actor, AWallpaperPlugin *desktop_plugin)
441 {
442     gint now = time(NULL);
443     Actor *a;
444     a = g_ptr_array_index(actor->child, 0);
445     if (a->visible)
446         a->visible = FALSE;
447     else 
448         a->visible = TRUE;
449     set_actor_visible(a, a->visible);
450     
451     a = g_ptr_array_index(actor->child, 1);
452     if (a->visible)
453         a->visible = FALSE;
454     else 
455         a->visible = TRUE;
456     set_actor_visible(a, a->visible);
457
458     actor->time_start_animation = now + fast_rnd(30) + 10;
459 }
460
461 void
462 change_layer(Actor * actor, AWallpaperPlugin *desktop_plugin)
463 {
464     gint y;
465     Actor *a;
466
467     if (!desktop_plugin->priv->rich_animation) return;
468
469     a = g_ptr_array_index(actor->child, 0);
470     y = a->y + 10;
471     if (y > 480) y = -480;
472     set_actor_position(a, a->x, y, a->z, desktop_plugin);
473     a->y = y;
474     
475     a = g_ptr_array_index(actor->child, 1);
476     y = a->y + 10;
477     if (y > 480) y = -480;
478     set_actor_position(a, a->x, y, a->z, desktop_plugin);
479     a->y = y;
480
481     a = g_ptr_array_index(actor->child, 2);
482     y = a->y + 20;
483     if (y > 480) y = -480;
484     set_actor_position(a, a->x, y, a->z, desktop_plugin);
485     a->y = y;
486
487     a = g_ptr_array_index(actor->child, 3);
488     y = a->y + 20;
489     if (y > 480) y = -480;
490     set_actor_position(a, a->x, y, a->z, desktop_plugin);
491     a->y = y;
492 }
493
494 void 
495 change_static_actor(Actor * actor, AWallpaperPlugin *desktop_plugin)
496 {
497     gchar *newfile;
498     newfile = g_strdup_printf("%s%d.png", actor->name, desktop_plugin->priv->scene->daytime); 
499     if (actor->filename)
500             g_free(actor->filename);
501     actor->filename = newfile;
502     change_hildon_actor(actor, desktop_plugin);
503 }
504
505 void 
506 change_static_actor_with_corner(Actor * actor, AWallpaperPlugin *desktop_plugin)
507 {
508     gchar buffer[2048];
509
510     if (desktop_plugin->priv->right_corner)
511         gtk_widget_destroy(desktop_plugin->priv->right_corner);
512     snprintf(buffer, sizeof(buffer) - 1, "%s/%s/town%i_right_corner.png", \
513                                   THEME_PATH, desktop_plugin->priv->theme, desktop_plugin->priv->scene->daytime);
514     desktop_plugin->priv->right_corner = gtk_image_new_from_file (buffer);
515     if (desktop_plugin->priv->right_corner){
516         gtk_fixed_put(GTK_FIXED(desktop_plugin->priv->main_widget), desktop_plugin->priv->right_corner, 0, 0);
517         gtk_widget_show (desktop_plugin->priv->right_corner);
518     }
519     change_static_actor(actor, desktop_plugin);
520
521 }