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