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