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