Back to index

gcompris  8.2.2
anim.c
Go to the documentation of this file.
00001 /* gcompris - anim.c
00002  *
00003  * Time-stamp: <2005/02/13 11:59:55 joe>
00004  *
00005  * Copyright (C) 2005 Joe Neeman
00006  *
00007  *   This program is free software; you can redistribute it and/or modify
00008  *   it under the terms of the GNU General Public License as published by
00009  *   the Free Software Foundation; either version 2 of the License, or
00010  *   (at your option) any later version.
00011  *
00012  *   This program is distributed in the hope that it will be useful,
00013  *   but WITHOUT ANY WARRANTY; without even the implied warranty of
00014  *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00015  *   GNU General Public License for more details.
00016  *
00017  *   You should have received a copy of the GNU General Public License
00018  *   along with this program; if not, write to the Free Software
00019  *   Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
00020  */
00021 
00022 #include "anim.h"
00023 #include <glib/gstdio.h>
00024 
00025 #define TICK_TIME 20
00026 
00027 /* the list of active animations; we need to update it if active != NULL */
00028 static GSList *active;
00029 
00030 /* private callback */
00031 static gboolean anim_tick(void*);
00032 
00033 GcomprisAnimation *
00034 gc_anim_load(char *filename)
00035 {
00036   FILE *f = NULL;
00037 
00038   gchar *absolute_filename;
00039 
00040   absolute_filename = gc_file_find_absolute(filename);
00041 
00042   if (absolute_filename){
00043     f = g_fopen(absolute_filename, "r");
00044     g_free(absolute_filename);
00045   }
00046 
00047   if(!f)
00048     {
00049       g_warning("Couldn't open animation-spec file '%s'\n", filename);
00050       return NULL;
00051     }
00052 
00053   char tmp[100];
00054   GSList *files = NULL;
00055   GcomprisAnimation *anim = NULL;
00056 
00057   /* read filenames, one per line, from the animation spec-file */
00058   while(fscanf(f, "%99s", tmp) == 1)
00059     {
00060       GcomprisBoard   *gcomprisBoard = gc_board_get_current();
00061       files = g_slist_append(files, 
00062                              g_strdup_printf("%s/%s", gcomprisBoard->board_dir, tmp));
00063     }
00064   fclose(f);
00065   anim = g_malloc(sizeof(GcomprisAnimation));
00066   anim->numstates = g_slist_length(files);
00067   anim->anim = g_malloc(sizeof(GdkPixbuf*) * anim->numstates);
00068 
00069   /* open the animations and assign them */
00070   GError *error = NULL;
00071   GSList *cur;
00072   char *name;
00073   int i;
00074   for(cur=files, i=0; cur; cur = g_slist_next(cur), i++)
00075     {
00076       name = (char*) cur->data;
00077       anim->anim[i] = gdk_pixbuf_animation_new_from_file(name, &error);
00078       g_warning("Opened animation %s\n", name);
00079       if(!anim->anim[i])
00080         {
00081           g_critical("Couldn't open animation %s: %s\n", name, error->message);
00082           return NULL;
00083         }
00084       g_free(name);
00085     }
00086   g_slist_free(files);
00087   return anim;
00088 }
00089 
00090 GcomprisAnimCanvasItem *
00091 gc_anim_activate(GnomeCanvasGroup *parent,
00092                GcomprisAnimation *anim)
00093 {
00094   GcomprisAnimCanvasItem *item = g_malloc(sizeof(GcomprisAnimCanvasItem));
00095 
00096   item->state = 0;
00097   item->anim = anim;
00098   item->iter = gdk_pixbuf_animation_get_iter(anim->anim[0], NULL);
00099   item->canvas = (GnomeCanvasPixbuf*) gnome_canvas_item_new(
00100                             parent,
00101                             GNOME_TYPE_CANVAS_PIXBUF,
00102                             "pixbuf",
00103                             gdk_pixbuf_animation_iter_get_pixbuf(item->iter),
00104                             NULL);
00105 
00106   if(active == NULL)
00107       g_timeout_add(TICK_TIME, (GSourceFunc)anim_tick, NULL);
00108 
00109   active = g_slist_append(active, item);
00110   return item;
00111 }
00112 
00113 void
00114 gc_anim_swap(GcomprisAnimCanvasItem *item, GcomprisAnimation *new_anim)
00115 {
00116   item->anim = new_anim;
00117   gc_anim_set_state(item, 0);
00118 }
00119 
00120 void
00121 gc_anim_deactivate(GcomprisAnimCanvasItem *item)
00122 {
00123   GSList *node = g_slist_find( active, item );
00124   if( !node )
00125   {
00126     g_critical( "Tried to deactive non-existant animation" );
00127     return;
00128   }
00129 
00130   if (GNOME_IS_CANVAS_ITEM(item->canvas)){
00131     gtk_object_destroy(GTK_OBJECT(item->canvas));
00132     item->canvas = NULL;
00133   }
00134 
00135   active = g_slist_delete_link(active, node);
00136   g_object_unref(item->iter);
00137   g_free(item);
00138 }
00139 
00140 void
00141 gc_anim_free(GcomprisAnimation *anim)
00142 {
00143   int i;
00144   for(i=0; i<anim->numstates; i++)
00145     {
00146       g_object_unref(anim->anim[i]);
00147     }
00148   g_free(anim->anim);
00149   g_free(anim);
00150 }
00151 
00152 void
00153 gc_anim_set_state(GcomprisAnimCanvasItem *item, int state)
00154 {
00155   if(state < item->anim->numstates)
00156     {
00157       item->state = state;
00158     }
00159   else
00160     {
00161       item->state = 0;
00162     }
00163   g_object_unref( item->iter );
00164   item->iter = gdk_pixbuf_animation_get_iter( item->anim->anim[item->state],
00165                                               NULL );
00166   gnome_canvas_item_set( (GnomeCanvasItem*)item->canvas, "pixbuf",
00167                          gdk_pixbuf_animation_iter_get_pixbuf(item->iter),
00168                          NULL);
00169 }
00170 
00171 /* private callback functions */
00172 
00173 static gboolean
00174 anim_tick(void *ignore)
00175 {
00176   if(active == NULL)
00177     {
00178       g_warning("deactivating anim_tick\n");
00179       return FALSE;
00180     }
00181 
00182   GSList *cur;
00183   for(cur=active; cur; cur = g_slist_next(cur))
00184     {
00185       GcomprisAnimCanvasItem *a = (GcomprisAnimCanvasItem*)cur->data;
00186       if( gdk_pixbuf_animation_iter_advance( a->iter, NULL) )
00187         {
00188           gnome_canvas_item_set((GnomeCanvasItem*)a->canvas, "pixbuf", 
00189                                 gdk_pixbuf_animation_iter_get_pixbuf(a->iter),
00190                                 NULL);
00191         }
00192     }
00193   return TRUE;
00194 }
00195