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