07f076d8965d5ae6d79ae6655dd0c5717dc9dad9
[blender.git] / source / blender / src / editipo.c
1 /**
2  * $Id$
3  *
4  * ***** BEGIN GPL 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.
10  *
11  * This program is distributed in the hope that it will be useful,
12  * but WITHOUT ANY WARRANTY; without even the implied warranty of
13  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14  * GNU General Public License for more details.
15  *
16  * You should have received a copy of the GNU General Public License
17  * along with this program; if not, write to the Free Software Foundation,
18  * Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
19  *
20  * The Original Code is Copyright (C) 2001-2002 by NaN Holding BV.
21  * All rights reserved.
22  *
23  * Contributor(s): Blender Foundation, 2005. Full recode.
24  * Roland Hess, 2007. Visual Key refactor.
25  *
26  * ***** END GPL LICENSE BLOCK *****
27  */
28
29
30 /* this code feels over-complex, mostly because I choose in the past to devise a system
31   that converts the Ipo blocks (linked to Object, Material, etc), into a copy of that
32   data which is being worked on;  the 'editipo'.
33   The editipo then can have 'ipokey' data, which is optimized for editing curves as if
34   it were key positions. This is still a great feature to work with, which makes ipo editing
35   in Blender still valuable. However, getting this beast under control was hard, even
36   for me... (ton) */
37
38 #include <stdlib.h>
39 #include <string.h>
40 #include <math.h>
41
42 #ifndef WIN32
43 #include <unistd.h>
44 #else
45 #include <io.h>
46 #endif   
47 #include "MEM_guardedalloc.h"
48 #include "PIL_time.h"
49
50 #include "BLI_blenlib.h"
51 #include "BLI_arithb.h"
52
53 #include "DNA_constraint_types.h"
54 #include "DNA_action_types.h"
55 #include "DNA_armature_types.h"
56 #include "DNA_camera_types.h"
57 #include "DNA_curve_types.h"
58 #include "DNA_group_types.h"
59 #include "DNA_ipo_types.h"
60 #include "DNA_key_types.h"
61 #include "DNA_lamp_types.h"
62 #include "DNA_material_types.h"
63 #include "DNA_object_types.h"
64 #include "DNA_object_fluidsim.h"
65 #include "DNA_screen_types.h"
66 #include "DNA_scene_types.h"
67 #include "DNA_space_types.h"
68 #include "DNA_sequence_types.h"
69 #include "DNA_sound_types.h"
70 #include "DNA_texture_types.h"
71 #include "DNA_userdef_types.h"
72 #include "DNA_view3d_types.h"
73 #include "DNA_world_types.h"
74
75 #include "BKE_action.h"
76 #include "BKE_armature.h"
77 #include "BKE_anim.h"
78 #include "BKE_constraint.h"
79 #include "BKE_depsgraph.h"
80 #include "BKE_global.h"
81 #include "BKE_group.h"
82 #include "BKE_ipo.h"
83 #include "BKE_key.h"
84 #include "BKE_material.h"
85 #include "BKE_texture.h"
86 #include "BKE_utildefines.h"
87
88 #include "BIF_butspace.h"
89 #include "BIF_editaction.h"
90 #include "BIF_editconstraint.h"
91 #include "BIF_editkey.h"
92 #include "BIF_editnla.h"
93 #include "BIF_editseq.h"
94 #include "BIF_editview.h"
95 #include "BIF_interface.h"
96 #include "BIF_mywindow.h"
97 #include "BIF_poseobject.h"
98 #include "BIF_screen.h"
99 #include "BIF_space.h"
100 #include "BIF_toolbox.h"
101 #include "BIF_poseobject.h"
102
103 #include "BDR_drawobject.h"
104 #include "BDR_editobject.h"
105 #include "BDR_editcurve.h"      // for bezt_compare 
106
107 #include "BSE_trans_types.h"
108 #include "BSE_editipo_types.h"
109 #include "BSE_drawipo.h"
110 #include "BSE_editipo.h"
111 #include "BSE_edit.h"
112 #include "BSE_drawview.h"
113 #include "BSE_headerbuttons.h"
114 #include "BSE_node.h"
115 #include "BSE_sequence.h"
116 #include "BSE_time.h"
117
118 #include "blendef.h"
119 #include "mydevice.h"
120
121 extern int ob_ar[];
122 extern int ma_ar[];
123 extern int seq_ar[];
124 extern int cu_ar[];
125 extern int wo_ar[];
126 extern int la_ar[];
127 extern int cam_ar[];
128 extern int snd_ar[];
129 extern int ac_ar[];
130 extern int co_ar[];
131 extern int te_ar[];
132 extern int fluidsim_ar[]; // NT
133
134 /* forwards */
135 #define IPOTHRESH       0.9
136
137 /* tests if only one editipo is active */
138 static void check_active_editipo(void)
139 {
140         EditIpo *ei, *actei;
141         int a;
142         
143         actei= G.sipo->editipo;
144         if(actei) {
145                 for(a=0; a<G.sipo->totipo; a++, actei++) {
146                         if(actei->flag & IPO_ACTIVE) 
147                                 break;
148                 }
149                 if(actei==NULL) {
150                         /* set visible active */
151                         for(a=0, ei=G.sipo->editipo; a<G.sipo->totipo; a++, ei++) {
152                                 if(ei->flag & IPO_VISIBLE)
153                                         break;
154                         }
155                         if(ei==NULL) ei=G.sipo->editipo;
156                         ei->flag |= IPO_ACTIVE;
157                         if(ei->icu) ei->icu->flag |= IPO_ACTIVE;
158                 }
159                 else {
160                         /* make sure no others are active */
161                         for(a=0, ei=G.sipo->editipo; a<G.sipo->totipo; a++, ei++) {
162                                 if(ei!=actei) {
163                                         ei->flag &= ~IPO_ACTIVE;
164                                         if(ei->icu) ei->icu->flag &= ~IPO_ACTIVE;
165                                 }
166                         }
167                 }
168         }
169 }
170
171 /* sets this ei channel active */
172 static void set_active_editipo(EditIpo *actei)
173 {
174         EditIpo *ei;
175         int a;
176         
177         for(a=0, ei=G.sipo->editipo; a<G.sipo->totipo; a++, ei++) {
178                 ei->flag &= ~IPO_ACTIVE;
179                 if(ei->icu) ei->icu->flag &= ~IPO_ACTIVE;
180         }
181         actei->flag |= IPO_ACTIVE;
182         if(actei->icu) actei->icu->flag |= IPO_ACTIVE;
183 }
184
185 EditIpo *get_active_editipo(void)
186 {
187         EditIpo *ei;
188         int a;
189         
190         if(G.sipo==NULL)
191                 return NULL;
192         
193         /* prevent confusing situations, like for sequencer */
194         if(G.sipo->totipo==1) {
195                 ei= G.sipo->editipo;
196                 ei->flag |= IPO_ACTIVE;
197                 return ei;
198         }
199         for(a=0, ei=G.sipo->editipo; a<G.sipo->totipo; a++, ei++)
200                 if(ei->flag & IPO_ACTIVE)
201                         return ei;
202         
203         return NULL;
204 }
205
206 static void set_active_key(int index)
207 {
208         if(G.sipo->blocktype==ID_KE && G.sipo->from) {
209                 Object *ob= (Object *)G.sipo->from;
210                 Key *key= ob_get_key(ob);
211                 
212                 if(key) {
213                         KeyBlock *curkb;
214                         
215                         curkb= BLI_findlink(&key->block, index-1);
216                         if(curkb) {
217                                 ob->shapenr= index;
218                                 ob->shapeflag |= OB_SHAPE_TEMPLOCK;
219                                 
220                                 /* calc keypos */
221                                 DAG_object_flush_update(G.scene, ob, OB_RECALC_DATA);
222                                 allqueue(REDRAWVIEW3D, 0);
223                                 allqueue(REDRAWBUTSEDIT, 0);
224                         }
225                 }
226         }                       
227 }
228
229 void editipo_changed(SpaceIpo *si, int doredraw)
230 {
231         EditIpo *ei;
232         View2D *v2d;
233         Key *key;
234         KeyBlock *kb;
235         int a, first=1;
236
237         ei= si->editipo;
238         if(ei==0)
239                 return;
240         
241         for(a=0; a<si->totipo; a++, ei++) {
242                 
243                 if(ei->icu) {
244                         
245                                 /* twice because of ittererating new autohandle */
246                         calchandles_ipocurve(ei->icu);
247                         calchandles_ipocurve(ei->icu);
248                         
249                         if(ei->flag & IPO_VISIBLE) {
250                 
251                                 boundbox_ipocurve(ei->icu, 0);
252                                 sort_time_ipocurve(ei->icu);
253                                 if(first) {
254                                         si->v2d.tot= ei->icu->totrct;
255                                         first= 0;
256                                 }
257                                 else BLI_union_rctf(&(si->v2d.tot), &(ei->icu->totrct));
258                         }
259                 }
260         }
261         
262
263         v2d= &(si->v2d);        
264
265         /* keylines? */
266         if(si->blocktype==ID_KE) {
267                 key= ob_get_key((Object *)G.sipo->from);
268                 if(key && key->block.first) {
269                         kb= key->block.first;
270                         if(kb->pos < v2d->tot.ymin) v2d->tot.ymin= kb->pos;
271                         kb= key->block.last;
272                         if(kb->pos > v2d->tot.ymax) v2d->tot.ymax= kb->pos;
273                 }
274         }
275         
276         /* is there no curve? */
277         if(first) {
278                 v2d->tot.xmin= 0.0;
279                 v2d->tot.xmax= EFRA;
280                 v2d->tot.ymin= (float)-0.1;
281                 v2d->tot.ymax= (float)1.1;
282         
283                 if(si->blocktype==ID_SEQ) {
284                         v2d->tot.xmin= -5.0;
285                         v2d->tot.xmax= 105.0;
286                         v2d->tot.ymin= (float)-0.1;
287                         v2d->tot.ymax= (float)1.1;
288                 }
289         }
290         
291         si->tot= v2d->tot;      
292         
293         if(doredraw) {
294                 /* if you always call do_ipo: you get problems with insertkey, for example
295                  * when inserting only a 'loc' the 'ob->rot' value then is changed.
296                  */
297
298                 if(si->blocktype==ID_OB) {                      
299                                 /* clear delta loc,rot,size (when free/delete ipo) */
300                         clear_delta_obipo(si->ipo);
301                         
302                 }
303         
304                 do_ipo(si->ipo);
305
306                 allqueue(REDRAWIPO, 0);
307                 allqueue(REDRAWACTION, 0);
308                 allqueue(REDRAWTIME, 0);
309                 allqueue(REDRAWNLA, 0);
310                 allqueue(REDRAWBUTSOBJECT, 0);
311                 
312                 if(si->blocktype==ID_OB) {
313                         Object *ob= (Object *)si->from;                 
314                         if(ob) DAG_object_flush_update(G.scene, ob, OB_RECALC_OB);
315                         allqueue(REDRAWVIEW3D, 0);
316                         allqueue(REDRAWNLA, 0);
317                 }
318
319                 else if(si->blocktype==ID_MA) allqueue(REDRAWBUTSSHADING, 0);
320                 else if(si->blocktype==ID_TE) allqueue(REDRAWBUTSSHADING, 0);
321                 else if(si->blocktype==ID_WO) allqueue(REDRAWBUTSSHADING, 0);
322                 else if(si->blocktype==ID_LA) allqueue(REDRAWBUTSSHADING, 0);
323 //              else if(si->blocktype==ID_SO) allqueue(REDRAWBUTSSOUND, 0);
324                 else if(si->blocktype==ID_CA) {
325                         allqueue(REDRAWBUTSEDIT, 0);
326                         allqueue(REDRAWVIEW3D, 0);
327                 }
328                 else if(si->blocktype==ID_SEQ) free_imbuf_seq_with_ipo(si->ipo);
329                 else if(si->blocktype==ID_PO) {
330                         Object *ob= OBACT;
331                         if(ob && ob->pose) {
332                                 DAG_object_flush_update(G.scene, OBACT, OB_RECALC_DATA);
333                         }
334                         allqueue(REDRAWVIEW3D, 0);
335                         allqueue(REDRAWACTION, 0);
336                         allqueue(REDRAWNLA, 0);
337                 }
338                 else if(si->blocktype==ID_KE) {
339                         DAG_object_flush_update(G.scene, OBACT, OB_RECALC_DATA);
340                         allqueue(REDRAWVIEW3D, 0);
341                 }
342                 else if(si->blocktype==ID_CU) {
343                         DAG_object_flush_update(G.scene, OBACT, OB_RECALC_DATA);
344                         allqueue(REDRAWVIEW3D, 0);
345                 }
346         }
347
348         if(si->showkey) make_ipokey();
349         
350         if(si->actname[0])
351                 synchronize_action_strips();
352 }
353
354 void scale_editipo(void)
355 {
356         /* comes from buttons, scale with G.sipo->tot rect */
357         
358         EditIpo *ei;
359         BezTriple *bezt;
360         float facx, facy;
361         int a, b;       
362         
363         facx= (G.sipo->tot.xmax-G.sipo->tot.xmin)/(G.sipo->v2d.tot.xmax-G.sipo->v2d.tot.xmin);
364         facy= (G.sipo->tot.ymax-G.sipo->tot.ymin)/(G.sipo->v2d.tot.ymax-G.sipo->v2d.tot.ymin);
365
366         ei= G.sipo->editipo;
367         if(ei==0) return;
368         for(a=0; a<G.sipo->totipo; a++, ei++) {
369                 if (ISPOIN(ei, flag & IPO_VISIBLE, icu)) {
370                         bezt= ei->icu->bezt;
371                         b= ei->icu->totvert;
372                         while(b--) {
373                                 
374                                 bezt->vec[0][0]= facx*(bezt->vec[0][0] - G.sipo->v2d.tot.xmin) + G.sipo->tot.xmin;
375                                 bezt->vec[1][0]= facx*(bezt->vec[1][0] - G.sipo->v2d.tot.xmin) + G.sipo->tot.xmin;
376                                 bezt->vec[2][0]= facx*(bezt->vec[2][0] - G.sipo->v2d.tot.xmin) + G.sipo->tot.xmin;
377                         
378                                 bezt->vec[0][1]= facy*(bezt->vec[0][1] - G.sipo->v2d.tot.ymin) + G.sipo->tot.ymin;
379                                 bezt->vec[1][1]= facy*(bezt->vec[1][1] - G.sipo->v2d.tot.ymin) + G.sipo->tot.ymin;
380                                 bezt->vec[2][1]= facy*(bezt->vec[2][1] - G.sipo->v2d.tot.ymin) + G.sipo->tot.ymin;
381
382                                 bezt++;
383                         }
384                 }
385         }
386
387         editipo_changed(G.sipo, 1);
388
389         BIF_undo_push("Scale Edit Ipo");
390         allqueue(REDRAWNLA, 0);
391         allqueue (REDRAWACTION, 0);
392         allqueue(REDRAWIPO, 0);
393 }
394
395 static void make_ob_editipo(Object *ob, SpaceIpo *si)
396 {
397         EditIpo *ei;
398         int a, len, colipo=0;
399         char *name;
400         
401         if(ob->type==OB_MESH) colipo= 1;
402
403         ei= si->editipo= MEM_callocN(OB_TOTIPO*sizeof(EditIpo), "editipo");
404         
405         si->totipo= OB_TOTIPO;
406         
407         for(a=0; a<OB_TOTIPO; a++) {
408                 name = getname_ob_ei(ob_ar[a], colipo);
409                 strcpy(ei->name, name);
410                 ei->adrcode= ob_ar[a];
411                 
412                 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;
413                 else if(ei->adrcode==OB_LAY) ei->disptype= IPO_DISPBITS;
414                 else if(ei->adrcode==OB_TIME) ei->disptype= IPO_DISPTIME;
415
416                 ei->col= ipo_rainbow(a, OB_TOTIPO);
417
418                 if(colipo) {
419                         len= strlen(ei->name);
420                         if(len) {
421                                 if( ei->name[ len-1 ]=='R') ei->col= 0x5050FF;
422                                 else if( ei->name[ len-1 ]=='G') ei->col= 0x50FF50;
423                                 else if( ei->name[ len-1 ]=='B') ei->col= 0xFF7050;
424                         }
425                 }
426                 
427                 ei->icu= find_ipocurve(si->ipo, ei->adrcode);
428                 if(ei->icu) {
429                         ei->flag= ei->icu->flag;
430                 }
431                 
432                 
433                 ei++;
434         }
435         //fprintf(stderr,"FSIMAKE_OPBJ call %d \n", si->totipo);
436 }
437
438 // copied from make_seq_editipo
439 static void make_fluidsim_editipo(SpaceIpo *si) // NT
440 {
441         EditIpo *ei;
442         int a;
443         char *name;
444         ei= si->editipo= MEM_callocN(FLUIDSIM_TOTIPO*sizeof(EditIpo), "fluidsim_editipo");
445         si->totipo = FLUIDSIM_TOTIPO;
446         for(a=0; a<FLUIDSIM_TOTIPO; a++) {
447                 //fprintf(stderr,"FSINAME %d %d \n",a,fluidsim_ar[a], (int)(getname_fluidsim_ei(fluidsim_ar[a]))  );
448                 name = getname_fluidsim_ei(fluidsim_ar[a]);
449                 strcpy(ei->name, name);
450                 ei->adrcode= fluidsim_ar[a];
451                 ei->col= ipo_rainbow(a, FLUIDSIM_TOTIPO);
452                 ei->icu= find_ipocurve(si->ipo, ei->adrcode);
453                 if(ei->icu) {
454                         ei->flag = ei->icu->flag;
455                 } 
456                 //else { ei->flag |= IPO_VISIBLE; }
457                 //fprintf(stderr,"FSIMAKE eif%d,icuf%d icu%d %d|%d\n", ei->flag,ei->icu->flag, (int)ei->icu, IPO_VISIBLE,IPO_SELECT);
458                 //fprintf(stderr,"FSIMAKE eif%d icu%d %d|%d\n", ei->flag, (int)ei->icu, IPO_VISIBLE,IPO_SELECT);
459                 ei++;
460         }
461 }
462
463 static void make_seq_editipo(SpaceIpo *si)
464 {
465         EditIpo *ei;
466         int a;
467         char *name;
468         
469         ei= si->editipo= MEM_callocN(SEQ_TOTIPO*sizeof(EditIpo), "editipo");
470         
471         si->totipo= SEQ_TOTIPO;
472         
473         
474         for(a=0; a<SEQ_TOTIPO; a++) {
475                 name = getname_seq_ei(seq_ar[a]);
476                 strcpy(ei->name, name);
477                 ei->adrcode= seq_ar[a];
478                 
479                 ei->col= ipo_rainbow(a, SEQ_TOTIPO);
480                 
481                 ei->icu= find_ipocurve(si->ipo, ei->adrcode);
482                 if(ei->icu) {
483                         ei->flag= ei->icu->flag;
484                 }
485                 else ei->flag |= IPO_VISIBLE;
486                 
487                 ei++;
488         }
489 }
490
491 static void make_cu_editipo(SpaceIpo *si)
492 {
493         EditIpo *ei;
494         int a;
495         char *name;
496         
497         ei= si->editipo= MEM_callocN(CU_TOTIPO*sizeof(EditIpo), "editipo");
498         
499         si->totipo= CU_TOTIPO;
500         
501         
502         for(a=0; a<CU_TOTIPO; a++) {
503                 name = getname_cu_ei(cu_ar[a]);
504                 strcpy(ei->name, name);
505                 ei->adrcode= cu_ar[a];
506                 
507                 ei->col= ipo_rainbow(a, CU_TOTIPO);
508                 
509                 ei->icu= find_ipocurve(si->ipo, ei->adrcode);
510                 if(ei->icu) {
511                         ei->flag= ei->icu->flag;
512                 }
513                 else ei->flag |= IPO_VISIBLE;
514                  
515                 ei++;
516         }
517 }
518
519 static void make_key_editipo(SpaceIpo *si)
520 {
521         Key *key;
522         KeyBlock *kb=NULL;
523         EditIpo *ei;
524         int a;
525         
526         key= ob_get_key((Object *)G.sipo->from);
527         if(key==NULL) return;
528         
529         si->totipo= BLI_countlist(&key->block);
530         ei= si->editipo= MEM_callocN(si->totipo*sizeof(EditIpo), "editipo");
531         
532         for(a=0, kb= key->block.first; a<si->totipo; a++, ei++, kb= kb->next) {
533                 
534                 if(kb->name[0] != 0) strncpy(ei->name, kb->name, 31);   // length both same
535                 ei->adrcode= kb->adrcode;
536                 
537                 ei->col= ipo_rainbow(a, KEY_TOTIPO);
538                 
539                 ei->icu= find_ipocurve(si->ipo, ei->adrcode);
540                 if(ei->icu) {
541                         ei->flag= ei->icu->flag;
542                 }
543                 else if(a==0) 
544                         if(key && key->type==KEY_NORMAL)
545                                 ei->flag |= IPO_VISIBLE;
546                 
547                 /* active ipo is tied to active shape  */
548                 {
549                         Object *ob= OBACT;
550                         if(a==ob->shapenr-1)
551                                 set_active_editipo(ei);
552                 }
553         }
554         
555         ei= si->editipo;
556         if(key && key->type==KEY_RELATIVE) {
557                 strcpy(ei->name, "----");
558         }
559         else {
560                 ei->flag |= IPO_VISIBLE;
561         }
562 }
563
564 static void make_mat_editipo(SpaceIpo *si)
565 {
566         EditIpo *ei;
567         int a, len;
568         char *name;
569         
570         if(si->from==0) return;
571         
572         ei= si->editipo= MEM_callocN(MA_TOTIPO*sizeof(EditIpo), "editipo");
573         
574         si->totipo= MA_TOTIPO;
575         
576         for(a=0; a<MA_TOTIPO; a++) {
577                 name = getname_mat_ei(ma_ar[a]);
578                 strcpy(ei->name, name);
579                 ei->adrcode= ma_ar[a];
580                 
581                 if(ei->adrcode & MA_MAP1) {
582                         ei->adrcode-= MA_MAP1;
583                         ei->adrcode |= texchannel_to_adrcode(si->channel);
584                 }
585                 else {
586                         if(ei->adrcode==MA_MODE) ei->disptype= IPO_DISPBITS;
587                 }
588                 
589                 ei->col= ipo_rainbow(a, MA_TOTIPO);
590                 
591                 len= strlen(ei->name);
592                 if(len) {
593                         if( ei->name[ len-1 ]=='R') ei->col= 0x5050FF;
594                         else if( ei->name[ len-1 ]=='G') ei->col= 0x50FF50;
595                         else if( ei->name[ len-1 ]=='B') ei->col= 0xFF7050;
596                 }
597                 
598                 ei->icu= find_ipocurve(si->ipo, ei->adrcode);
599                 if(ei->icu) {
600                         ei->flag= ei->icu->flag;
601                 }
602                 
603                 ei++;
604         }
605 }
606
607 static void make_texture_editipo(SpaceIpo *si)
608 {
609         EditIpo *ei;
610         int a, len;
611         char *name;
612         
613         if(si->from==0) return;    
614         
615         ei= si->editipo= MEM_callocN(TE_TOTIPO*sizeof(EditIpo), "editipo");
616         
617         si->totipo= TE_TOTIPO;
618         
619         for(a=0; a<TE_TOTIPO; a++) {
620                 name = getname_tex_ei(te_ar[a]);
621                 strcpy(ei->name, name);
622                         ei->adrcode= te_ar[a];
623
624                 ei->col= ipo_rainbow(a, TE_TOTIPO);
625         
626                 len= strlen(ei->name);
627                 if(len) {
628                         if( ei->name[ len-1 ]=='R') ei->col= 0x5050FF;
629                         else if( ei->name[ len-1 ]=='G') ei->col= 0x50FF50;
630                         else if( ei->name[ len-1 ]=='B') ei->col= 0xFF7050;
631                 }       
632                 ei->icu= find_ipocurve(si->ipo, ei->adrcode);
633                 if(ei->icu) {
634                         ei->flag= ei->icu->flag;
635                 }
636                 
637                 ei++;
638         }
639 }
640
641 static void make_world_editipo(SpaceIpo *si)
642 {
643         EditIpo *ei;
644         int a, len;
645         char *name;
646         
647         if(si->from==0) return;
648         
649         ei= si->editipo= MEM_callocN(WO_TOTIPO*sizeof(EditIpo), "editipo");
650         
651         si->totipo= WO_TOTIPO;
652         
653         for(a=0; a<WO_TOTIPO; a++) {
654                 name = getname_world_ei(wo_ar[a]);
655                 
656                 strcpy(ei->name, name); 
657                 ei->adrcode= wo_ar[a];
658                 
659                 if(ei->adrcode & MA_MAP1) {
660                         ei->adrcode-= MA_MAP1;
661                         ei->adrcode |= texchannel_to_adrcode(si->channel);
662                 }
663                 else {
664                         if(ei->adrcode==MA_MODE) ei->disptype= IPO_DISPBITS;
665                 }
666                 
667                 ei->col= ipo_rainbow(a, WO_TOTIPO);
668                 
669                 len= strlen(ei->name);
670                 if(len) {
671                         if( ei->name[ len-1 ]=='R') ei->col= 0x5050FF;
672                         else if( ei->name[ len-1 ]=='G') ei->col= 0x50FF50;
673                         else if( ei->name[ len-1 ]=='B') ei->col= 0xFF7050;
674                 }
675                 
676                 ei->icu= find_ipocurve(si->ipo, ei->adrcode);
677                 if(ei->icu) {
678                         ei->flag= ei->icu->flag;
679                 }
680                 
681                 ei++;
682         }
683 }
684
685 static void make_lamp_editipo(SpaceIpo *si)
686 {
687         EditIpo *ei;
688         int a;
689         char *name;
690         
691         ei= si->editipo= MEM_callocN(LA_TOTIPO*sizeof(EditIpo), "editipo");
692         
693         si->totipo= LA_TOTIPO;
694         
695         for(a=0; a<LA_TOTIPO; a++) {
696                 name = getname_la_ei(la_ar[a]);
697                 strcpy(ei->name, name);
698                 ei->adrcode= la_ar[a];
699
700                 if(ei->adrcode & MA_MAP1) {
701                         ei->adrcode-= MA_MAP1;
702                         ei->adrcode |= texchannel_to_adrcode(si->channel);
703                 }
704
705                 ei->col= ipo_rainbow(a, LA_TOTIPO);
706                 
707                 ei->icu= find_ipocurve(si->ipo, ei->adrcode);
708                 if(ei->icu) {
709                         ei->flag= ei->icu->flag;
710                 }
711                 
712                 ei++;
713         }
714 }
715
716 static void make_camera_editipo(SpaceIpo *si)
717 {
718         EditIpo *ei;
719         int a;
720         char *name;
721         
722         ei= si->editipo= MEM_callocN(CAM_TOTIPO*sizeof(EditIpo), "editipo");
723         
724         si->totipo= CAM_TOTIPO;
725         
726         
727         for(a=0; a<CAM_TOTIPO; a++) {
728                 name = getname_cam_ei(cam_ar[a]);
729                 strcpy(ei->name, name);
730                 ei->adrcode= cam_ar[a];
731
732                 ei->col= ipo_rainbow(a, CAM_TOTIPO);
733                 
734                 ei->icu= find_ipocurve(si->ipo, ei->adrcode);
735                 if(ei->icu) {
736                         ei->flag= ei->icu->flag;
737                 }
738                 
739                 ei++;
740         }
741 }
742
743 static int make_constraint_editipo(Ipo *ipo, EditIpo **si)
744 {
745         EditIpo *ei;
746         int a;
747         char *name;
748         
749         ei= *si= MEM_callocN(CO_TOTIPO*sizeof(EditIpo), "editipo");
750         
751         for(a=0; a<CO_TOTIPO; a++) {
752                 name = getname_co_ei(co_ar[a]);
753                 strcpy(ei->name, name);
754                 ei->adrcode= co_ar[a];
755
756                 ei->col= ipo_rainbow(a, CO_TOTIPO);
757                 
758                 ei->icu= find_ipocurve(ipo, ei->adrcode);
759                 if(ei->icu) {
760                         ei->flag= ei->icu->flag;
761                 }
762                 
763                 ei++;
764         }
765
766         return CO_TOTIPO;
767 }
768
769 static int make_bone_editipo(Ipo *ipo, EditIpo **si)
770 {
771         EditIpo *ei;
772         int a;
773         char *name;
774         
775         ei= *si= MEM_callocN(AC_TOTIPO*sizeof(EditIpo), "editipo");
776         
777         for(a=0; a<AC_TOTIPO; a++) {
778                 name = getname_ac_ei(ac_ar[a]);
779                 strcpy(ei->name, name);
780                 ei->adrcode= ac_ar[a];
781
782                 ei->col= ipo_rainbow(a, AC_TOTIPO);
783                 
784                 ei->icu= find_ipocurve(ipo, ei->adrcode);
785                 if(ei->icu) {
786                         ei->flag= ei->icu->flag;
787                 }
788                 
789                 ei++;
790         }
791
792         return AC_TOTIPO;
793 }
794
795 static void make_sound_editipo(SpaceIpo *si)
796 {
797         EditIpo *ei;
798         int a;
799         char *name;
800         
801         ei= si->editipo= MEM_callocN(SND_TOTIPO*sizeof(EditIpo), "editipo");
802         
803         si->totipo= SND_TOTIPO;
804         
805         
806         for(a=0; a<SND_TOTIPO; a++) {
807                 name = getname_snd_ei(snd_ar[a]);
808                 strcpy(ei->name, name);
809                 ei->adrcode= snd_ar[a];
810
811                 ei->col= ipo_rainbow(a, SND_TOTIPO);
812                 
813                 ei->icu= find_ipocurve(si->ipo, ei->adrcode);
814                 if(ei->icu) {
815                         ei->flag= ei->icu->flag;
816                 }
817                 
818                 ei++;
819         }
820 }
821
822 /* only called in test_editipo() below */
823 static void make_editipo(void)
824 {
825         EditIpo *ei;
826         Object *ob;
827         rctf *rf;
828         int a;
829
830         if(G.sipo->editipo)
831                 MEM_freeN(G.sipo->editipo);
832         
833         G.sipo->editipo= NULL;
834         G.sipo->totipo= 0;
835         
836         if(G.sipo->from==NULL) return;
837         
838         ob= OBACT;
839
840         if(G.sipo->ipo) G.sipo->showkey= G.sipo->ipo->showkey;
841
842         if(G.sipo->blocktype==ID_SEQ) {
843                 make_seq_editipo(G.sipo);
844         }
845         else if(G.sipo->blocktype==ID_WO) {
846                 make_world_editipo(G.sipo);
847         } 
848         else if(G.sipo->blocktype==ID_OB) {
849                 if (ob) {
850                         ob->ipowin= ID_OB;
851                         make_ob_editipo(ob, G.sipo);
852                 }
853         }
854         else if(G.sipo->blocktype==ID_MA) {
855                 if (ob) {
856                         ob->ipowin= ID_MA;
857                         make_mat_editipo(G.sipo);
858                 }
859         }
860         else if(G.sipo->blocktype==ID_CU) {
861                 if (ob) {
862                         ob->ipowin= ID_CU;
863                         make_cu_editipo(G.sipo);
864                 }
865         }
866         else if(G.sipo->blocktype==ID_KE) {
867                 if (ob) {
868                         ob->ipowin= ID_KE;
869                         make_key_editipo(G.sipo);
870                 }
871         }
872         else if(G.sipo->blocktype==ID_LA) {
873                 if (ob) {
874                         ob->ipowin= ID_LA;
875                         make_lamp_editipo(G.sipo);
876                 }
877         }
878         else if(G.sipo->blocktype==ID_TE) {
879                 if (ob) {
880                         ob->ipowin= ID_TE;
881                         make_texture_editipo(G.sipo);
882                 }
883         }
884         else if(G.sipo->blocktype==ID_CA) {
885                 if (ob) {
886                         ob->ipowin= ID_CA;
887                         make_camera_editipo(G.sipo);
888                 }
889         }
890         else if(G.sipo->blocktype==ID_SO) {
891                 if (ob) {
892                         ob->ipowin= ID_SO;
893                         make_sound_editipo(G.sipo);
894                 }
895         }
896         else if(G.sipo->blocktype==ID_CO){
897                 G.sipo->totipo = make_constraint_editipo(G.sipo->ipo, (EditIpo**)&G.sipo->editipo);
898                 if (ob) {
899                         ob->ipowin= ID_CO;
900                 }
901         }
902         else if(G.sipo->blocktype==ID_PO) {
903
904                 G.sipo->totipo = make_bone_editipo(G.sipo->ipo, (EditIpo**)&G.sipo->editipo);
905                 if (ob) {
906                         ob->ipowin= ID_PO;
907                 }
908         }
909         else if(G.sipo->blocktype==ID_FLUIDSIM) {
910                 if (ob) { // NT
911                         ob->ipowin= ID_FLUIDSIM;
912                         make_fluidsim_editipo(G.sipo);
913                 }
914         }
915
916         if(G.sipo->editipo==0) return;
917         
918         ei= G.sipo->editipo;
919         for(a=0; a<G.sipo->totipo; a++, ei++) {
920                 if(ei->icu) ei->icu->flag= ei->flag;
921         }
922         editipo_changed(G.sipo, 0);
923         
924         /* sets globals, bad stuff but we need these variables in other parts of code */
925         get_status_editipo();
926         
927         if(G.sipo->ipo) {
928
929                 if (G.sipo->pin)
930                         rf= &(G.sipo->v2d.cur);
931                 else
932                         rf= &(G.sipo->ipo->cur);
933                 
934                 if(rf->xmin<rf->xmax && rf->ymin<rf->ymax) G.v2d->cur= *rf;
935                 else ipo_default_v2d_cur(G.sipo->blocktype, &G.v2d->cur);
936         }
937         else {
938                 ipo_default_v2d_cur(G.sipo->blocktype, &G.v2d->cur);
939         }
940         
941         view2d_do_locks(curarea, V2D_LOCK_COPY);
942 }
943
944 /* evaluates context in the current UI */
945 /* blocktype is type of ipo */
946 /* from is the base pointer to find data to change (ob in case of action or pose) */
947 static void get_ipo_context(short blocktype, ID **from, Ipo **ipo, char *actname, char *constname)
948 {
949         Object *ob= OBACT;
950         
951         *from= NULL;
952         *ipo= NULL;
953         
954         if(blocktype==ID_CO) {
955                 if (ob) {
956                         bConstraintChannel *chan;
957                         bConstraint *con= get_active_constraint(ob);
958                         
959                         if(con) {
960                                 BLI_strncpy(constname, con->name, 32);
961                                 
962                                 chan= get_active_constraint_channel(ob);
963                                 if(chan) {
964                                         *ipo= chan->ipo;
965                                         BLI_strncpy(constname, con->name, 32);
966                                 }
967                                 
968                                 *from= &ob->id;
969                                 
970                                 /* set actname if in posemode */
971                                 if(ob->action) {
972                                         if(ob->flag & OB_POSEMODE) {
973                                                 bPoseChannel *pchan= get_active_posechannel(ob);
974                                                 if(pchan)
975                                                         BLI_strncpy(actname, pchan->name, 32);
976                                         }
977                                         else if(ob->ipoflag & OB_ACTION_OB)
978                                                 strcpy(actname, "Object");
979                                 }
980                         }
981                 }
982         }
983         else if(blocktype==ID_PO) {
984                 if (ob && ob->action && ob->type==OB_ARMATURE) {
985                         bPoseChannel *pchan= get_active_posechannel(ob);
986                         
987                         *from= (ID *)ob;
988                         if (pchan) {
989                                 bActionChannel *achan;
990                                 
991                                 BLI_strncpy(actname, pchan->name, 32);  /* also set when no channel yet */
992                                 
993                                 achan= get_action_channel(ob->action, pchan->name);
994                                 if(achan)
995                                         *ipo= achan->ipo;
996                         }
997                 } 
998                 
999         }
1000         else if(blocktype==ID_OB) {
1001                 if(ob) {
1002                         *from= (ID *)ob;
1003                         if(ob->ipoflag & OB_ACTION_OB) {
1004                                 if (ob->action) {
1005                                         bActionChannel *achan= get_action_channel(ob->action, "Object");
1006                                         if(achan) {
1007                                                 *ipo= achan->ipo;
1008                                                 BLI_strncpy(actname, achan->name, 32);
1009                                         }
1010                                 }
1011                         }
1012                         else {
1013                                 *ipo= ob->ipo;
1014                         }
1015                 }
1016         }
1017         else if(blocktype==ID_SEQ) {
1018                 Sequence *last_seq = get_last_seq();
1019                 
1020                 if(last_seq && ((last_seq->type & SEQ_EFFECT)||(last_seq->type == SEQ_HD_SOUND)||(last_seq->type == SEQ_RAM_SOUND))) {
1021                         *from= (ID *)last_seq;
1022                         *ipo= last_seq->ipo;
1023                 }
1024         }
1025         else if(blocktype==ID_WO) {
1026                 World *wo= G.scene->world;
1027                 *from= (ID *)wo;
1028                 if(wo) *ipo= wo->ipo;
1029         }
1030         else if(blocktype==ID_TE) {
1031                 if(ob) {
1032                         Tex *tex= give_current_texture(ob, ob->actcol);
1033                         *from= (ID *)tex;
1034                         if(tex) *ipo= tex->ipo;
1035                 }
1036         }
1037         else if(blocktype==ID_MA) {
1038                 if(ob) {
1039                         Material *ma= give_current_material(ob, ob->actcol);
1040                         ma= editnode_get_active_material(ma);
1041                         *from= (ID *)ma;
1042                         if(ma) *ipo= ma->ipo;
1043                 }
1044         }
1045         else if(blocktype==ID_KE) {
1046                 if(ob) {
1047                         Key *key= ob_get_key(ob);
1048                         
1049                         if(ob->ipoflag & OB_ACTION_KEY) {
1050                                 if (ob->action) {
1051                                         bActionChannel *achan= get_action_channel(ob->action, "Shape");
1052                                         if(achan) {
1053                                                 *ipo= achan->ipo;
1054                                                 BLI_strncpy(actname, achan->name, 32);
1055                                         }
1056                                 }
1057                         }
1058                         else if(key) *ipo= key->ipo;
1059                         
1060                         *from= (ID *)ob;
1061                 }
1062         }
1063         else if(blocktype==ID_CU) {
1064                 if(ob && ob->type==OB_CURVE) {
1065                         Curve *cu= ob->data;
1066                         *from= (ID *)cu;
1067                         *ipo= cu->ipo;
1068                 }
1069         }
1070         else if(blocktype==ID_LA) {
1071                 if(ob && ob->type==OB_LAMP) {
1072                         Lamp *la= ob->data;
1073                         *from= (ID *)la;
1074                         *ipo= la->ipo;
1075                 }
1076         }
1077         else if(blocktype==ID_CA) {
1078                 if(ob && ob->type==OB_CAMERA) {
1079                         Camera *ca= ob->data;
1080                         *from= (ID *)ca;
1081                         if(ca) *ipo= ca->ipo;
1082                 }
1083         }
1084         else if(blocktype==ID_SO) {
1085                 
1086                 //              if (G.buts && G.buts->mainb == BUTS_SOUND) {
1087                 //                      bSound *sound = G.buts->lockpoin;
1088                 //                      *from= (ID *)sound;
1089                 //                      if(sound) *ipo= sound->ipo;
1090                 //              }
1091         }
1092         else if(blocktype==ID_FLUIDSIM) {
1093                 if(ob && ( ob->fluidsimFlag & OB_FLUIDSIM_ENABLE)) {
1094                         FluidsimSettings *fss= ob->fluidsimSettings;
1095                         *from= (ID *)ob;
1096                         if(fss) *ipo= fss->ipo;
1097                 }
1098         }
1099 }
1100
1101 /* called on each redraw, check if editipo data has to be remade */
1102 /* if doit already set, it always makes (in case no ipo exists, we need to see the channels */
1103 void test_editipo(int doit)
1104 {
1105         
1106         if(G.sipo->pin==0) {
1107                 Ipo *ipo;
1108                 ID *from;
1109                 char actname[32]="", constname[32]="";
1110                 
1111                 get_ipo_context(G.sipo->blocktype, &from, &ipo, actname, constname);
1112                 
1113                 if(G.sipo->ipo != ipo) {
1114                         G.sipo->ipo= ipo;
1115                         if(ipo) G.v2d->cur= ipo->cur;
1116                         doit= 1;
1117                 }
1118                 if(G.sipo->from != from) {
1119                         G.sipo->from= from;
1120                         doit= 1;
1121                 }
1122                 if( strcmp(G.sipo->actname, actname)) {
1123                         BLI_strncpy(G.sipo->actname, actname, 32);
1124                         doit= 1;
1125                 }
1126                 if( strcmp(G.sipo->constname, constname)) {
1127                         BLI_strncpy(G.sipo->constname, constname, 32);
1128                         doit= 1;
1129                 }
1130                 
1131                 if(G.sipo->ipo)
1132                         G.sipo->ipo->cur = G.v2d->cur;
1133                 
1134         }
1135                 
1136         if(G.sipo->editipo==NULL || doit) {
1137                 make_editipo();
1138         }
1139 }
1140
1141 /* ****************** EditIpo ************************ */
1142
1143 int totipo_edit=0, totipo_sel=0, totipo_curve=0, totipo_vis=0, totipo_vert=0, totipo_vertsel=0, totipo_key=0, totipo_keysel=0;
1144
1145 void get_status_editipo(void)
1146 {
1147         EditIpo *ei;
1148         IpoKey *ik;
1149         BezTriple *bezt;
1150         int a, b;
1151         
1152         totipo_vis= 0;
1153         totipo_curve= 0;
1154         totipo_sel= 0;
1155         totipo_edit= 0;
1156         totipo_vert= 0;
1157         totipo_vertsel= 0;
1158         totipo_key= 0;
1159         totipo_keysel= 0;
1160         
1161         if(G.sipo->ipo && G.sipo->ipo->id.lib) return;
1162         
1163         ei= G.sipo->editipo;
1164         if(ei==0) return;
1165         for(a=0; a<G.sipo->totipo; a++) {
1166                 if( ei->flag & IPO_VISIBLE ) {
1167                         totipo_vis++;
1168                         if(ei->flag & IPO_SELECT) totipo_sel++;
1169                         if(ei->icu && ei->icu->totvert) totipo_curve++;
1170                         if(G.sipo->showkey || (ei->flag & IPO_EDIT)) {
1171                                 
1172                                 /* if showkey: do count the vertices (for grab) */
1173                                 if(G.sipo->showkey==0) totipo_edit++;
1174                                 
1175                                 if(ei->icu) {
1176                                         if(ei->icu->bezt) {
1177                                                 bezt= ei->icu->bezt;
1178                                                 b= ei->icu->totvert;
1179                                                 while(b--) {
1180                                                         if(ei->icu->ipo==IPO_BEZ) {
1181                                                                 if(bezt->f1 & 1) totipo_vertsel++;
1182                                                                 if(bezt->f3 & 1) totipo_vertsel++;
1183                                                                 totipo_vert+= 2;
1184                                                         }
1185                                                         if(bezt->f2 & 1) totipo_vertsel++;
1186                                                         
1187                                                         totipo_vert++;
1188                                                         bezt++;
1189                                                 }
1190                                         }
1191                                 }
1192                         }
1193                 }
1194                 ei++;
1195         }
1196         
1197         if(G.sipo->showkey) {
1198                 ik= G.sipo->ipokey.first;
1199                 while(ik) {
1200                         totipo_key++;
1201                         if(ik->flag & 1) totipo_keysel++;
1202                         ik= ik->next;
1203                 }
1204         }
1205 }
1206
1207 /* synchronize editipo flag with icu flag and ipokey flags */
1208 void update_editipo_flags(void)
1209 {
1210         EditIpo *ei;
1211         IpoKey *ik;
1212         int a;
1213         
1214         ei= G.sipo->editipo;
1215         if(ei) {
1216                 for(a=0; a<G.sipo->totipo; a++, ei++) {
1217                         if(ei->icu) ei->icu->flag= ei->flag;
1218                 }
1219         }
1220         if(G.sipo->showkey) {
1221                 ik= G.sipo->ipokey.first;
1222                 while(ik) {
1223                         for(a=0; a<G.sipo->totipo; a++) {
1224                                 if(ik->data[a]) {
1225                                         if(ik->flag & 1) {
1226                                                 ik->data[a]->f1 |= 1;
1227                                                 ik->data[a]->f2 |= 1;
1228                                                 ik->data[a]->f3 |= 1;
1229                                         }
1230                                         else {
1231                                                 ik->data[a]->f1 &= ~1;
1232                                                 ik->data[a]->f2 &= ~1;
1233                                                 ik->data[a]->f3 &= ~1;
1234                                         }
1235                                 }
1236                         }
1237                         ik= ik->next;
1238                 }
1239         }
1240 }
1241
1242 /* sort of enter/leave editmode for curves */
1243 void set_editflag_editipo(void)
1244 {
1245         EditIpo *ei;
1246         int a; /*  , tot= 0, ok= 0; */
1247         
1248         /* after showkey immediately go to editing of selected points */
1249         if(G.sipo->showkey) {
1250                 G.sipo->showkey= 0;
1251                 if(G.sipo->ipo) G.sipo->ipo->showkey= 0;
1252                 ei= G.sipo->editipo;
1253                 for(a=0; a<G.sipo->totipo; a++, ei++) ei->flag |= IPO_SELECT;
1254                 scrarea_queue_headredraw(curarea);
1255                 allqueue(REDRAWVIEW3D, 0);
1256         }
1257         
1258         get_status_editipo();
1259         
1260         if(G.sipo->ipo && G.sipo->ipo->id.lib) return;
1261         
1262         ei= G.sipo->editipo;
1263         for(a=0; a<G.sipo->totipo; a++, ei++) {         
1264                 if(ei->icu) {
1265                         if(ei->flag & IPO_VISIBLE) {
1266                                 
1267                                 if(totipo_edit==0 && (ei->flag & IPO_SELECT)) {
1268                                         ei->flag |= IPO_EDIT;
1269                                         ei->icu->flag= ei->flag;
1270                                 }
1271                                 else if(totipo_edit && (ei->flag & IPO_EDIT)) {
1272                                         ei->flag -= IPO_EDIT;
1273                                         ei->icu->flag= ei->flag;
1274                                 }
1275                                 else if(totipo_vis==1) {
1276                                         if(ei->flag & IPO_EDIT) ei->flag -= IPO_EDIT;
1277                                         else ei->flag |= IPO_EDIT;
1278                                         ei->icu->flag= ei->flag;
1279                                 }
1280                         }
1281                 }
1282         }
1283         scrarea_queue_headredraw(curarea);
1284         scrarea_queue_winredraw(curarea);
1285 }
1286
1287 static short findnearest_ipovert(IpoCurve **icu, BezTriple **bezt)
1288 {
1289         /* selected verts get a disadvantage */
1290         /* in icu and (bezt or bp) the nearest is written */
1291         /* return 0 1 2: handlepunt */
1292         EditIpo *ei;
1293         BezTriple *bezt1;
1294         int dist= 100, temp, a, b;
1295         short mval[2], hpoint=0, sco[3][2];
1296
1297         *icu= 0;
1298         *bezt= 0;
1299
1300         getmouseco_areawin(mval);
1301
1302         ei= G.sipo->editipo;
1303         for(a=0; a<G.sipo->totipo; a++, ei++) {
1304                 if (ISPOIN3(ei, flag & IPO_VISIBLE, flag & IPO_EDIT, icu)) {
1305                         
1306                         if(ei->icu->bezt) {
1307                                 bezt1= ei->icu->bezt;
1308                                 b= ei->icu->totvert;
1309                                 while(b--) {
1310
1311                                         ipoco_to_areaco_noclip(G.v2d, bezt1->vec[0], sco[0]);
1312                                         ipoco_to_areaco_noclip(G.v2d, bezt1->vec[1], sco[1]);
1313                                         ipoco_to_areaco_noclip(G.v2d, bezt1->vec[2], sco[2]);
1314                                                                                 
1315                                         if(ei->disptype==IPO_DISPBITS) {
1316                                                 temp= abs(mval[0]- sco[1][0]);
1317                                         }
1318                                         else temp= abs(mval[0]- sco[1][0])+ abs(mval[1]- sco[1][1]);
1319
1320                                         if( bezt1->f2 & 1) temp+=5;
1321                                         if(temp<dist) { 
1322                                                 hpoint= 1; 
1323                                                 *bezt= bezt1; 
1324                                                 dist= temp; 
1325                                                 *icu= ei->icu; 
1326                                         }
1327                                         
1328                                         if(ei->disptype!=IPO_DISPBITS && ei->icu->ipo==IPO_BEZ) {
1329                                                 /* middle points get an advantage */
1330                                                 temp= -3+abs(mval[0]- sco[0][0])+ abs(mval[1]- sco[0][1]);
1331                                                 if( bezt1->f1 & 1) temp+=5;
1332                                                 if(temp<dist) { 
1333                                                         hpoint= 0; 
1334                                                         *bezt= bezt1; 
1335                                                         dist= temp; 
1336                                                         *icu= ei->icu; 
1337                                                 }
1338                 
1339                                                 temp= abs(mval[0]- sco[2][0])+ abs(mval[1]- sco[2][1]);
1340                                                 if( bezt1->f3 & 1) temp+=5;
1341                                                 if(temp<dist) { 
1342                                                         hpoint= 2; 
1343                                                         *bezt=bezt1; 
1344                                                         dist= temp; 
1345                                                         *icu= ei->icu; 
1346                                                 }
1347                                         }
1348                                         bezt1++;
1349                                 }
1350                         }
1351                 }
1352         }
1353
1354         return hpoint;
1355 }
1356
1357 void mouse_select_ipo(void)
1358 {
1359         Object *ob;
1360         KeyBlock *actkb=NULL;
1361         EditIpo *ei, *actei= 0;
1362         IpoCurve *icu;
1363         IpoKey *ik, *actik;
1364         BezTriple *bezt;
1365         TimeMarker *marker;
1366         float x, y, dist, mindist;
1367         int a, oldflag = 0, hand, ok;
1368         short mval[2], xo, yo;
1369         
1370         if(G.sipo->editipo==0) return;
1371         
1372         get_status_editipo();
1373         marker=find_nearest_marker(1);
1374         
1375         /* map ipo-points for editing if scaled ipo */
1376         if (NLA_IPO_SCALED) {
1377                 actstrip_map_ipo_keys(OBACT, G.sipo->ipo, 0, 0);
1378         }
1379         
1380         if(G.sipo->showkey) {
1381                 getmouseco_areawin(mval);
1382                 
1383                 areamouseco_to_ipoco(G.v2d, mval, &x, &y);
1384                 actik= 0;
1385                 mindist= 1000.0;
1386                 ik= G.sipo->ipokey.first;
1387                 while(ik) {
1388                         dist= (float)(fabs(ik->val-x));
1389                         if(ik->flag & 1) dist+= 1.0;
1390                         if(dist < mindist) {
1391                                 actik= ik;
1392                                 mindist= dist;
1393                         }
1394                         ik= ik->next;
1395                 }
1396                 if(actik) {
1397                         oldflag= actik->flag;
1398                         
1399                         if(G.qual & LR_SHIFTKEY);
1400                         else deselectall_editipo();
1401                         
1402                         if(G.qual & LR_SHIFTKEY) {
1403                                 if(oldflag & 1) actik->flag &= ~1;
1404                                 else actik->flag |= 1;
1405                         }
1406                         else {
1407                                 actik->flag |= 1;
1408                         }
1409                 }
1410         }
1411         else if(totipo_edit) {
1412                 
1413                 hand= findnearest_ipovert(&icu, &bezt);
1414                 
1415                 if(G.qual & LR_SHIFTKEY) {
1416                         if(bezt) {
1417                                 if(hand==1) {
1418                                         if(BEZSELECTED(bezt)) {
1419                                                 bezt->f1= bezt->f2= bezt->f3= 0;
1420                                         }
1421                                         else {
1422                                                 bezt->f1= bezt->f2= bezt->f3= 1;
1423                                         }
1424                                 }
1425                                 else if(hand==0) {
1426                                         if(bezt->f1 & 1) bezt->f1= 0;
1427                                         else bezt->f1= 1;
1428                                 }
1429                                 else {
1430                                         if(bezt->f3 & 1) bezt->f3= 0;
1431                                         else bezt->f3= 1;
1432                                 }
1433                         }                               
1434                 }
1435                 else {
1436                         deselectall_editipo();
1437                         
1438                         if(bezt) {
1439                                 if(hand==1) {
1440                                         bezt->f1|= 1; bezt->f2|= 1; bezt->f3|= 1;
1441                                 }
1442                                 else if(hand==0) bezt->f1|= 1;
1443                                 else bezt->f3|= 1;
1444                         }
1445                 }
1446         }
1447         else if (marker) {
1448                 /* select timeline marker */
1449                 if ((G.qual & LR_SHIFTKEY)==0) {
1450                         oldflag= marker->flag;
1451                         deselect_markers(0, 0);
1452                         
1453                         if (oldflag & SELECT)
1454                                 marker->flag &= ~SELECT;
1455                         else
1456                                 marker->flag |= SELECT;
1457                 }
1458                 else {
1459                         marker->flag |= SELECT;                         
1460                 }               
1461         }
1462         else {
1463                 
1464                 /* vertex keys ? */
1465                 if(G.sipo->blocktype==ID_KE && G.sipo->from) {
1466                         Key *key;
1467                         KeyBlock *kb, *curkb;
1468                         int i, index= 1;
1469                         
1470                         ob= (Object *)G.sipo->from;
1471                         key= ob_get_key(ob);
1472                         curkb= BLI_findlink(&key->block, ob->shapenr-1);
1473                         
1474                         ei= G.sipo->editipo;
1475                         if(key->type==KEY_NORMAL || (ei->flag & IPO_VISIBLE)) {
1476                                 getmouseco_areawin(mval);
1477                                 
1478                                 areamouseco_to_ipoco(G.v2d, mval, &x, &y);
1479                                 /* how much is 20 pixels? */
1480                                 mindist= (float)(20.0*(G.v2d->cur.ymax-G.v2d->cur.ymin)/(float)curarea->winy);
1481                                 
1482                                 for(i=1, kb= key->block.first; kb; kb= kb->next, i++) {
1483                                         dist= (float)(fabs(kb->pos-y));
1484                                         if(kb==curkb) dist+= (float)0.01;
1485                                         if(dist < mindist) {
1486                                                 actkb= kb;
1487                                                 mindist= dist;
1488                                                 index= i;
1489                                         }
1490                                 }
1491                                 if(actkb) {
1492                                         ok= TRUE;
1493                                         if(G.obedit && actkb!=curkb) {
1494                                                 ok= okee("Copy key after leaving Edit Mode");
1495                                         }
1496                                         if(ok) {
1497                                                 /* also does all keypos */
1498                                                 deselectall_editipo();
1499                                                 set_active_key(index);
1500                                                 set_active_editipo(ei+index-1);
1501                                         }
1502                                 }
1503                         }
1504                 }
1505                 
1506                 /* select curve */
1507                 if(actkb==NULL) {
1508                         if(totipo_vis==1) {
1509                                 ei= G.sipo->editipo;
1510                                 for(a=0; a<G.sipo->totipo; a++, ei++) {
1511                                         if(ei->icu) {
1512                                                 if(ei->flag & IPO_VISIBLE) actei= ei;
1513                                         }
1514                                 }
1515                         }
1516                         else if(totipo_vis>1) {
1517                                 actei= select_proj_ipo(0, 0);
1518                         }
1519                         
1520                         if(actei) oldflag= actei->flag;
1521                         
1522                         if(G.qual & LR_SHIFTKEY);
1523                         else deselectall_editipo();
1524                         
1525                         if(actei) {
1526                                 if(G.qual & LR_SHIFTKEY) {
1527                                         if(oldflag & IPO_SELECT) actei->flag &= ~IPO_SELECT;
1528                                         else actei->flag |= IPO_SELECT;
1529                                 }
1530                                 else {
1531                                         actei->flag |= IPO_SELECT;
1532                                 }
1533                                 set_active_editipo(actei);
1534                         }
1535                 }
1536         }
1537         
1538         /* undo mapping of ipo-points for editing if scaled ipo */
1539         if (NLA_IPO_SCALED) {
1540                 actstrip_map_ipo_keys(OBACT, G.sipo->ipo, 1, 0);
1541         }
1542         
1543         update_editipo_flags();
1544         
1545         force_draw(0);
1546         BIF_undo_push("Select Ipo");
1547         
1548         if(G.sipo->showkey && G.sipo->blocktype==ID_OB) {
1549                 ob= OBACT;
1550                 if(ob && (ob->ipoflag & OB_DRAWKEY)) allqueue(REDRAWVIEW3D, 0);
1551         }
1552         /* points inside of curve are drawn selected too */
1553         if(G.sipo->blocktype==ID_CU)
1554                 allqueue(REDRAWVIEW3D, 0);
1555         
1556         getmouseco_areawin(mval);
1557         xo= mval[0]; 
1558         yo= mval[1];
1559         
1560         while(get_mbut()&R_MOUSE) {             
1561                 getmouseco_areawin(mval);
1562                 if(abs(mval[0]-xo)+abs(mval[1]-yo) > 4) {
1563                         
1564                         if (marker) {
1565                                 transform_markers('g', 0);
1566                         }
1567                         else {
1568                                 if(actkb) move_keys(OBACT);
1569                                 else transform_ipo('g');
1570                         }
1571                         
1572                         return;
1573                 }
1574                 BIF_wait_for_statechange();
1575         }
1576 }
1577
1578
1579 /* *********************************** */
1580
1581 /* handling of right-hand channel/curve buttons in ipo window */
1582 void do_ipowin_buts(short event)
1583 {
1584         EditIpo *ei = NULL;
1585         int a;
1586
1587         /* without shift, all other channels are made invisible */
1588         if((G.qual & LR_SHIFTKEY)==0) {
1589                 if(event>G.sipo->totipo) return;
1590                 ei = G.sipo->editipo;
1591                 for(a=0; a<G.sipo->totipo; a++) {
1592                         if(a!=event) ei->flag &= ~IPO_VISIBLE;
1593                         else ei->flag |= IPO_VISIBLE;
1594                         ei++;
1595                 }
1596         }
1597         
1598         /* set active */
1599         if(event>=0 && event<G.sipo->totipo) {
1600                 ei= G.sipo->editipo;    // void pointer...
1601                 set_active_editipo(ei+event);
1602                 set_active_key(event+1);        // only if there's a key, of course
1603         }
1604         scrarea_queue_winredraw(curarea);
1605         
1606         update_editipo_flags();
1607         get_status_editipo();
1608
1609         if(G.sipo->showkey) {
1610                 make_ipokey();
1611                 if(G.sipo->blocktype==ID_OB) allqueue(REDRAWVIEW3D, 0);
1612         }
1613
1614 }
1615
1616 /* the fake buttons to the left of channel names, for select/deselect curves */
1617 void do_ipo_selectbuttons(void)
1618 {
1619         EditIpo *ei, *ei1;
1620         int a, nr;
1621         short mval[2];
1622         
1623         if(G.sipo->showkey) return;
1624         
1625         /* do not allow editipo here: convert editipos to selected */
1626         get_status_editipo();
1627         if(totipo_edit) {
1628                 set_editflag_editipo();
1629         }
1630         
1631         /* which */
1632         getmouseco_areawin(mval);
1633
1634         nr= -(mval[1]-curarea->winy+30-G.sipo->butofs-IPOBUTY)/IPOBUTY;
1635         if(G.sipo->blocktype==ID_KE) nr--;              /* keys show something else in first channel */
1636         
1637         if(nr>=0 && nr<G.sipo->totipo) {
1638                 ei= G.sipo->editipo;
1639                 ei+= nr;
1640                 
1641                 set_active_editipo(ei);
1642                 set_active_key(nr+1);
1643
1644                 if(ei->icu) {
1645                         if((ei->flag & IPO_VISIBLE)==0) {
1646                                 ei->flag |= IPO_VISIBLE|IPO_SELECT;
1647                         }
1648         
1649                         if((G.qual & LR_SHIFTKEY)==0) {
1650                                 ei1= G.sipo->editipo;
1651                                 for(a=0; a<G.sipo->totipo; a++) {
1652                                         ei1->flag &= ~IPO_SELECT;
1653                                         ei1++;
1654                                 }
1655                         }
1656
1657                         if(ei->flag & IPO_SELECT) {
1658                                 ei->flag &= ~IPO_SELECT;
1659                         }
1660                         else {
1661                                 ei->flag |= IPO_SELECT;
1662                         }
1663                         
1664                         update_editipo_flags();
1665                         scrarea_queue_winredraw(curarea);
1666                 }
1667         }
1668         BIF_undo_push("Select Ipo curve");
1669 }
1670
1671 /* ********************************* Inserting keys ********************************************* */
1672
1673 /* depending type, it returns ipo, if needed it creates one */
1674 /* returns either action ipo or "real" ipo */
1675 /* arguments define full context;
1676    - *from has to be set always, to Object in case of Actions
1677    - blocktype defines available channels of Ipo struct (blocktype ID_OB can be in action too)
1678    - if actname, use this to locate action, and optional constname to find the channel 
1679 */
1680
1681 /* note; check header_ipo.c, spaceipo_assign_ipo() too */
1682 Ipo *verify_ipo(ID *from, short blocktype, char *actname, char *constname)
1683 {
1684
1685         if(from==NULL || from->lib) return NULL;
1686         
1687         /* first check action ipos */
1688         if(actname && actname[0]) {
1689                 Object *ob= (Object *)from;
1690                 bActionChannel *achan;
1691                 
1692                 if(GS(from->name)!=ID_OB) {
1693                         printf("called ipo system for action with wrong base pointer\n");
1694                         return NULL;
1695                 }
1696                 
1697                 if(ob->action==NULL)
1698                         ob->action= add_empty_action("Action");
1699                 
1700                 achan= verify_action_channel(ob->action, actname);
1701                 
1702                 if(achan) {
1703                         /* constraint exception */
1704                         if(blocktype==ID_CO) {
1705                                 bConstraintChannel *conchan= verify_constraint_channel(&achan->constraintChannels, constname);
1706                                 if(conchan->ipo==NULL) {
1707                                         conchan->ipo= add_ipo("CoIpo", ID_CO);  
1708                                 }
1709                                 return conchan->ipo;
1710                         }
1711                         else {
1712                                 if(achan->ipo==NULL) {
1713                                         achan->ipo= add_ipo("ActIpo", blocktype);
1714                                 }
1715                                 
1716                                 return achan->ipo;
1717                         }
1718                 }
1719         }
1720         else {
1721                 
1722                 switch(GS(from->name)) {
1723                 case ID_OB:
1724                         {
1725                                 Object *ob= (Object *)from;
1726                                 /* constraint exception */
1727                                 if(blocktype==ID_CO) {
1728                                         bConstraintChannel *conchan= verify_constraint_channel(&ob->constraintChannels, constname);
1729                                         if(conchan->ipo==NULL) {
1730                                                 conchan->ipo= add_ipo("CoIpo", ID_CO);  
1731                                         }
1732                                         return conchan->ipo;
1733                                 }
1734                                 else if(blocktype==ID_OB) {
1735                                         if(ob->ipo==NULL) {
1736                                                 ob->ipo= add_ipo("ObIpo", ID_OB);
1737                                         }
1738                                         return ob->ipo;
1739                                 }
1740                                 else if(blocktype==ID_KE) {
1741                                         Key *key= ob_get_key((Object *)from);
1742                                         
1743                                         if(key) {
1744                                                 if(key->ipo==NULL) {
1745                                                         key->ipo= add_ipo("KeyIpo", ID_KE);
1746                                                 }
1747                                                 return key->ipo;
1748                                         }
1749                                         return NULL;
1750                                 }
1751                                 else if(blocktype== ID_FLUIDSIM) {
1752                                         Object *ob= (Object *)from;
1753                                         if(ob->fluidsimFlag & OB_FLUIDSIM_ENABLE) {
1754                                                 FluidsimSettings *fss= ob->fluidsimSettings;
1755                                                 if(fss->ipo==NULL) {
1756                                                         fss->ipo= add_ipo("FluidsimIpo", ID_FLUIDSIM);
1757                                                         //fprintf(stderr,"FSIPO NEW!\n");
1758                                                 }
1759                                                 return fss->ipo;
1760                                         }
1761                                 }
1762                         }
1763                         break;
1764                 case ID_MA:
1765                         {
1766                                 Material *ma= (Material *)from;
1767
1768                                 if(ma->ipo==NULL) {
1769                                         ma->ipo= add_ipo("MatIpo", ID_MA);
1770                                 }
1771                                 return ma->ipo;
1772                         }
1773                         break;
1774                 case ID_TE:
1775                         {
1776                                 Tex *tex= (Tex *)from;
1777
1778                                 if(tex->ipo==NULL) {
1779                                         tex->ipo= add_ipo("TexIpo", ID_TE);
1780                                 }
1781                                 return tex->ipo;
1782                         }
1783                         break;
1784                 case ID_SEQ:
1785                         {
1786                                 Sequence *seq= (Sequence *)from;        /* note, sequence is mimicing Id */
1787
1788                                 if((seq->type & SEQ_EFFECT)||
1789                                    (seq->type == SEQ_RAM_SOUND)||
1790                                    (seq->type == SEQ_HD_SOUND)) {
1791                                         if(seq->ipo==NULL) {
1792                                                 seq->ipo= add_ipo("SeqIpo", ID_SEQ);
1793                                         }
1794                                         update_seq_ipo_rect(seq);
1795                                         return seq->ipo;
1796                                 }
1797                         }
1798                         break;
1799                 case ID_CU:
1800                         {
1801                                 Curve *cu= (Curve *)from;
1802                                 
1803                                 if(cu->ipo==NULL) {
1804                                         cu->ipo= add_ipo("CuIpo", ID_CU);
1805                                 }
1806                                 return cu->ipo;
1807                         }
1808                         break;
1809                 case ID_WO:
1810                         {
1811                                 World *wo= (World *)from;
1812
1813                                 if(wo->ipo==NULL) {
1814                                         wo->ipo= add_ipo("WoIpo", ID_WO);
1815                                 }
1816                                 return wo->ipo;
1817                         }
1818                         break;
1819                 case ID_LA:
1820                         {
1821                                 Lamp *la= (Lamp *)from;
1822                                 
1823                                 if(la->ipo==NULL) {
1824                                         la->ipo= add_ipo("LaIpo", ID_LA);
1825                                 }
1826                                 return la->ipo;
1827                         }
1828                         break;
1829                 case ID_CA:
1830                         {
1831                                 Camera *ca= (Camera *)from;
1832
1833                                 if(ca->ipo==NULL) {
1834                                         ca->ipo= add_ipo("CaIpo", ID_CA);
1835                                 }
1836                                 return ca->ipo;
1837                         }
1838                         break;
1839                 case ID_SO:
1840                         {
1841                                 bSound *snd= (bSound *)from;
1842
1843                                 if(snd->ipo==NULL) {
1844                                         snd->ipo= add_ipo("SndIpo", ID_SO);
1845                                 }
1846                                 return snd->ipo;
1847                         }
1848                 }
1849         }
1850         
1851         return NULL;    
1852 }
1853
1854 /* returns and creates
1855  * Make sure functions check for NULL or they will crash!
1856  *  */
1857 IpoCurve *verify_ipocurve(ID *from, short blocktype, char *actname, char *constname, int adrcode)
1858 {
1859         Ipo *ipo;
1860         IpoCurve *icu= NULL;
1861         
1862         /* return 0 if lib */
1863         /* creates ipo too */
1864         ipo= verify_ipo(from, blocktype, actname, constname);
1865         
1866         if(ipo && ipo->id.lib==NULL && from->lib==NULL) {
1867                 
1868                 for(icu= ipo->curve.first; icu; icu= icu->next) {
1869                         if(icu->adrcode==adrcode) break;
1870                 }
1871                 if(icu==NULL) {
1872                         icu= MEM_callocN(sizeof(IpoCurve), "ipocurve");
1873
1874                         icu->flag |= IPO_VISIBLE|IPO_AUTO_HORIZ;
1875                         icu->blocktype= blocktype;
1876                         icu->adrcode= adrcode;
1877                         
1878                         set_icu_vars(icu);
1879
1880                         BLI_addtail( &(ipo->curve), icu);
1881
1882                         switch (GS(from->name)) {
1883                         case ID_SEQ: {
1884                                 Sequence *seq= (Sequence *)from;
1885
1886                                 update_seq_icu_rects(seq);
1887                                 break;
1888                         }
1889                         }
1890                 }
1891         }
1892
1893         return icu;
1894 }
1895
1896 void insert_vert_ipo(IpoCurve *icu, float x, float y)
1897 {
1898         BezTriple *bezt, beztr, *newbezt;
1899         int a = 0, h1, h2;
1900         
1901         memset(&beztr, 0, sizeof(BezTriple));
1902         beztr.vec[0][0]= x; // set all three points, for nicer start position
1903         beztr.vec[0][1]= y;
1904         beztr.vec[1][0]= x;
1905         beztr.vec[1][1]= y;
1906         beztr.vec[2][0]= x;
1907         beztr.vec[2][1]= y;
1908         beztr.hide= IPO_BEZ;
1909         beztr.f1= beztr.f2= beztr.f3= SELECT;
1910         beztr.h1= beztr.h2= HD_AUTO;
1911                 
1912         bezt= icu->bezt;
1913                 
1914         if(bezt==NULL) {
1915                 icu->bezt= MEM_callocN( sizeof(BezTriple), "beztriple");
1916                 *(icu->bezt)= beztr;
1917                 icu->totvert= 1;
1918         }
1919         else {
1920                 /* all vertices deselect */
1921                 for(a=0; a<icu->totvert; a++, bezt++) {
1922                         bezt->f1= bezt->f2= bezt->f3= 0;
1923                 }
1924         
1925                 bezt= icu->bezt;
1926                 for(a=0; a<=icu->totvert; a++, bezt++) {
1927                         
1928                         /* no double points - threshold to determine this should be good enough */
1929                         if(a<icu->totvert && IS_EQT(bezt->vec[1][0], x, 0.00001)) {
1930                                 *(bezt)= beztr;
1931                                 break;
1932                         }
1933                         if(a==icu->totvert || bezt->vec[1][0] > x) {
1934                                 newbezt= MEM_callocN( (icu->totvert+1)*sizeof(BezTriple), "beztriple");
1935                                 
1936                                 if(a>0) memcpy(newbezt, icu->bezt, a*sizeof(BezTriple));
1937                                 
1938                                 bezt= newbezt+a;
1939                                 *(bezt)= beztr;
1940                                 
1941                                 if(a<icu->totvert) memcpy(newbezt+a+1, icu->bezt+a, (icu->totvert-a)*sizeof(BezTriple));
1942                                 
1943                                 MEM_freeN(icu->bezt);
1944                                 icu->bezt= newbezt;
1945                                 
1946                                 icu->totvert++;
1947                                 break;
1948                         }
1949                 }
1950         }
1951         
1952         
1953         calchandles_ipocurve(icu);
1954         
1955         /* set handletype */
1956         if(icu->totvert>2) {
1957                 h1= h2= HD_AUTO;
1958                 if(a>0) h1= (bezt-1)->h2;
1959                 if(a<icu->totvert-1) h2= (bezt+1)->h1;
1960                 bezt->h1= h1;
1961                 bezt->h2= h2;
1962
1963                 calchandles_ipocurve(icu);
1964         }
1965 }
1966
1967 void add_vert_ipo(void)
1968 {
1969         EditIpo *ei;
1970         float x, y;
1971         int val;
1972         short mval[2];
1973
1974         if(G.sipo->ipo && G.sipo->ipo->id.lib) return;
1975         if(G.sipo->showkey) {
1976                 G.sipo->showkey= 0;
1977                 free_ipokey(&G.sipo->ipokey);
1978         }
1979         
1980         getmouseco_areawin(mval);
1981         
1982         if(mval[0]>G.v2d->mask.xmax) return;
1983         
1984         ei= get_active_editipo();
1985         if(ei==NULL) {
1986                 error("No active Ipo curve");
1987                 return;
1988         }
1989         ei->flag |= IPO_VISIBLE;        /* can happen it is active but not visible */
1990         
1991         areamouseco_to_ipoco(G.v2d, mval, &x, &y);
1992         
1993         /* convert click-time to ipo-time */
1994         if (NLA_IPO_SCALED) {
1995                 x= get_action_frame(OBACT, x);
1996         }
1997         
1998         if(ei->icu==NULL) {
1999                 if(G.sipo->from) {
2000                         ei->icu= verify_ipocurve(G.sipo->from, G.sipo->blocktype, G.sipo->actname, G.sipo->constname, ei->adrcode);
2001                         if (ei->icu)
2002                                 ei->flag |= ei->icu->flag & IPO_AUTO_HORIZ;     /* new curve could have been added, weak... */
2003                         else
2004                                 error("Cannot create an IPO curve, you may be using libdata");
2005                 }
2006         }
2007         if(ei->icu==NULL) return;
2008
2009         if(ei->disptype==IPO_DISPBITS) {
2010                 ei->icu->vartype= IPO_BITS;
2011                 val= (int)floor(y-0.5);
2012                 if(val<0) val= 0;
2013                 y= (float)(1 << val);
2014         }
2015         
2016         insert_vert_ipo(ei->icu, x, y);
2017
2018         /* to be sure: if icu was 0, or only 1 curve visible */
2019         ei->flag |= IPO_SELECT;
2020         ei->icu->flag= ei->flag;
2021         
2022         editipo_changed(G.sipo, 1);
2023         BIF_undo_push("Add Ipo vertex");
2024 }
2025
2026 static void *get_context_ipo_poin(ID *id, int blocktype, char *actname, IpoCurve *icu, int *vartype)
2027 {
2028         if(blocktype==ID_PO) {
2029                 if(GS(id->name)==ID_OB) {
2030                         Object *ob= (Object *)id;
2031                         bPoseChannel *pchan= get_pose_channel(ob->pose, actname);
2032                         
2033                         *vartype= IPO_FLOAT;
2034                         return get_pchan_ipo_poin(pchan, icu->adrcode);
2035                 }
2036                 return NULL;
2037         }
2038         else
2039                 return get_ipo_poin(id, icu, vartype);
2040
2041 }
2042
2043 #define KEYNEEDED_DONTADD       0
2044 #define KEYNEEDED_JUSTADD       1
2045 #define KEYNEEDED_DELPREV       2
2046 #define KEYNEEDED_DELNEXT       3
2047
2048 static int new_key_needed(IpoCurve *icu, float cFrame, float nValue) 
2049 {
2050         /* This function determines whether a new keyframe is needed */
2051         /* Cases where keyframes should not be added:
2052          *      1. Keyframe to be added bewteen two keyframes with similar values
2053          *      2. Keyframe to be added on frame where two keyframes are already situated
2054          *      3. Keyframe lies at point that intersects the linear line between two keyframes
2055          */
2056         
2057         BezTriple *bezt=NULL, *prev=NULL;
2058         int totCount, i;
2059         float valA = 0.0f, valB = 0.0f;
2060         
2061         /* safety checking */
2062         if (!icu) return KEYNEEDED_JUSTADD;
2063         totCount= icu->totvert;
2064         if (totCount==0) return KEYNEEDED_JUSTADD;
2065         
2066         /* loop through checking if any are the same */
2067         bezt= icu->bezt;
2068         for (i=0; i<totCount; i++) {
2069                 float prevPosi=0.0f, prevVal=0.0f;
2070                 float beztPosi=0.0f, beztVal=0.0f;
2071                         
2072                 /* get current time+value */    
2073                 beztPosi= bezt->vec[1][0];
2074                 beztVal= bezt->vec[1][1];
2075                         
2076                 if (prev) {
2077                         /* there is a keyframe before the one currently being examined */               
2078                         
2079                         /* get previous time+value */
2080                         prevPosi= prev->vec[1][0];
2081                         prevVal= prev->vec[1][1];
2082                         
2083                         /* keyframe to be added at point where there are already two similar points? */
2084                         if (IS_EQ(prevPosi, cFrame) && IS_EQ(beztPosi, cFrame) && IS_EQ(beztPosi, prevPosi)) {
2085                                 return KEYNEEDED_DONTADD;
2086                         }
2087                         
2088                         /* keyframe between prev+current points ? */
2089                         if ((prevPosi <= cFrame) && (cFrame <= beztPosi)) {
2090                                 /* is the value of keyframe to be added the same as keyframes on either side ? */
2091                                 if (IS_EQ(prevVal, nValue) && IS_EQ(beztVal, nValue) && IS_EQ(prevVal, beztVal)) {
2092                                         return KEYNEEDED_DONTADD;
2093                                 }
2094                                 else {
2095                                         float realVal;
2096                                         
2097                                         /* get real value of curve at that point */
2098                                         realVal= eval_icu(icu, cFrame);
2099                                 
2100                                         /* compare whether it's the same as proposed */
2101                                         if (IS_EQ(realVal, nValue)) 
2102                                                 return KEYNEEDED_DONTADD;
2103                                         else 
2104                                                 return KEYNEEDED_JUSTADD;
2105                                 }
2106                         }
2107                         
2108                         /* new keyframe before prev beztriple? */
2109                         if (cFrame < prevPosi) {
2110                                 /* A new keyframe will be added. However, whether the previous beztriple
2111                                  * stays around or not depends on whether the values of previous/current
2112                                  * beztriples and new keyframe are the same.
2113                                  */
2114                                 if (IS_EQ(prevVal, nValue) && IS_EQ(beztVal, nValue) && IS_EQ(prevVal, beztVal))
2115                                         return KEYNEEDED_DELNEXT;
2116                                 else 
2117                                         return KEYNEEDED_JUSTADD;
2118                         }
2119                 }
2120                 else {
2121                         /* just add a keyframe if there's only one keyframe 
2122                          * and the new one occurs before the exisiting one does.
2123                          */
2124                         if ((cFrame < beztPosi) && (totCount==1))
2125                                 return KEYNEEDED_JUSTADD;
2126                 }
2127                 
2128                 /* continue. frame to do not yet passed (or other conditions not met) */
2129                 if (i < (totCount-1)) {
2130                         prev= bezt;
2131                         bezt++;
2132                 }
2133                 else
2134                         break;
2135         }
2136         
2137         /* Frame in which to add a new-keyframe occurs after all other keys
2138          * -> If there are at least two existing keyframes, then if the values of the
2139          *       last two keyframes and the new-keyframe match, the last existing keyframe
2140          *       gets deleted as it is no longer required.
2141          * -> Otherwise, a keyframe is just added. 1.0 is added so that fake-2nd-to-last
2142          *       keyframe is not equal to last keyframe.
2143          */
2144         bezt= (icu->bezt + (icu->totvert - 1));
2145         valA= bezt->vec[1][1];
2146         
2147         if (prev)
2148                 valB= prev->vec[1][1];
2149         else 
2150                 valB= bezt->vec[1][1] + 1.0f; 
2151                 
2152         if (IS_EQ(valA, nValue) && IS_EQ(valA, valB)) 
2153                 return KEYNEEDED_DELPREV;
2154         else 
2155                 return KEYNEEDED_JUSTADD;
2156 }
2157
2158 /* a duplicate of insertkey that does not check for routing to insertmatrixkey 
2159         to avoid recursion problems */
2160 static void insertkey_nonrecurs(ID *id, int blocktype, char *actname, char *constname, int adrcode)
2161 {
2162         IpoCurve *icu;
2163         Object *ob;
2164         void *poin= NULL;
2165         float curval, cfra;
2166         int vartype;
2167         int matset=0;
2168         
2169         if (matset==0) {
2170                 icu= verify_ipocurve(id, blocktype, actname, constname, adrcode);
2171                 
2172                 if(icu) {
2173                         
2174                         poin= get_context_ipo_poin(id, blocktype, actname, icu, &vartype);
2175                         
2176                         if(poin) {
2177                                 curval= read_ipo_poin(poin, vartype);
2178                                 
2179                                 cfra= frame_to_float(CFRA);
2180                                 
2181                                 /* if action is mapped in NLA, it returns a correction */
2182                                 if(actname && actname[0] && GS(id->name)==ID_OB)
2183                                         cfra= get_action_frame((Object *)id, cfra);
2184                                 
2185                                 if( GS(id->name)==ID_OB ) {
2186                                         ob= (Object *)id;
2187                                         if(ob->sf!=0.0 && (ob->ipoflag & OB_OFFS_OB) ) {
2188                                                 /* actually frametofloat calc again! */
2189                                                 cfra-= ob->sf*G.scene->r.framelen;
2190                                         }
2191                                 }
2192                                 
2193                                 insert_vert_ipo(icu, cfra, curval);
2194                         }
2195                 }
2196         }
2197 }
2198
2199 int insertmatrixkey(ID *id, int blocktype, char *actname, char *constname, int adrcode)
2200 {
2201         int matindex=0;
2202         /* branch on adrcode and blocktype, generating the proper matrix-based
2203         values to send to insertfloatkey */
2204         if (GS(id->name)==ID_OB) {
2205                 Object *ob= (Object *)id;
2206
2207                 if ( blocktype==ID_OB ){ //working with an object
2208                         if ((ob)&&!(ob->parent)) {
2209                                 if ((adrcode==OB_ROT_X)||(adrcode==OB_ROT_Y)||(adrcode==OB_ROT_Z)) { //get a rotation
2210                                         float eul[3];
2211                                         switch (adrcode) {
2212                                                 case OB_ROT_X:
2213                                                         matindex=0;
2214                                                         break;
2215                                                 case OB_ROT_Y:
2216                                                         matindex=1;
2217                                                         break;
2218                                                 case OB_ROT_Z:
2219                                                         matindex=2;
2220                                                         break;
2221                                         }
2222                                         Mat4ToEul(ob->obmat, eul);
2223                                         insertfloatkey(id, ID_OB, actname, NULL, adrcode, eul[matindex]*(5.72958));
2224                                         return 1;
2225                                 } else if ((adrcode==OB_LOC_X)||(adrcode==OB_LOC_Y)||(adrcode==OB_LOC_Z)) {//get a translation
2226                                         switch (adrcode) {
2227                                                 case OB_LOC_X:
2228                                                         matindex=0;
2229                                                         break;
2230                                                 case OB_LOC_Y:
2231                                                         matindex=1;
2232                                                         break;
2233                                                 case OB_LOC_Z:
2234                                                         matindex=2;
2235                                                         break;
2236                                         }
2237                                         insertfloatkey(id, ID_OB, actname, NULL, adrcode, ob->obmat[3][matindex]);
2238                                         return 1;
2239                                 }
2240                         }
2241                 } else if ( blocktype==ID_PO) { //working with a pose channel
2242                         bPoseChannel *pchan= get_pose_channel(ob->pose, actname);
2243                         if (pchan) {
2244                                 if ((adrcode==AC_LOC_X)||(adrcode==AC_LOC_Y)||(adrcode==AC_LOC_Z)) {
2245                                         switch (adrcode) {
2246                                                 case AC_LOC_X:
2247                                                         matindex=0;
2248                                                         break;
2249                                                 case AC_LOC_Y:
2250                                                         matindex=1;
2251                                                         break;
2252                                                 case AC_LOC_Z:
2253                                                         matindex=2;
2254                                                         break;
2255                                         }
2256                                         if (!(pchan->bone->parent)||((pchan->bone->parent)&&!(pchan->bone->flag&BONE_CONNECTED))) { /* don't use for non-connected child bones */
2257                                                 float delta_mat[4][4]; 
2258                                                 armature_mat_pose_to_delta(delta_mat, pchan->pose_mat, pchan->bone->arm_mat);
2259                                                 insertfloatkey(id, ID_PO, pchan->name, NULL, adrcode, delta_mat[3][matindex]);
2260                                                 return 1;
2261                                         }
2262                                 } else if ((adrcode==AC_QUAT_W)||(adrcode==AC_QUAT_X)||(adrcode==AC_QUAT_Y)||(adrcode==AC_QUAT_Z)) { 
2263                                         switch (adrcode) {
2264                                                 case AC_QUAT_W:
2265                                                         matindex=0;
2266                                                         break;
2267                                                 case AC_QUAT_X:
2268                                                         matindex=1;
2269                                                         break;
2270                                                 case AC_QUAT_Y:
2271                                                         matindex=2;
2272                                                         break;
2273                                                 case AC_QUAT_Z:
2274                                                         matindex=3;
2275                                                         break;
2276                                         }
2277                                         if (!(pchan->bone->parent)||((pchan->bone->parent)&&!(pchan->bone->flag&BONE_HINGE))) {  /* don't use for non-hinged child bones */
2278                                                 float delta_mat[4][4],trimat[3][3];
2279                                                 float localQuat[4];
2280                                                 armature_mat_pose_to_delta(delta_mat, pchan->pose_mat, pchan->bone->arm_mat);
2281                                                 /* Fixed this bit up from the old "hacky" version, as it was called.
2282                                                         Not sure of the origin of Mat3ToQuat_is_ok or why its in there. In most cases, this
2283                                                         produces the same result of the "hacky" version, and in some
2284                                                         cases the results seem to be better. But whatever the case, this is unideal, as
2285                                                         we're decomposing a 3x3 rotation matrix into a quat, which is
2286                                                         not a discrete operation.                                                                                       */
2287                                                 Mat3CpyMat4(trimat, delta_mat);
2288                                                 Mat3ToQuat_is_ok(trimat, localQuat);
2289                                                 insertfloatkey(id, ID_PO, pchan->name, NULL, adrcode, localQuat[matindex]);
2290                                                 return 1;
2291                                         }
2292                                 }
2293                         }
2294                 }
2295         }
2296         /* failed to set a matrix key -- use traditional, but the non-recursing version */
2297         insertkey_nonrecurs(id,blocktype,actname,constname,adrcode);
2298         return 0;
2299 }
2300
2301 static int match_adr_constraint(ID * id, int blocktype, char *actname, int adrcode)
2302 {       /* This function matches constraint blocks with adrcodes to see if the
2303                 visual keying method should be used. For example, an object looking to key
2304                 location and having a CopyLoc constraint would return true. */
2305                 
2306         Object *ob=NULL;
2307         int foundmatch=0;
2308         int searchtype=0;
2309         bConstraint *conref=NULL, *con=NULL;
2310         
2311         /*Retrieve constraint list*/
2312         if( GS(id->name)==ID_OB ) 
2313                 ob= (Object *)id;
2314         if (ob) {
2315                 if (blocktype==ID_PO) {
2316                         bPoseChannel *pchan= get_pose_channel(ob->pose, actname);
2317                         conref=pchan->constraints.first;
2318                 } else if (blocktype==ID_OB) {
2319                         conref=ob->constraints.first;
2320                 }
2321                 
2322                 if (conref) {
2323                         /*Set search type: 1 is for translation contraints, 2 is for rotation*/
2324                         if ((adrcode==OB_LOC_X)||(adrcode==OB_LOC_Y)||(adrcode==OB_LOC_Z)||(adrcode==AC_LOC_X)||(adrcode==AC_LOC_Y)||(adrcode==AC_LOC_Z)) {
2325                                 searchtype=1;
2326                         } else if ((adrcode==OB_ROT_X)||(adrcode==OB_ROT_Y)||(adrcode==OB_ROT_Z)||(adrcode==AC_QUAT_W)||(adrcode==AC_QUAT_X)||(adrcode==AC_QUAT_Y)||(adrcode==AC_QUAT_Z)) {
2327                                 searchtype=2;
2328                         }
2329                         
2330                         if (searchtype>0) {
2331                                 for (con=conref; (con)&&(foundmatch==0); con=con->next) {
2332                                         switch (con->type) {
2333                                         /* match constraint types to which kinds of keying they would affect */
2334                                                 case CONSTRAINT_TYPE_CHILDOF:
2335                                                         foundmatch=1;
2336                                                         break;
2337                                                 case CONSTRAINT_TYPE_TRACKTO:
2338                                                         if (searchtype==2) foundmatch=1;
2339                                                         break;
2340                                                 case CONSTRAINT_TYPE_FOLLOWPATH:
2341                                                         foundmatch=1;
2342                                                         break;
2343                                                 case CONSTRAINT_TYPE_ROTLIMIT:
2344                                                         if (searchtype==2) foundmatch=1;
2345                                                         break;
2346                                                 case CONSTRAINT_TYPE_LOCLIMIT:
2347                                                         if (searchtype==1) foundmatch=1;
2348                                                         break;
2349                                                 case CONSTRAINT_TYPE_ROTLIKE:
2350                                                         if (searchtype==2) foundmatch=1;
2351                                                         break;
2352                                                 case CONSTRAINT_TYPE_LOCLIKE:
2353                                                         if (searchtype==1) foundmatch=1;
2354                                                         break;
2355                                                 case CONSTRAINT_TYPE_LOCKTRACK:
2356                                                         if (searchtype==2) foundmatch=1;
2357                                                         break;
2358                                                 case CONSTRAINT_TYPE_DISTANCELIMIT:
2359                                                         if (searchtype==1) foundmatch=1;
2360                                                         break;
2361                                                 case CONSTRAINT_TYPE_MINMAX:
2362                                                         if (searchtype==1) foundmatch=1;
2363                                                         break;
2364                                                 case CONSTRAINT_TYPE_TRANSFORM:
2365                                                         foundmatch=1;
2366                                                         break;
2367                                                 default:
2368                                                         break;
2369                                         }
2370                                 }
2371                         }
2372                 }
2373         }
2374         
2375         return foundmatch;
2376                         
2377 }
2378
2379 void insertkey(ID *id, int blocktype, char *actname, char *constname, int adrcode)
2380 {
2381         IpoCurve *icu;
2382         Object *ob;
2383         void *poin= NULL;
2384         float curval, cfra;
2385         int vartype;
2386         int matset=0;
2387         
2388         if ((G.flags&G_AUTOMATKEYS)&&(match_adr_constraint(id, blocktype, actname, adrcode))) {
2389                 matset=insertmatrixkey(id, blocktype, actname, constname, adrcode);
2390         } 
2391         if (matset==0) {
2392                 icu= verify_ipocurve(id, blocktype, actname, constname, adrcode);
2393                 
2394                 if(icu) {
2395                         
2396                         poin= get_context_ipo_poin(id, blocktype, actname, icu, &vartype);
2397                         
2398                         if(poin) {
2399                                 curval= read_ipo_poin(poin, vartype);
2400                                 
2401                                 cfra= frame_to_float(CFRA);
2402                                 
2403                                 /* if action is mapped in NLA, it returns a correction */
2404                                 if(actname && actname[0] && GS(id->name)==ID_OB)
2405                                         cfra= get_action_frame((Object *)id, cfra);
2406                                 
2407                                 if( GS(id->name)==ID_OB ) {
2408                                         ob= (Object *)id;
2409                                         if(ob->sf!=0.0 && (ob->ipoflag & OB_OFFS_OB) ) {
2410                                                 /* actually frametofloat calc again! */
2411                                                 cfra-= ob->sf*G.scene->r.framelen;
2412                                         }
2413                                 }
2414                                 
2415                                 insert_vert_ipo(icu, cfra, curval);
2416                         }
2417                 }
2418         }
2419 }
2420
2421
2422
2423 /* This function is a 'smarter' version of the insert key code.
2424  * It uses an auxilliary function to check whether a keyframe is really needed */
2425 void insertkey_smarter(ID *id, int blocktype, char *actname, char *constname, int adrcode)
2426 {
2427         IpoCurve *icu;
2428         Object *ob;
2429         void *poin= NULL;
2430         float curval, cfra;
2431         int vartype;
2432         int insert_mode;
2433         
2434         icu= verify_ipocurve(id, blocktype, actname, constname, adrcode);
2435         
2436         if(icu) {
2437                 
2438                 poin= get_context_ipo_poin(id, blocktype, actname, icu, &vartype);
2439                 
2440                 if(poin) {
2441                         curval= read_ipo_poin(poin, vartype);
2442                         
2443                         cfra= frame_to_float(CFRA);
2444                         
2445                         /* if action is mapped in NLA, it returns a correction */
2446                         if(actname && actname[0] && GS(id->name)==ID_OB)
2447                                 cfra= get_action_frame((Object *)id, cfra);
2448                         
2449                         if( GS(id->name)==ID_OB ) {
2450                                 ob= (Object *)id;
2451                                 if(ob->sf!=0.0 && (ob->ipoflag & OB_OFFS_OB) ) {
2452                                         /* actually frametofloat calc again! */
2453                                         cfra-= ob->sf*G.scene->r.framelen;
2454                                 }
2455                         }
2456                         
2457                         /* check whether this curve really needs a new keyframe */
2458                         insert_mode= new_key_needed(icu, cfra, curval);
2459                         
2460                         /* insert new keyframe at current frame */
2461                         if (insert_mode) 
2462                                 insert_vert_ipo(icu, cfra, curval);
2463                         
2464                         /* delete keyframe immediately before/after newly added */
2465                         switch (insert_mode) {
2466                                 case KEYNEEDED_DELPREV:
2467                                         delete_icu_key(icu, icu->totvert-2);
2468                                         break;
2469                                 case KEYNEEDED_DELNEXT:
2470                                         delete_icu_key(icu, 1);
2471                                         break;
2472                         }
2473                 }
2474         }
2475 }
2476
2477 /* For inserting keys based on an arbitrary float value */
2478 void insertfloatkey(ID *id, int blocktype, char *actname, char *constname, int adrcode, float floatkey)
2479 {
2480         IpoCurve *icu;
2481         Object *ob;
2482         void *poin= NULL;
2483         float cfra;
2484         int vartype;
2485         
2486         icu= verify_ipocurve(id, blocktype, actname, constname, adrcode);
2487         
2488         if(icu) {
2489                 
2490                 poin= get_context_ipo_poin(id, blocktype, actname, icu, &vartype);
2491                 
2492                 if(poin) {
2493                         
2494                         cfra= frame_to_float(CFRA);
2495                         
2496                         /* if action is mapped in NLA, it returns a correction */
2497                         if(actname && actname[0] && GS(id->name)==ID_OB)
2498                                 cfra= get_action_frame((Object *)id, cfra);
2499                         
2500                         if( GS(id->name)==ID_OB ) {
2501                                 ob= (Object *)id;
2502                                 if(ob->sf!=0.0 && (ob->ipoflag & OB_OFFS_OB) ) {
2503                                         /* actually frametofloat calc again! */
2504                                         cfra-= ob->sf*G.scene->r.framelen;
2505                                 }
2506                         }
2507                         
2508                         /* insert new keyframe at current frame */
2509                         insert_vert_ipo(icu, cfra, floatkey);
2510                 }
2511         }
2512 }
2513
2514 void insertkey_editipo(void)
2515 {
2516         EditIpo *ei;
2517         IpoKey *ik;
2518         ID *id;
2519         float *fp, cfra, *insertvals;
2520         int a, nr, ok, tot;
2521         short event;
2522         
2523         ei= get_active_editipo();
2524         if(ei && ei->icu && ei->icu->driver) 
2525                 event= pupmenu("Insert Curve %t|Default one-to-one mapping %x3");
2526         else if(G.sipo->showkey)
2527                 event= pupmenu("Insert Key Vertices %t|Current Frame %x1|Selected Keys %x2");
2528         else 
2529                 event= pupmenu("Insert Key Vertices %t|Current Frame %x1");
2530         
2531         if(event<1) return;
2532         
2533         if(event==3) {
2534                 IpoDriver *driver= ei->icu->driver;
2535                 
2536                 if(ei->icu->bezt) MEM_freeN(ei->icu->bezt);
2537                 ei->icu->totvert= 0;
2538                 ei->icu->bezt= NULL;
2539                 
2540                 insert_vert_ipo(ei->icu, 0.0f, 0.0f);
2541                 
2542                 if(ELEM3(driver->adrcode, OB_ROT_X, OB_ROT_Y, OB_ROT_Z)) {
2543                         if(ei->disptype==IPO_DISPDEGR)
2544                                 insert_vert_ipo(ei->icu, 18.0f, 18.0f);
2545                         else
2546                                 insert_vert_ipo(ei->icu, 18.0f, 1.0f);
2547                 }
2548                 else
2549                         insert_vert_ipo(ei->icu, 1.0f, 1.0f);
2550                 
2551                 ei->flag |= IPO_SELECT|IPO_VISIBLE;
2552                 ei->icu->flag= ei->flag;
2553                 ei->icu->extrap= IPO_DIR;
2554
2555                 do_ipo_buttons(B_IPOHOME);
2556         }
2557         else {
2558                 ei= G.sipo->editipo;
2559                 for(nr=0; nr<G.sipo->totipo; nr++, ei++) {
2560                         if (ISPOIN(ei, flag & IPO_VISIBLE, icu)) {
2561                         
2562                                 ok= 0;
2563                                 if(G.sipo->showkey) ok= 1;
2564                                 else if(ei->flag & IPO_SELECT) ok= 1;
2565
2566                                 if(ok) {
2567                                         /* count amount */
2568                                         if(event==1) tot= 1;
2569                                         else {
2570                                                 ik= G.sipo->ipokey.first;
2571                                                 tot= 0;
2572                                                 while(ik) {
2573                                                         if(ik->flag & 1) tot++;
2574                                                         ik= ik->next;
2575                                                 }
2576                                         }
2577                                         if(tot) {
2578                                         
2579                                                 /* correction for ob timeoffs */
2580                                                 cfra= frame_to_float(CFRA);
2581                                                 id= G.sipo->from;       
2582                                                 if(id && GS(id->name)==ID_OB ) {
2583                                                         Object *ob= (Object *)id;
2584                                                         if(ob->sf!=0.0 && (ob->ipoflag & OB_OFFS_OB) ) {
2585                                                                 cfra-= ob->sf*G.scene->r.framelen;
2586                                                         }
2587                                                 }
2588                                                 else if(id && GS(id->name)==ID_SEQ) {
2589                                                         Sequence *last_seq = get_last_seq();    /* editsequence.c */
2590                                                         
2591                                                         if(last_seq && (last_seq->flag & SEQ_IPO_FRAME_LOCKED) == 0) {
2592                                                                 cfra= (float)(100.0*(cfra-last_seq->startdisp)/((float)(last_seq->enddisp-last_seq->startdisp)));
2593                                                         }
2594                                                 }
2595                                                 
2596                                                 /* convert cfra to ipo-time */
2597                                                 if (NLA_IPO_SCALED) {
2598                                                         cfra= get_action_frame(OBACT, cfra);
2599                                                 }
2600                                 
2601                                                 insertvals= MEM_mallocN(sizeof(float)*2*tot, "insertkey_editipo");
2602                                                 /* make sure icu->curval is correct */
2603                                                 calc_ipo(G.sipo->ipo, cfra);
2604                                                 
2605                                                 if(event==1) {
2606                                                         insertvals[0]= cfra;
2607                                                         
2608                                                         insertvals[1]= ei->icu->curval;
2609                                                 }
2610                                                 else {
2611                                                         fp= insertvals;
2612                                                         ik= G.sipo->ipokey.first;
2613                                                         while(ik) {
2614                                                                 if(ik->flag & 1) {
2615                                                                         calc_ipo(G.sipo->ipo, ik->val);
2616
2617                                                                         fp[0]= ik->val;
2618                                                                         fp[1]= ei->icu->curval;
2619                                                                         fp+= 2;
2620                                                                 }
2621                                                                 ik= ik->next;
2622                                                         }
2623                                                 }
2624                                                 fp= insertvals;
2625                                                 for(a=0; a<tot; a++, fp+=2) {
2626                                                         insert_vert_ipo(ei->icu, fp[0], fp[1]);
2627                                                 }
2628                                                 
2629                                                 MEM_freeN(insertvals);
2630                                                 calc_ipo(G.sipo->ipo, (float)CFRA);
2631                                         }
2632                                 }
2633                         }
2634                 }
2635         }
2636         BIF_undo_push("Insert Key Ipo");
2637         allqueue (REDRAWACTION, 0);
2638         allqueue(REDRAWNLA, 0);
2639         allqueue(REDRAWIPO, 0);
2640         allspace(REMAKEIPO, 0);
2641 }
2642
2643
2644 void common_insertkey(void)
2645 {
2646         Base *base;
2647         Object *ob;
2648         Material *ma;
2649         ID *id;
2650         IpoCurve *icu;
2651         World *wo;
2652         Lamp *la;
2653         Tex *te;
2654         int tlay, map, event;
2655         char menustr[256];
2656
2657         if(curarea->spacetype==SPACE_IPO) {
2658                 insertkey_editipo();
2659         }
2660         else if(curarea->spacetype==SPACE_ACTION) {
2661                 insertkey_action();
2662         }
2663         else if(curarea->spacetype==SPACE_BUTS) {
2664                 if(G.buts->mainb==CONTEXT_SHADING) {
2665                         int tab= G.buts->tab[CONTEXT_SHADING];
2666
2667                         if(tab==TAB_SHADING_MAT) {
2668                                 ma = G.buts->lockpoin;
2669                                 ma = editnode_get_active_material(ma);
2670                                 id = (ID *)ma;
2671                                 
2672                                 if(id) {
2673                                         event= pupmenu("Insert Key %t|RGB%x0|Alpha%x1|Halo Size%x2|Mode %x3|All Color%x10|All Mirror%x14|Ofs%x12|Size%x13|All Mapping%x11");
2674                                         if(event== -1) return;
2675
2676                                         map= texchannel_to_adrcode(ma->texact);
2677
2678                                         if(event==0 || event==10) {
2679                                                 insertkey(id, ID_MA, NULL, NULL, MA_COL_R);
2680                                                 insertkey(id, ID_MA, NULL, NULL, MA_COL_G);
2681                                                 insertkey(id, ID_MA, NULL, NULL, MA_COL_B);
2682                                         }
2683                                         if(event==1 || event==10) {
2684                                                 insertkey(id, ID_MA, NULL, NULL, MA_ALPHA);
2685                                         }
2686                                         if(event==2 || event==10) {
2687                                                 insertkey(id, ID_MA, NULL, NULL, MA_HASIZE);
2688                                         }
2689                                         if(event==3 || event==10) {
2690                                                 insertkey(id, ID_MA, NULL, NULL, MA_MODE);
2691                                         }
2692                                         if(event==10) {
2693                                                 insertkey(id, ID_MA, NULL, NULL, MA_SPEC_R);
2694                                                 insertkey(id, ID_MA, NULL, NULL, MA_SPEC_G);
2695                                                 insertkey(id, ID_MA, NULL, NULL, MA_SPEC_B);
2696                                                 insertkey(id, ID_MA, NULL, NULL, MA_REF);
2697                                                 insertkey(id, ID_MA, NULL, NULL, MA_EMIT);
2698                                                 insertkey(id, ID_MA, NULL, NULL, MA_AMB);
2699                                                 insertkey(id, ID_MA, NULL, NULL, MA_SPEC);
2700                                                 insertkey(id, ID_MA, NULL, NULL, MA_HARD);
2701                                                 insertkey(id, ID_MA, NULL, NULL, MA_MODE);
2702                                                 insertkey(id, ID_MA, NULL, NULL, MA_TRANSLU);
2703                                                 insertkey(id, ID_MA, NULL, NULL, MA_ADD);
2704                                         }
2705                                         if(event==14) {
2706                                                 insertkey(id, ID_MA, NULL, NULL, MA_RAYM);
2707                                                 insertkey(id, ID_MA, NULL, NULL, MA_FRESMIR);
2708                                                 insertkey(id, ID_MA, NULL, NULL, MA_FRESMIRI);
2709                                                 insertkey(id, ID_MA, NULL, NULL, MA_FRESTRA);
2710                                                 insertkey(id, ID_MA, NULL, NULL, MA_FRESTRAI);
2711                                         }
2712                                         if(event==12 || event==11) {
2713                                                 insertkey(id, ID_MA, NULL, NULL, map+MAP_OFS_X);
2714                                                 insertkey(id, ID_MA, NULL, NULL, map+MAP_OFS_Y);
2715                                                 insertkey(id, ID_MA, NULL, NULL, map+MAP_OFS_Z);
2716                                         }
2717                                         if(event==13 || event==11) {
2718                                                 insertkey(id, ID_MA, NULL, NULL, map+MAP_SIZE_X);
2719                                                 insertkey(id, ID_MA, NULL, NULL, map+MAP_SIZE_Y);
2720                                                 insertkey(id, ID_MA, NULL, NULL, map+MAP_SIZE_Z);
2721                                         }
2722                                         if(event==11) {
2723                                                 insertkey(id, ID_MA, NULL, NULL, map+MAP_R);
2724                                                 insertkey(id, ID_MA, NULL, NULL, map+MAP_G);
2725                                                 insertkey(id, ID_MA, NULL, NULL, map+MAP_B);
2726                                                 insertkey(id, ID_MA, NULL, NULL, map+MAP_DVAR);
2727                                                 insertkey(id, ID_MA, NULL, NULL, map+MAP_COLF);
2728                                                 insertkey(id, ID_MA, NULL, NULL, map+MAP_NORF);
2729                                                 insertkey(id, ID_MA, NULL, NULL, map+MAP_VARF);
2730                                                 insertkey(id, ID_MA, NULL, NULL, map+MAP_DISP);
2731                                         }
2732                                 }
2733                         }
2734                         else if(tab==TAB_SHADING_WORLD) {
2735                                 id= G.buts->lockpoin;
2736                                 wo= G.buts->lockpoin;
2737                                 if(id) {
2738                                         event= pupmenu("Insert Key %t|Zenith RGB%x0|Horizon RGB%x1|Mist%x2|Stars %x3|Offset%x12|Size%x13");
2739                                         if(event== -1) return;
2740
2741                                         map= texchannel_to_adrcode(wo->texact);
2742
2743                                         if(event==0) {
2744                                                 insertkey(id, ID_WO, NULL, NULL, WO_ZEN_R);
2745                                                 insertkey(id, ID_WO, NULL, NULL, WO_ZEN_G);
2746                                                 insertkey(id, ID_WO, NULL, NULL, WO_ZEN_B);
2747                                         }
2748                                         if(event==1) {
2749                                                 insertkey(id, ID_WO, NULL, NULL, WO_HOR_R);
2750                                                 insertkey(id, ID_WO, NULL, NULL, WO_HOR_G);
2751                                                 insertkey(id, ID_WO, NULL, NULL, WO_HOR_B);
2752                                         }
2753                                         if(event==2) {
2754                                                 insertkey(id, ID_WO, NULL, NULL, WO_MISI);
2755                                                 insertkey(id, ID_WO, NULL, NULL, WO_MISTDI);
2756                                                 insertkey(id, ID_WO, NULL, NULL, WO_MISTSTA);
2757                                                 insertkey(id, ID_WO, NULL, NULL, WO_MISTHI);
2758                                         }
2759                                         if(event==3) {
2760                                                 insertkey(id, ID_WO, NULL, NULL, WO_STAR_R);
2761                                                 insertkey(id, ID_WO, NULL, NULL, WO_STAR_G);
2762                                                 insertkey(id, ID_WO, NULL, NULL, WO_STAR_B);
2763                                                 insertkey(id, ID_WO, NULL, NULL, WO_STARDIST);
2764                                                 insertkey(id, ID_WO, NULL, NULL, WO_STARSIZE);
2765                                         }
2766                                         if(event==12) {
2767                                                 insertkey(id, ID_WO, NULL, NULL, map+MAP_OFS_X);
2768                                                 insertkey(id, ID_WO, NULL, NULL, map+MAP_OFS_Y);
2769                                                 insertkey(id, ID_WO, NULL, NULL, map+MAP_OFS_Z);
2770                                         }
2771                                         if(event==13) {
2772                                                 insertkey(id, ID_WO, NULL, NULL, map+MAP_SIZE_X);
2773                                                 insertkey(id, ID_WO, NULL, NULL, map+MAP_SIZE_Y);
2774                                                 insertkey(id, ID_WO, NULL, NULL, map+MAP_SIZE_Z);
2775                                         }
2776                                 }
2777                         }
2778                         else if(tab==TAB_SHADING_LAMP) {
2779                                 id= G.buts->lockpoin;
2780                                 la= G.buts->lockpoin;
2781                                 if(id) {
2782                                         event= pupmenu("Insert Key %t|RGB%x0|Energy%x1|Spot Size%x2|Offset%x12|Size%x13");
2783                                         if(event== -1) return;
2784
2785                                         map= texchannel_to_adrcode(la->texact);
2786
2787                                         if(event==0) {
2788                                                 insertkey(id, ID_LA, NULL, NULL, LA_COL_R);
2789                                                 insertkey(id, ID_LA, NULL, NULL, LA_COL_G);
2790                                                 insertkey(id, ID_LA, NULL, NULL, LA_COL_B);
2791                                         }
2792                                         if(event==1) {
2793                                                 insertkey(id, ID_LA, NULL, NULL, LA_ENERGY);
2794                                         }
2795                                         if(event==2) {
2796                                                 insertkey(id, ID_LA, NULL, NULL, LA_SPOTSI);
2797                                         }
2798                                         if(event==12) {
2799                                                 insertkey(id, ID_LA, NULL, NULL, map+MAP_OFS_X);
2800                                                 insertkey(id, ID_LA, NULL, NULL, map+MAP_OFS_Y);
2801                                                 insertkey(id, ID_LA, NULL, NULL, map+MAP_OFS_Z);
2802                                         }
2803                                         if(event==13) {
2804                                                 insertkey(id, ID_LA, NULL, NULL, map+MAP_SIZE_X);
2805                                                 insertkey(id, ID_LA, NULL, NULL, map+MAP_SIZE_Y);
2806                                                 insertkey(id, ID_LA, NULL, NULL, map+MAP_SIZE_Z);
2807                                         }
2808
2809                                 }
2810                         }
2811                         else if(tab==TAB_SHADING_TEX) {
2812                                 id= G.buts->lockpoin;
2813                                 te= G.buts->lockpoin;
2814                                 if(id) {
2815                                         event= pupmenu("Insert Key %t|Clouds%x0|Marble%x1|Stucci%x2|Wood%x3|Magic%x4|Blend%x5|Musgrave%x6|Voronoi%x7|DistortedNoise%x8|ColorFilter%x9");
2816                                         if(event== -1) return;
2817
2818                                         if(event==0) {
2819                                                 insertkey(id, ID_TE, NULL, NULL, TE_NSIZE);
2820                                                 insertkey(id, ID_TE, NULL, NULL, TE_NDEPTH);
2821                                                 insertkey(id, ID_TE, NULL, NULL, TE_NTYPE);
2822                                                 insertkey(id, ID_TE, NULL, NULL, TE_MG_TYP);
2823                                                 insertkey(id, ID_TE, NULL, NULL, TE_N_BAS1);
2824                                         }
2825                                         if(event==1) {
2826                                                 insertkey(id, ID_TE, NULL, NULL, TE_NSIZE);
2827                                                 insertkey(id, ID_TE, NULL, NULL, TE_NDEPTH);
2828                                                 insertkey(id, ID_TE, NULL, NULL, TE_NTYPE);
2829                                                 insertkey(id, ID_TE, NULL, NULL, TE_TURB);
2830                                                 insertkey(id, ID_TE, NULL, NULL, TE_MG_TYP);
2831                                                 insertkey(id, ID_TE, NULL, NULL, TE_N_BAS1);
2832                                                 insertkey(id, ID_TE, NULL, NULL, TE_N_BAS2);
2833                                         }
2834                                         if(event==2) {
2835                                                 insertkey(id, ID_TE, NULL, NULL, TE_NSIZE);
2836                                                 insertkey(id, ID_TE, NULL, NULL, TE_NTYPE);
2837                                                 insertkey(id, ID_TE, NULL, NULL, TE_TURB);
2838                                                 insertkey(id, ID_TE, NULL, NULL, TE_MG_TYP);
2839                                                 insertkey(id, ID_TE, NULL, NULL, TE_N_BAS1);
2840                                         }
2841                                         if(event==3) {
2842                                                 insertkey(id, ID_TE, NULL, NULL, TE_NSIZE);
2843                                                 insertkey(id, ID_TE, NULL, NULL, TE_NTYPE);
2844                                                 insertkey(id, ID_TE, NULL, NULL, TE_TURB);
2845                                                 insertkey(id, ID_TE, NULL, NULL, TE_MG_TYP);
2846                                                 insertkey(id, ID_TE, NULL, NULL, TE_N_BAS1);
2847                                                 insertkey(id, ID_TE, NULL, NULL, TE_N_BAS2);
2848                                         }
2849                                         if(event==4) {
2850                                                 insertkey(id, ID_TE, NULL, NULL, TE_NDEPTH);
2851                                                 insertkey(id, ID_TE, NULL, NULL, TE_TURB);
2852                                         }
2853                                         if(event==5) {
2854                                                 insertkey(id, ID_TE, NULL, NULL, TE_MG_TYP);
2855                                         } 
2856                                         if(event==6) {
2857                                                 insertkey(id, ID_TE, NULL, NULL, TE_MG_TYP);
2858                                                 insertkey(id, ID_TE, NULL, NULL, TE_MGH);
2859                                                 insertkey(id, ID_TE, NULL, NULL, TE_MG_LAC);
2860                                                 insertkey(id, ID_TE, NULL, NULL, TE_MG_OCT);
2861                                                 insertkey(id, ID_TE, NULL, NULL, TE_MG_OFF);
2862                                                 insertkey(id, ID_TE, NULL, NULL, TE_MG_GAIN);
2863                                         }
2864                                         if(event==7) {
2865                                                 insertkey(id, ID_TE, NULL, NULL, TE_VNW1);
2866                                                 insertkey(id, ID_TE, NULL, NULL, TE_VNW2);
2867                                                 insertkey(id, ID_TE, NULL, NULL, TE_VNW3);
2868                                                 insertkey(id, ID_TE, NULL, NULL, TE_VNW4);
2869                                                 insertkey(id, ID_TE, NULL, NULL, TE_VNMEXP);
2870                                                 insertkey(id, ID_TE, NULL, NULL, TE_VN_DISTM);
2871                                                 insertkey(id, ID_TE, NULL, NULL, TE_VN_COLT);
2872                                                 insertkey(id, ID_TE, NULL, NULL, TE_ISCA);
2873                                                 insertkey(id, ID_TE, NULL, NULL, TE_NSIZE);
2874                                         }
2875                                         if(event==8) {
2876                                                 insertkey(id, ID_TE, NULL, NULL, TE_MG_OCT);
2877                                                 insertkey(id, ID_TE, NULL, NULL, TE_MG_OFF);
2878                                                 insertkey(id, ID_TE, NULL, NULL, TE_MG_GAIN);
2879                                                 insertkey(id, ID_TE, NULL, NULL, TE_DISTA);
2880                                         }
2881                                         if(event==9) {
2882                                                 insertkey(id, ID_TE, NULL, NULL, TE_COL_R);
2883                                                 insertkey(id, ID_TE, NULL, NULL, TE_COL_G);
2884                                                 insertkey(id, ID_TE, NULL, NULL, TE_COL_B);
2885                                                 insertkey(id, ID_TE, NULL, NULL, TE_BRIGHT);
2886                                                 insertkey(id, ID_TE, NULL, NULL, TE_CONTRA);
2887                                         }
2888                                 }
2889                         }
2890                 }
2891                 else if(G.buts->mainb==CONTEXT_OBJECT) {
2892                         ob= OBACT;
2893                         if(ob) {
2894                                 id= (ID *) (ob);
2895                                 if(id) {
2896                                         if(ob->type==OB_MESH) 
2897                                                 event= pupmenu("Insert Key %t|Surface Damping%x0|Random Damping%x1|Permeability%x2|Force Strength%x3|Force Falloff%x4");
2898                                         else
2899                                                 event= pupmenu("Insert Key %t|Force Strength%x3|Force Falloff%x4");
2900                                         if(event == -1) return;