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