1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163
|
// SPDX-License-Identifier: LGPL-2.1-or-later
/* SPDX-FileCopyrightText: 2006-2015 Simon Wunderlich <sw@simonwunderlich.de>
*/
#include <s3d.h>
#include <s3dw.h>
#include <s3dw_int.h>
#include <s3dlib.h>
#include <math.h>
/* the animation stack */
static s3dw_widget *ani_s[MAXANI];
static int ani_n = 0;
static int animation_on = 0;
int ani_need_arr = 0;
/* is item f already on stack? */
int s3dw_ani_stackpos(s3dw_widget *f)
{
int i;
for (i = 0; i < ani_n; i++)
if (ani_s[i] == f)
return i; /* already in list */
return -1;
}
/* add an item on the animation stack */
void s3dw_ani_add(s3dw_widget *f)
{
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));
if ((f->oid == 0) && (f->type != S3DW_TCAM)) {
s3dprintf(HIGH, "s3dw_ani_add() assert failed: weird, moving cam but its not a cam object?");
return;
}
if ((ani_n < MAXANI) && (animation_on)) {
if (s3dw_ani_stackpos(f) != -1)
return; /* already in list */
ani_s[ani_n] = f;
s3dw_ani_iterate(f);
ani_n++;
} else /* no place, finish now */
s3dw_ani_finish(f, -1);
}
/* delete an item from the animation stack */
void s3dw_ani_del(int i)
{
if ((i >= 0) && (i < ani_n)) {
s3dprintf(VLOW, "[A]ni DEL %d, ani_n = %d\n", i, ani_n);
ani_n--;
ani_s[i] = ani_s[ani_n]; /* that should also work if i is the last one */
} else {
s3dprintf(MED, "[F]ATAL: can't delete animation!\n");
}
}
/* apply the animation */
void s3dw_ani_doit(s3dw_widget *f)
{
if ((f->oid == 0) && (f->type != S3DW_TCAM)) {
s3dprintf(HIGH, "s3dw_ani_doit() assert failed: weird, moving cam but its not a cam object?");
} else {
if (f->oid == 0) {
s3dprintf(HIGH, "moving cam");
}
s3d_translate(f->oid, f->ax, f->ay, f->az);
s3d_rotate(f->oid, f->arx, f->ary, f->arz);
s3d_scale(f->oid, f->as);
}
}
/* finish an animation on the stack, stack index i */
void s3dw_ani_finish(s3dw_widget *f, int i)
{
f->ax = f->x;
f->ay = f->y;
f->az = f->z;
f->arx = f->rx;
f->ary = f->ry;
f->arz = f->rz;
f->as = f->s;
s3dw_ani_doit(f);
if (i != -1)
s3dw_ani_del(i);
}
/* do one step of the animation */
void s3dw_ani_iterate(s3dw_widget *f)
{
f->ax = (f->x + f->ax * ZOOMS) / (ZOOMS + 1);
f->ay = (f->y + f->ay * ZOOMS) / (ZOOMS + 1);
f->az = (f->z + f->az * ZOOMS) / (ZOOMS + 1);
f->arx = (f->rx + f->arx * ZOOMS) / (ZOOMS + 1);
f->ary = (f->ry + f->ary * ZOOMS) / (ZOOMS + 1);
f->arz = (f->rz + f->arz * ZOOMS) / (ZOOMS + 1);
f->as = (f->s + f->as * ZOOMS) / (ZOOMS + 1);
}
/* checks if f is good enough */
int s3dw_ani_check(s3dw_widget *f)
{
float x, y, z, rx, ry, rz;
x = f->ax - f->x;
y = f->ay - f->y;
z = f->az - f->z;
rx = f->arx - f->rx;
ry = f->ary - f->ry;
rz = f->arz - f->rz;
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))
return 0;
return 1;
}
/* need an arrangement ... */
void s3dw_ani_needarr(void)
{
ani_need_arr = 1;
if (!animation_on) {
while (ani_need_arr) s3dw_arrange();
}
}
/** \brief doing the whole animation thing
*
* Just call this in your mainloop if you want some nice window sliding
* animations. it's somewhat bloating, but you don't want to miss it ;)
*
* \code
* #include <time.h> // nanosleep()
* static struct timespec t={0.33*1000*1000}; // 33 mili seconds
* void mainloop()
* {
* // keep this in your mainloop. this will do smooth animations for you ...
* s3dw_ani_mate();
* nanosleep(&t,NULL);
* }
*
* ....
* s3d_mainloop(mainloop);
* \endcode
*/
void s3dw_ani_mate(void)
{
int i;
s3dw_widget *f;
animation_on = 1; /* animation is activated */
if (ani_need_arr) s3dw_arrange();
for (i = 0; i < ani_n; i++) {
f = ani_s[i];
s3dw_ani_iterate(f);
if (s3dw_ani_check(f)) {
s3dw_ani_finish(f, i);
i--; /* a new widget is here now, take care in the next iteration */
} else {
s3dw_ani_doit(f);
}
}
}
|