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