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