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