Extra selection support for the action window, including:
[blender.git] / source / blender / src / editipo.c
1 /**
2  * $Id$
3  *
4  * ***** BEGIN GPL/BL DUAL LICENSE BLOCK *****
5  *
6  * This program is free software; you can redistribute it and/or
7  * modify it under the terms of the GNU General Public License
8  * as published by the Free Software Foundation; either version 2
9  * of the License, or (at your option) any later version. The Blender
10  * Foundation also sells licenses for use in proprietary software under
11  * the Blender License.  See http://www.blender.org/BL/ for information
12  * about this.
13  *
14  * This program is distributed in the hope that it will be useful,
15  * but WITHOUT ANY WARRANTY; without even the implied warranty of
16  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
17  * GNU General Public License for more details.
18  *
19  * You should have received a copy of the GNU General Public License
20  * along with this program; if not, write to the Free Software Foundation,
21  * Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
22  *
23  * The Original Code is Copyright (C) 2001-2002 by NaN Holding BV.
24  * All rights reserved.
25  *
26  * The Original Code is: all of this file.
27  *
28  * Contributor(s): none yet.
29  *
30  * ***** END GPL/BL DUAL LICENSE BLOCK *****
31  */
32
33 #include <stdlib.h>
34 #include <string.h>
35 #include <math.h>
36
37 #ifdef HAVE_CONFIG_H
38 #include <config.h>
39 #endif
40
41 #ifndef WIN32
42 #include <unistd.h>
43 #else
44 #include <io.h>
45 #include "BLI_winstuff.h"
46 #endif   
47 #include "MEM_guardedalloc.h"
48 #include "PIL_time.h"
49
50 #include "BLI_blenlib.h"
51 #include "BLI_arithb.h"
52 #include "BLI_editVert.h"
53
54 #include "DNA_constraint_types.h"
55 #include "DNA_action_types.h"
56 #include "DNA_armature_types.h"
57 #include "DNA_object_types.h"
58 #include "DNA_lamp_types.h"
59 #include "DNA_sequence_types.h"
60 #include "DNA_sound_types.h"
61 #include "DNA_camera_types.h"
62 #include "DNA_material_types.h"
63 #include "DNA_key_types.h"
64 #include "DNA_screen_types.h"
65 #include "DNA_scene_types.h"
66 #include "DNA_ipo_types.h"
67 #include "DNA_curve_types.h"
68 #include "DNA_space_types.h"
69 #include "DNA_userdef_types.h"
70 #include "DNA_view3d_types.h"
71 #include "DNA_group_types.h"
72 #include "DNA_ika_types.h"
73
74 #include "BKE_utildefines.h"
75 #include "BKE_action.h"
76 #include "BKE_anim.h"
77 #include "BKE_material.h"
78 #include "BKE_ipo.h"
79 #include "BKE_key.h"
80 #include "BKE_ika.h"
81 #include "BKE_displist.h"
82 #include "BKE_global.h"
83 #include "BKE_group.h"
84
85 #include "BIF_buttons.h"
86 #include "BIF_editkey.h"
87 #include "BIF_editseq.h"
88 #include "BIF_editview.h"
89 #include "BIF_interface.h"
90 #include "BIF_mywindow.h"
91 #include "BIF_poseobject.h"
92 #include "BIF_screen.h"
93 #include "BIF_space.h"
94 #include "BIF_toolbox.h"
95 #include "BIF_poseobject.h"
96
97 #include "BDR_drawobject.h"
98 #include "BDR_editobject.h"
99
100 #include "BSE_trans_types.h"
101 #include "BSE_editipo_types.h"
102 #include "BSE_drawipo.h"
103 #include "BSE_editipo.h"
104 #include "BSE_editaction.h"
105 #include "BSE_edit.h"
106 #include "BSE_drawview.h"
107 #include "BSE_headerbuttons.h"
108
109 #include "blendef.h"
110 #include "mydevice.h"
111 #include "interface.h"
112 #include "render.h"
113
114 /* forwards */
115 #define BEZSELECTED(bezt)   (((bezt)->f1 & 1) || ((bezt)->f2 & 1) || ((bezt)->f3 & 1))
116
117 #define IPOTHRESH       0.9
118 #define ISPOIN(a, b, c)                       ( (a->b) && (a->c) )
119 #define ISPOIN3(a, b, c, d)           ( (a->b) && (a->c) && (a->d) )
120 #define ISPOIN4(a, b, c, d, e)        ( (a->b) && (a->c) && (a->d) && (a->e) )   
121
122 extern int ob_ar[];
123 extern int ma_ar[];
124 extern int seq_ar[];
125 extern int cu_ar[];
126 extern int key_ar[];
127 extern int wo_ar[];
128 extern int la_ar[];
129 extern int cam_ar[];
130 extern int snd_ar[];
131 extern int ac_ar[];
132 extern int co_ar[];
133
134 void getname_ac_ei(int nr, char *str)
135 {
136         switch(nr) {
137         case AC_LOC_X:
138                 strcpy(str, "LocX"); break;
139         case AC_LOC_Y:
140                 strcpy(str, "LocY"); break;
141         case AC_LOC_Z:
142                 strcpy(str, "LocZ"); break;
143         case AC_SIZE_X:
144                 strcpy(str, "SizeX"); break;
145         case AC_SIZE_Y:
146                 strcpy(str, "SizeY"); break;
147         case AC_SIZE_Z:
148                 strcpy(str, "SizeZ"); break;
149         case AC_QUAT_X:
150                 strcpy(str, "QuatX"); break;
151         case AC_QUAT_Y:
152                 strcpy(str, "QuatY"); break;
153         case AC_QUAT_Z:
154                 strcpy(str, "QuatZ"); break;
155         case AC_QUAT_W:
156                 strcpy(str, "QuatW"); break;
157         default:
158                 str[0]= 0;
159         }       
160 }
161
162 void getname_co_ei(int nr, char *str)
163 {
164         switch(nr){
165         case CO_ENFORCE:
166                 strcpy(str, "Inf"); break;
167         }
168 }
169
170 void getname_ob_ei(int nr, char *str, int colipo)
171 {
172         switch(nr) {
173         case OB_LOC_X:
174                 strcpy(str, "LocX"); break;
175         case OB_LOC_Y:
176                 strcpy(str, "LocY"); break;
177         case OB_LOC_Z:
178                 strcpy(str, "LocZ"); break;
179         case OB_DLOC_X:
180                 strcpy(str, "dLocX"); break;
181         case OB_DLOC_Y:
182                 strcpy(str, "dLocY"); break;
183         case OB_DLOC_Z:
184                 strcpy(str, "dLocZ"); break;
185
186         case OB_ROT_X:
187                 strcpy(str, "RotX"); break;
188         case OB_ROT_Y:
189                 strcpy(str, "RotY"); break;
190         case OB_ROT_Z:
191                 strcpy(str, "RotZ"); break;
192         case OB_DROT_X:
193                 strcpy(str, "dRotX"); break;
194         case OB_DROT_Y:
195                 strcpy(str, "dRotY"); break;
196         case OB_DROT_Z:
197                 strcpy(str, "dRotZ"); break;
198                 
199         case OB_SIZE_X:
200                 strcpy(str, "SizeX"); break;
201         case OB_SIZE_Y:
202                 strcpy(str, "SizeY"); break;
203         case OB_SIZE_Z:
204                 strcpy(str, "SizeZ"); break;
205         case OB_DSIZE_X:
206                 strcpy(str, "dSizeX"); break;
207         case OB_DSIZE_Y:
208                 strcpy(str, "dSizeY"); break;
209         case OB_DSIZE_Z:
210                 strcpy(str, "dSizeZ"); break;
211         
212         case OB_LAY:
213                 strcpy(str, "Layer"); break;
214
215         case OB_TIME:
216                 strcpy(str, "Time"); break;
217         case OB_EFF_X:
218                 if(colipo) strcpy(str, "ColR");
219                 else strcpy(str, "EffX");
220                 break;
221         case OB_EFF_Y:
222                 if(colipo) strcpy(str, "ColG");
223                 else strcpy(str, "EffY");
224                 break;
225         case OB_EFF_Z:
226                 if(colipo) strcpy(str, "ColB");
227                 else strcpy(str, "EffZ");
228                 break;
229         case OB_COL_A:
230                 strcpy(str, "ColA");
231                 break;
232         default:
233                 str[0]= 0;
234         }       
235 }
236
237 void getname_tex_ei(int nr, char *str)
238 {
239         switch(nr) {
240         case MAP_OFS_X:
241                 strcpy(str, "OfsX"); break;
242         case MAP_OFS_Y:
243                 strcpy(str, "OfsY"); break;
244         case MAP_OFS_Z:
245                 strcpy(str, "OfsZ"); break;
246         case MAP_SIZE_X:
247                 strcpy(str, "SizeX"); break;
248         case MAP_SIZE_Y:
249                 strcpy(str, "SizeY"); break;
250         case MAP_SIZE_Z:
251                 strcpy(str, "SizeZ"); break;
252         case MAP_R:
253                 strcpy(str, "texR"); break;
254         case MAP_G:
255                 strcpy(str, "texG"); break;
256         case MAP_B:
257                 strcpy(str, "texB"); break;
258         case MAP_DVAR:
259                 strcpy(str, "DefVar"); break;
260         case MAP_COLF:
261                 strcpy(str, "Col"); break;
262         case MAP_NORF:
263                 strcpy(str, "Nor"); break;
264         case MAP_VARF:
265                 strcpy(str, "Var"); break;
266         default:
267                 str[0]= 0;
268         }
269 }
270
271 void getname_mat_ei(int nr, char *str)
272 {
273         if(nr>=MA_MAP1) getname_tex_ei((nr & (MA_MAP1-1)), str);
274         else {
275                 switch(nr) {
276                 case MA_COL_R:
277                         strcpy(str, "R"); break;
278                 case MA_COL_G:
279                         strcpy(str, "G"); break;
280                 case MA_COL_B:
281                         strcpy(str, "B"); break;
282                 case MA_SPEC_R:
283                         strcpy(str, "SpecR"); break;
284                 case MA_SPEC_G:
285                         strcpy(str, "SpecG"); break;
286                 case MA_SPEC_B:
287                         strcpy(str, "SpecB"); break;
288                 case MA_MIR_R:
289                         strcpy(str, "MirR"); break;
290                 case MA_MIR_G:
291                         strcpy(str, "MirG"); break;
292                 case MA_MIR_B:
293                         strcpy(str, "MirB"); break;
294                 case MA_REF:
295                         strcpy(str, "Ref"); break;
296                 case MA_ALPHA:
297                         strcpy(str, "Alpha"); break;
298                 case MA_EMIT:
299                         strcpy(str, "Emit"); break;
300                 case MA_AMB:
301                         strcpy(str, "Amb"); break;
302                 case MA_SPEC:
303                         strcpy(str, "Spec"); break;
304                 case MA_HARD:
305                         strcpy(str, "Hard"); break;
306                 case MA_SPTR:
307                         strcpy(str, "SpTra"); break;
308                 case MA_ANG:
309                         strcpy(str, "Ang"); break;
310                 case MA_MODE:
311                         strcpy(str, "Mode"); break;
312                 case MA_HASIZE:
313                         strcpy(str, "HaSize"); break;
314                 default:
315                         str[0]= 0;
316                 }
317         }
318 }
319
320 void getname_world_ei(int nr, char *str)
321 {
322         if(nr>=MA_MAP1) getname_tex_ei((nr & (MA_MAP1-1)), str);
323         else {
324                 switch(nr) {
325                 case WO_HOR_R:
326                         strcpy(str, "HorR"); break;
327                 case WO_HOR_G:
328                         strcpy(str, "HorG"); break;
329                 case WO_HOR_B:
330                         strcpy(str, "HorB"); break;
331                 case WO_ZEN_R:
332                         strcpy(str, "ZenR"); break;
333                 case WO_ZEN_G:
334                         strcpy(str, "ZenG"); break;
335                 case WO_ZEN_B:
336                         strcpy(str, "ZenB"); break;
337
338                 case WO_EXPOS:
339                         strcpy(str, "Expos"); break;
340
341                 case WO_MISI:
342                         strcpy(str, "Misi"); break;
343                 case WO_MISTDI:
344                         strcpy(str, "MisDi"); break;
345                 case WO_MISTSTA:
346                         strcpy(str, "MisSta"); break;
347                 case WO_MISTHI:
348                         strcpy(str, "MisHi"); break;
349
350                 case WO_STAR_R:
351                         strcpy(str, "StarR"); break;
352                 case WO_STAR_G:
353                         strcpy(str, "StarB"); break;
354                 case WO_STAR_B:
355                         strcpy(str, "StarG"); break;
356
357                 case WO_STARDIST:
358                         strcpy(str, "StarDi"); break;
359                 case WO_STARSIZE:
360                         strcpy(str, "StarSi"); break;
361                 default:
362                         str[0]= 0;
363                 }
364         }
365 }
366
367 void getname_seq_ei(int nr, char *str)
368 {
369         switch(nr) {
370         case SEQ_FAC1:
371                 strcpy(str, "Fac"); break;
372         default:
373                 str[0]= 0;
374         }
375 }
376
377 void getname_cu_ei(int nr, char *str)
378 {
379
380         switch(nr) {
381         case CU_SPEED:
382                 strcpy(str, "Speed"); break;
383         default:
384                 str[0]= 0;
385         }
386 }
387
388 void getname_key_ei(int nr, char *str)
389 {
390         if(nr==KEY_SPEED) strcpy(str, "Speed");
391         else sprintf(str, "Key %d", nr);
392 }
393
394 void getname_la_ei(int nr, char *str)
395 {
396         if(nr>=MA_MAP1) getname_tex_ei((nr & (MA_MAP1-1)), str);
397         else {
398                 switch(nr) {
399                 case LA_ENERGY:
400                         strcpy(str, "Energ"); break;
401                 case LA_COL_R:
402                         strcpy(str, "R"); break;
403                 case LA_COL_G:
404                         strcpy(str, "G"); break;
405                 case LA_COL_B:
406                         strcpy(str, "B"); break;
407                 case LA_DIST:
408                         strcpy(str, "Dist"); break;
409                 case LA_SPOTSI:
410                         strcpy(str, "SpoSi"); break;
411                 case LA_SPOTBL:
412                         strcpy(str, "SpoBl"); break;
413                 case LA_QUAD1:
414                         strcpy(str, "Quad1"); break;
415                 case LA_QUAD2:
416                         strcpy(str, "Quad2"); break;
417                 case LA_HALOINT:
418                         strcpy(str, "HaInt"); break;
419                 default:
420                         str[0]= 0;
421                 }
422         }
423 }
424
425 void getname_cam_ei(int nr, char *str)
426 {
427         switch(nr) {
428         case CAM_LENS:
429                 strcpy(str, "Lens"); break;
430         case CAM_STA:
431                 strcpy(str, "ClSta"); break;
432         case CAM_END:
433                 strcpy(str, "ClEnd"); break;
434         default:
435                 str[0]= 0;
436         }
437 }
438
439 void getname_snd_ei(int nr, char *str)
440 {
441         switch(nr) {
442         case SND_VOLUME:
443                 strcpy(str, "Vol"); break;
444         case SND_PITCH:
445                 strcpy(str, "Pitch"); break;
446         case SND_PANNING:
447                 strcpy(str, "Pan"); break;
448         case SND_ATTEN:
449                 strcpy(str, "Atten"); break;
450         default:
451                 str[0]= 0;
452         }
453 }
454
455
456 IpoCurve *find_ipocurve(Ipo *ipo, int adrcode)
457 {
458         if(ipo) {
459                 IpoCurve *icu= ipo->curve.first;
460                 while(icu) {
461                         if(icu->adrcode==adrcode) return icu;
462                         icu= icu->next;
463                 }
464         }
465         return NULL;
466 }
467
468 void boundbox_ipocurve(IpoCurve *icu)
469 {
470         BezTriple *bezt;
471         float vec[3]={0.0,0.0,0.0};
472         float min[3], max[3];
473         int a;
474         
475         if(icu->totvert) {
476                 INIT_MINMAX(min, max);
477                 
478                 if(icu->bezt ) {
479                         a= icu->totvert;
480                         bezt= icu->bezt;
481                         while(a--) {
482                                 if(icu->vartype & IPO_BITS) {
483                                         vec[0]= bezt->vec[1][0];
484                                         vec[1]= 0.0;
485                                         DO_MINMAX(vec, min, max);
486                                         
487                                         vec[1]= 16.0;
488                                         DO_MINMAX(vec, min, max);
489                                 }
490                                 else {
491                                         if(icu->ipo==IPO_BEZ && a!=icu->totvert-1) {
492                                                 DO_MINMAX(bezt->vec[0], min, max);
493                                         }
494                                         DO_MINMAX(bezt->vec[1], min, max);
495                                         if(icu->ipo==IPO_BEZ && a!=0) {
496                                                 DO_MINMAX(bezt->vec[2], min, max);
497                                         }
498                                 }
499                                 
500                                 bezt++;
501                         }
502                 }
503                 if(min[0]==max[0]) max[0]= (float)(min[0]+1.0);
504                 if(min[1]==max[1]) max[1]= (float)(min[1]+0.1);
505                 
506                 icu->totrct.xmin= min[0];
507                 icu->totrct.ymin= min[1];
508                 icu->totrct.xmax= max[0];
509                 icu->totrct.ymax= max[1];
510         }
511         else {
512                 icu->totrct.xmin= icu->totrct.ymin= 0.0;
513                 icu->totrct.xmax= EFRA;
514                 icu->totrct.ymax= 1.0;
515         }
516 }
517
518 void boundbox_ipo(Ipo *ipo, rctf *bb)
519 {
520         IpoCurve *icu;
521         int first= 1;
522         
523         icu= ipo->curve.first;
524         while(icu) {
525                         
526                 boundbox_ipocurve(icu);
527                                 
528                 if(first) {
529                         *bb= icu->totrct;
530                         first= 0;
531                 }
532                 else BLI_union_rctf(bb, &(icu->totrct));
533                 
534                 icu= icu->next;
535         }
536 }
537
538
539
540 void editipo_changed(SpaceIpo *si, int doredraw)
541 {
542         EditIpo *ei;
543         View2D *v2d;
544         Key *key;
545         KeyBlock *kb;
546         int a, first=1;
547
548
549         ei= si->editipo;
550         if(ei==0)
551                 return;
552
553         for(a=0; a<si->totipo; a++, ei++) {
554                 
555                 if(ei->icu) {
556                         
557                                 /* 2 keer i.v.m. ittereren nieuwe autohandle */
558                         calchandles_ipocurve(ei->icu);
559                         calchandles_ipocurve(ei->icu);
560                         
561                         if(ei->flag & IPO_VISIBLE) {
562                 
563                                 boundbox_ipocurve(ei->icu);
564                                 sort_time_ipocurve(ei->icu);
565                                 if(first) {
566                                         si->v2d.tot= ei->icu->totrct;
567                                         first= 0;
568                                 }
569                                 else BLI_union_rctf(&(si->v2d.tot), &(ei->icu->totrct));
570                         }
571                 }
572         }
573
574         v2d= &(si->v2d);        
575 //      v2d = &G.v2d;
576
577         /* keylijnen? */
578         if(si->blocktype==ID_KE) {
579                 key= (Key *)si->from;
580                 if(key && key->block.first) {
581                         kb= key->block.first;
582                         if(kb->pos < v2d->tot.ymin) v2d->tot.ymin= kb->pos;
583                         kb= key->block.last;
584                         if(kb->pos > v2d->tot.ymax) v2d->tot.ymax= kb->pos;
585                 }
586         }
587         
588         
589         /* is er geen curve? */
590         if(first) {
591                 v2d->tot.xmin= 0.0;
592                 v2d->tot.xmax= EFRA;
593                 v2d->tot.ymin= (float)-0.1;
594                 v2d->tot.ymax= (float)1.1;
595         
596                 if(si->blocktype==ID_SEQ) {
597                         v2d->tot.xmin= -5.0;
598                         v2d->tot.xmax= 105.0;
599                         v2d->tot.ymin= (float)-0.1;
600                         v2d->tot.ymax= (float)1.1;
601                 }
602         }
603         
604         si->tot= v2d->tot;      
605         
606         if(doredraw) {
607                 /* als do_ipo altijd wordt aangeroepen: problemen met insertkey, bijvoorbeeld
608                  * als alleen een 'loc' wordt ge-insert wordt de 'ob->rot' veranderd.
609                  */
610
611
612                 if(si->blocktype==ID_OB) {                      
613                                 /* clear delta loc,rot,size (bij ipo vrijgeven/deleten) */
614                         clear_delta_obipo(si->ipo);
615                         
616                 }
617         
618                 do_ipo(si->ipo);
619
620                 allqueue(REDRAWIPO, 0);
621                 allqueue (REDRAWACTION, 0);
622                 allqueue(REDRAWNLA, 0);
623                 allqueue(REDRAWBUTSANIM, 0);
624                 
625                 if(si->blocktype==ID_OB) {
626                         Object *ob= (Object *)si->from;                 
627                         if(ob && ob->type==OB_IKA) itterate_ika(ob);
628                         allqueue(REDRAWVIEW3D, 0);
629                         allqueue(REDRAWNLA, 0);
630                 }
631
632                 else if(si->blocktype==ID_MA) allqueue(REDRAWBUTSMAT, 0);
633                 else if(si->blocktype==ID_WO) allqueue(REDRAWBUTSWORLD, 0);
634                 else if(si->blocktype==ID_LA) allqueue(REDRAWBUTSLAMP, 0);
635                 else if(si->blocktype==ID_SO) allqueue(REDRAWBUTSSOUND, 0);
636                 else if(si->blocktype==ID_CA) {
637                         allqueue(REDRAWBUTSEDIT, 0);
638                         allqueue(REDRAWVIEW3D, 0);
639                 }
640                 else if(si->blocktype==ID_SEQ) clear_last_seq();
641                 else if(si->blocktype==ID_AC){
642                         do_all_actions();
643                         allqueue(REDRAWACTION, 0);
644                         allqueue(REDRAWNLA, 0);
645                 }
646                 else if(si->blocktype==ID_KE) {
647                         do_spec_key((Key *)si->from);
648                         allqueue(REDRAWVIEW3D, 0);
649                 }
650                 else if(si->blocktype==ID_CU) {
651                         calc_curvepath(OBACT);
652                         allqueue(REDRAWVIEW3D, 0);
653                 }
654         }
655
656         if(si->showkey) make_ipokey();
657 }
658
659 void scale_editipo()
660 {
661         /* komt uit buttons, scale met G.sipo->tot rect */
662         
663         EditIpo *ei;
664         BezTriple *bezt;
665         float facx, facy;
666         int a, b;       
667         
668         facx= (G.sipo->tot.xmax-G.sipo->tot.xmin)/(G.sipo->v2d.tot.xmax-G.sipo->v2d.tot.xmin);
669         facy= (G.sipo->tot.ymax-G.sipo->tot.ymin)/(G.sipo->v2d.tot.ymax-G.sipo->v2d.tot.ymin);
670         
671         ei= G.sipo->editipo;
672         if(ei==0) return;
673         for(a=0; a<G.sipo->totipo; a++, ei++) {
674                 if ISPOIN(ei, flag & IPO_VISIBLE, icu) {
675                         bezt= ei->icu->bezt;
676                         b= ei->icu->totvert;
677                         while(b--) {
678                                 
679                                 bezt->vec[0][0]= facx*(bezt->vec[0][0] - G.sipo->v2d.tot.xmin) + G.sipo->tot.xmin;
680                                 bezt->vec[1][0]= facx*(bezt->vec[1][0] - G.sipo->v2d.tot.xmin) + G.sipo->tot.xmin;
681                                 bezt->vec[2][0]= facx*(bezt->vec[2][0] - G.sipo->v2d.tot.xmin) + G.sipo->tot.xmin;
682                         
683                                 bezt->vec[0][1]= facy*(bezt->vec[0][1] - G.sipo->v2d.tot.ymin) + G.sipo->tot.ymin;
684                                 bezt->vec[1][1]= facy*(bezt->vec[1][1] - G.sipo->v2d.tot.ymin) + G.sipo->tot.ymin;
685                                 bezt->vec[2][1]= facy*(bezt->vec[2][1] - G.sipo->v2d.tot.ymin) + G.sipo->tot.ymin;
686
687                                 bezt++;
688                         }
689                 }
690         }
691         editipo_changed(G.sipo, 1);
692         allqueue(REDRAWNLA, 0);
693         allqueue (REDRAWACTION, 0);
694         allqueue(REDRAWIPO, 0);
695 }
696
697
698 Ipo *get_ipo_to_edit(ID **from)
699 {
700         Object *ob= OBACT;
701         
702         *from= 0;
703         
704         
705         if (G.sipo->pin) {
706                 *from = G.sipo->from;
707                 return G.sipo->ipo;
708         }
709
710         if(G.sipo->blocktype==ID_SEQ) {
711                 extern Sequence *last_seq;
712                 
713                 *from= (ID *)last_seq;
714                 if(last_seq) return last_seq->ipo;
715         }
716         else if(G.sipo->blocktype==IPO_CO){
717                 if (ob && ob->activecon){
718                         *from= (ID*) ob;
719                         return ob->activecon->ipo;
720                 }
721         }
722         else if(G.sipo->blocktype==ID_AC) {
723                 bActionChannel *chan;
724                 if (ob && ob->action){
725                         *from= (ID *) ob->action;
726                         chan= get_hilighted_action_channel(ob->action);
727                         if (chan)
728                                 return chan->ipo;
729                         else{
730                                 *from = NULL;
731                                 return NULL;
732                         }
733                 }
734
735         }
736         else if(G.sipo->blocktype==ID_WO) {
737                 World *wo= G.scene->world;
738                 *from= (ID *)wo;
739                 if(wo) return wo->ipo;
740         }
741         else if(G.sipo->blocktype==ID_OB) {
742                 if(ob) {
743                         *from= (ID *)ob;
744                         return ob->ipo;
745                 }
746         }
747         else if(G.sipo->blocktype==ID_MA) {
748                 if(ob) {
749                         Material *ma= give_current_material(ob, ob->actcol);
750                         *from= (ID *)ma;
751                         if(ma) return ma->ipo;
752                 }
753         }
754         else if(G.sipo->blocktype==ID_KE) {
755                 if(ob) {
756                         Key *key= give_current_key(ob);
757                         *from= (ID *)key;
758                         if(key) return key->ipo;
759                 }
760         }
761         else if(G.sipo->blocktype==ID_CU) {
762                 if(ob && ob->type==OB_CURVE) {
763                         Curve *cu= ob->data;
764                         *from= (ID *)cu;
765                         return cu->ipo;
766                 }
767         }
768         else if(G.sipo->blocktype==ID_LA) {
769                 if(ob && ob->type==OB_LAMP) {
770                         Lamp *la= ob->data;
771                         *from= (ID *)la;
772                         return la->ipo;
773                 }
774         }
775         else if(G.sipo->blocktype==ID_CA) {
776                 if(ob && ob->type==OB_CAMERA) {
777                         Camera *ca= ob->data;
778                         *from= (ID *)ca;
779                         if(ca) return ca->ipo;
780                 }
781         }
782         else if(G.sipo->blocktype==ID_SO) {
783
784                 if (G.buts && G.buts->mainb == BUTS_SOUND) {
785
786                         bSound *sound = G.buts->lockpoin;
787
788                         *from= (ID *)sound;
789
790                         if(sound) return sound->ipo;
791
792                 }
793         }
794
795         return NULL;
796 }
797
798 unsigned int ipo_rainbow(int cur, int tot)
799 {
800         float dfac, fac, sat;
801
802         dfac= (float)(1.0/( (float)tot+1.0));
803
804         /* deze berekening zorgt voor twee verschillende cycles regenboogkleuren */
805         if(cur< tot/2) fac= (float)(cur*2.0*dfac);
806         else fac= (float)((cur-tot/2)*2.0*dfac +dfac);
807         
808         if(fac>0.5 && fac<0.8) sat= (float)0.4;
809         else sat= 0.5;
810         
811         return hsv_to_cpack(fac, sat, 1.0);
812 }               
813
814 void make_ob_editipo(Object *ob, SpaceIpo *si)
815 {
816         EditIpo *ei;
817         int a, len, colipo=0;
818         
819         if(ob->type==OB_MESH) colipo= 1;
820
821         ei= si->editipo= MEM_callocN(OB_TOTIPO*sizeof(EditIpo), "editipo");
822         
823         si->totipo= OB_TOTIPO;
824         
825         for(a=0; a<OB_TOTIPO; a++) {
826                 getname_ob_ei(ob_ar[a], ei->name, colipo);
827                 ei->adrcode= ob_ar[a];
828                 
829                 if ELEM6(ei->adrcode, OB_ROT_X, OB_ROT_Y, OB_ROT_Z, OB_DROT_X, OB_DROT_Y, OB_DROT_Z) ei->disptype= IPO_DISPDEGR;
830                 else if(ei->adrcode==OB_LAY) ei->disptype= IPO_DISPBITS;
831                 else if(ei->adrcode==OB_TIME) ei->disptype= IPO_DISPTIME;
832
833                 ei->col= ipo_rainbow(a, OB_TOTIPO);
834
835                 if(colipo) {
836                         len= strlen(ei->name);
837                         if(len) {
838                                 if( ei->name[ len-1 ]=='R') ei->col= 0x5050FF;
839                                 else if( ei->name[ len-1 ]=='G') ei->col= 0x50FF50;
840                                 else if( ei->name[ len-1 ]=='B') ei->col= 0xFF7050;
841                         }
842                 }
843                 
844                 ei->icu= find_ipocurve(si->ipo, ei->adrcode);
845                 if(ei->icu) {
846                         ei->flag= ei->icu->flag;
847                 }
848                 
849                 ei++;
850         }
851 }
852
853
854 void make_seq_editipo(SpaceIpo *si)
855 {
856         EditIpo *ei;
857         int a;
858         
859         ei= si->editipo= MEM_callocN(SEQ_TOTIPO*sizeof(EditIpo), "editipo");
860         
861         si->totipo= SEQ_TOTIPO;
862         
863         
864         for(a=0; a<SEQ_TOTIPO; a++) {
865                 getname_seq_ei(seq_ar[a], ei->name);
866                 ei->adrcode= seq_ar[a];
867                 
868                 ei->col= ipo_rainbow(a, SEQ_TOTIPO);
869                 
870                 ei->icu= find_ipocurve(si->ipo, ei->adrcode);
871                 if(ei->icu) {
872                         ei->flag= ei->icu->flag;
873                 }
874                 else ei->flag |= IPO_VISIBLE;
875                 
876                 ei++;
877         }
878 }
879
880 void make_cu_editipo(SpaceIpo *si)
881 {
882         EditIpo *ei;
883         int a;
884         
885         ei= si->editipo= MEM_callocN(CU_TOTIPO*sizeof(EditIpo), "editipo");
886         
887         si->totipo= CU_TOTIPO;
888         
889         
890         for(a=0; a<CU_TOTIPO; a++) {
891                 getname_cu_ei(cu_ar[a], ei->name);
892                 ei->adrcode= cu_ar[a];
893                 
894                 ei->col= ipo_rainbow(a, CU_TOTIPO);
895                 
896                 ei->icu= find_ipocurve(si->ipo, ei->adrcode);
897                 if(ei->icu) {
898                         ei->flag= ei->icu->flag;
899                 }
900                 else ei->flag |= IPO_VISIBLE;
901                  
902                 ei++;
903         }
904 }
905
906 void make_key_editipo(SpaceIpo *si)
907 {
908         Key *key;
909         EditIpo *ei;
910         int a;
911         
912         ei= si->editipo= MEM_callocN(KEY_TOTIPO*sizeof(EditIpo), "editipo");
913         
914         si->totipo= KEY_TOTIPO;
915         
916         for(a=0; a<KEY_TOTIPO; a++) {
917                 getname_key_ei(key_ar[a], ei->name);
918                 ei->adrcode= key_ar[a];
919                 
920                 ei->col= ipo_rainbow(a, KEY_TOTIPO);
921                 
922                 ei->icu= find_ipocurve(si->ipo, ei->adrcode);
923                 if(ei->icu) {
924                         ei->flag= ei->icu->flag;
925                 }
926                 else if(a==0) ei->flag |= IPO_VISIBLE;
927                  
928                 ei++;
929         }
930         
931         ei= si->editipo;
932         key= (Key *)G.sipo->from;
933         if(key && key->type==KEY_RELATIVE) {
934                 strcpy(ei->name, "----");
935         }
936         else {
937                 ei->flag |= IPO_VISIBLE;
938         }
939 }
940
941 int texchannel_to_adrcode(int channel)
942 {
943         switch(channel) {
944                 case 0: return MA_MAP1;
945                 case 1: return MA_MAP2; 
946                 case 2: return MA_MAP3; 
947                 case 3: return MA_MAP4; 
948                 case 4: return MA_MAP5; 
949                 case 5: return MA_MAP6; 
950                 case 6: return MA_MAP7; 
951                 case 7: return MA_MAP8; 
952                 default: return 0;
953         }
954 }
955
956 void make_mat_editipo(SpaceIpo *si)
957 {
958         EditIpo *ei;
959         int a, len;
960         
961         if(si->from==0) return;
962         
963         ei= si->editipo= MEM_callocN(MA_TOTIPO*sizeof(EditIpo), "editipo");
964         
965         si->totipo= MA_TOTIPO;
966         
967         for(a=0; a<MA_TOTIPO; a++) {
968                 getname_mat_ei(ma_ar[a], ei->name);
969                 ei->adrcode= ma_ar[a];
970                 
971                 if(ei->adrcode & MA_MAP1) {
972                         ei->adrcode-= MA_MAP1;
973                         ei->adrcode |= texchannel_to_adrcode(si->channel);
974                 }
975                 else {
976                         /* dit was weggecommentaard. Waarom? */
977                         if(ei->adrcode==MA_MODE) ei->disptype= IPO_DISPBITS;
978                 }
979                 
980                 ei->col= ipo_rainbow(a, WO_TOTIPO);
981                 
982                 len= strlen(ei->name);
983                 if(len) {
984                         if( ei->name[ len-1 ]=='R') ei->col= 0x5050FF;
985                         else if( ei->name[ len-1 ]=='G') ei->col= 0x50FF50;
986                         else if( ei->name[ len-1 ]=='B') ei->col= 0xFF7050;
987                 }
988                 
989                 ei->icu= find_ipocurve(si->ipo, ei->adrcode);
990                 if(ei->icu) {
991                         ei->flag= ei->icu->flag;
992                 }
993                 
994                 ei++;
995         }
996 }
997
998 void make_world_editipo(SpaceIpo *si)
999 {
1000         EditIpo *ei;
1001         int a, len;
1002         
1003         if(si->from==0) return;
1004         
1005         ei= si->editipo= MEM_callocN(WO_TOTIPO*sizeof(EditIpo), "editipo");
1006         
1007         si->totipo= WO_TOTIPO;
1008         
1009         for(a=0; a<WO_TOTIPO; a++) {
1010                 getname_world_ei(wo_ar[a], ei->name);
1011                 ei->adrcode= wo_ar[a];
1012                 
1013                 if(ei->adrcode & MA_MAP1) {
1014                         ei->adrcode-= MA_MAP1;
1015                         ei->adrcode |= texchannel_to_adrcode(si->channel);
1016                 }
1017                 else {
1018                         if(ei->adrcode==MA_MODE) ei->disptype= IPO_DISPBITS;
1019                 }
1020                 
1021                 ei->col= ipo_rainbow(a, MA_TOTIPO);
1022                 
1023                 len= strlen(ei->name);
1024                 if(len) {
1025                         if( ei->name[ len-1 ]=='R') ei->col= 0x5050FF;
1026                         else if( ei->name[ len-1 ]=='G') ei->col= 0x50FF50;
1027                         else if( ei->name[ len-1 ]=='B') ei->col= 0xFF7050;
1028                 }
1029                 
1030                 ei->icu= find_ipocurve(si->ipo, ei->adrcode);
1031                 if(ei->icu) {
1032                         ei->flag= ei->icu->flag;
1033                 }
1034                 
1035                 ei++;
1036         }
1037 }
1038
1039 void make_lamp_editipo(SpaceIpo *si)
1040 {
1041         EditIpo *ei;
1042         int a;
1043         
1044         ei= si->editipo= MEM_callocN(LA_TOTIPO*sizeof(EditIpo), "editipo");
1045         
1046         si->totipo= LA_TOTIPO;
1047         
1048         
1049         for(a=0; a<LA_TOTIPO; a++) {
1050                 getname_la_ei(la_ar[a], ei->name);
1051                 ei->adrcode= la_ar[a];
1052
1053                 if(ei->adrcode & MA_MAP1) {
1054                         ei->adrcode-= MA_MAP1;
1055                         ei->adrcode |= texchannel_to_adrcode(si->channel);
1056                 }
1057
1058                 ei->col= ipo_rainbow(a, LA_TOTIPO);
1059                 
1060                 ei->icu= find_ipocurve(si->ipo, ei->adrcode);
1061                 if(ei->icu) {
1062                         ei->flag= ei->icu->flag;
1063                 }
1064                 
1065                 ei++;
1066         }
1067 }
1068
1069 void make_camera_editipo(SpaceIpo *si)
1070 {
1071         EditIpo *ei;
1072         int a;
1073         
1074         ei= si->editipo= MEM_callocN(CAM_TOTIPO*sizeof(EditIpo), "editipo");
1075         
1076         si->totipo= CAM_TOTIPO;
1077         
1078         
1079         for(a=0; a<CAM_TOTIPO; a++) {
1080                 getname_cam_ei(cam_ar[a], ei->name);
1081                 ei->adrcode= cam_ar[a];
1082
1083                 ei->col= ipo_rainbow(a, CAM_TOTIPO);
1084                 
1085                 ei->icu= find_ipocurve(si->ipo, ei->adrcode);
1086                 if(ei->icu) {
1087                         ei->flag= ei->icu->flag;
1088                 }
1089                 
1090                 ei++;
1091         }
1092 }
1093
1094 int make_constraint_editipo(Ipo *ipo, EditIpo **si)
1095 {
1096         EditIpo *ei;
1097         int a;
1098         
1099         ei= *si= MEM_callocN(CO_TOTIPO*sizeof(EditIpo), "editipo");
1100         
1101         for(a=0; a<CO_TOTIPO; a++) {
1102                 getname_co_ei(co_ar[a], ei->name);
1103                 ei->adrcode= co_ar[a];
1104
1105                 ei->col= ipo_rainbow(a, CO_TOTIPO);
1106                 
1107                 ei->icu= find_ipocurve(ipo, ei->adrcode);
1108                 if(ei->icu) {
1109                         ei->flag= ei->icu->flag;
1110                 }
1111                 
1112                 ei++;
1113         }
1114
1115         return CO_TOTIPO;
1116 }
1117 int make_action_editipo(Ipo *ipo, EditIpo **si)
1118 {
1119         EditIpo *ei;
1120         int a;
1121         
1122         ei= *si= MEM_callocN(AC_TOTIPO*sizeof(EditIpo), "editipo");
1123         
1124         for(a=0; a<AC_TOTIPO; a++) {
1125                 getname_ac_ei(ac_ar[a], ei->name);
1126                 ei->adrcode= ac_ar[a];
1127
1128                 ei->col= ipo_rainbow(a, AC_TOTIPO);
1129                 
1130                 ei->icu= find_ipocurve(ipo, ei->adrcode);
1131                 if(ei->icu) {
1132                         ei->flag= ei->icu->flag;
1133                 }
1134                 
1135                 ei++;
1136         }
1137
1138         return AC_TOTIPO;
1139 }
1140
1141 void make_sound_editipo(SpaceIpo *si)
1142 {
1143         EditIpo *ei;
1144         int a;
1145         
1146         ei= si->editipo= MEM_callocN(SND_TOTIPO*sizeof(EditIpo), "editipo");
1147         
1148         si->totipo= SND_TOTIPO;
1149         
1150         
1151         for(a=0; a<SND_TOTIPO; a++) {
1152                 getname_snd_ei(snd_ar[a], ei->name);
1153                 ei->adrcode= snd_ar[a];
1154
1155                 ei->col= ipo_rainbow(a, SND_TOTIPO);
1156                 
1157                 ei->icu= find_ipocurve(si->ipo, ei->adrcode);
1158                 if(ei->icu) {
1159                         ei->flag= ei->icu->flag;
1160                 }
1161                 
1162                 ei++;
1163         }
1164 }
1165
1166 void make_editipo()
1167 {
1168         EditIpo *ei;
1169         Object *ob;
1170         ID *from;
1171         rctf *rf;
1172         int a;
1173
1174         if(G.sipo->editipo)
1175                 MEM_freeN(G.sipo->editipo);
1176         G.sipo->editipo= 0;
1177         G.sipo->totipo= 0;
1178         ob= OBACT;
1179
1180         G.sipo->ipo= get_ipo_to_edit(&from);
1181         G.sipo->from= from;
1182
1183         if(G.sipo->ipo) G.sipo->showkey= G.sipo->ipo->showkey;
1184
1185         if(G.sipo->blocktype==ID_SEQ) {
1186                 make_seq_editipo(G.sipo);
1187         }
1188         else if(G.sipo->blocktype==ID_WO) {
1189                 make_world_editipo(G.sipo);
1190         } 
1191         else if(G.sipo->blocktype==ID_OB) {
1192                 if (ob) {
1193                         ob->ipowin= ID_OB;
1194                         make_ob_editipo(ob, G.sipo);
1195                 }
1196         }
1197         else if(G.sipo->blocktype==ID_MA) {
1198                 if (ob) {
1199                         ob->ipowin= ID_MA;
1200                         make_mat_editipo(G.sipo);
1201                 }
1202         }
1203         else if(G.sipo->blocktype==ID_CU) {
1204                 if (ob) {
1205                         ob->ipowin= ID_CU;
1206                         make_cu_editipo(G.sipo);
1207                 }
1208         }
1209         else if(G.sipo->blocktype==ID_KE) {
1210                 if (ob) {
1211                         ob->ipowin= ID_KE;
1212                         make_key_editipo(G.sipo);
1213                 }
1214         }
1215         else if(G.sipo->blocktype==ID_LA) {
1216                 if (ob) {
1217                         ob->ipowin= ID_LA;
1218                         make_lamp_editipo(G.sipo);
1219                 }
1220         }
1221         else if(G.sipo->blocktype==ID_CA) {
1222                 if (ob) {
1223                         ob->ipowin= ID_CA;
1224                         make_camera_editipo(G.sipo);
1225                 }
1226         }
1227         else if(G.sipo->blocktype==ID_SO) {
1228                 if (ob) {
1229                         ob->ipowin= ID_SO;
1230                         make_sound_editipo(G.sipo);
1231                 }
1232         }
1233         else if(G.sipo->blocktype==IPO_CO){
1234                 G.sipo->totipo = make_constraint_editipo(G.sipo->ipo, (EditIpo**)&G.sipo->editipo);
1235                 if (ob) {
1236                         ob->ipowin= IPO_CO;
1237                 }
1238         }
1239         else if(G.sipo->blocktype==ID_AC) {
1240
1241                 G.sipo->totipo = make_action_editipo(G.sipo->ipo, (EditIpo**)&G.sipo->editipo);
1242                 if (ob) {
1243                         ob->ipowin= ID_AC;
1244                 }
1245         }
1246
1247         if(G.sipo->editipo==0) return;
1248         
1249         /* rowbut voor VISIBLE select */
1250         G.sipo->rowbut= 0;
1251         ei= G.sipo->editipo;
1252         for(a=0; a<G.sipo->totipo; a++, ei++) {
1253                 
1254                 if(ei->flag & IPO_VISIBLE) G.sipo->rowbut |= (1<<a);
1255                 
1256                 if(ei->icu) ei->icu->flag= ei->flag;
1257         }
1258         editipo_changed(G.sipo, 0);
1259         
1260         if(G.sipo->ipo) {
1261
1262                 if (G.sipo->pin)
1263                         rf= &(G.sipo->v2d.cur);
1264                 else
1265                         rf= &(G.sipo->ipo->cur);
1266                 
1267                 if(rf->xmin<rf->xmax && rf->ymin<rf->ymax) G.v2d->cur= *rf;
1268                 
1269         }
1270         else {
1271                 if(G.sipo->blocktype==ID_OB) {
1272                         G.v2d->cur.xmin= 0.0;
1273                         G.v2d->cur.xmax= EFRA;
1274                         G.v2d->cur.ymin= -5.0;
1275                         G.v2d->cur.ymax= +5.0;
1276                 }
1277                 else if(G.sipo->blocktype==ID_CA) {
1278                         G.v2d->cur.xmin= 0.0;
1279                         G.v2d->cur.xmax= EFRA;
1280                         G.v2d->cur.ymin= 0.0;
1281                         G.v2d->cur.ymax= 100.0;
1282                 }
1283                 else if ELEM5(G.sipo->blocktype, ID_MA, ID_CU, ID_WO, ID_LA, IPO_CO) {
1284                         G.v2d->cur.xmin= (float)-0.1;
1285                         G.v2d->cur.xmax= EFRA;
1286                         G.v2d->cur.ymin= (float)-0.1;
1287                         G.v2d->cur.ymax= (float)+1.1;
1288                 }
1289                 else if(G.sipo->blocktype==ID_SEQ) {
1290                         G.v2d->cur.xmin= -5.0;
1291                         G.v2d->cur.xmax= 105.0;
1292                         G.v2d->cur.ymin= (float)-0.1;
1293                         G.v2d->cur.ymax= (float)+1.1;
1294                 }
1295                 else if(G.sipo->blocktype==ID_KE) {
1296                         G.v2d->cur.xmin= (float)-0.1;
1297                         G.v2d->cur.xmax= EFRA;
1298                         G.v2d->cur.ymin= (float)-0.1;
1299                         G.v2d->cur.ymax= (float)+2.1;
1300                 }
1301
1302         }
1303 }
1304
1305
1306 void test_editipo()
1307 {
1308         Ipo *ipo;
1309         ID *from;
1310         
1311         if(G.sipo->editipo==0){
1312                 make_editipo();
1313         }
1314         else {
1315                 ipo= get_ipo_to_edit(&from);
1316
1317                 if(G.sipo->ipo != ipo || G.sipo->from!=from)
1318                         make_editipo();
1319                 
1320         }
1321
1322         if (G.sipo->pin)
1323                 return;
1324
1325
1326         if(G.sipo->ipo)
1327                 G.sipo->ipo->cur = G.v2d->cur;
1328
1329 }
1330
1331 /* ****************************************** */
1332
1333 int totipo_edit, totipo_sel, totipo_vis, totipo_vert, totipo_vertsel, totipo_key, totipo_keysel;
1334
1335 void get_status_editipo()
1336 {
1337         EditIpo *ei;
1338         IpoKey *ik;
1339         BezTriple *bezt;
1340         int a, b;
1341         
1342         totipo_vis= 0;
1343         totipo_sel= 0;
1344         totipo_edit= 0;
1345         totipo_vert= 0;
1346         totipo_vertsel= 0;
1347         totipo_key= 0;
1348         totipo_keysel= 0;
1349         
1350         if(G.sipo->ipo && G.sipo->ipo->id.lib) return;
1351         
1352         ei= G.sipo->editipo;
1353         if(ei==0) return;
1354         for(a=0; a<G.sipo->totipo; a++) {
1355                 if( ei->flag & IPO_VISIBLE ) {
1356                         totipo_vis++;
1357                         if(ei->flag & IPO_SELECT) totipo_sel++;
1358                         if(G.sipo->showkey || (ei->flag & IPO_EDIT)) {
1359                                 
1360                                 /* als showkey: wel de vertices tellen (voor grab) */
1361                                 if(G.sipo->showkey==0) totipo_edit++;
1362                                 
1363                                 if(ei->icu) {
1364                                         if(ei->icu->bezt) {
1365                                                 bezt= ei->icu->bezt;
1366                                                 b= ei->icu->totvert;
1367                                                 while(b--) {
1368                                                         if(ei->icu->ipo==IPO_BEZ) {
1369                                                                 if(bezt->f1 & 1) totipo_vertsel++;
1370                                                                 if(bezt->f3 & 1) totipo_vertsel++;
1371                                                                 totipo_vert+= 2;
1372                                                         }
1373                                                         if(bezt->f2 & 1) totipo_vertsel++;
1374                                                         
1375                                                         totipo_vert++;
1376                                                         bezt++;
1377                                                 }
1378                                         }
1379                                 }
1380                         }
1381                 }
1382                 ei++;
1383         }
1384         
1385         if(G.sipo->showkey) {
1386                 ik= G.sipo->ipokey.first;
1387                 while(ik) {
1388                         totipo_key++;
1389                         if(ik->flag & 1) totipo_keysel++;
1390                         ik= ik->next;
1391                 }
1392         }
1393 }
1394
1395
1396
1397 void update_editipo_flags()
1398 {
1399         EditIpo *ei;
1400         IpoKey *ik;
1401         unsigned int flag;
1402         int a;
1403         
1404         ei= G.sipo->editipo;
1405         if(ei) {
1406                 for(a=0; a<G.sipo->totipo; a++, ei++) {
1407                         ei->flag &= ~IPO_VISIBLE;
1408                         flag= (1<<a);
1409                         if( G.sipo->rowbut & flag ) ei->flag |= IPO_VISIBLE;
1410                         
1411                         if(ei->icu) ei->icu->flag= ei->flag;
1412                         
1413                 }
1414         }
1415         if(G.sipo->showkey) {
1416                 ik= G.sipo->ipokey.first;
1417                 while(ik) {
1418                         for(a=0; a<G.sipo->totipo; a++) {
1419                                 if(ik->data[a]) {
1420                                         if(ik->flag & 1) {
1421                                                 ik->data[a]->f1 |= 1;
1422                                                 ik->data[a]->f2 |= 1;
1423                                                 ik->data[a]->f3 |= 1;
1424                                         }
1425                                         else {
1426                                                 ik->data[a]->f1 &= ~1;
1427                                                 ik->data[a]->f2 &= ~1;
1428                                                 ik->data[a]->f3 &= ~1;
1429                                         }
1430                                 }
1431                         }
1432                         ik= ik->next;
1433                 }
1434         }
1435 }
1436
1437 void set_editflag_editipo()
1438 {
1439         EditIpo *ei;
1440         int a; /*  , tot= 0, ok= 0; */
1441         
1442         /* van showkey direkt door naar editen geselecteerde punten */
1443         if(G.sipo->showkey) {
1444                 G.sipo->showkey= 0;
1445                 if(G.sipo->ipo) G.sipo->ipo->showkey= 0;
1446                 ei= G.sipo->editipo;
1447                 for(a=0; a<G.sipo->totipo; a++, ei++) ei->flag |= IPO_SELECT;
1448                 scrarea_queue_headredraw(curarea);
1449                 allqueue(REDRAWVIEW3D, 0);
1450         }
1451         
1452         get_status_editipo();
1453         
1454         if(G.sipo->ipo && G.sipo->ipo->id.lib) return;
1455         
1456         ei= G.sipo->editipo;
1457         for(a=0; a<G.sipo->totipo; a++, ei++) {         
1458                 if(ei->icu) {
1459                         if(ei->flag & IPO_VISIBLE) {
1460                                 
1461                                 if(totipo_edit==0 && (ei->flag & IPO_SELECT)) {
1462                                         ei->flag |= IPO_EDIT;
1463                                         ei->icu->flag= ei->flag;
1464                                 }
1465                                 else if(totipo_edit && (ei->flag & IPO_EDIT)) {
1466                                         ei->flag -= IPO_EDIT;
1467                                         ei->icu->flag= ei->flag;
1468                                 }
1469                                 else if(totipo_vis==1) {
1470                                         if(ei->flag & IPO_EDIT) ei->flag -= IPO_EDIT;
1471                                         else ei->flag |= IPO_EDIT;
1472                                         ei->icu->flag= ei->flag;
1473                                 }
1474                         }
1475                 }
1476         }
1477         
1478         scrarea_queue_winredraw(curarea);
1479 }
1480
1481 void swap_selectall_editipo()
1482 {
1483         Object *ob;
1484         EditIpo *ei;
1485         IpoKey *ik;
1486         BezTriple *bezt;
1487         int a, b; /*  , sel=0; */
1488         
1489         
1490         deselectall_key();
1491
1492         get_status_editipo();
1493         
1494
1495
1496         if(G.sipo->showkey) {
1497                 ik= G.sipo->ipokey.first;
1498                 while(ik) {
1499                         if(totipo_vertsel) ik->flag &= ~1;
1500                         else ik->flag |= 1;
1501                         ik= ik->next;
1502                 }
1503                 update_editipo_flags();
1504
1505                 if(G.sipo->showkey && G.sipo->blocktype==ID_OB ) {
1506                         ob= OBACT;
1507                         if(ob && (ob->ipoflag & OB_DRAWKEY)) draw_object_ext(BASACT);
1508                 }
1509         }
1510         else if(totipo_edit==0) {
1511                 ei= G.sipo->editipo;
1512                 if (ei){
1513                         for(a=0; a<G.sipo->totipo; a++) {
1514                                 if( ei->flag & IPO_VISIBLE ) {
1515                                         if(totipo_sel) ei->flag &= ~IPO_SELECT;
1516                                         else ei->flag |= IPO_SELECT;
1517                                 }
1518                                 ei++;
1519                         }
1520                         update_editipo_flags();
1521                 }
1522         }
1523         else {
1524                 ei= G.sipo->editipo;
1525                 for(a=0; a<G.sipo->totipo; a++) {
1526                         if ISPOIN3(ei, flag & IPO_VISIBLE, flag & IPO_EDIT, icu ) {
1527                                 bezt= ei->icu->bezt;
1528                                 if(bezt) {
1529                                         b= ei->icu->totvert;
1530                                         while(b--) {
1531                                                 if(totipo_vertsel) {
1532                                                         bezt->f1= bezt->f2= bezt->f3= 0;
1533                                                 }
1534                                                 else {
1535                                                         bezt->f1= bezt->f2= bezt->f3= 1;
1536                                                 }
1537                                                 bezt++;
1538                                         }
1539                                 }
1540                         }
1541                         ei++;
1542                 }
1543                 
1544         }
1545         
1546         scrarea_queue_winredraw(curarea);
1547         
1548 }
1549
1550 void swap_visible_editipo()
1551 {
1552         EditIpo *ei;
1553         Object *ob;
1554         int a; /*  , sel=0; */
1555         
1556         get_status_editipo();
1557         
1558         G.sipo->rowbut= 0;
1559         
1560         ei= G.sipo->editipo;
1561         for(a=0; a<G.sipo->totipo; a++) {
1562                 if(totipo_vis==0) {
1563                         if(ei->icu) {
1564                                 ei->flag |= IPO_VISIBLE;
1565                                 G.sipo->rowbut |= (1<<a);
1566                         }
1567                 }
1568                 else ei->flag &= ~IPO_VISIBLE;
1569                 ei++;
1570         }
1571         
1572         update_editipo_flags();
1573         
1574         if(G.sipo->showkey) {
1575                 
1576                 make_ipokey();
1577                 
1578                 ob= OBACT;
1579                 if(ob && (ob->ipoflag & OB_DRAWKEY)) allqueue(REDRAWVIEW3D, 0);
1580         }
1581
1582         scrarea_queue_winredraw(curarea);
1583         
1584 }
1585
1586 void deselectall_editipo()
1587 {
1588         EditIpo *ei;
1589         IpoKey *ik;
1590         BezTriple *bezt;
1591         int a, b; /*  , sel=0; */
1592         
1593         deselectall_key();
1594
1595         get_status_editipo();
1596         
1597         if(G.sipo->showkey) {
1598                 ik= G.sipo->ipokey.first;
1599                 while(ik) {
1600                         ik->flag &= ~1;
1601                         ik= ik->next;
1602                 }
1603                 update_editipo_flags();
1604
1605         }
1606         else if(totipo_edit==0) {
1607                 
1608                 ei= G.sipo->editipo;
1609                 for(a=0; a<G.sipo->totipo; a++) {
1610                         if( ei->flag & IPO_VISIBLE ) {
1611                                 ei->flag &= ~IPO_SELECT;
1612                         }
1613                         ei++;
1614                 }
1615                 update_editipo_flags();
1616         }
1617         else {
1618                 ei= G.sipo->editipo;
1619                 for(a=0; a<G.sipo->totipo; a++) {
1620                         if ISPOIN3(ei, flag & IPO_VISIBLE, flag & IPO_EDIT, icu ) {
1621                                 if(ei->icu->bezt) {
1622                                         bezt= ei->icu->bezt;
1623                                         b= ei->icu->totvert;
1624                                         while(b--) {
1625                                                 bezt->f1= bezt->f2= bezt->f3= 0;
1626                                                 bezt++;
1627                                         }
1628                                 }
1629                         }
1630                         ei++;
1631                 }
1632         }
1633         
1634         scrarea_queue_winredraw(curarea);
1635 }
1636
1637 short findnearest_ipovert(IpoCurve **icu, BezTriple **bezt)
1638 {
1639         /* selected krijgen een nadeel */
1640         /* in icu en (bezt of bp) wordt nearest weggeschreven */
1641         /* return 0 1 2: handlepunt */
1642         EditIpo *ei;
1643         BezTriple *bezt1;
1644         int a, b;
1645         short dist= 100, temp, mval[2], hpoint=0;
1646
1647         *icu= 0;
1648         *bezt= 0;
1649
1650         getmouseco_areawin(mval);
1651
1652         ei= G.sipo->editipo;
1653         for(a=0; a<G.sipo->totipo; a++, ei++) {
1654                 if ISPOIN3(ei, flag & IPO_VISIBLE, flag & IPO_EDIT, icu) {
1655                         
1656                         if(ei->icu->bezt) {
1657                                 bezt1= ei->icu->bezt;
1658                                 b= ei->icu->totvert;
1659                                 while(b--) {
1660
1661                                         ipoco_to_areaco_noclip(G.v2d, bezt1->vec[0], bezt1->s[0]);
1662                                         ipoco_to_areaco_noclip(G.v2d, bezt1->vec[1], bezt1->s[1]);
1663                                         ipoco_to_areaco_noclip(G.v2d, bezt1->vec[2], bezt1->s[2]);
1664                                                                                 
1665                                         if(ei->disptype==IPO_DISPBITS) {
1666                                                 temp= abs(mval[0]- bezt1->s[1][0]);
1667                                         }
1668                                         else temp= abs(mval[0]- bezt1->s[1][0])+ abs(mval[1]- bezt1->s[1][1]);
1669
1670                                         if( bezt1->f2 & 1) temp+=5;
1671                                         if(temp<dist) { 
1672                                                 hpoint= 1; 
1673                                                 *bezt= bezt1; 
1674                                                 dist= temp; 
1675                                                 *icu= ei->icu; 
1676                                         }
1677                                         
1678                                         if(ei->disptype!=IPO_DISPBITS && ei->icu->ipo==IPO_BEZ) {
1679                                                 /* middelste punten een klein voordeel */
1680                                                 temp= -3+abs(mval[0]- bezt1->s[0][0])+ abs(mval[1]- bezt1->s[0][1]);
1681                                                 if( bezt1->f1 & 1) temp+=5;
1682                                                 if(temp<dist) { 
1683                                                         hpoint= 0; 
1684                                                         *bezt= bezt1; 
1685                                                         dist= temp; 
1686                                                         *icu= ei->icu; 
1687                                                 }
1688                 
1689                                                 temp= abs(mval[0]- bezt1->s[2][0])+ abs(mval[1]- bezt1->s[2][1]);
1690                                                 if( bezt1->f3 & 1) temp+=5;
1691                                                 if(temp<dist) { 
1692                                                         hpoint= 2; 
1693                                                         *bezt=bezt1; 
1694                                                         dist= temp; 
1695                                                         *icu= ei->icu; 
1696                                                 }
1697                                         }
1698                                         bezt1++;
1699                                 }
1700                         }
1701                 }
1702         }
1703
1704         return hpoint;
1705 }
1706
1707
1708 void move_to_frame()
1709 {
1710         EditIpo *ei;
1711         BezTriple *bezt;
1712         ID *id;
1713         float cfra;
1714         int a, b;
1715         
1716         if(G.sipo->editipo==0) return;
1717
1718         ei= G.sipo->editipo;
1719
1720         for(a=0; a<G.sipo->totipo; a++, ei++) {
1721                 if ISPOIN(ei, flag & IPO_VISIBLE, icu) {
1722                         if(G.sipo->showkey || (ei->flag & IPO_EDIT)) {
1723                         
1724                                 if(ei->icu->bezt) {
1725                                         
1726                                         b= ei->icu->totvert;
1727                                         bezt= ei->icu->bezt;
1728                                         while(b--) {
1729                                                 if(BEZSELECTED(bezt)) {
1730                                                 
1731                                                         cfra=  bezt->vec[1][0]/G.scene->r.framelen;
1732
1733                                                         id= G.sipo->from;
1734                                                         if(id && GS(id->name)==ID_OB ) {
1735                                                                 Object *ob= (Object *)id;
1736                                                                 if(ob->sf!=0.0 && (ob->ipoflag & OB_OFFS_OB) ) {
1737                                                                         cfra+= ob->sf/G.scene->r.framelen;
1738                                                                 }
1739                                                         }
1740                                                         CFRA= (short)floor(cfra+0.5);
1741                                                 
1742                                                         if(CFRA < 1) CFRA= 1;
1743                                                         update_for_newframe();
1744                                                         
1745                                                         break;
1746                                                 }
1747                                                 bezt++;
1748                                         }
1749                                 }
1750                         }
1751                 }
1752         }
1753 }
1754
1755 /* *********************************** */
1756
1757 void do_ipowin_buts(short event)
1758 {
1759         if((G.qual & LR_SHIFTKEY)==0) {
1760                 G.sipo->rowbut= (1<<event);
1761         }
1762         scrarea_queue_winredraw(curarea);
1763         
1764         update_editipo_flags();
1765
1766         if(G.sipo->showkey) {
1767                 make_ipokey();
1768                 if(G.sipo->blocktype==ID_OB) allqueue(REDRAWVIEW3D, 0);
1769         }
1770
1771 }
1772
1773 void do_ipo_selectbuttons()
1774 {
1775         EditIpo *ei, *ei1;
1776         int a, nr;
1777         short mval[2];
1778         
1779         if(G.sipo->showkey) return;
1780         
1781         /* geen editipo toestaan: editipo's naar selected omzetten */
1782         get_status_editipo();
1783         if(totipo_edit) {
1784                 set_editflag_editipo();
1785         }
1786         
1787         /* welke */
1788         getmouseco_areawin(mval);
1789
1790         nr= -(mval[1]-curarea->winy+30-G.sipo->butofs-IPOBUTY)/IPOBUTY;
1791         if(nr>=0 && nr<G.sipo->totipo) {
1792                 ei= G.sipo->editipo;
1793                 ei+= nr;
1794                 
1795                 if(ei->icu) {
1796                         if((ei->flag & IPO_VISIBLE)==0) {
1797                                 ei->flag |= IPO_VISIBLE;
1798                                 G.sipo->rowbut |= (1<<nr);
1799                         }
1800         
1801                         if((G.qual & LR_SHIFTKEY)==0) {
1802                                 ei1= G.sipo->editipo;
1803                                 for(a=0; a<G.sipo->totipo; a++) {
1804                                         ei1->flag &= ~IPO_SELECT;
1805                                         ei1++;
1806                                 }
1807                         }
1808
1809                         if(ei->flag & IPO_SELECT) {
1810                                 ei->flag &= ~IPO_SELECT;
1811                         }
1812                         else {
1813                                 ei->flag |= IPO_SELECT;
1814                         }
1815
1816                         update_editipo_flags();
1817                         scrarea_queue_winredraw(curarea);
1818                 }
1819         }
1820 }
1821
1822 /* ******************************************* */
1823
1824 EditIpo *get_editipo()
1825 {
1826         EditIpo *ei;
1827         int a; /*  , sel=0; */
1828         
1829         get_status_editipo();
1830         
1831         if(totipo_edit>1) {
1832                 error("Too many editipo's");
1833                 return 0;
1834         }
1835         if(G.sipo->editipo==0) return 0;
1836         
1837         ei= G.sipo->editipo;
1838         for(a=0; a<G.sipo->totipo; a++) {
1839                 if(ei->flag & IPO_VISIBLE) {
1840                         if( ei->flag & IPO_EDIT ) return ei;
1841                         else if(totipo_vis==1) return ei;
1842                         
1843                         if(ei->flag & IPO_SELECT) {
1844                                 if(totipo_sel==1) return ei;
1845                         }
1846                 }
1847                 ei++;
1848         }
1849         return 0;
1850 }
1851
1852
1853 static Ipo *get_ipo(ID *from, short type, int make)
1854 {
1855         Object *ob;
1856         Material *ma;
1857         Curve *cu;
1858         Sequence *seq;
1859         Key *key;
1860         World *wo;
1861         Lamp *la;
1862         Camera *ca;
1863         Ipo *ipo= 0;
1864         bAction *act;
1865
1866         if( type==ID_OB) {
1867                 ob= (Object *)from;
1868                 if(ob->id.lib) return 0;
1869                 
1870                 ipo= ob->ipo;
1871                 if(make && ipo==0) ipo= ob->ipo= add_ipo("ObIpo", ID_OB);       
1872         }
1873         else if( type==IPO_CO){
1874                 ob= (Object *)from;
1875                 if(ob->id.lib) return 0;
1876
1877                 if (ob->activecon){
1878                         ipo= ob->activecon->ipo;
1879                         if(make && ipo==0) ipo= ob->activecon->ipo= add_ipo("CoIpo", IPO_CO);   
1880                 }
1881         }
1882         else if( type==ID_AC) {
1883                 act= (bAction *)from;
1884                 if (!act->achan) return 0;
1885                 if (act->id.lib) return 0;
1886                 ipo= act->achan->ipo;
1887
1888                 /* This should never happen */
1889                 if(make && ipo==0) ipo= act->achan->ipo= add_ipo("AcIpo", ID_AC);
1890         }
1891         else if( type==ID_MA) {
1892                 ma= (Material *)from;
1893                 if(ma->id.lib) return 0;
1894                 ipo= ma->ipo;
1895                 
1896                 if(make && ipo==0) ipo= ma->ipo= add_ipo("MatIpo", ID_MA);
1897         }
1898
1899         else if( type==ID_SEQ) {
1900                 seq= (Sequence *)from;
1901
1902                 if(seq->type & SEQ_EFFECT) {
1903                         ipo= seq->ipo;
1904                         if(make && ipo==0) ipo= seq->ipo= add_ipo("SeqIpo", ID_SEQ);
1905                 }
1906                 else return 0;
1907         }       
1908         else if( type==ID_CU) {
1909                 cu= (Curve *)from;
1910                 if(cu->id.lib) return 0;
1911                 ipo= cu->ipo;
1912                 
1913                 if(make && ipo==0) ipo= cu->ipo= add_ipo("CuIpo", ID_CU);
1914         }
1915         else if( type==ID_KE) {
1916                 key= (Key *)from;
1917                 if(key->id.lib) return 0;
1918                 ipo= key->ipo;
1919                 
1920                 if(make && ipo==0) ipo= key->ipo= add_ipo("KeyIpo", ID_KE);
1921         }
1922         else if( type==ID_WO) {
1923                 wo= (World *)from;
1924                 if(wo->id.lib) return 0;
1925                 ipo= wo->ipo;
1926                 
1927                 if(make && ipo==0) ipo= wo->ipo= add_ipo("WoIpo", ID_WO);
1928         }
1929         else if( type==ID_LA) {
1930                 la= (Lamp *)from;
1931                 if(la->id.lib) return 0;
1932                 ipo= la->ipo;
1933                 
1934                 if(make && ipo==0) ipo= la->ipo= add_ipo("LaIpo", ID_LA);
1935         }
1936         else if( type==ID_CA) {
1937                 ca= (Camera *)from;
1938                 if(ca->id.lib) return 0;
1939                 ipo= ca->ipo;
1940                 
1941                 if(make && ipo==0) ipo= ca->ipo= add_ipo("CaIpo", ID_CA);
1942         }
1943         else if( type==ID_SO) {
1944                 bSound *snd= (bSound *)from;
1945                 if(snd->id.lib) return 0;
1946                 ipo= snd->ipo;
1947                 
1948                 if(make && ipo==0) ipo= snd->ipo= add_ipo("SndIpo", ID_SO);
1949         }
1950         else return 0;
1951         
1952         return ipo;     
1953 }
1954
1955
1956 // this function should not have the G.sipo in it...
1957
1958 IpoCurve *get_ipocurve(ID *from, short type, int adrcode, Ipo *useipo)
1959 {
1960         Ipo *ipo= 0;
1961         IpoCurve *icu=0;
1962         
1963         /* return 0 als lib */
1964         /* ook testen of ipo en ipocurve bestaan */
1965
1966         if (useipo==NULL) {
1967
1968                 if (G.sipo==NULL || G.sipo->pin==0){
1969                         ipo= get_ipo(from, type, 1);    /* 1= make */
1970                 }
1971                 else
1972                         ipo = G.sipo->ipo;
1973
1974                 
1975                 if(G.sipo) {
1976                         if (G.sipo->pin==0) G.sipo->ipo= ipo;
1977                 }
1978         }
1979         else
1980                 ipo= useipo;
1981
1982                 
1983         if(ipo && ipo->id.lib==0) {
1984         
1985                 icu= ipo->curve.first;
1986                 while(icu) {
1987                         if(icu->adrcode==adrcode) break;
1988                         icu= icu->next;
1989                 }
1990                 if(icu==0) {
1991                         icu= MEM_callocN(sizeof(IpoCurve), "ipocurve");
1992                         
1993                         icu->flag |= IPO_VISIBLE;
1994
1995                         if (!useipo && G.sipo && G.sipo->pin)
1996                                 icu->blocktype = G.sipo->blocktype;
1997                         else
1998                                 icu->blocktype= type;
1999                         icu->adrcode= adrcode;
2000                         
2001                         set_icu_vars(icu);
2002                         
2003                         BLI_addtail( &(ipo->curve), icu);
2004                 }
2005         }
2006         return icu;
2007 }
2008
2009 void insert_vert_ipo(IpoCurve *icu, float x, float y)
2010 {
2011         BezTriple *bezt, beztr, *newbezt;
2012         int a = 0, h1, h2;
2013         
2014         memset(&beztr, 0, sizeof(BezTriple));
2015         beztr.vec[1][0]= x;
2016         beztr.vec[1][1]= y;
2017         beztr.hide= IPO_BEZ;
2018         beztr.f1= beztr.f2= beztr.f3= SELECT;
2019         beztr.h1= beztr.h2= HD_AUTO;
2020                 
2021         bezt= icu->bezt;
2022                 
2023         if(bezt==0) {
2024                 icu->bezt= MEM_callocN( sizeof(BezTriple), "beztriple");
2025                 *(icu->bezt)= beztr;
2026                 icu->totvert= 1;
2027         }
2028         else {
2029                 /* alle vertices deselect */
2030                 for(a=0; a<icu->totvert; a++, bezt++) {
2031                         bezt->f1= bezt->f2= bezt->f3= 0;
2032                 }
2033         
2034                 bezt= icu->bezt;
2035                 for(a=0; a<=icu->totvert; a++, bezt++) {
2036                         
2037                         /* geen dubbele punten */
2038                         if(a<icu->totvert && (bezt->vec[1][0]>x-IPOTHRESH && bezt->vec[1][0]<x+IPOTHRESH)) {
2039                                 *(bezt)= beztr;
2040                                 break;
2041                         }
2042                         if(a==icu->totvert || bezt->vec[1][0] > x) {
2043                                 newbezt= MEM_callocN( (icu->totvert+1)*sizeof(BezTriple), "beztriple");
2044                                 
2045                                 if(a>0) memcpy(newbezt, icu->bezt, a*sizeof(BezTriple));
2046                                 
2047                                 bezt= newbezt+a;
2048                                 *(bezt)= beztr;
2049                                 
2050                                 if(a<icu->totvert) memcpy(newbezt+a+1, icu->bezt+a, (icu->totvert-a)*sizeof(BezTriple));
2051                                 
2052                                 MEM_freeN(icu->bezt);
2053                                 icu->bezt= newbezt;
2054                                 
2055                                 icu->totvert++;
2056                                 break;
2057                         }
2058                 }
2059         }
2060         
2061         
2062         calchandles_ipocurve(icu);
2063         
2064         /* handletype goedzetten */
2065         if(icu->totvert>2) {
2066                 h1= h2= HD_AUTO;
2067                 if(a>0) h1= (bezt-1)->h2;
2068                 if(a<icu->totvert-1) h2= (bezt+1)->h1;
2069                 bezt->h1= h1;
2070                 bezt->h2= h2;
2071
2072                 calchandles_ipocurve(icu);
2073         }
2074 }
2075
2076 void add_vert_ipo()
2077 {
2078         EditIpo *ei;
2079         float x, y;
2080         int val;
2081         short mval[2];
2082
2083         if(G.sipo->ipo && G.sipo->ipo->id.lib) return;
2084         if(G.sipo->showkey) {
2085                 G.sipo->showkey= 0;
2086                 free_ipokey(&G.sipo->ipokey);
2087         }
2088         
2089         getmouseco_areawin(mval);
2090         
2091         if(mval[0]>G.v2d->mask.xmax) return;
2092         
2093         ei= get_editipo();
2094         if(ei==0) return;
2095
2096         areamouseco_to_ipoco(G.v2d, mval, &x, &y);
2097         
2098         if(ei->icu==0) {
2099                 if(G.sipo->from)
2100                         ei->icu= get_ipocurve(G.sipo->from, G.sipo->blocktype, ei->adrcode, 0);
2101         }
2102         if(ei->icu==0) return;
2103
2104         if(ei->disptype==IPO_DISPBITS) {
2105                 ei->icu->vartype= IPO_BITS;
2106                 val= (int)floor(y-0.5);
2107                 if(val<0) val= 0;
2108                 y= (float)(1 << val);
2109         }
2110         
2111         insert_vert_ipo(ei->icu, x, y);
2112
2113         /* voor zekerheid: als icu 0 was, of maar 1 curve visible */
2114         ei->flag |= IPO_SELECT;
2115         ei->icu->flag= ei->flag;
2116
2117         editipo_changed(G.sipo, 1);
2118 }
2119
2120 void add_duplicate_editipo()
2121 {
2122         Object *ob;
2123         EditIpo *ei;
2124         IpoCurve *icu;
2125         BezTriple *bezt, *beztn, *newb;
2126         int tot, a, b;
2127         
2128         get_status_editipo();
2129         if(totipo_vertsel==0) return;
2130         
2131         ei= G.sipo->editipo;
2132         for(a=0; a<G.sipo->totipo; a++, ei++) {
2133                 if ISPOIN3(ei, flag & IPO_VISIBLE, icu, icu->bezt) {
2134                         if(G.sipo->showkey || (ei->flag & IPO_EDIT)) {
2135                                 icu= ei->icu;
2136                                 
2137                                 /* hoeveel punten */
2138                                 tot= 0;
2139                                 b= icu->totvert;
2140                                 bezt= icu->bezt;
2141                                 while(b--) {
2142                                         if(bezt->f2 & 1) tot++;
2143                                         bezt++;
2144                                 }
2145                                 
2146                                 if(tot) {
2147                                         icu->totvert+= tot;
2148                                         newb= beztn= MEM_mallocN(icu->totvert*sizeof(BezTriple), "bezt");
2149                                         bezt= icu->bezt;
2150                                         b= icu->totvert-tot;
2151                                         while(b--) {
2152                                                 *beztn= *bezt;
2153                                                 if(bezt->f2 & 1) {
2154                                                         beztn->f1= beztn->f2= beztn->f3= 0;
2155                                                         beztn++;
2156                                                         *beztn= *bezt;
2157                                                 }
2158                                                 beztn++;
2159                                                 bezt++;
2160                                         }
2161                                         MEM_freeN(icu->bezt);
2162                                         icu->bezt= newb;
2163                                         
2164                                         calchandles_ipocurve(icu);
2165                                 }
2166                         }
2167                 }
2168         }
2169         
2170         if(G.sipo->showkey) {
2171                 make_ipokey();
2172                 if(G.sipo->blocktype==ID_OB) {
2173                         ob= OBACT;
2174                         if(ob && (ob->ipoflag & OB_DRAWKEY)) allqueue(REDRAWVIEW3D, 0);
2175                 }
2176         }
2177         transform_ipo('g');
2178 }
2179
2180 void remove_doubles_ipo()
2181 {
2182         EditIpo *ei;
2183         IpoKey *ik, *ikn;
2184         BezTriple *bezt, *newb, *new1;
2185         float val;
2186         int mode, a, b;
2187         
2188         ei= G.sipo->editipo;
2189         for(a=0; a<G.sipo->totipo; a++, ei++) {
2190                 if ISPOIN3(ei, flag & IPO_VISIBLE, icu, icu->bezt) {
2191                         
2192                         /* OF de curve is selected OF in editmode OF in keymode */
2193                         mode= 0;
2194                         if(G.sipo->showkey || (ei->flag & IPO_EDIT)) mode= 1;
2195                         else if(ei->flag & IPO_SELECT) mode= 2;
2196                         
2197                         if(mode) {
2198                                 bezt= ei->icu->bezt;
2199                                 newb= new1= MEM_mallocN(ei->icu->totvert*sizeof(BezTriple), "newbezt");
2200                                 *newb= *bezt;
2201                                 b= ei->icu->totvert-1;
2202                                 bezt++;
2203                                 while(b--) {
2204                                         
2205                                         /* mag er verwijderd worden? */
2206                                         if(mode==2 || (bezt->f2 & 1)) {
2207                                         
2208                                                 /* verschillen de punten? */
2209                                                 if( fabs( bezt->vec[1][0]-newb->vec[1][0] ) > 0.9 ) {
2210                                                         newb++;
2211                                                         *newb= *bezt;
2212                                                 }
2213                                                 else {
2214                                                         /* gemiddelde */
2215                                                         VecMidf(newb->vec[0], newb->vec[0], bezt->vec[0]);
2216                                                         VecMidf(newb->vec[1], newb->vec[1], bezt->vec[1]);
2217                                                         VecMidf(newb->vec[2], newb->vec[2], bezt->vec[2]);
2218                                                         
2219                                                         newb->h1= newb->h2= HD_FREE;
2220                                                         
2221                                                         ei->icu->totvert--;
2222                                                 }
2223                                                 
2224                                         }
2225                                         else {
2226                                                 newb++;
2227                                                 *newb= *bezt;
2228                                         }
2229                                         bezt++;
2230                                 }
2231                                 
2232                                 MEM_freeN(ei->icu->bezt);
2233                                 ei->icu->bezt= new1;
2234                                 
2235                                 calchandles_ipocurve(ei->icu);                          
2236                         }
2237                 }
2238         }
2239         
2240         editipo_changed(G.sipo, 1);     /* maakt ook ipokeys opnieuw! */
2241
2242         /* dubbele keys weg */
2243         if(G.sipo->showkey) {
2244                 ik= G.sipo->ipokey.first;
2245                 ikn= ik->next;
2246                 
2247                 while(ik && ikn) {
2248                         if( (ik->flag & 1) && (ikn->flag & 1) ) {
2249                                 if( fabs(ik->val-ikn->val) < 0.9 ) {
2250                                         val= (float)((ik->val + ikn->val)/2.0);
2251                                         
2252                                         for(a=0; a<G.sipo->totipo; a++) {
2253                                                 if(ik->data[a]) ik->data[a]->vec[1][0]= val;
2254                                                 if(ikn->data[a]) ikn->data[a]->vec[1][0]= val;                                          
2255                                         }
2256                                 }
2257                         }
2258                         ik= ikn;
2259                         ikn= ikn->next;
2260
2261                 }
2262                 
2263                 editipo_changed(G.sipo, 1);     /* maakt ook ipokeys opnieuw! */
2264
2265         }
2266         deselectall_editipo();
2267 }
2268
2269 void join_ipo()
2270 {
2271         EditIpo *ei;
2272         IpoKey *ik;
2273         IpoCurve *icu;
2274         BezTriple *bezt, *beztn, *newb;
2275         float val;
2276         int mode, tot, a, b;
2277         
2278         get_status_editipo();
2279         
2280         mode= pupmenu("Join %t|All Selected %x1|Selected doubles %x2");
2281         if( mode==2 ) {
2282                 remove_doubles_ipo();
2283                 return;
2284         }
2285         else if(mode!=1) return;
2286         
2287         /* eerst: meerdere geselecteerde verts in 1 curve */
2288         ei= G.sipo->editipo;
2289         for(a=0; a<G.sipo->totipo; a++, ei++) {
2290                 if ISPOIN3(ei, flag & IPO_VISIBLE, icu, icu->bezt) {
2291                         if(G.sipo->showkey || (ei->flag & IPO_EDIT)) {
2292                                 icu= ei->icu;
2293                                 
2294                                 /* hoeveel punten */
2295                                 tot= 0;
2296                                 b= icu->totvert;
2297                                 bezt= icu->bezt;
2298                                 while(b--) {
2299                                         if(bezt->f2 & 1) tot++;
2300                                         bezt++;
2301                                 }
2302                                 
2303                                 if(tot>1) {
2304                                         tot--;
2305                                         icu->totvert-= tot;
2306                                         
2307                                         newb= MEM_mallocN(icu->totvert*sizeof(BezTriple), "bezt");
2308                                         /* het eerste punt wordt het nieuwe punt */
2309                                         beztn= newb+1;
2310                                         tot= 0;
2311                                         
2312                                         bezt= icu->bezt;
2313                                         b= icu->totvert+tot+1;
2314                                         while(b--) {
2315                                                 
2316                                                 if(bezt->f2 & 1) {
2317                                                         if(tot==0) *newb= *bezt;
2318                                                         else {
2319                                                                 VecAddf(newb->vec[0], newb->vec[0], bezt->vec[0]);
2320                                                                 VecAddf(newb->vec[1], newb->vec[1], bezt->vec[1]);
2321                                                                 VecAddf(newb->vec[2], newb->vec[2], bezt->vec[2]);
2322                                                         }
2323                                                         tot++;
2324                                                 }
2325                                                 else {
2326                                                         *beztn= *bezt;
2327                                                         beztn++;
2328                                                 }
2329                                                 bezt++;
2330                                         }
2331                                         
2332                                         VecMulf(newb->vec[0], (float)(1.0/((float)tot)));
2333                                         VecMulf(newb->vec[1], (float)(1.0/((float)tot)));
2334                                         VecMulf(newb->vec[2], (float)(1.0/((float)tot)));
2335                                         
2336                                         MEM_freeN(icu->bezt);
2337                                         icu->bezt= newb;
2338                                         
2339                                         sort_time_ipocurve(icu);
2340                                         calchandles_ipocurve(icu);
2341                                 }
2342                         }
2343                 }
2344         }
2345         
2346         /* dan: in keymode: meerdere geselecteerde keys samenvoegen */
2347         
2348         editipo_changed(G.sipo, 1);     /* maakt ook ipokeys opnieuw! */
2349         
2350         if(G.sipo->showkey) {
2351                 ik= G.sipo->ipokey.first;
2352                 val= 0.0;
2353                 tot= 0;
2354                 while(ik) {
2355                         if(ik->flag & 1) {
2356                                 for(a=0; a<G.sipo->totipo; a++) {
2357                                         if(ik->data[a]) {
2358                                                 val+= ik->data[a]->vec[1][0];
2359                                                 break;
2360                                         }
2361                                 }
2362                                 tot++;
2363                         }
2364                         ik= ik->next;
2365                 }
2366                 if(tot>1) {
2367                         val/= (float)tot;
2368                         
2369                         ik= G.sipo->ipokey.first;
2370                         while(ik) {
2371                                 if(ik->flag & 1) {
2372                                         for(a=0; a<G.sipo->totipo; a++) {
2373                                                 if(ik->data[a]) {
2374                                                         ik->data[a]->vec[1][0]= val;
2375                                                 }
2376                                         }
2377                                 }
2378                                 ik= ik->next;
2379                         }
2380                         editipo_changed(G.sipo, 0);
2381                 }
2382         }
2383         deselectall_editipo();
2384 }
2385
2386 void ipo_snapmenu()
2387 {
2388         EditIpo *ei;
2389         BezTriple *bezt;
2390         float dx = 0.0;
2391         int a, b;
2392         short event, ok, ok2;
2393         
2394         event= pupmenu("Snap %t|Horizontal %x1|To next %x2|To frame %x3|To current frame%x4");
2395         if(event < 1) return;
2396         
2397         get_status_editipo();
2398
2399         ei= G.sipo->editipo;
2400         for(b=0; b<G.sipo->totipo; b++, ei++) {
2401                 if ISPOIN3(ei, flag & IPO_VISIBLE, icu, icu->bezt) {
2402                 
2403                         ok2= 0;
2404                         if(G.sipo->showkey) ok2= 1;
2405                         else if(totipo_vert && (ei->flag & IPO_EDIT)) ok2= 2;
2406                         else if(totipo_vert==0 && (ei->flag & IPO_SELECT)) ok2= 3;
2407                         
2408                         if(ok2) {
2409                                 bezt= ei->icu->bezt;
2410                                 a= ei->icu->totvert;
2411                                 while(a--) {
2412                                         ok= 0;
2413                                         if(totipo_vert) {
2414                                                  if(bezt->f2 & 1) ok= 1;
2415                                         }
2416                                         else ok= 1;
2417                                         
2418                                         if(ok) {
2419                                                 if(event==1) {
2420                                                         bezt->vec[0][1]= bezt->vec[2][1]= bezt->vec[1][1];
2421                                                         if(bezt->h1==HD_AUTO || bezt->h1==HD_VECT) bezt->h1= HD_ALIGN;
2422                                                         if(bezt->h2==HD_AUTO || bezt->h2==HD_VECT) bezt->h2= HD_ALIGN;
2423                                                 }
2424                                                 else if(event==2) {
2425                                                         if(a) {
2426                                                                 bezt->vec[0][1]= bezt->vec[1][1]= bezt->vec[2][1]= (bezt+1)->vec[1][1];
2427                                                                 if(bezt->h1==HD_AUTO || bezt->h1==HD_VECT) bezt->h1= HD_ALIGN;
2428                                                                 if(bezt->h2==HD_AUTO || bezt->h2==HD_VECT) bezt->h2= HD_ALIGN;
2429                                                         }
2430                                                 }
2431                                                 else if(event==3) {
2432                                                         bezt->vec[1][0]= (float)(floor(bezt->vec[1][0]+0.5));
2433                                                 }
2434                                                 else if(event==4) {     /* to current frame */
2435                                                         
2436                                                         if(ok2==1 || ok2==2) {
2437                                                                 
2438                                                                 if(G.sipo->blocktype==ID_SEQ) {
2439                                                                         Sequence *seq;
2440                                                         
2441                                                                         seq= (Sequence *)G.sipo->from;
2442                                                                         if(seq) {
2443                                                                                 dx= (float)(CFRA-seq->startdisp);
2444                                                                                 dx= (float)(100.0*dx/((float)(seq->enddisp-seq->startdisp)));
2445                                                                                 
2446                                                                                 dx-= bezt->vec[1][0];
2447                                                                         }
2448                                                                 }
2449                                                                 else dx= G.scene->r.framelen*CFRA - bezt->vec[1][0];
2450                                                                 
2451                                                                 bezt->vec[0][0]+= dx;
2452                                                                 bezt->vec[1][0]+= dx;
2453                                                                 bezt->vec[2][0]+= dx;
2454                                                         }
2455                                                 }
2456                                         }
2457                                         
2458                                         bezt++;
2459                                 }
2460                                 calchandles_ipocurve(ei->icu);
2461                         }
2462                 }
2463         }
2464         editipo_changed(G.sipo, 1);
2465 }
2466
2467
2468
2469 void mouse_select_ipo()
2470 {
2471         Object *ob;
2472         EditIpo *ei, *actei= 0;
2473         IpoCurve *icu;
2474         IpoKey *ik, *actik;
2475         BezTriple *bezt;
2476         Key *key;
2477         KeyBlock *kb, *actkb=0;
2478         float x, y, dist, mindist;
2479         int a, oldflag = 0, hand, ok;
2480         short mval[2], xo, yo;
2481         
2482         if(G.sipo->editipo==0) return;
2483         
2484         get_status_editipo();
2485         
2486         if(G.sipo->showkey) {
2487                 getmouseco_areawin(mval);
2488         
2489                 areamouseco_to_ipoco(G.v2d, mval, &x, &y);
2490                 actik= 0;
2491                 mindist= 1000.0;
2492                 ik= G.sipo->ipokey.first;
2493                 while(ik) {
2494                         dist= (float)(fabs(ik->val-x));
2495                         if(ik->flag & 1) dist+= 1.0;
2496                         if(dist < mindist) {
2497                                 actik= ik;
2498                                 mindist= dist;
2499                         }
2500                         ik= ik->next;
2501                 }
2502                 if(actik) {
2503                         oldflag= actik->flag;
2504                         
2505                         if(G.qual & LR_SHIFTKEY);
2506                         else deselectall_editipo();
2507                         
2508                         if(G.qual & LR_SHIFTKEY) {
2509                                 if(oldflag & 1) actik->flag &= ~1;
2510                                 else actik->flag |= 1;
2511                         }
2512                         else {
2513                                 actik->flag |= 1;
2514                         }
2515                 }
2516         }
2517         else if(totipo_edit) {
2518         
2519                 hand= findnearest_ipovert(&icu, &bezt);
2520
2521                 if(G.qual & LR_SHIFTKEY) {
2522                         if(bezt) {
2523                                 if(hand==1) {
2524                                         if(BEZSELECTED(bezt)) {
2525                                                 bezt->f1= bezt->f2= bezt->f3= 0;
2526                                         }
2527                                         else {
2528                                                 bezt->f1= bezt->f2= bezt->f3= 1;
2529                                         }
2530                                 }
2531                                 else if(hand==0) {
2532                                         if(bezt->f1 & 1) bezt->f1= 0;
2533                                         else bezt->f1= 1;
2534                                 }
2535                                 else {
2536                                         if(bezt->f3 & 1) bezt->f3= 0;
2537                                         else bezt->f3= 1;
2538                                 }
2539                         }                               
2540                 }
2541                 else {
2542                         deselectall_editipo();
2543                 
2544                         if(bezt) {
2545                                 if(hand==1) {
2546                                         bezt->f1|= 1; bezt->f2|= 1; bezt->f3|= 1;
2547                                 }
2548                                 else if(hand==0) bezt->f1|= 1;
2549                                 else bezt->f3|= 1;
2550                         }
2551                 }
2552         }
2553         else {
2554                 
2555                 /* vertex keys ? */
2556                 
2557                 if(G.sipo->blocktype==ID_KE && G.sipo->from) {
2558                         key= (Key *)G.sipo->from;
2559                         
2560                         ei= G.sipo->editipo;
2561                         if(key->type==KEY_NORMAL || (ei->flag & IPO_VISIBLE)) {
2562                                 getmouseco_areawin(mval);
2563                                 
2564                                 areamouseco_to_ipoco(G.v2d, mval, &x, &y);
2565                                 /* hoeveel is 20 pixels? */
2566                                 mindist= (float)(20.0*(G.v2d->cur.ymax-G.v2d->cur.ymin)/(float)curarea->winy);
2567                                 
2568                                 kb= key->block.first;
2569                                 while(kb) {
2570                                         dist= (float)(fabs(kb->pos-y));
2571                                         if(kb->flag & SELECT) dist+= (float)0.01;
2572                                         if(dist < mindist) {
2573                                                 actkb= kb;
2574                                                 mindist= dist;
2575                                         }
2576                                         kb= kb->next;
2577                                 }
2578                                 if(actkb) {
2579                                         ok= TRUE;
2580                                         if(G.obedit && (actkb->flag & 1)==0) {
2581                                                 ok= okee("Copy Key after leaving EditMode");
2582                                         }
2583                                         if(ok) {
2584                                                 /* doet ook alle keypos */
2585                                                 deselectall_editipo();
2586                                                 
2587                                                 /* oldflag= actkb->flag; */
2588                                                 
2589                                                 /* if(G.qual & LR_SHIFTKEY); */
2590                                                 /* else { */
2591                                                 /*      deselectall_key(); */
2592                                                 /* } */
2593                                                 
2594                                                 /* if(G.qual & LR_SHIFTKEY) { */
2595                                                 /*      if(oldflag & 1) actkb->flag &= ~1; */
2596                                                 /*      else actkb->flag |= 1; */
2597                                                 /* } */
2598                                                 /* else { */
2599                                                         actkb->flag |= 1;
2600                                                 /* } */
2601                                                 
2602                                                 /* bereken keypos */
2603                                                 showkeypos((Key *)G.sipo->from, actkb);
2604                                         }
2605                                 }
2606                         }
2607                 }
2608                         
2609                 /* select curve */
2610                 if(actkb==0) {
2611                         if(totipo_vis==1) {
2612                                 ei= G.sipo->editipo;
2613                                 for(a=0; a<G.sipo->totipo; a++, ei++) {
2614                                         if(ei->icu) {
2615                                                 if(ei->flag & IPO_VISIBLE) actei= ei;
2616                                         }
2617                                 }
2618                         }
2619                         else if(totipo_vis>1) {
2620                                 actei= select_proj_ipo(0, 0);
2621                         }
2622                         
2623                         if(actei) oldflag= actei->flag;
2624                         
2625                         if(G.qual & LR_SHIFTKEY);
2626                         else deselectall_editipo();
2627                         
2628                         if(actei) {
2629                                 if(G.qual & LR_SHIFTKEY) {
2630                                         if(oldflag & IPO_SELECT) actei->flag &= ~IPO_SELECT;
2631                                         else actei->flag |= IPO_SELECT;
2632                                 }
2633                                 else {
2634                                         actei->flag |= IPO_SELECT;
2635                                 }
2636                         }
2637                 }
2638         }
2639         
2640         update_editipo_flags();
2641         
2642         force_draw();
2643         
2644         if(G.sipo->showkey && G.sipo->blocktype==ID_OB) {
2645                 ob= OBACT;
2646                 if(ob && (ob->ipoflag & OB_DRAWKEY)) draw_object_ext(BASACT);
2647         }
2648         
2649         getmouseco_areawin(mval);
2650         xo= mval[0]; 
2651         yo= mval[1];
2652
2653         while(get_mbut()&R_MOUSE) {             
2654                 getmouseco_areawin(mval);
2655                 if(abs(mval[0]-xo)+abs(mval[1]-yo) > 4) {
2656                         
2657                         if(actkb) move_keys();
2658                         else transform_ipo('g');
2659                         
2660                         return;
2661                 }
2662                 BIF_wait_for_statechange();
2663         }
2664 }
2665
2666 int icu_keys_bezier_loop(IpoCurve *icu,
2667                          int (*bezier_function)(BezTriple *),
2668                          void (ipocurve_function)(struct IpoCurve *icu)) 
2669 {
2670     /*  This loops through the beziers in the Ipocurve, and executes 
2671      *  the generic user provided 'bezier_function' on each one. 
2672      *  Optionally executes the generic function ipocurve_function on the 
2673      *  IPO curve after looping (eg. calchandles_ipocurve)
2674      */
2675
2676     int b;
2677     BezTriple *bezt;
2678
2679     b    = icu->totvert;
2680     bezt = icu->bezt;
2681
2682     /* if bezier_function has been specified
2683      * then loop through each bezier executing
2684      * it.
2685      */
2686
2687     if (bezier_function != NULL) {
2688         while(b--) {
2689             /* exit with return code 1 if the bezier function 
2690              * returns 1 (good for when you are only interested
2691              * in finding the first bezier that
2692              * satisfies a condition).
2693              */
2694             if (bezier_function(bezt)) return 1;
2695             bezt++;
2696         }
2697     }
2698
2699     /* if ipocurve_function has been specified 
2700      * then execute it
2701      */
2702     if (ipocurve_function != NULL)
2703         ipocurve_function(icu);
2704
2705     return 0;
2706
2707 }
2708
2709 int ipo_keys_bezier_loop(Ipo *ipo,
2710                          int (*bezier_function)(BezTriple *),
2711                          void (ipocurve_function)(struct IpoCurve *icu))
2712 {
2713     /*  This loops through the beziers that are attached to
2714      *  the selected keys on the Ipocurves of the Ipo, and executes 
2715      *  the generic user provided 'bezier_function' on each one. 
2716      *  Optionally executes the generic function ipocurve_function on a 
2717      *  IPO curve after looping (eg. calchandles_ipocurve)
2718      */
2719
2720     IpoCurve *icu;
2721
2722     /* Loop through each curve in the Ipo
2723      */
2724     for (icu=ipo->curve.first; icu; icu=icu->next){
2725         if (icu_keys_bezier_loop(icu,bezier_function, ipocurve_function))
2726             return 1;
2727     }
2728
2729     return 0;
2730 }
2731
2732 int selected_bezier_loop(int (*looptest)(EditIpo *),
2733                          int (*bezier_function)(BezTriple *),
2734                          void (ipocurve_function)(struct IpoCurve *icu))
2735 {
2736         /*  This loops through the beziers that are attached to
2737          *  selected keys in editmode in the IPO window, and executes 
2738          *  the generic user-provided 'bezier_function' on each one 
2739          *  that satisfies the 'looptest' function. Optionally executes
2740          *  the generic function ipocurve_function on a IPO curve
2741          *  after looping (eg. calchandles_ipocurve)
2742          */
2743
2744         EditIpo *ei;
2745         BezTriple *bezt;
2746         int a, b;
2747
2748         /* Get the first Edit Ipo from the selected Ipos
2749          */
2750         ei= G.sipo->editipo;
2751
2752         /* Loop throught all of the selected Ipo's
2753          */
2754         for(a=0; a<G.sipo->totipo; a++, ei++) {
2755                 /* Do a user provided test on the Edit Ipo
2756                  * to determine whether we want to process it
2757                  */
2758                 if (looptest(ei)) {
2759                         /* Loop through the selected
2760                          * beziers on the Edit Ipo
2761                          */
2762                         bezt = ei->icu->bezt;
2763                         b    = ei->icu->totvert;
2764                         
2765                         /* if bezier_function has been specified
2766                          * then loop through each bezier executing
2767                          * it.
2768                          */
2769                         if (bezier_function != NULL) {
2770                                 while(b--) {
2771                                         /* exit with return code 1 if the bezier function 
2772                                          * returns 1 (good for when you are only interested
2773                                          * in finding the first bezier that
2774                                          * satisfies a condition).
2775                                          */
2776                                         if (bezier_function(bezt)) return 1;
2777                                         bezt++;
2778                                 }
2779                         }
2780
2781                         /* if ipocurve_function has been specified 
2782                          * then execute it
2783                          */
2784                         if (ipocurve_function != NULL)
2785                                 ipocurve_function(ei->icu);
2786                 }
2787                 /* nufte flourdje zim ploopydu <-- random dutch looking comment ;) */
2788         }
2789
2790         return 0;
2791 }
2792
2793 int select_bezier_add(BezTriple *bezt) {
2794   /* Select the bezier triple */
2795   bezt->f1 |= 1;
2796   bezt->f2 |= 1;
2797   bezt->f3 |= 1;
2798   return 0;
2799 }
2800
2801 int select_bezier_subtract(BezTriple *bezt) {
2802   /* Deselect the bezier triple */
2803   bezt->f1 &= ~1;
2804   bezt->f2 &= ~1;
2805   bezt->f3 &= ~1;
2806   return 0;
2807 }
2808
2809 int select_bezier_invert(BezTriple *bezt) {
2810   /* Invert the selection for the bezier triple */
2811   bezt->f2 ^= 1;
2812   if ( bezt->f2 & 1 ) {
2813     bezt->f1 |= 1;
2814     bezt->f3 |= 1;
2815   }
2816   else {
2817     bezt->f1 &= ~1;
2818     bezt->f3 &= ~1;
2819   }
2820   return 0;
2821 }
2822
2823 int set_bezier_auto(BezTriple *bezt) 
2824 {
2825         /* Sets the selected bezier handles to type 'auto' 
2826          */
2827
2828         /* is a handle selected? If so
2829          * set it to type auto
2830          */
2831         if(bezt->f1 || bezt->f3) {
2832                 if(bezt->f1) bezt->h1= 1; /* the secret code for auto */
2833                 if(bezt->f3) bezt->h2= 1;
2834
2835                 /* if the handles are not of the same type, set them
2836                  * to type free
2837                  */
2838                 if(bezt->h1!=bezt->h2) {
2839                         if ELEM(bezt->h1, HD_ALIGN, HD_AUTO) bezt->h1= HD_FREE;
2840                         if ELEM(bezt->h2, HD_ALIGN, HD_AUTO) bezt->h2= HD_FREE;
2841                 }
2842         }
2843         return 0;
2844 }
2845
2846 int set_bezier_vector(BezTriple *bezt) 
2847 {
2848         /* Sets the selected bezier handles to type 'vector' 
2849          */
2850
2851         /* is a handle selected? If so
2852          * set it to type vector
2853          */
2854         if(bezt->f1 || bezt->f3) {
2855                 if(bezt->f1) bezt->h1= 2; /* the code for vector */
2856                 if(bezt->f3) bezt->h2= 2;
2857     
2858                 /* if the handles are not of the same type, set them
2859                  * to type free
2860                  */
2861                 if(bezt->h1!=bezt->h2) {
2862                         if ELEM(bezt->h1, HD_ALIGN, HD_AUTO) bezt->h1= HD_FREE;
2863                         if ELEM(bezt->h2, HD_ALIGN, HD_AUTO) bezt->h2= HD_FREE;
2864                 }
2865         }
2866         return 0;
2867 }
2868
2869 int bezier_isfree(BezTriple *bezt) 
2870 {
2871         /* queries whether the handle should be set
2872          * to type 'free' (I think)
2873          */
2874         if(bezt->f1 && bezt->h1) return 1;
2875         if(bezt->f3 && bezt->h2) return 1;
2876         return 0;
2877 }
2878
2879 int set_bezier_free(BezTriple *bezt) 
2880 {
2881         /* Sets selected bezier handles to type 'free' 
2882          */
2883         if(bezt->f1) bezt->h1= HD_FREE;
2884         if(bezt->f3) bezt->h2= HD_FREE;
2885         return 0;
2886 }
2887
2888 int set_bezier_align(BezTriple *bezt) 
2889 {
2890         /* Sets selected bezier handles to type 'align' 
2891          */
2892         if(bezt->f1) bezt->h1= HD_ALIGN;
2893         if(bezt->f3) bezt->h2= HD_ALIGN;
2894         return 0;
2895 }
2896
2897 int vis_edit_icu_bez(EditIpo *ei) {
2898         /* A 4 part test for an EditIpo :
2899          *   is it a) visible
2900          *         b) in edit mode
2901          *         c) does it contain an Ipo Curve
2902          *         d) does that ipo curve have a bezier
2903          *
2904          * (The reason why I don't just use the macro
2905          * is I need a pointer to a function.)
2906          */
2907         return ISPOIN4(ei, flag & IPO_VISIBLE, flag & IPO_EDIT, icu, icu->bezt);
2908 }
2909
2910 void select_ipo_bezier_keys(Ipo *ipo, int selectmode)
2911 {
2912   /* Select all of the beziers in all
2913    * of the Ipo curves belonging to the
2914    * Ipo, using the selection mode.
2915    */
2916   switch (selectmode) {
2917   case SELECT_ADD:
2918     ipo_keys_bezier_loop(ipo, select_bezier_add, NULL);
2919     break;
2920   case SELECT_SUBTRACT:
2921     ipo_keys_bezier_loop(ipo, select_bezier_subtract, NULL);
2922     break;
2923   case SELECT_INVERT:
2924     ipo_keys_bezier_loop(ipo, select_bezier_invert, NULL);
2925     break;
2926   }
2927 }
2928
2929 void sethandles_ipo_keys(Ipo *ipo, int code)
2930 {
2931         /* this function lets you set bezier handles all to
2932          * one type for some Ipo's (e.g. with hotkeys through
2933          * the action window).
2934          */ 
2935
2936         /* code==1: set autohandle */
2937         /* code==2: set vectorhandle */
2938         /* als code==3 (HD_ALIGN) toggelt het, vectorhandles worden HD_FREE */
2939         
2940         switch(code) {
2941         case 1:
2942                 /*** Set to auto ***/
2943                 ipo_keys_bezier_loop(ipo, set_bezier_auto,
2944                                                          calchandles_ipocurve);
2945                 break;
2946         case 2:
2947                 /*** Set to vector ***/
2948                 ipo_keys_bezier_loop(ipo, set_bezier_vector,
2949                          calchandles_ipocurve);
2950                 break;
2951         default:
2952                 if ( ipo_keys_bezier_loop(ipo, bezier_isfree, NULL) ) {
2953                         /*** Set to free ***/
2954                         ipo_keys_bezier_loop(ipo, set_bezier_free,
2955                            calchandles_ipocurve);
2956                 }
2957                 else {
2958                         /*** Set to align ***/
2959                         ipo_keys_bezier_loop(ipo, set_bezier_align,
2960                            calchandles_ipocurve);
2961                 }
2962                 break;
2963         }
2964
2965
2966 }
2967
2968 void sethandles_ipo(int code)
2969 {
2970         /* this function lets you set bezier handles all to
2971          * one type for some selected keys in edit mode in the
2972          * IPO window (e.g. with hotkeys)
2973          */ 
2974
2975         /* code==1: set autohandle */
2976         /* code==2: set vectorhandle */
2977         /* als code==3 (HD_ALIGN) toggelt het, vectorhandles worden HD_FREE */
2978
2979         if(G.sipo->ipo && G.sipo->ipo->id.lib) return;
2980
2981         switch(code) {
2982         case 1:
2983                 /*** Set to auto ***/
2984                 selected_bezier_loop(vis_edit_icu_bez, set_bezier_auto,
2985                          calchandles_ipocurve);
2986                 break;
2987         case 2:
2988                 /*** Set to vector ***/
2989                 selected_bezier_loop(vis_edit_icu_bez, set_bezier_vector,
2990                          calchandles_ipocurve);
2991                 break;
2992         default:
2993                 if (selected_bezier_loop(vis_edit_icu_bez, bezier_isfree, NULL) ) {
2994                         /*** Set to free ***/
2995                         selected_bezier_loop(vis_edit_icu_bez, set_bezier_free,
2996                                                                  calchandles_ipocurve);
2997                 }
2998                 else {
2999                         /*** Set to align ***/
3000                         selected_bezier_loop(vis_edit_icu_bez, set_bezier_align,
3001                                                                  calchandles_ipocurve);
3002                 }
3003                 break;
3004         }
3005
3006         editipo_changed(G.sipo, 1);
3007 }
3008
3009
3010 void set_ipocurve_constant(struct IpoCurve *icu) {
3011         /* Sets the type of the IPO curve to constant
3012          */
3013         icu->ipo= IPO_CONST;
3014 }
3015
3016 void set_ipocurve_linear(struct IpoCurve *icu) {
3017         /* Sets the type of the IPO curve to linear
3018          */
3019         icu->ipo= IPO_LIN;
3020 }
3021
3022 void set_ipocurve_bezier(struct IpoCurve *icu) {
3023         /* Sets the type of the IPO curve to bezier
3024          */
3025         icu->ipo= IPO_BEZ;
3026 }
3027
3028
3029 void setipotype_ipo(Ipo *ipo, int code)
3030 {
3031         /* Sets the type of the each ipo curve in the
3032          * Ipo to a value based on the code
3033          */
3034         switch (code) {
3035         case 1:
3036                 ipo_keys_bezier_loop(ipo, NULL, set_ipocurve_constant);
3037                 break;
3038         case 2:
3039                 ipo_keys_bezier_loop(ipo, NULL, set_ipocurve_linear);
3040                 break;
3041         case 3:
3042                 ipo_keys_bezier_loop(ipo, NULL, set_ipocurve_bezier);
3043                 break;
3044         }
3045 }
3046
3047 void set_ipotype()
3048 {
3049         EditIpo *ei;
3050         Key *key;
3051         KeyBlock *kb;
3052         int a;
3053         short event;
3054
3055         if(G.sipo->ipo && G.sipo->ipo->id.lib) return;
3056         if(G.sipo->showkey) return;
3057         get_status_editipo();
3058         
3059         if(G.sipo->blocktype==ID_KE && totipo_edit==0 && totipo_sel==0) {
3060                 key= (Key *)G.sipo->from;
3061                 if(key==0) return;
3062                 
3063                 event= pupmenu("Key Type %t|Linear %x1|Cardinal %x2|B spline %x3");
3064                 if(event < 1) return;
3065                 
3066                 kb= key->block.first;
3067                 while(kb) {
3068                         if(kb->flag & SELECT) {
3069                                 kb->type= 0;
3070                                 if(event==1) kb->type= KEY_LINEAR;
3071                                 if(event==2) kb->type= KEY_CARDINAL;
3072                                 if(event==3) kb->type= KEY_BSPLINE;
3073                         }
3074                         kb= kb->next;
3075                 }
3076         }
3077         else {
3078                 event= pupmenu("Ipo Type %t|Constant %x1|Linear %x2|Bezier %x3");
3079                 if(event < 1) return;
3080                 
3081                 ei= G.sipo->editipo;
3082                 for(a=0; a<G.sipo->totipo; a++, ei++) {
3083                         if ISPOIN3(ei, flag & IPO_VISIBLE, flag & IPO_SELECT, icu) {
3084                                 if(event==1) ei->icu->ipo= IPO_CONST;
3085                                 else if(event==2) ei->icu->ipo= IPO_LIN;
3086                                 else ei->icu->ipo= IPO_BEZ;
3087                         }
3088                 }
3089         }
3090         scrarea_queue_winredraw(curarea);
3091 }
3092
3093 void borderselect_ipo()
3094 {
3095         EditIpo *ei;
3096         IpoKey *ik;
3097         BezTriple *bezt;
3098         rcti rect;
3099         rctf rectf;
3100         int a, b, val;
3101         short mval[2];
3102
3103         get_status_editipo();
3104         
3105         val= get_border(&rect, 3);
3106
3107         if(val) {
3108                 mval[0]= rect.xmin;
3109                 mval[1]= rect.ymin;
3110                 areamouseco_to_ipoco(G.v2d, mval, &rectf.xmin, &rectf.ymin);
3111                 mval[0]= rect.xmax;
3112                 mval[1]= rect.ymax;
3113                 areamouseco_to_ipoco(G.v2d, mval, &rectf.xmax, &rectf.ymax);
3114
3115                 if(G.sipo->showkey) {
3116                         ik= G.sipo->ipokey.first;
3117                         while(ik) {
3118                                 if(rectf.xmin<ik->val && rectf.xmax>ik->val) {
3119                                         if(val==LEFTMOUSE) ik->flag |= 1;
3120                                         else ik->flag &= ~1;
3121                                 }
3122                                 ik= ik->next;
3123                         }
3124                         update_editipo_flags();
3125                 }
3126                 else if(totipo_edit==0) {
3127                         if(rect.xmin<rect.xmax && rect.ymin<rect.ymax)
3128                                 select_proj_ipo(&rectf, val);
3129                 }
3130                 else {
3131                         
3132                         ei= G.sipo->editipo;
3133                         for(a=0; a<G.sipo->totipo; a++, ei++) {
3134                                 if ISPOIN3(ei, flag & IPO_VISIBLE, flag & IPO_EDIT, icu) {
3135                                         if(ei->icu->bezt) {
3136                                                 b= ei->icu->totvert;
3137                                                 bezt= ei->icu->bezt;
3138                                                 while(b--) {
3139                                                         int bit= (val==LEFTMOUSE);
3140                                                         
3141                                                         if(BLI_in_rctf(&rectf, bezt->vec[0][0], bezt->vec[0][1]))
3142                                                                 bezt->f1 = (bezt->f1&~1) | bit;
3143                                                         if(BLI_in_rctf(&rectf, bezt->vec[1][0], bezt->vec[1][1]))
3144                                                                 bezt->f2 = (bezt->f2&~1) | bit;
3145                                                         if(BLI_in_rctf(&rectf, bezt->vec[2][0], bezt->vec[2][1]))
3146                                                                 bezt->f3 = (bezt->f3&~1) | bit;
3147
3148                                                         bezt++;
3149                                                 }
3150                                         }
3151                                 }
3152                         }
3153                 }
3154                 scrarea_queue_winredraw(curarea);
3155         }
3156 }
3157
3158
3159
3160
3161 void del_ipo()
3162 {
3163         EditIpo *ei;
3164         BezTriple *bezt, *bezt1;
3165         int a, b;
3166         int del, event;
3167
3168         get_status_editipo();
3169         if(G.sipo->ipo && G.sipo->ipo->id.lib) return;
3170         
3171         if(totipo_edit==0 && totipo_sel==0 && totipo_vertsel==0) {
3172                 delete_key();
3173                 return;
3174         }
3175         
3176         if( okee("Erase selected")==0 ) return;
3177
3178         // eerste doorloop, kunnen hele stukken weg? 
3179         ei= G.sipo->editipo;
3180         for(a=0; a<G.sipo->totipo; a++, ei++) {
3181         
3182                 del= 0;