Initial revision
[blender.git] / source / blender / blenkernel / intern / ipo.c
1 /* ipo.c                MIXED MODEL
2  * 
3  * jan 95
4  * 
5  * $Id$
6  *
7  * ***** BEGIN GPL/BL DUAL LICENSE BLOCK *****
8  *
9  * This program is free software; you can redistribute it and/or
10  * modify it under the terms of the GNU General Public License
11  * as published by the Free Software Foundation; either version 2
12  * of the License, or (at your option) any later version. The Blender
13  * Foundation also sells licenses for use in proprietary software under
14  * the Blender License.  See http://www.blender.org/BL/ for information
15  * about this.
16  *
17  * This program is distributed in the hope that it will be useful,
18  * but WITHOUT ANY WARRANTY; without even the implied warranty of
19  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
20  * GNU General Public License for more details.
21  *
22  * You should have received a copy of the GNU General Public License
23  * along with this program; if not, write to the Free Software Foundation,
24  * Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
25  *
26  * The Original Code is Copyright (C) 2001-2002 by NaN Holding BV.
27  * All rights reserved.
28  *
29  * The Original Code is: all of this file.
30  *
31  * Contributor(s): none yet.
32  *
33  * ***** END GPL/BL DUAL LICENSE BLOCK *****
34  */
35
36 #include <math.h>
37 #include <stdio.h>
38 #include <string.h>
39 #ifdef WIN32
40 #include "BLI_winstuff.h"
41 #endif
42 #include "MEM_guardedalloc.h"
43
44 #include "DNA_ika_types.h"
45 #include "DNA_sequence_types.h"
46 #include "DNA_camera_types.h"
47 #include "DNA_sound_types.h"
48 #include "DNA_lamp_types.h"
49 #include "DNA_view3d_types.h"
50 #include "DNA_key_types.h"
51 #include "DNA_scene_types.h"
52 #include "DNA_texture_types.h"
53 #include "DNA_material_types.h"
54 #include "DNA_object_types.h"
55 #include "DNA_curve_types.h"
56 #include "DNA_ipo_types.h"
57 #include "DNA_action_types.h"
58 #include "BLI_blenlib.h"
59 #include "BLI_arithb.h"
60
61 #include "BKE_bad_level_calls.h"
62 #include "BKE_utildefines.h"
63
64 #include "BKE_main.h"
65 #include "BKE_global.h"
66 #include "BKE_library.h"
67 #include "BKE_curve.h"
68 #include "BKE_object.h"
69 #include "BKE_blender.h"
70 #include "BKE_ipo.h"
71 #include "BKE_constraint.h"
72
73 #define SMALL -1.0e-10
74
75 /* Dit array is ervoor zodat defines zoals OB_LOC_X niet persee 0 hoeft te zijn.
76    Ook voor toekomstige backward compatibility.
77    Zo kan met een for-next lus alles worden afgelopen */
78
79 int co_ar[CO_TOTIPO]= {
80         CO_ENFORCE
81 };
82
83 int ob_ar[OB_TOTIPO]= {
84         OB_LOC_X, OB_LOC_Y, OB_LOC_Z, OB_DLOC_X, OB_DLOC_Y, OB_DLOC_Z, 
85         OB_ROT_X, OB_ROT_Y, OB_ROT_Z, OB_DROT_X, OB_DROT_Y, OB_DROT_Z, 
86         OB_SIZE_X, OB_SIZE_Y, OB_SIZE_Z, OB_DSIZE_X, OB_DSIZE_Y, OB_DSIZE_Z, 
87         OB_LAY, OB_TIME, OB_EFF_X, OB_EFF_Y, OB_EFF_Z, OB_COL_A
88 };
89
90 int ac_ar[AC_TOTIPO]= {
91         AC_LOC_X, AC_LOC_Y, AC_LOC_Z,  
92          AC_QUAT_W, AC_QUAT_X, AC_QUAT_Y, AC_QUAT_Z,
93         AC_SIZE_X, AC_SIZE_Y, AC_SIZE_Z
94 };
95
96 int ma_ar[MA_TOTIPO]= {
97         MA_COL_R, MA_COL_G, MA_COL_B, 
98         MA_SPEC_R, MA_SPEC_G, MA_SPEC_B, 
99         MA_MIR_R, MA_MIR_G, MA_MIR_B, 
100         MA_REF, MA_ALPHA, MA_EMIT, MA_AMB, 
101         MA_SPEC, MA_HARD, MA_SPTR, MA_ANG, 
102         MA_MODE, MA_HASIZE, 
103         
104         MA_MAP1+MAP_OFS_X, MA_MAP1+MAP_OFS_Y, MA_MAP1+MAP_OFS_Z, 
105         MA_MAP1+MAP_SIZE_X, MA_MAP1+MAP_SIZE_Y, MA_MAP1+MAP_SIZE_Z, 
106         MA_MAP1+MAP_R, MA_MAP1+MAP_G, MA_MAP1+MAP_B,
107         MA_MAP1+MAP_DVAR, MA_MAP1+MAP_COLF, MA_MAP1+MAP_NORF, MA_MAP1+MAP_VARF
108 };
109
110 int seq_ar[SEQ_TOTIPO]= {
111         SEQ_FAC1
112 };
113
114 int cu_ar[CU_TOTIPO]= {
115         CU_SPEED
116 };
117
118 int key_ar[KEY_TOTIPO]= {
119         KEY_SPEED, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 
120         11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 
121         21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31
122 };
123
124 int wo_ar[WO_TOTIPO]= {
125         WO_HOR_R, WO_HOR_G, WO_HOR_B, WO_ZEN_R, WO_ZEN_G, WO_ZEN_B, 
126         WO_EXPOS, WO_MISI, WO_MISTDI, WO_MISTSTA, WO_MISTHI,
127         WO_STAR_R, WO_STAR_G, WO_STAR_B, WO_STARDIST, WO_STARSIZE, 
128
129         MA_MAP1+MAP_OFS_X, MA_MAP1+MAP_OFS_Y, MA_MAP1+MAP_OFS_Z, 
130         MA_MAP1+MAP_SIZE_X, MA_MAP1+MAP_SIZE_Y, MA_MAP1+MAP_SIZE_Z, 
131         MA_MAP1+MAP_R, MA_MAP1+MAP_G, MA_MAP1+MAP_B,
132         MA_MAP1+MAP_DVAR, MA_MAP1+MAP_COLF, MA_MAP1+MAP_NORF, MA_MAP1+MAP_VARF
133 };
134
135 int la_ar[LA_TOTIPO]= {
136         LA_ENERGY,  LA_COL_R, LA_COL_G,  LA_COL_B, 
137         LA_DIST, LA_SPOTSI, LA_SPOTBL, 
138         LA_QUAD1,  LA_QUAD2,  LA_HALOINT,  
139
140         MA_MAP1+MAP_OFS_X, MA_MAP1+MAP_OFS_Y, MA_MAP1+MAP_OFS_Z, 
141         MA_MAP1+MAP_SIZE_X, MA_MAP1+MAP_SIZE_Y, MA_MAP1+MAP_SIZE_Z, 
142         MA_MAP1+MAP_R, MA_MAP1+MAP_G, MA_MAP1+MAP_B,
143         MA_MAP1+MAP_DVAR, MA_MAP1+MAP_COLF, MA_MAP1+MAP_NORF, MA_MAP1+MAP_VARF
144 };
145
146 int cam_ar[CAM_TOTIPO]= {
147         CAM_LENS, CAM_STA, CAM_END
148 };
149
150 int snd_ar[SND_TOTIPO]= {
151         SND_VOLUME, SND_PITCH, SND_PANNING, SND_ATTEN
152 };
153
154
155
156 float frame_to_float(int cfra)          /* zie ook bsystem_time in object.c */
157 {
158         extern float bluroffs;  /* object.c */
159         float ctime;
160         
161         ctime= (float)cfra;
162         if(R.flag & R_SEC_FIELD) {
163                 if((R.r.mode & R_FIELDSTILL)==0) ctime+= 0.5;
164         }
165         ctime+= bluroffs;
166         ctime*= G.scene->r.framelen;
167         
168         return ctime;
169 }
170
171 /* niet ipo zelf vrijgeven */
172 void free_ipo(Ipo *ipo)
173 {
174         IpoCurve *icu;
175         
176         icu= ipo->curve.first;
177         while(icu) {
178                 if(icu->bezt) MEM_freeN(icu->bezt);
179                 icu= icu->next;
180         }
181         BLI_freelistN(&ipo->curve);
182 }
183
184 Ipo *add_ipo(char *name, int idcode)
185 {
186         Ipo *ipo;
187         
188         ipo= alloc_libblock(&G.main->ipo, ID_IP, name);
189         ipo->blocktype= idcode;
190         
191         return ipo;
192 }
193
194 Ipo *copy_ipo(Ipo *ipo)
195 {
196         Ipo *ipon;
197         IpoCurve *icu;
198         
199         if(ipo==0) return 0;
200         
201         ipon= copy_libblock(ipo);
202         
203         duplicatelist(&(ipon->curve), &(ipo->curve));
204         
205         icu= ipon->curve.first;
206         while(icu) {
207                 icu->bezt= MEM_dupallocN(icu->bezt);
208                 icu= icu->next;
209         }
210         
211         return ipon;
212 }
213
214 void make_local_obipo(Ipo *ipo)
215 {
216         Object *ob;
217         Ipo *ipon;
218         int local=0, lib=0;
219         
220         /* - zijn er alleen lib users: niet doen
221          * - zijn er alleen locale users: flag zetten
222          * - mixed: copy
223          */
224
225         ob= G.main->object.first;
226         while(ob) {
227                 if(ob->ipo==ipo) {
228                         if(ob->id.lib) lib= 1;
229                         else local= 1;
230                 }
231                 ob= ob->id.next;
232         }
233         
234         if(local && lib==0) {
235                 ipo->id.lib= 0;
236                 ipo->id.flag= LIB_LOCAL;
237                 new_id(0, (ID *)ipo, 0);
238         }
239         else if(local && lib) {
240                 ipon= copy_ipo(ipo);
241                 ipon->id.us= 0;
242                 
243                 ob= G.main->object.first;
244                 while(ob) {
245                         if(ob->ipo==ipo) {
246                                 
247                                 if(ob->id.lib==0) {
248                                         ob->ipo= ipon;
249                                         ipon->id.us++;
250                                         ipo->id.us--;
251                                 }
252                         }
253                         ob= ob->id.next;
254                 }
255         }
256 }
257
258 void make_local_matipo(Ipo *ipo)
259 {
260         Material *ma;
261         Ipo *ipon;
262         int local=0, lib=0;
263         
264         /* - zijn er alleen lib users: niet doen
265          * - zijn er alleen locale users: flag zetten
266          * - mixed: copy
267          */
268
269         ma= G.main->mat.first;
270         while(ma) {
271                 if(ma->ipo==ipo) {
272                         if(ma->id.lib) lib= 1;
273                         else local= 1;
274                 }
275                 ma= ma->id.next;
276         }
277         
278         if(local && lib==0) {
279                 ipo->id.lib= 0;
280                 ipo->id.flag= LIB_LOCAL;
281                 new_id(0, (ID *)ipo, 0);
282         }
283         else if(local && lib) {
284                 ipon= copy_ipo(ipo);
285                 ipon->id.us= 0;
286                 
287                 ma= G.main->mat.first;
288                 while(ma) {
289                         if(ma->ipo==ipo) {
290                                 
291                                 if(ma->id.lib==0) {
292                                         ma->ipo= ipon;
293                                         ipon->id.us++;
294                                         ipo->id.us--;
295                                 }
296                         }
297                         ma= ma->id.next;
298                 }
299         }
300 }
301
302 void make_local_keyipo(Ipo *ipo)
303 {
304         Key *key;
305         Ipo *ipon;
306         int local=0, lib=0;
307         
308         /* - zijn er alleen lib users: niet doen
309          * - zijn er alleen locale users: flag zetten
310          * - mixed: copy
311          */
312
313         key= G.main->key.first;
314         while(key) {
315                 if(key->ipo==ipo) {
316                         if(key->id.lib) lib= 1;
317                         else local= 1;
318                 }
319                 key= key->id.next;
320         }
321         
322         if(local && lib==0) {
323                 ipo->id.lib= 0;
324                 ipo->id.flag= LIB_LOCAL;
325                 new_id(0, (ID *)ipo, 0);
326         }
327         else if(local && lib) {
328                 ipon= copy_ipo(ipo);
329                 ipon->id.us= 0;
330                 
331                 key= G.main->key.first;
332                 while(key) {
333                         if(key->ipo==ipo) {
334                                 
335                                 if(key->id.lib==0) {
336                                         key->ipo= ipon;
337                                         ipon->id.us++;
338                                         ipo->id.us--;
339                                 }
340                         }
341                         key= key->id.next;
342                 }
343         }
344 }
345
346
347 void make_local_ipo(Ipo *ipo)
348 {
349         
350         if(ipo->id.lib==0) return;
351         if(ipo->id.us==1) {
352                 ipo->id.lib= 0;
353                 ipo->id.flag= LIB_LOCAL;
354                 new_id(0, (ID *)ipo, 0);
355                 return;
356         }
357         
358         if(ipo->blocktype==ID_OB) make_local_obipo(ipo);
359         else if(ipo->blocktype==ID_MA) make_local_matipo(ipo);
360         else if(ipo->blocktype==ID_KE) make_local_keyipo(ipo);
361
362 }
363
364
365 void calchandles_ipocurve(IpoCurve *icu)
366 {
367         BezTriple *bezt, *prev, *next;
368         int a;
369
370         a= icu->totvert;
371         if(a<2) return;
372         
373         bezt= icu->bezt;
374         prev= 0;
375         next= bezt+1;
376
377         while(a--) {
378
379                 if(bezt->vec[0][0]>bezt->vec[1][0]) bezt->vec[0][0]= bezt->vec[1][0];
380                 if(bezt->vec[2][0]<bezt->vec[1][0]) bezt->vec[2][0]= bezt->vec[1][0];
381
382                 calchandleNurb(bezt, prev, next, 1);    /* 1==speciale autohandle */
383
384                 prev= bezt;
385                 if(a==1) {
386                         next= 0;
387                 }
388                 else next++;
389                         
390                 /* voor automatische ease in en out */
391                 if(bezt->h1==HD_AUTO && bezt->h2==HD_AUTO) {
392                         if(a==0 || a==icu->totvert-1) {
393                                 if(icu->extrap==IPO_HORIZ) {
394                                         bezt->vec[0][1]= bezt->vec[2][1]= bezt->vec[1][1];
395                                 }
396                         }
397                 }
398                 
399                 bezt++;
400         }
401 }
402
403 void testhandles_ipocurve(IpoCurve *icu)
404 {
405         /* Te gebruiken als er iets aan de handles is veranderd.
406          * Loopt alle BezTriples af met de volgende regels:
407      * FASE 1: types veranderen?
408      *  Autocalchandles: worden ligned als NOT(000 || 111)
409      *  Vectorhandles worden 'niets' als (selected en andere niet) 
410      * FASE 2: handles herberekenen
411      */
412         BezTriple *bezt;
413         int flag, a;
414
415         bezt= icu->bezt;
416         if(bezt==0) return;
417         
418         a= icu->totvert;
419         while(a--) {
420                 flag= 0;
421                 if(bezt->f1 & 1) flag++;
422                 if(bezt->f2 & 1) flag += 2;
423                 if(bezt->f3 & 1) flag += 4;
424
425                 if( !(flag==0 || flag==7) ) {
426                         if(bezt->h1==HD_AUTO) {   /* auto */
427                                 bezt->h1= HD_ALIGN;
428                         }
429                         if(bezt->h2==HD_AUTO) {   /* auto */
430                                 bezt->h2= HD_ALIGN;
431                         }
432
433                         if(bezt->h1==HD_VECT) {   /* vector */
434                                 if(flag < 4) bezt->h1= 0;
435                         }
436                         if(bezt->h2==HD_VECT) {   /* vector */
437                                 if( flag > 3) bezt->h2= 0;
438                         }
439                 }
440                 bezt++;
441         }
442
443         calchandles_ipocurve(icu);
444 }
445
446
447 void sort_time_ipocurve(IpoCurve *icu)
448 {
449         BezTriple *bezt;
450         int a, ok= 1;
451         
452         while(ok) {
453                 ok= 0;
454
455                 if(icu->bezt) {
456                         bezt= icu->bezt;
457                         a= icu->totvert;
458                         while(a--) {
459                                 if(a>0) {
460                                         if( bezt->vec[1][0] > (bezt+1)->vec[1][0]) {
461                                                 SWAP(BezTriple, *bezt, *(bezt+1));
462                                                 ok= 1;
463                                         }
464                                 }
465                                 if(bezt->vec[0][0]>=bezt->vec[1][0] && bezt->vec[2][0]<=bezt->vec[1][0]) {
466                                         SWAP(float, bezt->vec[0][0], bezt->vec[2][0]);
467                                         SWAP(float, bezt->vec[0][1], bezt->vec[2][1]);
468                                 }
469                                 else {
470                                         if(bezt->vec[0][0]>bezt->vec[1][0]) bezt->vec[0][0]= bezt->vec[1][0];
471                                         if(bezt->vec[2][0]<bezt->vec[1][0]) bezt->vec[2][0]= bezt->vec[1][0];
472                                 }
473                                 bezt++;
474                         }
475                 }
476                 else {
477                         
478                 }
479         }
480 }
481
482 int test_time_ipocurve(IpoCurve *icu)
483 {
484         BezTriple *bezt;
485         int a;
486         
487         if(icu->bezt) {
488                 bezt= icu->bezt;
489                 a= icu->totvert-1;
490                 while(a--) {
491                         if( bezt->vec[1][0] > (bezt+1)->vec[1][0]) {
492                                 return 1;
493                         }
494                         bezt++;
495                 }       
496         }
497         else {
498                 
499         }
500
501         return 0;
502 }
503
504 void correct_bezpart(float *v1, float *v2, float *v3, float *v4)
505 {
506         /* de totale lengte van de handles mag niet langer zijn
507          * dan de horizontale afstand tussen de punten (v1-v4)
508          */
509         float h1[2], h2[2], len1, len2, len, fac;
510         
511         h1[0]= v1[0]-v2[0];
512         h1[1]= v1[1]-v2[1];
513         h2[0]= v4[0]-v3[0];
514         h2[1]= v4[1]-v3[1];
515         
516         len= v4[0]- v1[0];
517         len1= (float)fabs(h1[0]);
518         len2= (float)fabs(h2[0]);
519         
520         if(len1+len2==0.0) return;
521         if(len1+len2 > len) {
522                 fac= len/(len1+len2);
523                 
524                 v2[0]= (v1[0]-fac*h1[0]);
525                 v2[1]= (v1[1]-fac*h1[1]);
526                 
527                 v3[0]= (v4[0]-fac*h2[0]);
528                 v3[1]= (v4[1]-fac*h2[1]);
529                 
530         }
531 }
532
533 /* *********************** ARITH *********************** */
534
535 int findzero(float x, float q0, float q1, float q2, float q3, float *o)
536 {
537         double c0, c1, c2, c3, a, b, c, p, q, d, t, phi;
538         int nr= 0;
539
540         c0= q0-x;
541         c1= 3*(q1-q0);
542         c2= 3*(q0-2*q1+q2);
543         c3= q3-q0+3*(q1-q2);
544         
545         if(c3!=0.0) {
546                 a= c2/c3;
547                 b= c1/c3;
548                 c= c0/c3;
549                 a= a/3;
550
551                 p= b/3-a*a;
552                 q= (2*a*a*a-a*b+c)/2;
553                 d= q*q+p*p*p;
554
555                 if(d>0.0) {
556                         t= sqrt(d);
557                         o[0]= (float)(Sqrt3d(-q+t)+Sqrt3d(-q-t)-a);
558                         if(o[0]>= SMALL && o[0]<=1.000001) return 1;
559                         else return 0;
560                 }
561                 else if(d==0.0) {
562                         t= Sqrt3d(-q);
563                         o[0]= (float)(2*t-a);
564                         if(o[0]>=SMALL && o[0]<=1.000001) nr++;
565                         o[nr]= (float)(-t-a);
566                         if(o[nr]>=SMALL && o[nr]<=1.000001) return nr+1;
567                         else return nr;
568                 }
569                 else {
570                         phi= acos(-q/sqrt(-(p*p*p)));
571                         t= sqrt(-p);
572                         p= cos(phi/3);
573                         q= sqrt(3-3*p*p);
574                         o[0]= (float)(2*t*p-a);
575                         if(o[0]>=SMALL && o[0]<=1.000001) nr++;
576                         o[nr]= (float)(-t*(p+q)-a);
577                         if(o[nr]>=SMALL && o[nr]<=1.000001) nr++;
578                         o[nr]= (float)(-t*(p-q)-a);
579                         if(o[nr]>=SMALL && o[nr]<=1.000001) return nr+1;
580                         else return nr;
581                 }
582         }
583         else {
584                 a=c2;
585                 b=c1;
586                 c=c0;
587                 
588                 if(a!=0.0) {
589                         p=b*b-4*a*c;
590                         if(p>0) {
591                                 p= sqrt(p);
592                                 o[0]= (float)((-b-p)/(2*a));
593                                 if(o[0]>=SMALL && o[0]<=1.000001) nr++;
594                                 o[nr]= (float)((-b+p)/(2*a));
595                                 if(o[nr]>=SMALL && o[nr]<=1.000001) return nr+1;
596                                 else return nr;
597                         }
598                         else if(p==0) {
599                                 o[0]= (float)(-b/(2*a));
600                                 if(o[0]>=SMALL && o[0]<=1.000001) return 1;
601                                 else return 0;
602                         }
603                 }
604                 else if(b!=0.0) {
605                         o[0]= (float)(-c/b);
606                         if(o[0]>=SMALL && o[0]<=1.000001) return 1;
607                         else return 0;
608                 }
609                 else if(c==0.0) {
610                         o[0]= 0.0;
611                         return 1;
612                 }
613                 return 0;       
614         }
615 }
616
617 void berekeny(float f1, float f2, float f3, float f4, float *o, int b)
618 {
619         float t, c0, c1, c2, c3;
620         int a;
621
622         c0= f1;
623         c1= 3.0f*(f2 - f1);
624         c2= 3.0f*(f1 - 2.0f*f2 + f3);
625         c3= f4 - f1 + 3.0f*(f2-f3);
626         
627         for(a=0; a<b; a++) {
628                 t= o[a];
629                 o[a]= c0+t*c1+t*t*c2+t*t*t*c3;
630         }
631 }
632 void berekenx(float *f, float *o, int b)
633 {
634         float t, c0, c1, c2, c3;
635         int a;
636
637         c0= f[0];
638         c1= 3*(f[3]-f[0]);
639         c2= 3*(f[0]-2*f[3]+f[6]);
640         c3= f[9]-f[0]+3*(f[3]-f[6]);
641         for(a=0; a<b; a++) {
642                 t= o[a];
643                 o[a]= c0+t*c1+t*t*c2+t*t*t*c3;
644         }
645 }
646
647 float eval_icu(IpoCurve *icu, float ipotime) 
648 {
649         BezTriple *bezt, *prevbezt;
650         float v1[2], v2[2], v3[2], v4[2], opl[32], dx, fac;
651         float cycdx, cycdy, ofs, cycyofs, cvalue = 0.0;
652         int a, b;
653         
654         cycyofs= 0.0;
655         
656         if(icu->bezt) {
657                 prevbezt= icu->bezt;
658                 bezt= prevbezt+1;
659                 a= icu->totvert-1;
660                 
661                 /* cyclic? */
662                 if(icu->extrap & IPO_CYCL) {
663                         ofs= icu->bezt->vec[1][0];
664                         cycdx= (icu->bezt+icu->totvert-1)->vec[1][0] - ofs;
665                         cycdy= (icu->bezt+icu->totvert-1)->vec[1][1] - icu->bezt->vec[1][1];
666                         if(cycdx!=0.0) {
667                                 
668                                 if(icu->extrap & IPO_DIR) {
669                                         cycyofs= (float)floor((ipotime-ofs)/cycdx);
670                                         cycyofs*= cycdy;
671                                 }
672
673                                 ipotime= (float)(fmod(ipotime-ofs, cycdx)+ofs);
674                                 if(ipotime<ofs) ipotime+= cycdx;
675                         }
676                 }
677                 
678                 /* uiteinden? */
679         
680                 if(prevbezt->vec[1][0]>=ipotime) {
681                         if( (icu->extrap & IPO_DIR) && icu->ipo!=IPO_CONST) {
682                                 dx= prevbezt->vec[1][0]-ipotime;
683                                 fac= prevbezt->vec[1][0]-prevbezt->vec[0][0];
684                                 if(fac!=0.0) {
685                                         fac= (prevbezt->vec[1][1]-prevbezt->vec[0][1])/fac;
686                                         cvalue= prevbezt->vec[1][1]-fac*dx;
687                                 }
688                                 else cvalue= prevbezt->vec[1][1];
689                         }
690                         else cvalue= prevbezt->vec[1][1];
691                         
692                         cvalue+= cycyofs;
693                 }
694                 else if( (prevbezt+a)->vec[1][0]<=ipotime) {
695                         if( (icu->extrap & IPO_DIR) && icu->ipo!=IPO_CONST) {
696                                 prevbezt+= a;
697                                 dx= ipotime-prevbezt->vec[1][0];
698                                 fac= prevbezt->vec[2][0]-prevbezt->vec[1][0];
699                                 
700                                 if(fac!=0) {
701                                         fac= (prevbezt->vec[2][1]-prevbezt->vec[1][1])/fac;
702                                         cvalue= prevbezt->vec[1][1]+fac*dx;
703                                 }
704                                 else cvalue= prevbezt->vec[1][1];
705                         }
706                         else cvalue= (prevbezt+a)->vec[1][1];
707                         
708                         cvalue+= cycyofs;
709                 }
710                 else {
711                         while(a--) {
712                                 if(prevbezt->vec[1][0]<=ipotime && bezt->vec[1][0]>=ipotime) {
713                                         if(icu->ipo==IPO_CONST) {
714                                                 cvalue= prevbezt->vec[1][1]+cycyofs;
715                                         }
716                                         else if(icu->ipo==IPO_LIN) {
717                                                 fac= bezt->vec[1][0]-prevbezt->vec[1][0];
718                                                 if(fac==0) cvalue= cycyofs+prevbezt->vec[1][1];
719                                                 else {
720                                                         fac= (ipotime-prevbezt->vec[1][0])/fac;
721                                                         cvalue= cycyofs+prevbezt->vec[1][1]+ fac*(bezt->vec[1][1]-prevbezt->vec[1][1]);
722                                                 }
723                                         }
724                                         else {
725                                                 v1[0]= prevbezt->vec[1][0];
726                                                 v1[1]= prevbezt->vec[1][1];
727                                                 v2[0]= prevbezt->vec[2][0];
728                                                 v2[1]= prevbezt->vec[2][1];
729                                                 
730                                                 v3[0]= bezt->vec[0][0];
731                                                 v3[1]= bezt->vec[0][1];
732                                                 v4[0]= bezt->vec[1][0];
733                                                 v4[1]= bezt->vec[1][1];
734
735                                                 correct_bezpart(v1, v2, v3, v4);
736                                                 
737                                                 b= findzero(ipotime, v1[0], v2[0], v3[0], v4[0], opl);
738                                                 if(b) {
739                                                         berekeny(v1[1], v2[1], v3[1], v4[1], opl, 1);
740                                                         cvalue= opl[0]+cycyofs;
741                                                         break;
742                                                 }
743                                         }
744                                 }
745                                 prevbezt= bezt;
746                                 bezt++;
747                         }
748                 }
749         }
750
751         if(icu->ymin < icu->ymax) {
752                 if(cvalue < icu->ymin) cvalue= icu->ymin;
753                 else if(cvalue > icu->ymax) cvalue= icu->ymax;
754         }
755         
756         return cvalue;
757 }
758
759 void calc_icu(IpoCurve *icu, float ctime)
760 {
761         icu->curval= eval_icu(icu, ctime);
762 }
763
764 float calc_ipo_time(Ipo *ipo, float ctime)
765 {
766
767         if(ipo && ipo->blocktype==ID_OB) {
768                 IpoCurve *icu= ipo->curve.first;
769
770                 while(icu) {
771                         if (icu->adrcode==OB_TIME) {
772                                 calc_icu(icu, ctime);
773                                 return 10.0f*icu->curval;
774                         }
775                         icu= icu->next;
776                 }       
777         }
778         
779         return ctime;
780 }
781
782 void calc_ipo(Ipo *ipo, float ctime)
783 {
784         IpoCurve *icu;
785         
786         icu= ipo->curve.first;
787         while(icu) {
788                 
789                 if( (icu->flag & IPO_LOCK)==0) calc_icu(icu, ctime);
790                 
791                 icu= icu->next;
792         }
793 }
794
795 /* ************************************** */
796 /*              DO THE IPO!                                               */
797 /* ************************************** */
798
799 void write_ipo_poin(void *poin, int type, float val)
800 {
801
802         switch(type) {
803         case IPO_FLOAT:
804                 *( (float *)poin)= val;
805                 break;
806         case IPO_FLOAT_DEGR:
807                 *( (float *)poin)= (float)(val*M_PI_2/9.0);
808                 break;
809         case IPO_INT:
810         case IPO_INT_BIT:
811         case IPO_LONG:
812                 *( (int *)poin)= (int)val;
813                 break;
814         case IPO_SHORT:
815         case IPO_SHORT_BIT:
816                 *( (short *)poin)= (short)val;
817                 break;
818         case IPO_CHAR:
819         case IPO_CHAR_BIT:
820                 *( (char *)poin)= (char)val;
821                 break;
822         }
823 }
824
825 float read_ipo_poin(void *poin, int type)
826 {
827         float val = 0.0;
828         
829         switch(type) {
830         case IPO_FLOAT:
831                 val= *( (float *)poin);
832                 break;
833         case IPO_FLOAT_DEGR:
834                 val= *( (float *)poin);
835                 val = (float)(val/(M_PI_2/9.0));
836                 break;
837         case IPO_INT:
838         case IPO_INT_BIT:
839         case IPO_LONG:
840                 val= (float)(*( (int *)poin));
841                 break;
842         case IPO_SHORT:
843         case IPO_SHORT_BIT:
844                 val= *( (short *)poin);
845                 break;
846         case IPO_CHAR:
847         case IPO_CHAR_BIT:
848                 val= *( (char *)poin);
849                 break;
850         }
851         return val;
852 }
853
854 void *give_mtex_poin(MTex *mtex, int adrcode )
855 {
856         void *poin=0;
857                 
858         switch(adrcode) {
859         case MAP_OFS_X:
860                 poin= &(mtex->ofs[0]); break;
861         case MAP_OFS_Y:
862                 poin= &(mtex->ofs[1]); break;
863         case MAP_OFS_Z:
864                 poin= &(mtex->ofs[2]); break;
865         case MAP_SIZE_X:
866                 poin= &(mtex->size[0]); break;
867         case MAP_SIZE_Y:
868                 poin= &(mtex->size[1]); break;
869         case MAP_SIZE_Z:
870                 poin= &(mtex->size[2]); break;
871         case MAP_R:
872                 poin= &(mtex->r); break;
873         case MAP_G:
874                 poin= &(mtex->g); break;
875         case MAP_B:
876                 poin= &(mtex->b); break;
877         case MAP_DVAR:
878                 poin= &(mtex->def_var); break;
879         case MAP_COLF:
880                 poin= &(mtex->colfac); break;
881         case MAP_NORF:
882                 poin= &(mtex->norfac); break;
883         case MAP_VARF:
884                 poin= &(mtex->varfac); break;
885         }
886         
887         return poin;
888 }
889
890 /* GS reads the memory pointed at in a specific ordering. There are,
891  * however two definitions for it. I have jotted them down here, both,
892  * but I think the first one is actually used. The thing is that
893  * big-endian systems might read this the wrong way round. OTOH, we
894  * constructed the IDs that are read out with this macro explicitly as
895  * well. I expect we'll sort it out soon... */
896
897 /* from blendef: */
898 #define GS(a)   (*((short *)(a)))
899
900 /* from misc_util: flip the bytes from x  */
901 /*  #define GS(x) (((unsigned char *)(x))[0] << 8 | ((unsigned char *)(x))[1]) */
902
903 void *get_ipo_poin(ID *id, IpoCurve *icu, int *type)
904 {
905         void *poin= 0;
906         Object *ob;
907         Material *ma;
908         MTex *mtex;
909         Ika *ika= 0;
910         Lamp *la;
911         Sequence *seq;
912         World *wo;
913         bAction                 *act;
914         bActionChannel  *achan;
915         bPoseChannel    *pchan;
916
917         *type= IPO_FLOAT;
918
919
920         if( GS(id->name)==ID_OB) {
921         
922                 ob= (Object *)id;
923
924                 if(ob->type==OB_IKA) ika= ob->data;
925                 
926                 switch(icu->adrcode) {
927                 case OB_LOC_X:
928                         poin= &(ob->loc[0]); break;
929                 case OB_LOC_Y:
930                         poin= &(ob->loc[1]); break;
931                 case OB_LOC_Z:
932                         poin= &(ob->loc[2]); break;
933                 case OB_DLOC_X:
934                         poin= &(ob->dloc[0]); break;
935                 case OB_DLOC_Y:
936                         poin= &(ob->dloc[1]); break;
937                 case OB_DLOC_Z:
938                         poin= &(ob->dloc[2]); break;
939         
940                 case OB_ROT_X:
941                         poin= &(ob->rot[0]); *type= IPO_FLOAT_DEGR; break;
942                 case OB_ROT_Y:
943                         poin= &(ob->rot[1]); *type= IPO_FLOAT_DEGR; break;
944                 case OB_ROT_Z:
945                         poin= &(ob->rot[2]); *type= IPO_FLOAT_DEGR; break;
946                 case OB_DROT_X:
947                         poin= &(ob->drot[0]); *type= IPO_FLOAT_DEGR; break;
948                 case OB_DROT_Y:
949                         poin= &(ob->drot[1]); *type= IPO_FLOAT_DEGR; break;
950                 case OB_DROT_Z:
951                         poin= &(ob->drot[2]); *type= IPO_FLOAT_DEGR; break;
952                         
953                 case OB_SIZE_X:
954                         poin= &(ob->size[0]); break;
955                 case OB_SIZE_Y:
956                         poin= &(ob->size[1]); break;
957                 case OB_SIZE_Z:
958                         poin= &(ob->size[2]); break;
959                 case OB_DSIZE_X:
960                         poin= &(ob->dsize[0]); break;
961                 case OB_DSIZE_Y:
962                         poin= &(ob->dsize[1]); break;
963                 case OB_DSIZE_Z:
964                         poin= &(ob->dsize[2]); break;
965                 
966                 case OB_LAY:
967                         poin= &(ob->lay); *type= IPO_INT_BIT; break;
968                         
969                 case OB_EFF_X:  /* OB_COL_R */
970                         if(ika) poin= &(ika->effg[0]);
971                         else poin= &(ob->col[0]);
972                         break;
973                 case OB_EFF_Y:  /* OB_COL_G */
974                         if(ika) poin= &(ika->effg[1]);
975                         else poin= &(ob->col[1]);
976                         break;
977                 case OB_EFF_Z:  /* OB_COL_B */
978                         if(ika) poin= &(ika->effg[2]);
979                         else poin= &(ob->col[2]);
980                         break;
981                 case OB_COL_A:
982                         poin= &(ob->col[3]);
983                         break;
984                 }
985         }
986         else if (GS(id->name)==ID_AC){
987                 act= (bAction *)id;
988                 achan = act->achan;
989                 pchan = act->pchan;
990                 if (!pchan || !achan)
991                         return NULL;
992                 switch (icu->adrcode){
993                 case AC_QUAT_W:
994                         poin= &(pchan->quat[0]); break;
995                 case AC_QUAT_X:
996                         poin= &(pchan->quat[1]); break;
997                 case AC_QUAT_Y:
998                         poin= &(pchan->quat[2]); break;
999                 case AC_QUAT_Z:
1000                         poin= &(pchan->quat[3]); break;
1001                 case AC_LOC_X:
1002                         poin= &(pchan->loc[0]); break;
1003                 case AC_LOC_Y:
1004                         poin= &(pchan->loc[1]); break;
1005                 case AC_LOC_Z:
1006                         poin= &(pchan->loc[2]); break;                  
1007                 case AC_SIZE_X:
1008                         poin= &(pchan->size[0]); break;
1009                 case AC_SIZE_Y:
1010                         poin= &(pchan->size[1]); break;
1011                 case AC_SIZE_Z:
1012                         poin= &(pchan->size[2]); break;
1013                 };
1014         }
1015
1016         else if( GS(id->name)==ID_MA) {
1017                 
1018                 ma= (Material *)id;
1019                 
1020                 switch(icu->adrcode) {
1021                 case MA_COL_R:
1022                         poin= &(ma->r); break;
1023                 case MA_COL_G:
1024                         poin= &(ma->g); break;
1025                 case MA_COL_B:
1026                         poin= &(ma->b); break;
1027                 case MA_SPEC_R:
1028                         poin= &(ma->specr); break;
1029                 case MA_SPEC_G:
1030                         poin= &(ma->specg); break;
1031                 case MA_SPEC_B:
1032                         poin= &(ma->specb); break;
1033                 case MA_MIR_R:
1034                         poin= &(ma->mirr); break;
1035                 case MA_MIR_G:
1036                         poin= &(ma->mirg); break;
1037                 case MA_MIR_B:
1038                         poin= &(ma->mirb); break;
1039                 case MA_REF:
1040                         poin= &(ma->ref); break;
1041                 case MA_ALPHA:
1042                         poin= &(ma->alpha); break;
1043                 case MA_EMIT:
1044                         poin= &(ma->emit); break;
1045                 case MA_AMB:
1046                         poin= &(ma->amb); break;
1047                 case MA_SPEC:
1048                         poin= &(ma->spec); break;
1049                 case MA_HARD:
1050                         poin= &(ma->har); *type= IPO_SHORT; break;
1051                 case MA_SPTR:
1052                         poin= &(ma->spectra); break;
1053                 case MA_ANG:
1054                         poin= &(ma->ang); break;
1055                 case MA_MODE:
1056                         poin= &(ma->mode); *type= IPO_INT_BIT; break;
1057                 case MA_HASIZE:
1058                         poin= &(ma->hasize); break;
1059                 }
1060                 
1061                 if(poin==0) {
1062                         mtex= 0;
1063                         if(icu->adrcode & MA_MAP1) mtex= ma->mtex[0];
1064                         else if(icu->adrcode & MA_MAP2) mtex= ma->mtex[1];
1065                         else if(icu->adrcode & MA_MAP3) mtex= ma->mtex[2];
1066                         else if(icu->adrcode & MA_MAP4) mtex= ma->mtex[3];
1067                         else if(icu->adrcode & MA_MAP5) mtex= ma->mtex[4];
1068                         else if(icu->adrcode & MA_MAP6) mtex= ma->mtex[5];
1069                         else if(icu->adrcode & MA_MAP7) mtex= ma->mtex[6];
1070                         else if(icu->adrcode & MA_MAP8) mtex= ma->mtex[7];
1071                         
1072                         if(mtex) {
1073                                 poin= give_mtex_poin(mtex, icu->adrcode & (MA_MAP1-1) );
1074                         }
1075                 }
1076         }
1077         else if( GS(id->name)==ID_SEQ) {
1078                 seq= (Sequence *)id;
1079                 
1080                 switch(icu->adrcode) {
1081                 case SEQ_FAC1:
1082                         poin= &(seq->facf0); break;
1083                 }
1084         }
1085         else if( GS(id->name)==ID_CU) {
1086                 
1087                 poin= &(icu->curval);
1088                 
1089         }
1090         else if( GS(id->name)==ID_KE) {
1091                 
1092                 poin= &(icu->curval);
1093                 
1094         }
1095         else if(GS(id->name)==ID_WO) {
1096                 
1097                 wo= (World *)id;
1098                 
1099                 switch(icu->adrcode) {
1100                 case WO_HOR_R:
1101                         poin= &(wo->horr); break;
1102                 case WO_HOR_G:
1103                         poin= &(wo->horg); break;
1104                 case WO_HOR_B:
1105                         poin= &(wo->horb); break;
1106                 case WO_ZEN_R:
1107                         poin= &(wo->zenr); break;
1108                 case WO_ZEN_G:
1109                         poin= &(wo->zeng); break;
1110                 case WO_ZEN_B:
1111                         poin= &(wo->zenb); break;
1112
1113                 case WO_EXPOS:
1114                         poin= &(wo->exposure); break;
1115
1116                 case WO_MISI:
1117                         poin= &(wo->misi); break;
1118                 case WO_MISTDI:
1119                         poin= &(wo->mistdist); break;
1120                 case WO_MISTSTA:
1121                         poin= &(wo->miststa); break;
1122                 case WO_MISTHI:
1123                         poin= &(wo->misthi); break;
1124
1125                 case WO_STAR_R:
1126                         poin= &(wo->starr); break;
1127                 case WO_STAR_G:
1128                         poin= &(wo->starg); break;
1129                 case WO_STAR_B:
1130                         poin= &(wo->starb); break;
1131
1132                 case WO_STARDIST:
1133                         poin= &(wo->stardist); break;
1134                 case WO_STARSIZE:
1135                         poin= &(wo->starsize); break;
1136                 }
1137
1138                 if(poin==0) {
1139                         mtex= 0;
1140                         if(icu->adrcode & MA_MAP1) mtex= wo->mtex[0];
1141                         else if(icu->adrcode & MA_MAP2) mtex= wo->mtex[1];
1142                         else if(icu->adrcode & MA_MAP3) mtex= wo->mtex[2];
1143                         else if(icu->adrcode & MA_MAP4) mtex= wo->mtex[3];
1144                         else if(icu->adrcode & MA_MAP5) mtex= wo->mtex[4];
1145                         else if(icu->adrcode & MA_MAP6) mtex= wo->mtex[5];
1146                         else if(icu->adrcode & MA_MAP7) mtex= wo->mtex[6];
1147                         else if(icu->adrcode & MA_MAP8) mtex= wo->mtex[7];
1148                         
1149                         if(mtex) {
1150                                 poin= give_mtex_poin(mtex, icu->adrcode & (MA_MAP1-1) );
1151                         }
1152                 }
1153         }
1154         else if( GS(id->name)==ID_LA) {
1155                 
1156                 la= (Lamp *)id;
1157         
1158                 switch(icu->adrcode) {
1159                 case LA_ENERGY:
1160                         poin= &(la->energy); break;             
1161                 case LA_COL_R:
1162                         poin= &(la->r); break;
1163                 case LA_COL_G:
1164                         poin= &(la->g); break;
1165                 case LA_COL_B:
1166                         poin= &(la->b); break;
1167                 case LA_DIST:
1168                         poin= &(la->dist); break;               
1169                 case LA_SPOTSI:
1170                         poin= &(la->spotsize); break;
1171                 case LA_SPOTBL:
1172                         poin= &(la->spotblend); break;
1173                 case LA_QUAD1:
1174                         poin= &(la->att1); break;
1175                 case LA_QUAD2:
1176                         poin= &(la->att2); break;
1177                 case LA_HALOINT:
1178                         poin= &(la->haint); break;
1179                 }
1180                 
1181                 if(poin==0) {
1182                         mtex= 0;
1183                         if(icu->adrcode & MA_MAP1) mtex= la->mtex[0];
1184                         else if(icu->adrcode & MA_MAP2) mtex= la->mtex[1];
1185                         else if(icu->adrcode & MA_MAP3) mtex= la->mtex[2];
1186                         else if(icu->adrcode & MA_MAP4) mtex= la->mtex[3];
1187                         else if(icu->adrcode & MA_MAP5) mtex= la->mtex[4];
1188                         else if(icu->adrcode & MA_MAP6) mtex= la->mtex[5];
1189                         else if(icu->adrcode & MA_MAP7) mtex= la->mtex[6];
1190                         else if(icu->adrcode & MA_MAP8) mtex= la->mtex[7];
1191                         
1192                         if(mtex) {
1193                                 poin= give_mtex_poin(mtex, icu->adrcode & (MA_MAP1-1) );
1194                         }
1195                 }
1196         }
1197         else if(GS(id->name)==ID_CA) {
1198                 Camera *ca= (Camera *)id;
1199                 
1200                 switch(icu->adrcode) {
1201                 case CAM_LENS:
1202                         poin= &(ca->lens); break;
1203                 case CAM_STA:
1204                         poin= &(ca->clipsta); break;
1205                 case CAM_END:
1206                         poin= &(ca->clipend); break;
1207                 }
1208         }
1209         else if(GS(id->name)==ID_SO) {
1210                 bSound *snd= (bSound *)id;
1211                 
1212                 switch(icu->adrcode) {
1213                 case SND_VOLUME:
1214                         poin= &(snd->volume); break;
1215                 case SND_PITCH:
1216                         poin= &(snd->pitch); break;
1217                 case SND_PANNING:
1218                         poin= &(snd->panning); break;
1219                 case SND_ATTEN:
1220                         poin= &(snd->attenuation); break;
1221                 }
1222         }
1223         
1224         return poin;
1225 }
1226
1227 void set_icu_vars(IpoCurve *icu)
1228 {
1229         
1230         icu->ymin= icu->ymax= 0.0;
1231         icu->ipo= IPO_BEZ;
1232         
1233         if(icu->blocktype==ID_OB) {
1234         
1235                 if(icu->adrcode==OB_LAY) {
1236                         icu->ipo= IPO_CONST;
1237                         icu->vartype= IPO_BITS;
1238                 }
1239                 
1240         }
1241         else if(icu->blocktype==ID_MA) {
1242                 
1243                 if(icu->adrcode < MA_MAP1) {
1244                         switch(icu->adrcode) {
1245                         case MA_HASIZE:
1246                                 icu->ymax= 10000.0; break;
1247                         case MA_HARD:
1248                                 icu->ymax= 128.0; break;
1249                         case MA_SPEC:
1250                                 icu->ymax= 2.0; break;
1251                         case MA_MODE:
1252                                 icu->ipo= IPO_CONST;
1253                                 icu->vartype= IPO_BITS;
1254                                 break;
1255                                 
1256                         default:
1257                                 icu->ymax= 1.0;
1258                                 break;
1259                         }
1260                 }
1261                 else {
1262                         switch(icu->adrcode & (MA_MAP1-1)) {
1263                         case MAP_OFS_X:
1264                         case MAP_OFS_Y:
1265                         case MAP_OFS_Z:
1266                         case MAP_SIZE_X:
1267                         case MAP_SIZE_Y:
1268                         case MAP_SIZE_Z:
1269                                 icu->ymax= 1000.0;
1270                                 icu->ymin= -1000.0;
1271                         
1272                                 break;
1273                         case MAP_R:
1274                         case MAP_G:
1275                         case MAP_B:
1276                         case MAP_DVAR:
1277                         case MAP_COLF:
1278                         case MAP_VARF:
1279                                 icu->ymax= 1.0;
1280                                 break;
1281                         case MAP_NORF:
1282                                 icu->ymax= 5.0;
1283                                 break;
1284                         }
1285                 }
1286         }
1287         else if(icu->blocktype==ID_SEQ) {
1288         
1289                 icu->ymax= 1.0;
1290                 
1291         }
1292         else if(icu->blocktype==ID_CU) {
1293         
1294                 icu->ymax= 1.0;
1295                 
1296         }
1297         else if(icu->blocktype==ID_WO) {
1298                 
1299                 if(icu->adrcode < MA_MAP1) {
1300                         switch(icu->adrcode) {
1301                         case WO_EXPOS:
1302                                 icu->ymax= 5.0; break;
1303                         case WO_MISTDI:
1304                         case WO_MISTSTA:
1305                         case WO_MISTHI:
1306                         case WO_STARDIST:
1307                         case WO_STARSIZE:
1308                                 break;
1309                                 
1310                         default:
1311                                 icu->ymax= 1.0;
1312                                 break;
1313                         }
1314                 }
1315                 else {
1316                         switch(icu->adrcode & (MA_MAP1-1)) {
1317                         case MAP_OFS_X:
1318                         case MAP_OFS_Y:
1319                         case MAP_OFS_Z:
1320                         case MAP_SIZE_X:
1321                         case MAP_SIZE_Y:
1322                         case MAP_SIZE_Z:
1323                                 icu->ymax= 100.0;
1324                                 icu->ymin= -100.0;
1325                         
1326                                 break;
1327                         case MAP_R:
1328                         case MAP_G:
1329                         case MAP_B:
1330                         case MAP_DVAR:
1331                         case MAP_COLF:
1332                         case MAP_NORF:
1333                         case MAP_VARF:
1334                                 icu->ymax= 1.0;
1335                         }
1336                 }
1337         }
1338         else if(icu->blocktype==ID_LA) {
1339                 if(icu->adrcode < MA_MAP1) {
1340                         switch(icu->adrcode) {
1341                         case LA_ENERGY:
1342                         case LA_DIST:
1343                                 break;          
1344         
1345                         case LA_COL_R:
1346                         case LA_COL_G:
1347                         case LA_COL_B:
1348                         case LA_SPOTBL:
1349                         case LA_QUAD1:
1350                         case LA_QUAD2:
1351                                 icu->ymax= 1.0; break;
1352                         case LA_SPOTSI:
1353                                 icu->ymax= 180.0; break;
1354                         case LA_HALOINT:
1355                                 icu->ymax= 5.0; break;
1356                         }
1357                 }
1358                 else {
1359                         switch(icu->adrcode & (MA_MAP1-1)) {
1360                         case MAP_OFS_X:
1361                         case MAP_OFS_Y:
1362                         case MAP_OFS_Z:
1363                         case MAP_SIZE_X:
1364                         case MAP_SIZE_Y:
1365                         case MAP_SIZE_Z:
1366                                 icu->ymax= 100.0;
1367                                 icu->ymin= -100.0;
1368                                 break;
1369                         case MAP_R:
1370                         case MAP_G:
1371                         case MAP_B:
1372                         case MAP_DVAR:
1373                         case MAP_COLF:
1374                         case MAP_NORF:
1375                         case MAP_VARF:
1376                                 icu->ymax= 1.0;
1377                         }
1378                 }
1379         }       
1380         else if(icu->blocktype==ID_CA) {
1381
1382                 switch(icu->adrcode) {
1383                 case CAM_LENS:
1384                         icu->ymin= 5.0;
1385                         icu->ymax= 1000.0; break;
1386                 case CAM_STA:
1387                         icu->ymin= 0.001f;
1388                         break;
1389                 case CAM_END:
1390                         icu->ymin= 0.1f;
1391                 }
1392         }
1393         else if(icu->blocktype==ID_SO) {
1394
1395                 switch(icu->adrcode) {
1396                 case SND_VOLUME:
1397                         icu->ymin= 0.0;
1398                         icu->ymax= 1.0;
1399                         break;
1400                 case SND_PITCH:
1401                         icu->ymin= -12.0;
1402                         icu->ymin= 12.0;
1403                         break;
1404                 case SND_PANNING:
1405                         icu->ymin= 0.0;
1406                         icu->ymax= 1.0;
1407                         break;
1408                 case SND_ATTEN:
1409                         icu->ymin= 0.0;
1410                         icu->ymin= 1.0;
1411                         break;
1412                 }
1413         }
1414 }
1415
1416
1417 void execute_ipo(ID *id, Ipo *ipo)
1418 {
1419         IpoCurve *icu;
1420         void *poin;
1421         int type;
1422         
1423         if(ipo==0) return;
1424         
1425         icu= ipo->curve.first;
1426         while(icu) {
1427                 poin= get_ipo_poin(id, icu, &type);
1428                 if(poin) write_ipo_poin(poin, type, icu->curval);
1429                 icu= icu->next;
1430         }
1431 }
1432
1433 /* exception: it does calc for objects...
1434  * now find out why this routine was used anyway!
1435  */
1436 void do_ipo_nocalc(Ipo *ipo)
1437 {
1438         Object *ob;
1439         Material *ma;
1440         World *wo;
1441         Lamp *la;
1442         Camera *ca;
1443         bSound *snd;
1444         
1445         if(ipo==0) return;
1446         
1447         switch(ipo->blocktype) {
1448         case ID_OB:
1449                 ob= G.main->object.first;
1450                 while(ob) {
1451                         if(ob->ipo==ipo) {
1452                                 do_ob_ipo(ob);
1453                                 /* execute_ipo((ID *)ob, ipo); */
1454                         }
1455                         ob= ob->id.next;
1456                 }
1457                 break;
1458         case ID_MA:
1459                 ma= G.main->mat.first;
1460                 while(ma) {
1461                         if(ma->ipo==ipo) execute_ipo((ID *)ma, ipo);
1462                         ma= ma->id.next;
1463                 }
1464                 break;
1465         case ID_WO:
1466                 wo= G.main->world.first;
1467                 while(wo) {
1468                         if(wo->ipo==ipo) execute_ipo((ID *)wo, ipo);
1469                         wo= wo->id.next;
1470                 }
1471                 break;
1472         case ID_LA:
1473                 la= G.main->lamp.first;
1474                 while(la) {
1475                         if(la->ipo==ipo) execute_ipo((ID *)la, ipo);
1476                         la= la->id.next;
1477                 }
1478                 break;
1479         case ID_CA:
1480                 ca= G.main->camera.first;
1481                 while(ca) {
1482                         if(ca->ipo==ipo) execute_ipo((ID *)ca, ipo);
1483                         ca= ca->id.next;
1484                 }
1485                 break;
1486         case ID_SO:
1487                 snd= G.main->sound.first;
1488                 while(snd) {
1489                         if(snd->ipo==ipo) execute_ipo((ID *)snd, ipo);
1490                         snd= snd->id.next;
1491                 }
1492                 break;
1493         }
1494 }
1495
1496 void do_ipo(Ipo *ipo)
1497 {
1498         if(ipo) {
1499                 float ctime= frame_to_float(G.scene->r.cfra);
1500                 calc_ipo(ipo, ctime);
1501         
1502                 do_ipo_nocalc(ipo);
1503         }
1504 }
1505
1506
1507
1508 void do_mat_ipo(Material *ma)
1509 {
1510         float ctime;
1511         
1512         if(ma==0 || ma->ipo==0) return;
1513         
1514         ctime= frame_to_float(G.scene->r.cfra);
1515         /* if(ob->ipoflag & OB_OFFS_OB) ctime-= ob->sf; */
1516
1517         calc_ipo(ma->ipo, ctime);
1518         
1519         execute_ipo((ID *)ma, ma->ipo);
1520 }
1521
1522 void do_ob_ipo(Object *ob)
1523 {
1524         float ctime;
1525         unsigned int lay;
1526         
1527         if(ob->ipo==0) return;
1528
1529         /* hier NIET ob->ctime zetten: bijv bij parent in onzichtb. layer */
1530         
1531         ctime= bsystem_time(ob, 0, (float) G.scene->r.cfra, 0.0);
1532
1533         calc_ipo(ob->ipo, ctime);
1534
1535         /* Patch: de localview onthouden */
1536         lay= ob->lay & 0xFF000000;
1537         
1538         execute_ipo((ID *)ob, ob->ipo);
1539
1540         ob->lay |= lay;
1541         if(ob->id.name[2]=='S' && ob->id.name[3]=='C' && ob->id.name[4]=='E') {
1542                 if(strcmp(G.scene->id.name+2, ob->id.name+6)==0) {
1543                         G.scene->lay= ob->lay;
1544                         copy_view3d_lock(0);
1545                         /* hier geen REDRAW: gaat rondzingen! */
1546                 }
1547         }
1548 }
1549
1550 void do_seq_ipo(Sequence *seq)
1551 {
1552         float ctime, div;
1553         
1554         /* seq_ipo gaat iets anders: beide fields direkt berekenen */
1555         
1556         if(seq->ipo) {
1557                 ctime= frame_to_float(G.scene->r.cfra - seq->startdisp);
1558                 div= (seq->enddisp - seq->startdisp)/100.0f;
1559                 if(div==0) return;
1560                 
1561                 /* tweede field */
1562                 calc_ipo(seq->ipo, (ctime+0.5f)/div);
1563                 execute_ipo((ID *)seq, seq->ipo);
1564                 seq->facf1= seq->facf0;
1565
1566                 /* eerste field */
1567                 calc_ipo(seq->ipo, ctime/div);
1568                 execute_ipo((ID *)seq, seq->ipo);
1569
1570         }
1571         else seq->facf1= seq->facf0= 1.0f;
1572 }
1573
1574 int has_ipo_code(Ipo *ipo, int code)
1575 {
1576         IpoCurve *icu;
1577         
1578         if(ipo==0) return 0;
1579         
1580         icu= ipo->curve.first;
1581         while(icu) {
1582         
1583                 if(icu->adrcode==code) return 1;
1584                 
1585                 icu= icu->next;
1586         }
1587         return 0;
1588 }
1589
1590 void do_all_ipos()
1591 {
1592         Base *base;
1593         Material *ma;
1594         World *wo;
1595         Ipo *ipo;
1596         Lamp *la;
1597         Camera *ca;
1598         bSound *snd;
1599         float ctime;
1600         int set;
1601
1602         ctime= frame_to_float(G.scene->r.cfra);
1603         
1604         ipo= G.main->ipo.first;
1605         while(ipo) {
1606                 if(ipo->id.us && ipo->blocktype!=ID_OB) {
1607                         calc_ipo(ipo, ctime);
1608                 }
1609                 ipo= ipo->id.next;
1610         }
1611
1612         /* NEW: current scene ob ipo's */
1613         base= G.scene->base.first;
1614         set= 0;
1615         while(base) {
1616
1617                 /* Do object ipos */
1618                 do_constraint_channels(&base->object->constraints, &base->object->constraintChannels, ctime);
1619
1620                 if(base->object->ipo) {
1621                         /* per object ipo ook de calc_ipo doen: ivm mogelijke timeoffs */
1622                         do_ob_ipo(base->object);
1623                         if(base->object->type==OB_MBALL) where_is_object(base->object);
1624                 }
1625                 base= base->next;
1626                 
1627                 if(base==0 && set==0 && G.scene->set) {
1628                         set= 1;
1629                         base= G.scene->set->base.first;
1630                 }
1631         }
1632
1633         ma= G.main->mat.first;
1634         while(ma) {
1635                 if(ma->ipo) execute_ipo((ID *)ma, ma->ipo);
1636                 ma= ma->id.next;
1637         }
1638
1639         wo= G.main->world.first;
1640         while(wo) {
1641                 if(wo->ipo) execute_ipo((ID *)wo, wo->ipo);
1642                 wo= wo->id.next;
1643         }
1644
1645         la= G.main->lamp.first;
1646         while(la) {
1647                 if(la->ipo) execute_ipo((ID *)la, la->ipo);
1648                 la= la->id.next;
1649         }
1650
1651         ca= G.main->camera.first;
1652         while(ca) {
1653                 if(ca->ipo) execute_ipo((ID *)ca, ca->ipo);
1654                 ca= ca->id.next;
1655         }
1656
1657         snd= G.main->sound.first;
1658         while(snd) {
1659                 if(snd->ipo) execute_ipo((ID *)snd, snd->ipo);
1660                 snd= snd->id.next;
1661         }
1662
1663         /* voor het geval dat...  LET OP: 2x */
1664         base= G.scene->base.first;
1665         while(base) {
1666                 
1667                 /* alleen layer updaten als ipo */
1668                 if( has_ipo_code(base->object->ipo, OB_LAY) ) {
1669                         base->lay= base->object->lay;
1670                 }
1671                 
1672                 base= base->next;
1673         }
1674         
1675         /* voor het geval dat...*/
1676         if(G.scene->set) {
1677                 base= G.scene->set->base.first;
1678                 while(base) {
1679                         
1680                         /* alleen layer updaten als ipo */
1681                         if( has_ipo_code(base->object->ipo, OB_LAY) ) {
1682                                 base->lay= base->object->lay;
1683                         }
1684                         
1685                         base= base->next;
1686                 }
1687         }
1688 }
1689
1690
1691 int calc_ipo_spec(Ipo *ipo, int adrcode, float *ctime)
1692 {
1693         IpoCurve *icu;
1694
1695         if(ipo==0) return 0;
1696
1697         icu= ipo->curve.first;
1698         while(icu) {
1699                 if(icu->adrcode == adrcode) {
1700                         if(icu->flag & IPO_LOCK);
1701                         else calc_icu(icu, *ctime);
1702                         
1703                         *ctime= icu->curval;
1704                         return 1;
1705                 }
1706                 icu= icu->next;
1707         }
1708         
1709         return 0;
1710 }
1711
1712
1713 /* ************************** */
1714
1715 void clear_delta_obipo(Ipo *ipo)
1716 {
1717         Object *ob;
1718         
1719         if(ipo==0) return;
1720         
1721         ob= G.main->object.first;
1722         while(ob) {
1723                 if(ob->id.lib==0) {
1724                         if(ob->ipo==ipo) {
1725                                 memset(&ob->dloc, 0, 12);
1726                                 memset(&ob->drot, 0, 12);
1727                                 memset(&ob->dsize, 0, 12);
1728                         }
1729                 }
1730                 ob= ob->id.next;
1731         }
1732 }
1733
1734 void add_to_cfra_elem(ListBase *lb, BezTriple *bezt)
1735 {
1736         CfraElem *ce, *cen;
1737         
1738         ce= lb->first;
1739         while(ce) {
1740                 
1741                 if( ce->cfra==bezt->vec[1][0] ) {
1742                         /* doen ivm dubbele keys */
1743                         if(bezt->f2 & 1) ce->sel= bezt->f2;
1744                         return;
1745                 }
1746                 else if(ce->cfra > bezt->vec[1][0]) break;
1747                 
1748                 ce= ce->next;
1749         }       
1750         
1751         cen= MEM_callocN(sizeof(CfraElem), "add_to_cfra_elem"); 
1752         if(ce) BLI_insertlinkbefore(lb, ce, cen);
1753         else BLI_addtail(lb, cen);
1754
1755         cen->cfra= bezt->vec[1][0];
1756         cen->sel= bezt->f2;
1757 }
1758
1759
1760
1761 void make_cfra_list(Ipo *ipo, ListBase *elems)
1762 {
1763         IpoCurve *icu;
1764         CfraElem *ce;
1765         BezTriple *bezt;
1766         int a;
1767         
1768         if(ipo->blocktype==ID_OB) {
1769                 icu= ipo->curve.first;
1770                 while(icu) {
1771                         if(icu->flag & IPO_VISIBLE) {
1772                                 switch(icu->adrcode) {
1773                                 case OB_DLOC_X:
1774                                 case OB_DLOC_Y:
1775                                 case OB_DLOC_Z:
1776                                 case OB_DROT_X:
1777                                 case OB_DROT_Y:
1778                                 case OB_DROT_Z:
1779                                 case OB_DSIZE_X:
1780                                 case OB_DSIZE_Y:
1781                                 case OB_DSIZE_Z:
1782
1783                                 case OB_LOC_X:
1784                                 case OB_LOC_Y:
1785                                 case OB_LOC_Z:
1786                                 case OB_ROT_X:
1787                                 case OB_ROT_Y:
1788                                 case OB_ROT_Z:
1789                                 case OB_SIZE_X:
1790                                 case OB_SIZE_Y:
1791                                 case OB_SIZE_Z:
1792                                         bezt= icu->bezt;
1793                                         if(bezt) {
1794                                                 a= icu->totvert;
1795                                                 while(a--) {
1796                                                         add_to_cfra_elem(elems, bezt);
1797                                                         bezt++;
1798                                                 }
1799                                         }
1800                                         break;
1801                                 }
1802                         }
1803                         icu= icu->next;
1804                 }
1805         }
1806         if(ipo->showkey==0) {
1807                 /* alle keys deselecteren */
1808                 ce= elems->first;
1809                 while(ce) {
1810                         ce->sel= 0;
1811                         ce= ce->next;
1812                 }
1813         }
1814 }
1815
1816 /* *********************** INTERFACE FOR KETSJI ********** */
1817
1818
1819 int IPO_GetChannels(Ipo *ipo, IPO_Channel *channels)
1820 {
1821         /* channels is max 32 items, allocated by calling function */   
1822
1823         IpoCurve *icu;
1824         int total=0;
1825         
1826         if(ipo==NULL) return 0;
1827         
1828         icu= ipo->curve.first;
1829         while(icu) {
1830                 
1831                 channels[total]= icu->adrcode;
1832                 total++;
1833                 if(total>31) break;
1834                 
1835                 icu= icu->next;
1836         }
1837         
1838         return total;
1839 }
1840
1841
1842
1843 /* Get the float value for channel 'channel' at time 'ctime' */
1844
1845 float IPO_GetFloatValue(Ipo *ipo, IPO_Channel channel, float ctime)
1846 {
1847         if(ipo==NULL) return 0;
1848         
1849         calc_ipo_spec(ipo, channel, &ctime);
1850         
1851         if (OB_ROT_X <= channel && channel <= OB_DROT_Z) {
1852                 ctime *= (float)(M_PI_2/9.0); 
1853         }
1854
1855         return ctime;
1856 }
1857
1858
1859 void test_ipo_get()
1860 {
1861         Object *ob;
1862         int tot;
1863         IPO_Channel chan[32];
1864
1865         ob = (G.scene->basact ? G.scene->basact->object : 0);
1866         
1867         if(ob==NULL) return;
1868         if(ob->ipo==NULL) return;
1869         
1870         tot= IPO_GetChannels(ob->ipo, chan);
1871         printf("tot %d \n", tot);
1872         
1873         while(tot--) {
1874                 printf("var1 %d \n", chan[tot]);
1875         }
1876         
1877         printf("var1 %f \n", IPO_GetFloatValue(ob->ipo, chan[0], 10.0));
1878 }