Release s3d 0.2.2
[s3d.git] / libs3dw / animate.c
blob8bfd5f9546b0d8264b4fefe16d2555eeaf8f9eca
1 /*
2 * animate.c
4 * Copyright (C) 2006-2011 Simon Wunderlich <dotslash@packetmixer.de>
6 * This file is part of the s3d Widgets, a Widget Library for s3d.
7 * See http://s3d.berlios.de/ for more updates.
9 * s3d Widgets is free software; you can redistribute it and/or modify
10 * it under the terms of the GNU Lesser General Public License as published by
11 * the Free Software Foundation; either version 2.1 of the License, or
12 * (at your option) any later version.
14 * s3d Widgets is distributed in the hope that it will be useful,
15 * but WITHOUT ANY WARRANTY; without even the implied warranty of
16 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17 * GNU Lesser General Public License for more details.
19 * You should have received a copy of the GNU Lesser General Public License
20 * along with the s3d Widgets; if not, write to the Free Software
21 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
24 #include <s3d.h>
25 #include <s3dw.h>
26 #include <s3dw_int.h>
27 #include <math.h>
29 /* the animation stack */
30 static s3dw_widget *ani_s[MAXANI];
31 static int ani_n = 0;
32 static int animation_on = 0;
33 int ani_need_arr = 0;
35 /* is item f already on stack? */
36 int s3dw_ani_stackpos(s3dw_widget *f)
38 int i;
39 for (i = 0; i < ani_n; i++)
40 if (ani_s[i] == f)
41 return i; /* already in list */
42 return -1;
46 /* add an item on the animation stack */
47 void s3dw_ani_add(s3dw_widget *f)
50 s3dprintf(VLOW, "[A]ni ADD (%10p), oid = %d, ani_n = %d, type is %s\n", (void*)f, f->oid, ani_n, s3dw_get_type_string(f->type));
51 if ((f->oid == 0) && (f->type != S3DW_TCAM)) {
52 s3dprintf(HIGH, "s3dw_ani_add() assert failed: weird, moving cam but its not a cam object?");
53 return;
55 if ((ani_n < MAXANI) && (animation_on)) {
56 if (s3dw_ani_stackpos(f) != -1)
57 return; /* already in list */
58 ani_s[ani_n] = f;
59 s3dw_ani_iterate(f);
60 ani_n++;
61 } else /* no place, finish now */
62 s3dw_ani_finish(f, -1);
65 /* delete an item from the animation stack */
66 void s3dw_ani_del(int i)
68 if ((i >= 0) && (i < ani_n)) {
69 s3dprintf(VLOW, "[A]ni DEL %d, ani_n = %d\n", i, ani_n);
70 ani_n--;
71 ani_s[i] = ani_s[ani_n]; /* that should also work if i is the last one */
72 } else {
73 s3dprintf(MED, "[F]ATAL: can't delete animation!\n");
77 /* apply the animation */
78 void s3dw_ani_doit(s3dw_widget *f)
80 if ((f->oid == 0) && (f->type != S3DW_TCAM)) {
81 s3dprintf(HIGH, "s3dw_ani_doit() assert failed: weird, moving cam but its not a cam object?");
82 } else {
83 if (f->oid == 0) {
84 s3dprintf(HIGH, "moving cam");
86 s3d_translate(f->oid, f->ax, f->ay, f->az);
87 s3d_rotate(f->oid, f->arx, f->ary, f->arz);
88 s3d_scale(f->oid, f->as);
92 /* finish an animation on the stack, stack index i */
93 void s3dw_ani_finish(s3dw_widget *f, int i)
95 f->ax = f->x;
96 f->ay = f->y;
97 f->az = f->z;
98 f->arx = f->rx;
99 f->ary = f->ry;
100 f->arz = f->rz;
101 f->as = f->s;
102 s3dw_ani_doit(f);
103 if (i != -1)
104 s3dw_ani_del(i);
107 /* do one step of the animation */
108 void s3dw_ani_iterate(s3dw_widget *f)
110 f->ax = (f->x + f->ax * ZOOMS) / (ZOOMS + 1);
111 f->ay = (f->y + f->ay * ZOOMS) / (ZOOMS + 1);
112 f->az = (f->z + f->az * ZOOMS) / (ZOOMS + 1);
113 f->arx = (f->rx + f->arx * ZOOMS) / (ZOOMS + 1);
114 f->ary = (f->ry + f->ary * ZOOMS) / (ZOOMS + 1);
115 f->arz = (f->rz + f->arz * ZOOMS) / (ZOOMS + 1);
116 f->as = (f->s + f->as * ZOOMS) / (ZOOMS + 1);
120 /* checks if f is good enough */
121 int s3dw_ani_check(s3dw_widget *f)
123 float x, y, z, rx, ry, rz;
124 x = f->ax - f->x;
125 y = f->ay - f->y;
126 z = f->az - f->z;
127 rx = f->arx - f->rx;
128 ry = f->ary - f->ry;
129 rz = f->arz - f->rz;
131 if (((fabs(f->as - f->s) / f->s) > 0.01) || (sqrt(x*x + y*y + z*z) > 0.01) || (sqrt(rx*rx + ry*ry + rz*rz) > 0.01))
132 return 0;
133 return 1;
136 /* need an arrangement ... */
137 void s3dw_ani_needarr(void)
139 ani_need_arr = 1;
140 if (!animation_on) {
141 while (ani_need_arr) s3dw_arrange();
146 /** \brief doing the whole animation thing
148 * Just call this in your mainloop if you want some nice window sliding
149 * animations. it's somewhat bloating, but you don't want to miss it ;)
151 * \code
152 * #include <time.h> // nanosleep()
153 * static struct timespec t={0.33*1000*1000}; // 33 mili seconds
154 * void mainloop()
156 * // keep this in your mainloop. this will do smooth animations for you ...
157 * s3dw_ani_mate();
158 * nanosleep(&t,NULL);
161 * ....
162 * s3d_mainloop(mainloop);
163 * \endcode
165 void s3dw_ani_mate(void)
167 int i;
168 s3dw_widget *f;
169 animation_on = 1; /* animation is activated */
170 if (ani_need_arr) s3dw_arrange();
171 for (i = 0; i < ani_n; i++) {
172 f = ani_s[i];
173 s3dw_ani_iterate(f);
174 if (s3dw_ani_check(f)) {
175 s3dw_ani_finish(f, i);
176 i--; /* a new widget is here now, take care in the next iteration */
177 } else {
178 s3dw_ani_doit(f);