Orange: more work on float/exr buffers;
[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;
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                 ei->icu= find_ipocurve(si->ipo, ei->adrcode);
607                 if(ei->icu) {
608                         ei->flag= ei->icu->flag;
609                 }
610                 
611                 ei++;
612         }
613 }
614
615 static void make_world_editipo(SpaceIpo *si)
616 {
617         EditIpo *ei;
618         int a, len;
619         char *name;
620         
621         if(si->from==0) return;
622         
623         ei= si->editipo= MEM_callocN(WO_TOTIPO*sizeof(EditIpo), "editipo");
624         
625         si->totipo= WO_TOTIPO;
626         
627         for(a=0; a<WO_TOTIPO; a++) {
628                 name = getname_world_ei(wo_ar[a]);
629                 
630                 strcpy(ei->name, name); 
631                 ei->adrcode= wo_ar[a];
632                 
633                 if(ei->adrcode & MA_MAP1) {
634                         ei->adrcode-= MA_MAP1;
635                         ei->adrcode |= texchannel_to_adrcode(si->channel);
636                 }
637                 else {
638                         if(ei->adrcode==MA_MODE) ei->disptype= IPO_DISPBITS;
639                 }
640                 
641                 ei->col= ipo_rainbow(a, WO_TOTIPO);
642                 
643                 len= strlen(ei->name);
644                 if(len) {
645                         if( ei->name[ len-1 ]=='R') ei->col= 0x5050FF;
646                         else if( ei->name[ len-1 ]=='G') ei->col= 0x50FF50;
647                         else if( ei->name[ len-1 ]=='B') ei->col= 0xFF7050;
648                 }
649                 
650                 ei->icu= find_ipocurve(si->ipo, ei->adrcode);
651                 if(ei->icu) {
652                         ei->flag= ei->icu->flag;
653                 }
654                 
655                 ei++;
656         }
657 }
658
659 static void make_lamp_editipo(SpaceIpo *si)
660 {
661         EditIpo *ei;
662         int a;
663         char *name;
664         
665         ei= si->editipo= MEM_callocN(LA_TOTIPO*sizeof(EditIpo), "editipo");
666         
667         si->totipo= LA_TOTIPO;
668         
669         for(a=0; a<LA_TOTIPO; a++) {
670                 name = getname_la_ei(la_ar[a]);
671                 strcpy(ei->name, name);
672                 ei->adrcode= la_ar[a];
673
674                 if(ei->adrcode & MA_MAP1) {
675                         ei->adrcode-= MA_MAP1;
676                         ei->adrcode |= texchannel_to_adrcode(si->channel);
677                 }
678
679                 ei->col= ipo_rainbow(a, LA_TOTIPO);
680                 
681                 ei->icu= find_ipocurve(si->ipo, ei->adrcode);
682                 if(ei->icu) {
683                         ei->flag= ei->icu->flag;
684                 }
685                 
686                 ei++;
687         }
688 }
689
690 static void make_camera_editipo(SpaceIpo *si)
691 {
692         EditIpo *ei;
693         int a;
694         char *name;
695         
696         ei= si->editipo= MEM_callocN(CAM_TOTIPO*sizeof(EditIpo), "editipo");
697         
698         si->totipo= CAM_TOTIPO;
699         
700         
701         for(a=0; a<CAM_TOTIPO; a++) {
702                 name = getname_cam_ei(cam_ar[a]);
703                 strcpy(ei->name, name);
704                 ei->adrcode= cam_ar[a];
705
706                 ei->col= ipo_rainbow(a, CAM_TOTIPO);
707                 
708                 ei->icu= find_ipocurve(si->ipo, ei->adrcode);
709                 if(ei->icu) {
710                         ei->flag= ei->icu->flag;
711                 }
712                 
713                 ei++;
714         }
715 }
716
717 static int make_constraint_editipo(Ipo *ipo, EditIpo **si)
718 {
719         EditIpo *ei;
720         int a;
721         char *name;
722         
723         ei= *si= MEM_callocN(CO_TOTIPO*sizeof(EditIpo), "editipo");
724         
725         for(a=0; a<CO_TOTIPO; a++) {
726                 name = getname_co_ei(co_ar[a]);
727                 strcpy(ei->name, name);
728                 ei->adrcode= co_ar[a];
729
730                 ei->col= ipo_rainbow(a, CO_TOTIPO);
731                 
732                 ei->icu= find_ipocurve(ipo, ei->adrcode);
733                 if(ei->icu) {
734                         ei->flag= ei->icu->flag;
735                 }
736                 
737                 ei++;
738         }
739
740         return CO_TOTIPO;
741 }
742
743 static int make_bone_editipo(Ipo *ipo, EditIpo **si)
744 {
745         EditIpo *ei;
746         int a;
747         char *name;
748         
749         ei= *si= MEM_callocN(AC_TOTIPO*sizeof(EditIpo), "editipo");
750         
751         for(a=0; a<AC_TOTIPO; a++) {
752                 name = getname_ac_ei(ac_ar[a]);
753                 strcpy(ei->name, name);
754                 ei->adrcode= ac_ar[a];
755
756                 ei->col= ipo_rainbow(a, AC_TOTIPO);
757                 
758                 ei->icu= find_ipocurve(ipo, ei->adrcode);
759                 if(ei->icu) {
760                         ei->flag= ei->icu->flag;
761                 }
762                 
763                 ei++;
764         }
765
766         return AC_TOTIPO;
767 }
768
769 static void make_sound_editipo(SpaceIpo *si)
770 {
771         EditIpo *ei;
772         int a;
773         char *name;
774         
775         ei= si->editipo= MEM_callocN(SND_TOTIPO*sizeof(EditIpo), "editipo");
776         
777         si->totipo= SND_TOTIPO;
778         
779         
780         for(a=0; a<SND_TOTIPO; a++) {
781                 name = getname_snd_ei(snd_ar[a]);
782                 strcpy(ei->name, name);
783                 ei->adrcode= snd_ar[a];
784
785                 ei->col= ipo_rainbow(a, SND_TOTIPO);
786                 
787                 ei->icu= find_ipocurve(si->ipo, ei->adrcode);
788                 if(ei->icu) {
789                         ei->flag= ei->icu->flag;
790                 }
791                 
792                 ei++;
793         }
794 }
795
796 /* only called in test_editipo() below */
797 static void make_editipo(void)
798 {
799         EditIpo *ei;
800         Object *ob;
801         rctf *rf;
802         int a;
803
804         if(G.sipo->editipo)
805                 MEM_freeN(G.sipo->editipo);
806         
807         G.sipo->editipo= NULL;
808         G.sipo->totipo= 0;
809         
810         if(G.sipo->from==NULL) return;
811         
812         ob= OBACT;
813
814         if(G.sipo->ipo) G.sipo->showkey= G.sipo->ipo->showkey;
815
816         if(G.sipo->blocktype==ID_SEQ) {
817                 make_seq_editipo(G.sipo);
818         }
819         else if(G.sipo->blocktype==ID_WO) {
820                 make_world_editipo(G.sipo);
821         } 
822         else if(G.sipo->blocktype==ID_OB) {
823                 if (ob) {
824                         ob->ipowin= ID_OB;
825                         make_ob_editipo(ob, G.sipo);
826                 }
827         }
828         else if(G.sipo->blocktype==ID_MA) {
829                 if (ob) {
830                         ob->ipowin= ID_MA;
831                         make_mat_editipo(G.sipo);
832                 }
833         }
834         else if(G.sipo->blocktype==ID_CU) {
835                 if (ob) {
836                         ob->ipowin= ID_CU;
837                         make_cu_editipo(G.sipo);
838                 }
839         }
840         else if(G.sipo->blocktype==ID_KE) {
841                 if (ob) {
842                         ob->ipowin= ID_KE;
843                         make_key_editipo(G.sipo);
844                 }
845         }
846         else if(G.sipo->blocktype==ID_LA) {
847                 if (ob) {
848                         ob->ipowin= ID_LA;
849                         make_lamp_editipo(G.sipo);
850                 }
851         }
852         else if(G.sipo->blocktype==ID_TE) {
853                 if (ob) {
854                         ob->ipowin= ID_TE;
855                         make_texture_editipo(G.sipo);
856                 }
857         }
858         else if(G.sipo->blocktype==ID_CA) {
859                 if (ob) {
860                         ob->ipowin= ID_CA;
861                         make_camera_editipo(G.sipo);
862                 }
863         }
864         else if(G.sipo->blocktype==ID_SO) {
865                 if (ob) {
866                         ob->ipowin= ID_SO;
867                         make_sound_editipo(G.sipo);
868                 }
869         }
870         else if(G.sipo->blocktype==ID_CO){
871                 G.sipo->totipo = make_constraint_editipo(G.sipo->ipo, (EditIpo**)&G.sipo->editipo);
872                 if (ob) {
873                         ob->ipowin= ID_CO;
874                 }
875         }
876         else if(G.sipo->blocktype==ID_PO) {
877
878                 G.sipo->totipo = make_bone_editipo(G.sipo->ipo, (EditIpo**)&G.sipo->editipo);
879                 if (ob) {
880                         ob->ipowin= ID_PO;
881                 }
882         }
883
884         if(G.sipo->editipo==0) return;
885         
886         ei= G.sipo->editipo;
887         for(a=0; a<G.sipo->totipo; a++, ei++) {
888                 if(ei->icu) ei->icu->flag= ei->flag;
889         }
890         editipo_changed(G.sipo, 0);
891         
892         if(G.sipo->ipo) {
893
894                 if (G.sipo->pin)
895                         rf= &(G.sipo->v2d.cur);
896                 else
897                         rf= &(G.sipo->ipo->cur);
898                 
899                 if(rf->xmin<rf->xmax && rf->ymin<rf->ymax) G.v2d->cur= *rf;
900                 else ipo_default_v2d_cur(G.sipo->blocktype, &G.v2d->cur);
901         }
902         else {
903                 ipo_default_v2d_cur(G.sipo->blocktype, &G.v2d->cur);
904         }
905         
906         view2d_do_locks(curarea, V2D_LOCK_COPY);
907 }
908
909 /* evaluates context in the current UI */
910 /* blocktype is type of ipo */
911 /* from is the base pointer to find data to change (ob in case of action or pose) */
912 static void get_ipo_context(short blocktype, ID **from, Ipo **ipo, char *actname, char *constname)
913 {
914         Object *ob= OBACT;
915         
916         *from= NULL;
917         *ipo= NULL;
918         
919         if(blocktype==ID_CO) {
920                 if (ob) {
921                         bConstraintChannel *chan;
922                         bConstraint *con= get_active_constraint(ob);
923                         
924                         if(con) {
925                                 BLI_strncpy(constname, con->name, 32);
926                                 
927                                 chan= get_active_constraint_channel(ob);
928                                 if(chan) {
929                                         *ipo= chan->ipo;
930                                         BLI_strncpy(constname, con->name, 32);
931                                 }
932                                 
933                                 *from= &ob->id;
934                                 
935                                 /* set actname if in posemode */
936                                 if(ob->action) {
937                                         if(ob->flag & OB_POSEMODE) {
938                                                 bPoseChannel *pchan= get_active_posechannel(ob);
939                                                 if(pchan)
940                                                         BLI_strncpy(actname, pchan->name, 32);
941                                         }
942                                         else if(ob->ipoflag & OB_ACTION_OB)
943                                                 strcpy(actname, "Object");
944                                 }
945                         }
946                 }
947         }
948         else if(blocktype==ID_PO) {
949                 if (ob && ob->action && ob->type==OB_ARMATURE) {
950                         bPoseChannel *pchan= get_active_posechannel(ob);
951                         
952                         *from= (ID *)ob;
953                         if (pchan) {
954                                 bActionChannel *achan;
955                                 
956                                 BLI_strncpy(actname, pchan->name, 32);  /* also set when no channel yet */
957                                 
958                                 achan= get_action_channel(ob->action, pchan->name);
959                                 if(achan)
960                                         *ipo= achan->ipo;
961                         }
962                 } 
963                 
964         }
965         else if(blocktype==ID_OB) {
966                 if(ob) {
967                         *from= (ID *)ob;
968                         if(ob->ipoflag & OB_ACTION_OB) {
969                                 if (ob->action) {
970                                         bActionChannel *achan= get_action_channel(ob->action, "Object");
971                                         if(achan) {
972                                                 *ipo= achan->ipo;
973                                                 BLI_strncpy(actname, achan->name, 32);
974                                         }
975                                 }
976                         }
977                         else {
978                                 *ipo= ob->ipo;
979                         }
980                 }
981         }
982         else if(blocktype==ID_SEQ) {
983                 extern Sequence *last_seq;
984                 
985                 if(last_seq && ((last_seq->type & SEQ_EFFECT)||(last_seq->type == SEQ_SOUND))) {
986                         *from= (ID *)last_seq;
987                         *ipo= last_seq->ipo;
988                 }
989         }
990         else if(blocktype==ID_WO) {
991                 World *wo= G.scene->world;
992                 *from= (ID *)wo;
993                 if(wo) *ipo= wo->ipo;
994         }
995         else if(blocktype==ID_TE) {
996                 if(ob) {
997                         Tex *tex= give_current_texture(ob, ob->actcol);
998                         *from= (ID *)tex;
999                         if(tex) *ipo= tex->ipo;
1000                 }
1001         }
1002         else if(blocktype==ID_MA) {
1003                 if(ob) {
1004                         Material *ma= give_current_material(ob, ob->actcol);
1005                         *from= (ID *)ma;
1006                         if(ma) *ipo= ma->ipo;
1007                 }
1008         }
1009         else if(blocktype==ID_KE) {
1010                 if(ob) {
1011                         Key *key= ob_get_key(ob);
1012                         
1013                         if(ob->ipoflag & OB_ACTION_KEY) {
1014                                 if (ob->action) {
1015                                         bActionChannel *achan= get_action_channel(ob->action, "Shape");
1016                                         if(achan) {
1017                                                 *ipo= achan->ipo;
1018                                                 BLI_strncpy(actname, achan->name, 32);
1019                                         }
1020                                 }
1021                         }
1022                         else if(key) *ipo= key->ipo;
1023                         
1024                         *from= (ID *)ob;
1025                 }
1026         }
1027         else if(blocktype==ID_CU) {
1028                 if(ob && ob->type==OB_CURVE) {
1029                         Curve *cu= ob->data;
1030                         *from= (ID *)cu;
1031                         *ipo= cu->ipo;
1032                 }
1033         }
1034         else if(blocktype==ID_LA) {
1035                 if(ob && ob->type==OB_LAMP) {
1036                         Lamp *la= ob->data;
1037                         *from= (ID *)la;
1038                         *ipo= la->ipo;
1039                 }
1040         }
1041         else if(blocktype==ID_CA) {
1042                 if(ob && ob->type==OB_CAMERA) {
1043                         Camera *ca= ob->data;
1044                         *from= (ID *)ca;
1045                         if(ca) *ipo= ca->ipo;
1046                 }
1047         }
1048         else if(blocktype==ID_SO) {
1049                 
1050                 //              if (G.buts && G.buts->mainb == BUTS_SOUND) {
1051                 //                      bSound *sound = G.buts->lockpoin;
1052                 //                      *from= (ID *)sound;
1053                 //                      if(sound) *ipo= sound->ipo;
1054                 //              }
1055         }
1056 }
1057
1058 /* called on each redraw, check if editipo data has to be remade */
1059 /* if doit already set, it always makes (in case no ipo exists, we need to see the channels */
1060 void test_editipo(int doit)
1061 {
1062         
1063         if(G.sipo->pin==0) {
1064                 Ipo *ipo;
1065                 ID *from;
1066                 char actname[32]="", constname[32]="";
1067                 
1068                 get_ipo_context(G.sipo->blocktype, &from, &ipo, actname, constname);
1069                 
1070                 if(G.sipo->ipo != ipo) {
1071                         G.sipo->ipo= ipo;
1072                         if(ipo) G.v2d->cur= ipo->cur;
1073                         doit= 1;
1074                 }
1075                 if(G.sipo->from != from) {
1076                         G.sipo->from= from;
1077                         doit= 1;
1078                 }
1079                 if( strcmp(G.sipo->actname, actname)) {
1080                         BLI_strncpy(G.sipo->actname, actname, 32);
1081                         doit= 1;
1082                 }
1083                 if( strcmp(G.sipo->constname, constname)) {
1084                         BLI_strncpy(G.sipo->constname, constname, 32);
1085                         doit= 1;
1086                 }
1087                 
1088                 if(G.sipo->ipo)
1089                         G.sipo->ipo->cur = G.v2d->cur;
1090                 
1091         }
1092                 
1093         if(G.sipo->editipo==NULL || doit) {
1094                 make_editipo();
1095         }
1096 }
1097
1098 /* ****************** EditIpo ************************ */
1099
1100 int totipo_edit, totipo_sel, totipo_curve, totipo_vis, totipo_vert, totipo_vertsel, totipo_key, totipo_keysel;
1101
1102 void get_status_editipo(void)
1103 {
1104         EditIpo *ei;
1105         IpoKey *ik;
1106         BezTriple *bezt;
1107         int a, b;
1108         
1109         totipo_vis= 0;
1110         totipo_curve= 0;
1111         totipo_sel= 0;
1112         totipo_edit= 0;
1113         totipo_vert= 0;
1114         totipo_vertsel= 0;
1115         totipo_key= 0;
1116         totipo_keysel= 0;
1117         
1118         if(G.sipo->ipo && G.sipo->ipo->id.lib) return;
1119         
1120         ei= G.sipo->editipo;
1121         if(ei==0) return;
1122         for(a=0; a<G.sipo->totipo; a++) {
1123                 if( ei->flag & IPO_VISIBLE ) {
1124                         totipo_vis++;
1125                         if(ei->flag & IPO_SELECT) totipo_sel++;
1126                         if(ei->icu && ei->icu->totvert) totipo_curve++;
1127                         if(G.sipo->showkey || (ei->flag & IPO_EDIT)) {
1128                                 
1129                                 /* if showkey: do count the vertices (for grab) */
1130                                 if(G.sipo->showkey==0) totipo_edit++;
1131                                 
1132                                 if(ei->icu) {
1133                                         if(ei->icu->bezt) {
1134                                                 bezt= ei->icu->bezt;
1135                                                 b= ei->icu->totvert;
1136                                                 while(b--) {
1137                                                         if(ei->icu->ipo==IPO_BEZ) {
1138                                                                 if(bezt->f1 & 1) totipo_vertsel++;
1139                                                                 if(bezt->f3 & 1) totipo_vertsel++;
1140                                                                 totipo_vert+= 2;
1141                                                         }
1142                                                         if(bezt->f2 & 1) totipo_vertsel++;
1143                                                         
1144                                                         totipo_vert++;
1145                                                         bezt++;
1146                                                 }
1147                                         }
1148                                 }
1149                         }
1150                 }
1151                 ei++;
1152         }
1153         
1154         if(G.sipo->showkey) {
1155                 ik= G.sipo->ipokey.first;
1156                 while(ik) {
1157                         totipo_key++;
1158                         if(ik->flag & 1) totipo_keysel++;
1159                         ik= ik->next;
1160                 }
1161         }
1162 }
1163
1164 /* synchronize editipo flag with icu flag and ipokey flags */
1165 void update_editipo_flags(void)
1166 {
1167         EditIpo *ei;
1168         IpoKey *ik;
1169         int a;
1170         
1171         ei= G.sipo->editipo;
1172         if(ei) {
1173                 for(a=0; a<G.sipo->totipo; a++, ei++) {
1174                         if(ei->icu) ei->icu->flag= ei->flag;
1175                 }
1176         }
1177         if(G.sipo->showkey) {
1178                 ik= G.sipo->ipokey.first;
1179                 while(ik) {
1180                         for(a=0; a<G.sipo->totipo; a++) {
1181                                 if(ik->data[a]) {
1182                                         if(ik->flag & 1) {
1183                                                 ik->data[a]->f1 |= 1;
1184                                                 ik->data[a]->f2 |= 1;
1185                                                 ik->data[a]->f3 |= 1;
1186                                         }
1187                                         else {
1188                                                 ik->data[a]->f1 &= ~1;
1189                                                 ik->data[a]->f2 &= ~1;
1190                                                 ik->data[a]->f3 &= ~1;
1191                                         }
1192                                 }
1193                         }
1194                         ik= ik->next;
1195                 }
1196         }
1197 }
1198
1199 /* sort of enter/leave editmode for curves */
1200 void set_editflag_editipo(void)
1201 {
1202         EditIpo *ei;
1203         int a; /*  , tot= 0, ok= 0; */
1204         
1205         /* after showkey immediately go to editing of selected points */
1206         if(G.sipo->showkey) {
1207                 G.sipo->showkey= 0;
1208                 if(G.sipo->ipo) G.sipo->ipo->showkey= 0;
1209                 ei= G.sipo->editipo;
1210                 for(a=0; a<G.sipo->totipo; a++, ei++) ei->flag |= IPO_SELECT;
1211                 scrarea_queue_headredraw(curarea);
1212                 allqueue(REDRAWVIEW3D, 0);
1213         }
1214         
1215         get_status_editipo();
1216         
1217         if(G.sipo->ipo && G.sipo->ipo->id.lib) return;
1218         
1219         ei= G.sipo->editipo;
1220         for(a=0; a<G.sipo->totipo; a++, ei++) {         
1221                 if(ei->icu) {
1222                         if(ei->flag & IPO_VISIBLE) {
1223                                 
1224                                 if(totipo_edit==0 && (ei->flag & IPO_SELECT)) {
1225                                         ei->flag |= IPO_EDIT;
1226                                         ei->icu->flag= ei->flag;
1227                                 }
1228                                 else if(totipo_edit && (ei->flag & IPO_EDIT)) {
1229                                         ei->flag -= IPO_EDIT;
1230                                         ei->icu->flag= ei->flag;
1231                                 }
1232                                 else if(totipo_vis==1) {
1233                                         if(ei->flag & IPO_EDIT) ei->flag -= IPO_EDIT;
1234                                         else ei->flag |= IPO_EDIT;
1235                                         ei->icu->flag= ei->flag;
1236                                 }
1237                         }
1238                 }
1239         }
1240         scrarea_queue_headredraw(curarea);
1241         scrarea_queue_winredraw(curarea);
1242 }
1243
1244 static short findnearest_ipovert(IpoCurve **icu, BezTriple **bezt)
1245 {
1246         /* selected verts get a disadvantage */
1247         /* in icu and (bezt or bp) the nearest is written */
1248         /* return 0 1 2: handlepunt */
1249         EditIpo *ei;
1250         BezTriple *bezt1;
1251         int dist= 100, temp, a, b;
1252         short mval[2], hpoint=0, sco[3][2];
1253
1254         *icu= 0;
1255         *bezt= 0;
1256
1257         getmouseco_areawin(mval);
1258
1259         ei= G.sipo->editipo;
1260         for(a=0; a<G.sipo->totipo; a++, ei++) {
1261                 if (ISPOIN3(ei, flag & IPO_VISIBLE, flag & IPO_EDIT, icu)) {
1262                         
1263                         if(ei->icu->bezt) {
1264                                 bezt1= ei->icu->bezt;
1265                                 b= ei->icu->totvert;
1266                                 while(b--) {
1267
1268                                         ipoco_to_areaco_noclip(G.v2d, bezt1->vec[0], sco[0]);
1269                                         ipoco_to_areaco_noclip(G.v2d, bezt1->vec[1], sco[1]);
1270                                         ipoco_to_areaco_noclip(G.v2d, bezt1->vec[2], sco[2]);
1271                                                                                 
1272                                         if(ei->disptype==IPO_DISPBITS) {
1273                                                 temp= abs(mval[0]- sco[1][0]);
1274                                         }
1275                                         else temp= abs(mval[0]- sco[1][0])+ abs(mval[1]- sco[1][1]);
1276
1277                                         if( bezt1->f2 & 1) temp+=5;
1278                                         if(temp<dist) { 
1279                                                 hpoint= 1; 
1280                                                 *bezt= bezt1; 
1281                                                 dist= temp; 
1282                                                 *icu= ei->icu; 
1283                                         }
1284                                         
1285                                         if(ei->disptype!=IPO_DISPBITS && ei->icu->ipo==IPO_BEZ) {
1286                                                 /* middle points get an advantage */
1287                                                 temp= -3+abs(mval[0]- sco[0][0])+ abs(mval[1]- sco[0][1]);
1288                                                 if( bezt1->f1 & 1) temp+=5;
1289                                                 if(temp<dist) { 
1290                                                         hpoint= 0; 
1291                                                         *bezt= bezt1; 
1292                                                         dist= temp; 
1293                                                         *icu= ei->icu; 
1294                                                 }
1295                 
1296                                                 temp= abs(mval[0]- sco[2][0])+ abs(mval[1]- sco[2][1]);
1297                                                 if( bezt1->f3 & 1) temp+=5;
1298                                                 if(temp<dist) { 
1299                                                         hpoint= 2; 
1300                                                         *bezt=bezt1; 
1301                                                         dist= temp; 
1302                                                         *icu= ei->icu; 
1303                                                 }
1304                                         }
1305                                         bezt1++;
1306                                 }
1307                         }
1308                 }
1309         }
1310
1311         return hpoint;
1312 }
1313
1314 void mouse_select_ipo(void)
1315 {
1316         Object *ob;
1317         KeyBlock *actkb=NULL;
1318         EditIpo *ei, *actei= 0;
1319         IpoCurve *icu;
1320         IpoKey *ik, *actik;
1321         BezTriple *bezt;
1322         float x, y, dist, mindist;
1323         int a, oldflag = 0, hand, ok;
1324         short mval[2], xo, yo;
1325         
1326         if(G.sipo->editipo==0) return;
1327         
1328         get_status_editipo();
1329         
1330         if(G.sipo->showkey) {
1331                 getmouseco_areawin(mval);
1332                 
1333                 areamouseco_to_ipoco(G.v2d, mval, &x, &y);
1334                 actik= 0;
1335                 mindist= 1000.0;
1336                 ik= G.sipo->ipokey.first;
1337                 while(ik) {
1338                         dist= (float)(fabs(ik->val-x));
1339                         if(ik->flag & 1) dist+= 1.0;
1340                         if(dist < mindist) {
1341                                 actik= ik;
1342                                 mindist= dist;
1343                         }
1344                         ik= ik->next;
1345                 }
1346                 if(actik) {
1347                         oldflag= actik->flag;
1348                         
1349                         if(G.qual & LR_SHIFTKEY);
1350                         else deselectall_editipo();
1351                         
1352                         if(G.qual & LR_SHIFTKEY) {
1353                                 if(oldflag & 1) actik->flag &= ~1;
1354                                 else actik->flag |= 1;
1355                         }
1356                         else {
1357                                 actik->flag |= 1;
1358                         }
1359                 }
1360         }
1361         else if(totipo_edit) {
1362                 
1363                 hand= findnearest_ipovert(&icu, &bezt);
1364                 
1365                 if(G.qual & LR_SHIFTKEY) {
1366                         if(bezt) {
1367                                 if(hand==1) {
1368                                         if(BEZSELECTED(bezt)) {
1369                                                 bezt->f1= bezt->f2= bezt->f3= 0;
1370                                         }
1371                                         else {
1372                                                 bezt->f1= bezt->f2= bezt->f3= 1;
1373                                         }
1374                                 }
1375                                 else if(hand==0) {
1376                                         if(bezt->f1 & 1) bezt->f1= 0;
1377                                         else bezt->f1= 1;
1378                                 }
1379                                 else {
1380                                         if(bezt->f3 & 1) bezt->f3= 0;
1381                                         else bezt->f3= 1;
1382                                 }
1383                         }                               
1384                 }
1385                 else {
1386                         deselectall_editipo();
1387                         
1388                         if(bezt) {
1389                                 if(hand==1) {
1390                                         bezt->f1|= 1; bezt->f2|= 1; bezt->f3|= 1;
1391                                 }
1392                                 else if(hand==0) bezt->f1|= 1;
1393                                 else bezt->f3|= 1;
1394                         }
1395                 }
1396         }
1397         else {
1398                 
1399                 /* vertex keys ? */
1400                 if(G.sipo->blocktype==ID_KE && G.sipo->from) {
1401                         Key *key;
1402                         KeyBlock *kb, *curkb;
1403                         int i, index= 1;
1404                         
1405                         ob= (Object *)G.sipo->from;
1406                         key= ob_get_key(ob);
1407                         curkb= BLI_findlink(&key->block, ob->shapenr-1);
1408                         
1409                         ei= G.sipo->editipo;
1410                         if(key->type==KEY_NORMAL || (ei->flag & IPO_VISIBLE)) {
1411                                 getmouseco_areawin(mval);
1412                                 
1413                                 areamouseco_to_ipoco(G.v2d, mval, &x, &y);
1414                                 /* how much is 20 pixels? */
1415                                 mindist= (float)(20.0*(G.v2d->cur.ymax-G.v2d->cur.ymin)/(float)curarea->winy);
1416                                 
1417                                 for(i=1, kb= key->block.first; kb; kb= kb->next, i++) {
1418                                         dist= (float)(fabs(kb->pos-y));
1419                                         if(kb==curkb) dist+= (float)0.01;
1420                                         if(dist < mindist) {
1421                                                 actkb= kb;
1422                                                 mindist= dist;
1423                                                 index= i;
1424                                         }
1425                                 }
1426                                 if(actkb) {
1427                                         ok= TRUE;
1428                                         if(G.obedit && actkb!=curkb) {
1429                                                 ok= okee("Copy key after leaving Edit Mode");
1430                                         }
1431                                         if(ok) {
1432                                                 /* also does all keypos */
1433                                                 deselectall_editipo();
1434                                                 set_active_key(index);
1435                                                 set_active_editipo(ei+index-1);
1436                                         }
1437                                 }
1438                         }
1439                 }
1440                 
1441                 /* select curve */
1442                 if(actkb==NULL) {
1443                         if(totipo_vis==1) {
1444                                 ei= G.sipo->editipo;
1445                                 for(a=0; a<G.sipo->totipo; a++, ei++) {
1446                                         if(ei->icu) {
1447                                                 if(ei->flag & IPO_VISIBLE) actei= ei;
1448                                         }
1449                                 }
1450                         }
1451                         else if(totipo_vis>1) {
1452                                 actei= select_proj_ipo(0, 0);
1453                         }
1454                         
1455                         if(actei) oldflag= actei->flag;
1456                         
1457                         if(G.qual & LR_SHIFTKEY);
1458                         else deselectall_editipo();
1459                         
1460                         if(actei) {
1461                                 if(G.qual & LR_SHIFTKEY) {
1462                                         if(oldflag & IPO_SELECT) actei->flag &= ~IPO_SELECT;
1463                                         else actei->flag |= IPO_SELECT;
1464                                 }
1465                                 else {
1466                                         actei->flag |= IPO_SELECT;
1467                                 }
1468                                 set_active_editipo(actei);
1469                         }
1470                 }
1471         }
1472         
1473         update_editipo_flags();
1474         
1475         force_draw(0);
1476         BIF_undo_push("Select Ipo");
1477         
1478         if(G.sipo->showkey && G.sipo->blocktype==ID_OB) {
1479                 ob= OBACT;
1480                 if(ob && (ob->ipoflag & OB_DRAWKEY)) allqueue(REDRAWVIEW3D, 0);
1481         }
1482         
1483         getmouseco_areawin(mval);
1484         xo= mval[0]; 
1485         yo= mval[1];
1486         
1487         while(get_mbut()&R_MOUSE) {             
1488                 getmouseco_areawin(mval);
1489                 if(abs(mval[0]-xo)+abs(mval[1]-yo) > 4) {
1490                         
1491                         if(actkb) move_keys(OBACT);
1492                         else transform_ipo('g');
1493                         
1494                         return;
1495                 }
1496                 BIF_wait_for_statechange();
1497         }
1498 }
1499
1500
1501 /* *********************************** */
1502
1503 /* handling of right-hand channel/curve buttons in ipo window */
1504 void do_ipowin_buts(short event)
1505 {
1506         EditIpo *ei = NULL;
1507         int a;
1508
1509         /* without shift, all other channels are made invisible */
1510         if((G.qual & LR_SHIFTKEY)==0) {
1511                 if(event>G.sipo->totipo) return;
1512                 ei = G.sipo->editipo;
1513                 for(a=0; a<G.sipo->totipo; a++) {
1514                         if(a!=event) ei->flag &= ~IPO_VISIBLE;
1515                         else ei->flag |= IPO_VISIBLE;
1516                         ei++;
1517                 }
1518         }
1519         
1520         /* set active */
1521         if(event>=0 && event<G.sipo->totipo) {
1522                 ei= G.sipo->editipo;    // void pointer...
1523                 set_active_editipo(ei+event);
1524                 set_active_key(event+1);        // only if there's a key, of course
1525         }
1526         scrarea_queue_winredraw(curarea);
1527         
1528         update_editipo_flags();
1529         get_status_editipo();
1530
1531         if(G.sipo->showkey) {
1532                 make_ipokey();
1533                 if(G.sipo->blocktype==ID_OB) allqueue(REDRAWVIEW3D, 0);
1534         }
1535
1536 }
1537
1538 /* the fake buttons to the left of channel names, for select/deselect curves */
1539 void do_ipo_selectbuttons(void)
1540 {
1541         EditIpo *ei, *ei1;
1542         int a, nr;
1543         short mval[2];
1544         
1545         if(G.sipo->showkey) return;
1546         
1547         /* do not allow editipo here: convert editipos to selected */
1548         get_status_editipo();
1549         if(totipo_edit) {
1550                 set_editflag_editipo();
1551         }
1552         
1553         /* which */
1554         getmouseco_areawin(mval);
1555
1556         nr= -(mval[1]-curarea->winy+30-G.sipo->butofs-IPOBUTY)/IPOBUTY;
1557         if(nr>=0 && nr<G.sipo->totipo) {
1558                 ei= G.sipo->editipo;
1559                 ei+= nr;
1560                 
1561                 set_active_editipo(ei);
1562                 set_active_key(nr+1);
1563
1564                 if(ei->icu) {
1565                         if((ei->flag & IPO_VISIBLE)==0) {
1566                                 ei->flag |= IPO_VISIBLE|IPO_SELECT;
1567                         }
1568         
1569                         if((G.qual & LR_SHIFTKEY)==0) {
1570                                 ei1= G.sipo->editipo;
1571                                 for(a=0; a<G.sipo->totipo; a++) {
1572                                         ei1->flag &= ~IPO_SELECT;
1573                                         ei1++;
1574                                 }
1575                         }
1576
1577                         if(ei->flag & IPO_SELECT) {
1578                                 ei->flag &= ~IPO_SELECT;
1579                         }
1580                         else {
1581                                 ei->flag |= IPO_SELECT;
1582                         }
1583                         
1584                         update_editipo_flags();
1585                         scrarea_queue_winredraw(curarea);
1586                 }
1587         }
1588         BIF_undo_push("Select Ipo curve");
1589 }
1590
1591 /* ********************************* Inserting keys ********************************************* */
1592
1593 /* depending type, it returns ipo, if neded it creates one */
1594 /* returns either action ipo or "real" ipo */
1595 /* arguments define full context;
1596    - *from has to be set always, to Object in case of Actions
1597    - blocktype defines available channels of Ipo struct (blocktype ID_OB can be in action too)
1598    - if actname, use this to locate action, and optional constname to find the channel 
1599 */
1600
1601 /* note; check header_ipo.c, spaceipo_assign_ipo() too */
1602 Ipo *verify_ipo(ID *from, short blocktype, char *actname, char *constname)
1603 {
1604
1605         if(from==NULL || from->lib) return NULL;
1606         
1607         /* first check action ipos */
1608         if(actname && actname[0]) {
1609                 Object *ob= (Object *)from;
1610                 bActionChannel *achan;
1611                 
1612                 if(GS(from->name)!=ID_OB) {
1613                         printf("called ipo system for action with wrong base pointer\n");
1614                         return NULL;
1615                 }
1616                 
1617                 if(ob->action==NULL)
1618                         ob->action= add_empty_action(blocktype);
1619                 
1620                 achan= verify_action_channel(ob->action, actname);
1621                 
1622                 if(achan) {
1623                         /* constraint exception */
1624                         if(blocktype==ID_CO) {
1625                                 bConstraintChannel *conchan= verify_constraint_channel(&achan->constraintChannels, constname);
1626                                 if(conchan->ipo==NULL) {
1627                                         conchan->ipo= add_ipo("CoIpo", ID_CO);  
1628                                 }
1629                                 return conchan->ipo;
1630                         }
1631                         else {
1632                                 if(achan->ipo==NULL) {
1633                                         achan->ipo= add_ipo("ActIpo", blocktype);
1634                                 }
1635                                 
1636                                 return achan->ipo;
1637                         }
1638                 }
1639         }
1640         else {
1641                 
1642                 switch(GS(from->name)) {
1643                 case ID_OB:
1644                         {
1645                                 Object *ob= (Object *)from;
1646                                 /* constraint exception */
1647                                 if(blocktype==ID_CO) {
1648                                         bConstraintChannel *conchan= verify_constraint_channel(&ob->constraintChannels, constname);
1649                                         if(conchan->ipo==NULL) {
1650                                                 conchan->ipo= add_ipo("CoIpo", ID_CO);  
1651                                         }
1652                                         return conchan->ipo;
1653                                 }
1654                                 else if(blocktype==ID_OB) {
1655                                         if(ob->ipo==NULL) {
1656                                                 ob->ipo= add_ipo("ObIpo", ID_OB);
1657                                         }
1658                                         return ob->ipo;
1659                                 }
1660                                 else if(blocktype==ID_KE) {
1661                                         Key *key= ob_get_key((Object *)from);
1662                                         
1663                                         if(key) {
1664                                                 if(key->ipo==NULL) {
1665                                                         key->ipo= add_ipo("KeyIpo", ID_KE);
1666                                                 }
1667                                                 return key->ipo;
1668                                         }
1669                                         return NULL;
1670                                 }
1671                         }
1672                         break;
1673                 case ID_MA:
1674                         {
1675                                 Material *ma= (Material *)from;
1676
1677                                 if(ma->ipo==NULL) {
1678                                         ma->ipo= add_ipo("MatIpo", ID_MA);
1679                                 }
1680                                 return ma->ipo;
1681                         }
1682                         break;
1683                 case ID_TE:
1684                         {
1685                                 Tex *tex= (Tex *)from;
1686
1687                                 if(tex->ipo==NULL) {
1688                                         tex->ipo= add_ipo("TexIpo", ID_TE);
1689                                 }
1690                                 return tex->ipo;
1691                         }
1692                         break;
1693                 case ID_SEQ:
1694                         {
1695                                 Sequence *seq= (Sequence *)from;        /* note, sequence is mimicing Id */
1696
1697                                 if((seq->type & SEQ_EFFECT)||(seq->type == SEQ_SOUND)) {
1698                                         if(seq->ipo==NULL) {
1699                                                 seq->ipo= add_ipo("SeqIpo", ID_SEQ);
1700                                         }
1701                                         return seq->ipo;
1702                                 }
1703                         }
1704                         break;
1705                 case ID_CU:
1706                         {
1707                                 Curve *cu= (Curve *)from;
1708                                 
1709                                 if(cu->ipo==NULL) {
1710                                         cu->ipo= add_ipo("CuIpo", ID_CU);
1711                                 }
1712                                 return cu->ipo;
1713                         }
1714                         break;
1715                 case ID_WO:
1716                         {
1717                                 World *wo= (World *)from;
1718
1719                                 if(wo->ipo==NULL) {
1720                                         wo->ipo= add_ipo("WoIpo", ID_WO);
1721                                 }
1722                                 return wo->ipo;
1723                         }
1724                         break;
1725                 case ID_LA:
1726                         {
1727                                 Lamp *la= (Lamp *)from;
1728                                 
1729                                 if(la->ipo==NULL) {
1730                                         la->ipo= add_ipo("LaIpo", ID_LA);
1731                                 }
1732                                 return la->ipo;
1733                         }
1734                         break;
1735                 case ID_CA:
1736                         {
1737                                 Camera *ca= (Camera *)from;
1738
1739                                 if(ca->ipo==NULL) {
1740                                         ca->ipo= add_ipo("CaIpo", ID_CA);
1741                                 }
1742                                 return ca->ipo;
1743                         }
1744                         break;
1745                 case ID_SO:
1746                         {
1747                                 bSound *snd= (bSound *)from;
1748
1749                                 if(snd->ipo==NULL) {
1750                                         snd->ipo= add_ipo("SndIpo", ID_SO);
1751                                 }
1752                                 return snd->ipo;
1753                         }
1754                 }
1755         }
1756         
1757         return NULL;    
1758 }
1759
1760 /* returns and creates */
1761 IpoCurve *verify_ipocurve(ID *from, short blocktype, char *actname, char *constname, int adrcode)
1762 {
1763         Ipo *ipo;
1764         IpoCurve *icu= NULL;
1765         
1766         /* return 0 if lib */
1767         /* creates ipo too */
1768         ipo= verify_ipo(from, blocktype, actname, constname);
1769         
1770         if(ipo && ipo->id.lib==NULL) {
1771                 
1772                 for(icu= ipo->curve.first; icu; icu= icu->next) {
1773                         if(icu->adrcode==adrcode) break;
1774                 }
1775                 if(icu==NULL) {
1776                         icu= MEM_callocN(sizeof(IpoCurve), "ipocurve");
1777
1778                         icu->flag |= IPO_VISIBLE|IPO_AUTO_HORIZ;
1779                         icu->blocktype= blocktype;
1780                         icu->adrcode= adrcode;
1781                         
1782                         set_icu_vars(icu);
1783                         
1784                         BLI_addtail( &(ipo->curve), icu);
1785                 }
1786         }
1787
1788         return icu;
1789 }
1790
1791 void insert_vert_ipo(IpoCurve *icu, float x, float y)
1792 {
1793         BezTriple *bezt, beztr, *newbezt;
1794         int a = 0, h1, h2;
1795         
1796         memset(&beztr, 0, sizeof(BezTriple));
1797         beztr.vec[0][0]= x; // set all three points, for nicer start position
1798         beztr.vec[0][1]= y;
1799         beztr.vec[1][0]= x;
1800         beztr.vec[1][1]= y;
1801         beztr.vec[2][0]= x;
1802         beztr.vec[2][1]= y;
1803         beztr.hide= IPO_BEZ;
1804         beztr.f1= beztr.f2= beztr.f3= SELECT;
1805         beztr.h1= beztr.h2= HD_AUTO;
1806                 
1807         bezt= icu->bezt;
1808                 
1809         if(bezt==NULL) {
1810                 icu->bezt= MEM_callocN( sizeof(BezTriple), "beztriple");
1811                 *(icu->bezt)= beztr;
1812                 icu->totvert= 1;
1813         }
1814         else {
1815                 /* all vertices deselect */
1816                 for(a=0; a<icu->totvert; a++, bezt++) {
1817                         bezt->f1= bezt->f2= bezt->f3= 0;
1818                 }
1819         
1820                 bezt= icu->bezt;
1821                 for(a=0; a<=icu->totvert; a++, bezt++) {
1822                         
1823                         /* no double points */
1824                         if(a<icu->totvert && (bezt->vec[1][0]>x-IPOTHRESH && bezt->vec[1][0]<x+IPOTHRESH)) {
1825                                 *(bezt)= beztr;
1826                                 break;
1827                         }
1828                         if(a==icu->totvert || bezt->vec[1][0] > x) {
1829                                 newbezt= MEM_callocN( (icu->totvert+1)*sizeof(BezTriple), "beztriple");
1830                                 
1831                                 if(a>0) memcpy(newbezt, icu->bezt, a*sizeof(BezTriple));
1832                                 
1833                                 bezt= newbezt+a;
1834                                 *(bezt)= beztr;
1835                                 
1836                                 if(a<icu->totvert) memcpy(newbezt+a+1, icu->bezt+a, (icu->totvert-a)*sizeof(BezTriple));
1837                                 
1838                                 MEM_freeN(icu->bezt);
1839                                 icu->bezt= newbezt;
1840                                 
1841                                 icu->totvert++;
1842                                 break;
1843                         }
1844                 }
1845         }
1846         
1847         
1848         calchandles_ipocurve(icu);
1849         
1850         /* set handletype */
1851         if(icu->totvert>2) {
1852                 h1= h2= HD_AUTO;
1853                 if(a>0) h1= (bezt-1)->h2;
1854                 if(a<icu->totvert-1) h2= (bezt+1)->h1;
1855                 bezt->h1= h1;
1856                 bezt->h2= h2;
1857
1858                 calchandles_ipocurve(icu);
1859         }
1860 }
1861
1862 void add_vert_ipo(void)
1863 {
1864         EditIpo *ei;
1865         float x, y;
1866         int val;
1867         short mval[2];
1868
1869         if(G.sipo->ipo && G.sipo->ipo->id.lib) return;
1870         if(G.sipo->showkey) {
1871                 G.sipo->showkey= 0;
1872                 free_ipokey(&G.sipo->ipokey);
1873         }
1874         
1875         getmouseco_areawin(mval);
1876         
1877         if(mval[0]>G.v2d->mask.xmax) return;
1878         
1879         ei= get_active_editipo();
1880         if(ei==NULL) {
1881                 error("No active Ipo curve");
1882                 return;
1883         }
1884         ei->flag |= IPO_VISIBLE;        /* can happen it is active but not visible */
1885         
1886         areamouseco_to_ipoco(G.v2d, mval, &x, &y);
1887         
1888         if(ei->icu==NULL) {
1889                 if(G.sipo->from) {
1890                         ei->icu= verify_ipocurve(G.sipo->from, G.sipo->blocktype, G.sipo->actname, G.sipo->constname, ei->adrcode);
1891                         ei->flag |= ei->icu->flag & IPO_AUTO_HORIZ;     /* new curve could have been added, weak... */
1892                 }
1893         }
1894         if(ei->icu==NULL) return;
1895
1896         if(ei->disptype==IPO_DISPBITS) {
1897                 ei->icu->vartype= IPO_BITS;
1898                 val= (int)floor(y-0.5);
1899                 if(val<0) val= 0;
1900                 y= (float)(1 << val);
1901         }
1902         
1903         insert_vert_ipo(ei->icu, x, y);
1904
1905         /* to be sure: if icu was 0, or only 1 curve visible */
1906         ei->flag |= IPO_SELECT;
1907         ei->icu->flag= ei->flag;
1908         
1909         editipo_changed(G.sipo, 1);
1910         BIF_undo_push("Add Ipo vertex");
1911 }
1912
1913 static void *get_context_ipo_poin(ID *id, int blocktype, char *actname, IpoCurve *icu, int *vartype)
1914 {
1915         if(blocktype==ID_PO) {
1916                 if(GS(id->name)==ID_OB) {
1917                         Object *ob= (Object *)id;
1918                         bPoseChannel *pchan= get_pose_channel(ob->pose, actname);
1919                         
1920                         *vartype= IPO_FLOAT;
1921                         return get_pchan_ipo_poin(pchan, icu->adrcode);
1922                 }
1923                 return NULL;
1924         }
1925         else
1926                 return get_ipo_poin(id, icu, vartype);
1927
1928 }
1929
1930 void insertkey(ID *id, int blocktype, char *actname, char *constname, int adrcode)
1931 {
1932         IpoCurve *icu;
1933         Object *ob;
1934         void *poin= NULL;
1935         float curval, cfra;
1936         int vartype;
1937         
1938         icu= verify_ipocurve(id, blocktype, actname, constname, adrcode);
1939         
1940         if(icu) {
1941                 
1942                 poin= get_context_ipo_poin(id, blocktype, actname, icu, &vartype);
1943                 
1944                 if(poin) {
1945                         curval= read_ipo_poin(poin, vartype);
1946                         
1947                         cfra= frame_to_float(CFRA);
1948                         
1949                         /* if action is mapped in NLA, it returns a correction */
1950                         if(actname && actname[0] && GS(id->name)==ID_OB)
1951                                 cfra= get_action_frame((Object *)id, cfra);
1952                         
1953                         if( GS(id->name)==ID_OB ) {
1954                                 ob= (Object *)id;
1955                                 if(ob->sf!=0.0 && (ob->ipoflag & OB_OFFS_OB) ) {
1956                                         /* actually frametofloat calc again! */
1957                                         cfra-= ob->sf*G.scene->r.framelen;
1958                                 }
1959                         }
1960                         
1961                         insert_vert_ipo(icu, cfra, curval);
1962                 }
1963         }
1964 }
1965
1966 /* For inserting keys based on the object matrix - not on the current IPO value
1967    Generically - it inserts the passed float value into the appropriate IPO */
1968 void insertmatrixkey(ID *id, int blocktype, char *actname, char *constname, int adrcode, float matrixvalue)
1969 {
1970         IpoCurve *icu;
1971         Object *ob;
1972         void *poin= NULL;
1973         float cfra;
1974         int vartype;
1975         
1976         icu= verify_ipocurve(id, blocktype, actname, constname, adrcode);
1977         
1978         if(icu) {
1979                 
1980                 poin= get_context_ipo_poin(id, blocktype, actname, icu, &vartype);
1981                 
1982                 if(poin) {
1983                         
1984                         cfra= frame_to_float(CFRA);
1985                         
1986                         /* if action is mapped in NLA, it returns a correction */
1987                         if(actname && actname[0] && GS(id->name)==ID_OB)
1988                                 cfra= get_action_frame((Object *)id, cfra);
1989                         
1990                         if( GS(id->name)==ID_OB ) {
1991                                 ob= (Object *)id;
1992                                 if(ob->sf!=0.0 && (ob->ipoflag & OB_OFFS_OB) ) {
1993                                         /* actually frametofloat calc again! */
1994                                         cfra-= ob->sf*G.scene->r.framelen;
1995                                 }
1996                         }
1997                         insert_vert_ipo(icu, cfra, matrixvalue);
1998                 }
1999         }
2000 }
2001
2002 void insertkey_editipo(void)
2003 {
2004         EditIpo *ei;
2005         IpoKey *ik;
2006         ID *id;
2007         float *fp, cfra, *insertvals;
2008         int a, nr, ok, tot;
2009         short event;
2010         
2011         ei= get_active_editipo();
2012         if(ei && ei->icu && ei->icu->driver) 
2013                 event= pupmenu("Insert Curve %t|Default one-to-one mapping %x3");
2014         else if(G.sipo->showkey)
2015                 event= pupmenu("Insert Key Vertices %t|Current Frame %x1|Selected Keys %x2");
2016         else 
2017                 event= pupmenu("Insert Key Vertices %t|Current Frame %x1");
2018         
2019         if(event<1) return;
2020         
2021         if(event==3) {
2022                 IpoDriver *driver= ei->icu->driver;
2023                 
2024                 if(ei->icu->bezt) MEM_freeN(ei->icu->bezt);
2025                 ei->icu->totvert= 0;
2026                 ei->icu->bezt= NULL;
2027                 
2028                 insert_vert_ipo(ei->icu, 0.0f, 0.0f);
2029                 
2030                 if(ELEM3(driver->adrcode, OB_ROT_X, OB_ROT_Y, OB_ROT_Z)) {
2031                         if(ei->disptype==IPO_DISPDEGR)
2032                                 insert_vert_ipo(ei->icu, 18.0f, 18.0f);
2033                         else
2034                                 insert_vert_ipo(ei->icu, 18.0f, 1.0f);
2035                 }
2036                 else
2037                         insert_vert_ipo(ei->icu, 1.0f, 1.0f);
2038                 
2039                 ei->flag |= IPO_SELECT|IPO_VISIBLE;
2040                 ei->icu->flag= ei->flag;
2041                 ei->icu->extrap= IPO_DIR;
2042
2043                 do_ipo_buttons(B_IPOHOME);
2044         }
2045         else {
2046                 ei= G.sipo->editipo;
2047                 for(nr=0; nr<G.sipo->totipo; nr++, ei++) {
2048                         if (ISPOIN(ei, flag & IPO_VISIBLE, icu)) {
2049                         
2050                                 ok= 0;
2051                                 if(G.sipo->showkey) ok= 1;
2052                                 else if(ei->flag & IPO_SELECT) ok= 1;
2053
2054                                 if(ok) {
2055                                         /* count amount */
2056                                         if(event==1) tot= 1;
2057                                         else {
2058                                                 ik= G.sipo->ipokey.first;
2059                                                 tot= 0;
2060                                                 while(ik) {
2061                                                         if(ik->flag & 1) tot++;
2062                                                         ik= ik->next;
2063                                                 }
2064                                         }
2065                                         if(tot) {
2066                                         
2067                                                 /* correction for ob timeoffs */
2068                                                 cfra= frame_to_float(CFRA);
2069                                                 id= G.sipo->from;       
2070                                                 if(id && GS(id->name)==ID_OB ) {
2071                                                         Object *ob= (Object *)id;
2072                                                         if(ob->sf!=0.0 && (ob->ipoflag & OB_OFFS_OB) ) {
2073                                                                 cfra-= ob->sf*G.scene->r.framelen;
2074                                                         }
2075                                                 }
2076                                                 else if(id && GS(id->name)==ID_SEQ) {
2077                                                         extern Sequence *last_seq;      /* editsequence.c */
2078                                                         
2079                                                         if(last_seq) {
2080                                                                 cfra= (float)(100.0*(cfra-last_seq->startdisp)/((float)(last_seq->enddisp-last_seq->startdisp)));
2081                                                         }
2082                                                 }
2083                                 
2084                                                 insertvals= MEM_mallocN(sizeof(float)*2*tot, "insertkey_editipo");
2085                                                 /* make sure icu->curval is correct */
2086                                                 calc_ipo(G.sipo->ipo, cfra);
2087                                                 
2088                                                 if(event==1) {
2089                                                         insertvals[0]= cfra;
2090                                                         
2091                                                         insertvals[1]= ei->icu->curval;
2092                                                 }
2093                                                 else {
2094                                                         fp= insertvals;
2095                                                         ik= G.sipo->ipokey.first;
2096                                                         while(ik) {
2097                                                                 if(ik->flag & 1) {
2098                                                                         calc_ipo(G.sipo->ipo, ik->val);
2099
2100                                                                         fp[0]= ik->val;
2101                                                                         fp[1]= ei->icu->curval;
2102                                                                         fp+= 2;
2103                                                                 }
2104                                                                 ik= ik->next;
2105                                                         }
2106                                                 }
2107                                                 fp= insertvals;
2108                                                 for(a=0; a<tot; a++, fp+=2) {
2109                                                         insert_vert_ipo(ei->icu, fp[0], fp[1]);
2110                                                 }
2111                                                 
2112                                                 MEM_freeN(insertvals);
2113                                                 calc_ipo(G.sipo->ipo, (float)CFRA);
2114                                         }
2115                                 }
2116                         }
2117                 }
2118         }
2119         BIF_undo_push("Insert Key Ipo");
2120         allqueue (REDRAWACTION, 0);
2121         allqueue(REDRAWNLA, 0);
2122         allqueue(REDRAWIPO, 0);
2123         allspace(REMAKEIPO, 0);
2124 }
2125
2126
2127 void common_insertkey(void)
2128 {
2129         Base *base;
2130         Object *ob;
2131         Material *ma;
2132         ID *id;
2133         IpoCurve *icu;
2134         World *wo;
2135         Lamp *la;
2136         int tlay, map, event;
2137         char menustr[256];
2138         
2139         if(curarea->spacetype==SPACE_IPO) {
2140                 insertkey_editipo();
2141         }
2142         else if(curarea->spacetype==SPACE_BUTS) {
2143                 if(G.buts->mainb==CONTEXT_SHADING) {
2144                         int tab= G.buts->tab[CONTEXT_SHADING];
2145                         
2146                         if(tab==TAB_SHADING_MAT) {
2147                                 id= G.buts->lockpoin;
2148                                 ma= G.buts->lockpoin;
2149                                 if(id) {
2150                                         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");
2151                                         if(event== -1) return;
2152                                         
2153                                         map= texchannel_to_adrcode(ma->texact);
2154                                         
2155                                         if(event==0 || event==10) {
2156                                                 insertkey(id, ID_MA, NULL, NULL, MA_COL_R);
2157                                                 insertkey(id, ID_MA, NULL, NULL, MA_COL_G);
2158                                                 insertkey(id, ID_MA, NULL, NULL, MA_COL_B);
2159                                         }
2160                                         if(event==1 || event==10) {
2161                                                 insertkey(id, ID_MA, NULL, NULL, MA_ALPHA);
2162                                         }
2163                                         if(event==2 || event==10) {
2164                                                 insertkey(id, ID_MA, NULL, NULL, MA_HASIZE);
2165                                         }
2166                                         if(event==3 || event==10) {
2167                                                 insertkey(id, ID_MA, NULL, NULL, MA_MODE);
2168                                         }
2169                                         if(event==10) {
2170                                                 insertkey(id, ID_MA, NULL, NULL, MA_SPEC_R);
2171                                                 insertkey(id, ID_MA, NULL, NULL, MA_SPEC_G);
2172                                                 insertkey(id, ID_MA, NULL, NULL, MA_SPEC_B);
2173                                                 insertkey(id, ID_MA, NULL, NULL, MA_REF);
2174                                                 insertkey(id, ID_MA, NULL, NULL, MA_EMIT);
2175                                                 insertkey(id, ID_MA, NULL, NULL, MA_AMB);
2176                                                 insertkey(id, ID_MA, NULL, NULL, MA_SPEC);
2177                                                 insertkey(id, ID_MA, NULL, NULL, MA_HARD);
2178                                                 insertkey(id, ID_MA, NULL, NULL, MA_MODE);
2179                                                 insertkey(id, ID_MA, NULL, NULL, MA_TRANSLU);
2180                                                 insertkey(id, ID_MA, NULL, NULL, MA_ADD);
2181                                         }
2182                                         if(event==14) {
2183                                                 insertkey(id, ID_MA, NULL, NULL, MA_RAYM);
2184                                                 insertkey(id, ID_MA, NULL, NULL, MA_FRESMIR);
2185                                                 insertkey(id, ID_MA, NULL, NULL, MA_FRESMIRI);
2186                                                 insertkey(id, ID_MA, NULL, NULL, MA_FRESTRA);
2187                                                 insertkey(id, ID_MA, NULL, NULL, MA_FRESTRAI);
2188                                         }
2189                                         if(event==12 || event==11) {
2190                                                 insertkey(id, ID_MA, NULL, NULL, map+MAP_OFS_X);
2191                                                 insertkey(id, ID_MA, NULL, NULL, map+MAP_OFS_Y);
2192                                                 insertkey(id, ID_MA, NULL, NULL, map+MAP_OFS_Z);
2193                                         }
2194                                         if(event==13 || event==11) {
2195                                                 insertkey(id, ID_MA, NULL, NULL, map+MAP_SIZE_X);
2196                                                 insertkey(id, ID_MA, NULL, NULL, map+MAP_SIZE_Y);
2197                                                 insertkey(id, ID_MA, NULL, NULL, map+MAP_SIZE_Z);
2198                                         }
2199                                         if(event==11) {
2200                                                 insertkey(id, ID_MA, NULL, NULL, map+MAP_R);
2201                                                 insertkey(id, ID_MA, NULL, NULL, map+MAP_G);
2202                                                 insertkey(id, ID_MA, NULL, NULL, map+MAP_B);
2203                                                 insertkey(id, ID_MA, NULL, NULL, map+MAP_DVAR);
2204                                                 insertkey(id, ID_MA, NULL, NULL, map+MAP_COLF);
2205                                                 insertkey(id, ID_MA, NULL, NULL, map+MAP_NORF);
2206                                                 insertkey(id, ID_MA, NULL, NULL, map+MAP_VARF);
2207                                                 insertkey(id, ID_MA, NULL, NULL, map+MAP_DISP);
2208                                         }
2209                                 }
2210                         }
2211                         else if(tab==TAB_SHADING_WORLD) {
2212                                 id= G.buts->lockpoin;
2213                                 wo= G.buts->lockpoin;
2214                                 if(id) {
2215                                         event= pupmenu("Insert Key %t|Zenith RGB%x0|Horizon RGB%x1|Mist%x2|Stars %x3|Offset%x12|Size%x13");
2216                                         if(event== -1) return;
2217                                         
2218                                         map= texchannel_to_adrcode(wo->texact);
2219                                         
2220                                         if(event==0) {
2221                                                 insertkey(id, ID_WO, NULL, NULL, WO_ZEN_R);
2222                                                 insertkey(id, ID_WO, NULL, NULL, WO_ZEN_G);
2223                                                 insertkey(id, ID_WO, NULL, NULL, WO_ZEN_B);
2224                                         }
2225                                         if(event==1) {
2226                                                 insertkey(id, ID_WO, NULL, NULL, WO_HOR_R);
2227                                                 insertkey(id, ID_WO, NULL, NULL, WO_HOR_G);
2228                                                 insertkey(id, ID_WO, NULL, NULL, WO_HOR_B);
2229                                         }
2230                                         if(event==2) {
2231                                                 insertkey(id, ID_WO, NULL, NULL, WO_MISI);
2232                                                 insertkey(id, ID_WO, NULL, NULL, WO_MISTDI);
2233                                                 insertkey(id, ID_WO, NULL, NULL, WO_MISTSTA);
2234                                                 insertkey(id, ID_WO, NULL, NULL, WO_MISTHI);
2235                                         }
2236                                         if(event==3) {
2237                                                 insertkey(id, ID_WO, NULL, NULL, WO_STAR_R);
2238                                                 insertkey(id, ID_WO, NULL, NULL, WO_STAR_G);
2239                                                 insertkey(id, ID_WO, NULL, NULL, WO_STAR_B);
2240                                                 insertkey(id, ID_WO, NULL, NULL, WO_STARDIST);
2241                                                 insertkey(id, ID_WO, NULL, NULL, WO_STARSIZE);
2242                                         }
2243                                         if(event==12) {
2244                                                 insertkey(id, ID_WO, NULL, NULL, map+MAP_OFS_X);
2245                                                 insertkey(id, ID_WO, NULL, NULL, map+MAP_OFS_Y);
2246                                                 insertkey(id, ID_WO, NULL, NULL, map+MAP_OFS_Z);
2247                                         }
2248                                         if(event==13) {
2249                                                 insertkey(id, ID_WO, NULL, NULL, map+MAP_SIZE_X);
2250                                                 insertkey(id, ID_WO, NULL, NULL, map+MAP_SIZE_Y);
2251                                                 insertkey(id, ID_WO, NULL, NULL, map+MAP_SIZE_Z);
2252                                         }
2253                                 }
2254                         }
2255                         else if(tab==TAB_SHADING_LAMP) {
2256                                 id= G.buts->lockpoin;
2257                                 la= G.buts->lockpoin;
2258                                 if(id) {
2259                                         event= pupmenu("Insert Key %t|RGB%x0|Energy%x1|Spot Size%x2|Offset%x12|Size%x13");
2260                                         if(event== -1) return;
2261                                         
2262                                         map= texchannel_to_adrcode(la->texact);
2263                                         
2264                                         if(event==0) {
2265                                                 insertkey(id, ID_LA, NULL, NULL, LA_COL_R);
2266                                                 insertkey(id, ID_LA, NULL, NULL, LA_COL_G);
2267                                                 insertkey(id, ID_LA, NULL, NULL, LA_COL_B);
2268                                         }
2269                                         if(event==1) {
2270                                                 insertkey(id, ID_LA, NULL, NULL, LA_ENERGY);
2271                                         }
2272                                         if(event==2) {
2273                                                 insertkey(id, ID_LA, NULL, NULL, LA_SPOTSI);
2274                                         }
2275                                         if(event==12) {
2276                                                 insertkey(id, ID_LA, NULL, NULL, map+MAP_OFS_X);
2277                                                 insertkey(id, ID_LA, NULL, NULL, map+MAP_OFS_Y);
2278                                                 insertkey(id, ID_LA, NULL, NULL, map+MAP_OFS_Z);
2279                                         }
2280                                         if(event==13) {
2281                                                 insertkey(id, ID_LA, NULL, NULL, map+MAP_SIZE_X);
2282                                                 insertkey(id, ID_LA, NULL, NULL, map+MAP_SIZE_Y);
2283                                                 insertkey(id, ID_LA, NULL, NULL, map+MAP_SIZE_Z);
2284                                         }
2285
2286                                 }
2287                         }
2288                 }
2289                 else if(G.buts->mainb==CONTEXT_OBJECT) {
2290                         ob= OBACT;
2291                         if(ob && ob->type==OB_MESH) {
2292                                 id= (ID *) (ob);
2293                                 if(id) {
2294                                         event= pupmenu("Insert Key %t|Surface Damping%x0|Random Damping%x1|Permeability%x2|Force Strength%x3|Force Falloff%x4");
2295                                         if(event== -1) return;
2296
2297                                         if(event==0) {
2298                                                 insertkey(id, ID_OB, NULL, NULL, OB_PD_SDAMP);
2299                                         }
2300                                         if(event==1) {
2301                                                 insertkey(id, ID_OB, NULL, NULL, OB_PD_RDAMP);
2302                                         }
2303                                         if(event==2) {
2304                                                 insertkey(id, ID_OB, NULL, NULL, OB_PD_PERM);
2305                                         }
2306                                         if(event==3) {
2307                                                 insertkey(id, ID_OB, NULL, NULL, OB_PD_FSTR);
2308                                         }
2309                                         if(event==4) {
2310                                                 insertkey(id, ID_OB, NULL, NULL, OB_PD_FFALL);
2311                                         }
2312
2313                                 }
2314                         }
2315                 }
2316                 else if(G.buts->mainb==CONTEXT_EDITING) {
2317                         ob= OBACT;
2318                         if(ob && ob->type==OB_CAMERA) {
2319                                 id= G.buts->lockpoin;
2320                                 if(id) {
2321                                         /* yafray: insert key extended with aperture and focal distance */
2322                                         if (G.scene->r.renderer==R_INTERN)
2323                                                 event= pupmenu("Insert Key %t|Lens%x0|Clipping%x1");
2324                                         else
2325                                                 event= pupmenu("Insert Key %t|Lens%x0|Clipping%x1|Aperture%x2|FocalDistance%x3");
2326                                         if(event== -1) return;
2327
2328                                         if(event==0) {
2329                                                 insertkey(id, ID_CA, NULL, NULL, CAM_LENS);
2330                                         }
2331                                         else if(event==1) {
2332                                                 insertkey(id, ID_CA, NULL, NULL, CAM_STA);
2333                                                 insertkey(id, ID_CA, NULL, NULL, CAM_END);
2334                                         }
2335                                         else if(event==2) {
2336                                                 insertkey(id, ID_CA, NULL, NULL, CAM_YF_APERT);
2337                                         }
2338                                         else if(event==3) {
2339                                                 insertkey(id, ID_CA, NULL, NULL, CAM_YF_FDIST);
2340                                         }
2341                                 }
2342                         }
2343                 }
2344                 else if(FALSE /* && G.buts->mainb==BUTS_SOUND */) {
2345                         if(G.ssound) {
2346                                 id= G.buts->lockpoin;
2347                                 if(id) {
2348                                         event= pupmenu("Insert Key %t|Volume%x0|Pitch%x1|Panning%x2|Attennuation%x3");
2349                                         if(event== -1) return;
2350
2351                                         if(event==0) {
2352                                                 insertkey(id, ID_SO, NULL, NULL, SND_VOLUME);
2353                                         }
2354                                         if(event==1) {
2355                                                 insertkey(id, ID_SO, NULL, NULL, SND_PITCH);
2356                                         }
2357                                         if(event==2) {
2358                                                 insertkey(id, ID_SO, NULL, NULL, SND_PANNING);
2359                                         }
2360                                         if(event==3) {
2361                                                 insertkey(id, ID_SO, NULL, NULL, SND_ATTEN);
2362                                         }
2363                                 }
2364                         }
2365                 }
2366                 
2367                 BIF_undo_push("Insert Key Buttons");
2368
2369                 allqueue(REDRAWACTION, 0);
2370                 allqueue(REDRAWNLA, 0);
2371                 allqueue(REDRAWIPO, 0);
2372                 allspace(REMAKEIPO, 0);
2373
2374         }
2375         else if(curarea->spacetype==SPACE_VIEW3D) {
2376                 ob= OBACT;
2377
2378                 if (ob && (ob->flag & OB_POSEMODE)) {
2379                         strcpy(menustr, "Insert Key%t|Loc%x0|Rot%x1|Size%x2|LocRot%x3|LocRotSize%x4|Avail%x9|VisualLoc%x11|VisualRot%x12|VisualLocRot%x13");
2380                 }
2381                 else {
2382                         base= FIRSTBASE;
2383                         while(base) {
2384                                 if TESTBASELIB(base) break;
2385                                 base= base->next;
2386                         }
2387                         if(base==NULL) return;
2388                 
2389                         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");
2390                 }
2391                 
2392                 if(ob) {
2393                         if(ob->type==OB_MESH) strcat(menustr, "| %x6|Mesh%x7");
2394                         else if(ob->type==OB_LATTICE) strcat(menustr, "| %x6|Lattice%x7");
2395                         else if(ob->type==OB_CURVE) strcat(menustr, "| %x6|Curve%x7");
2396                         else if(ob->type==OB_SURF) strcat(menustr, "| %x6|Surface%x7");
2397                 }
2398                 
2399                 event= pupmenu(menustr);
2400                 if(event== -1) return;
2401                 
2402                 if(event==7) { // ob != NULL
2403                         insert_shapekey(ob);
2404                         return;
2405                 }
2406                 
2407                 if (ob && (ob->flag & OB_POSEMODE)){
2408                         bPoseChannel *pchan;
2409
2410                         if (ob->action && ob->action->id.lib) {
2411                                 error ("Can't key libactions");
2412                                 return;
2413                         }
2414                         
2415                         set_pose_keys(ob);  // sets pchan->flag to POSE_KEY if bone selected
2416                         id= &ob->id;
2417                         for (pchan=ob->pose->chanbase.first; pchan; pchan=pchan->next) {
2418                                 if (pchan->flag & POSE_KEY){
2419                                         if(event==0 || event==3 ||event==4) {
2420                                                 insertkey(id, ID_PO, pchan->name, NULL, AC_LOC_X);
2421                                                 insertkey(id, ID_PO, pchan->name, NULL, AC_LOC_Y);
2422                                                 insertkey(id, ID_PO, pchan->name, NULL, AC_LOC_Z);
2423                                         }
2424                                         if(event==1 || event==3 ||event==4) {
2425                                                 insertkey(id, ID_PO, pchan->name, NULL, AC_QUAT_X);
2426                                                 insertkey(id, ID_PO, pchan->name, NULL, AC_QUAT_Y);
2427                                                 insertkey(id, ID_PO, pchan->name, NULL, AC_QUAT_Z);
2428                                                 insertkey(id, ID_PO, pchan->name, NULL, AC_QUAT_W);
2429                                         }
2430                                         if(event==2 || event==4) {
2431                                                 insertkey(id, ID_PO, pchan->name, NULL, AC_SIZE_X);
2432                                                 insertkey(id, ID_PO, pchan->name, NULL, AC_SIZE_Y);
2433                                                 insertkey(id, ID_PO, pchan->name, NULL, AC_SIZE_Z);
2434                                         }
2435                                         if (event==9 && ob->action) {
2436                                                 bActionChannel *achan;
2437                                                 
2438                                                 for (achan = ob->action->chanbase.first; achan; achan=achan->next){
2439                                                         if (achan->ipo && !strcmp (achan->name, pchan->name)){
2440                                                                 for (icu = achan->ipo->curve.first; icu; icu=icu->next){
2441                                                                         insertkey(id, ID_PO, achan->name, NULL, icu->adrcode);
2442                                                                 }
2443                                                                 break;
2444                                                         }
2445                                                 }
2446                                         }
2447                                         if(event==11 || event==13) {
2448                                                 float obSpaceBoneMat[4][4]; 
2449                                                 
2450                                                 bone2objectspace(obSpaceBoneMat, pchan->pose_mat, pchan->bone->arm_mat);
2451                                                 insertmatrixkey(id, ID_PO, pchan->name, NULL, AC_LOC_X, obSpaceBoneMat[3][0]);
2452                                                 insertmatrixkey(id, ID_PO, pchan->name, NULL, AC_LOC_Y, obSpaceBoneMat[3][1]);
2453                                                 insertmatrixkey(id, ID_PO, pchan->name, NULL, AC_LOC_Z, obSpaceBoneMat[3][2]);
2454                                         }
2455                                         if(event==12 || event==13) {
2456                                                 float obSpaceBoneMat[4][4];
2457                                                 float localQuat[4];
2458                                                 
2459                                                 bone2objectspace(obSpaceBoneMat, pchan->pose_mat, pchan->bone->arm_mat);
2460                                                 Mat4ToQuat(obSpaceBoneMat, localQuat);
2461                                                 insertmatrixkey(id, ID_PO, pchan->name, NULL, AC_QUAT_W, localQuat[0]);
2462                                                 insertmatrixkey(id, ID_PO, pchan->name, NULL, AC_QUAT_X, localQuat[1]);
2463                                                 insertmatrixkey(id, ID_PO, pchan->name, NULL, AC_QUAT_Y, localQuat[2]);
2464                                                 insertmatrixkey(id, ID_PO, pchan->name, NULL, AC_QUAT_Z, localQuat[2]);
2465                                         }
2466                                 }
2467                         }
2468                         if(ob->action)
2469                                 remake_action_ipos(ob->action);
2470
2471                         allqueue(REDRAWIPO, 0);
2472                         allqueue(REDRAWACTION, 0);
2473                         allqueue(REDRAWNLA, 0);
2474                 }
2475                 else {
2476                         base= FIRSTBASE;
2477                         while(base) {
2478                                 if TESTBASELIB(base) {
2479                                         char *actname= NULL;
2480                                         
2481                                         id= (ID *)(base->object);
2482                                         
2483                                         if(ob->ipoflag & OB_ACTION_OB)
2484                                                 actname= "Object";
2485                                         
2486                                         /* all curves in ipo deselect */
2487                                         if(base->object->ipo) {
2488                                                 icu= base->object->ipo->curve.first;
2489                                                 while(icu) {
2490                                                         icu->flag &= ~IPO_SELECT;
2491                                                         if(event==9) insertkey(id, ID_OB, actname, NULL, icu->adrcode);
2492                                                         icu= icu->next;
2493                                                 }
2494                                         }
2495                                         
2496                                         if(event==0 || event==3 ||event==4) {
2497                                                 insertkey(id, ID_OB, actname, NULL, OB_LOC_X);
2498                                                 insertkey(id, ID_OB, actname, NULL, OB_LOC_Y);
2499                                                 insertkey(id, ID_OB, actname, NULL, OB_LOC_Z);
2500                                         }
2501                                         if(event==1 || event==3 ||event==4) {
2502                                                 insertkey(id, ID_OB, actname, NULL, OB_ROT_X);
2503                                                 insertkey(id, ID_OB, actname, NULL, OB_ROT_Y);
2504                                                 insertkey(id, ID_OB, actname, NULL, OB_ROT_Z);
2505                                         }
2506                                         if(event==2 || event==4) {
2507                                                 insertkey(id, ID_OB, actname, NULL, OB_SIZE_X);
2508                                                 insertkey(id, ID_OB, actname, NULL, OB_SIZE_Y);
2509                                                 insertkey(id, ID_OB, actname, NULL, OB_SIZE_Z);
2510                                         }
2511                                         if(event==5) {
2512                                                 /* remove localview  */
2513                                                 tlay= base->object->lay;
2514                                                 base->object->lay &= 0xFFFFFF;
2515                                                 insertkey(id, ID_OB, actname, NULL, OB_LAY);
2516                                                 base->object->lay= tlay;
2517                                         }
2518                                         if(event==11 || event==13) {
2519                                                 insertmatrixkey(id, ID_OB, actname, NULL, OB_LOC_X, ob->obmat[3][0]);
2520                                                 insertmatrixkey(id, ID_OB, actname, NULL, OB_LOC_Y, ob->obmat[3][1]);
2521                                                 insertmatrixkey(id, ID_OB, actname, NULL, OB_LOC_Z, ob->obmat[3][2]);
2522                                         }
2523                                         if(event==12 || event==13) {
2524                                                 float eul[3];
2525                                                 float rotMat[3][3];
2526                                                 
2527                                                 Mat3CpyMat4(rotMat, ob->obmat);
2528                                                 Mat3ToEul(rotMat, eul);
2529                                                 insertmatrixkey(id, ID_OB, actname, NULL, OB_ROT_X, eul[0]*(5.72958));
2530                                                 insertmatrixkey(id, ID_OB, actname, NULL, OB_ROT_Y, eul[1]*(5.72958));
2531                                                 insertmatrixkey(id, ID_OB, actname, NULL, OB_ROT_Z, eul[2]*(5.72958));
2532                                         }
2533                                 }
2534                                 base= base->next;
2535                         }
2536                 }
2537
2538                 if(event==0) BIF_undo_push("Insert Loc Key");
2539                 else if(event==1) BIF_undo_push("Insert Rot Key");
2540                 else if(event==2) BIF_undo_push("Insert Size Key");
2541                 else if(event==3) BIF_undo_push("Insert LocRot Key");
2542                 else if(event==4) BIF_undo_push("Insert LocRotSize Key");
2543                 else if(event==5) BIF_undo_push("Insert Layer Key");
2544                 else if(event==7) BIF_undo_push("Insert Vertex Key");
2545                 else if(event==9) BIF_undo_push("Insert Avail Key");
2546
2547                 allspace(REMAKEIPO, 0);
2548                 allqueue(REDRAWIPO, 0);
2549                 allqueue(REDRAWVIEW3D, 0);
2550                 allqueue(REDRAWACTION, 0);
2551                 allqueue(REDRAWNLA, 0);
2552         }
2553         
2554 }
2555
2556 /* ****************************************************************************** */
2557
2558 void add_duplicate_editipo(void)
2559 {
2560         Object *ob;
2561         EditIpo *ei;
2562         IpoCurve *icu;
2563         BezTriple *bezt, *beztn, *newb;
2564         int tot, a, b;
2565         
2566         get_status_editipo();
2567         if(totipo_vertsel==0) return;
2568         
2569         ei= G.sipo->editipo;
2570         for(a=0; a<G.sipo->totipo; a++, ei++) {
2571                 if (ISPOIN3(ei, flag & IPO_VISIBLE, icu, icu->bezt)) {
2572                         if(G.sipo->showkey || (ei->flag & IPO_EDIT)) {
2573                                 icu= ei->icu;
2574                                 
2575                                 /* how many points */
2576                                 tot= 0;
2577                                 b= icu->totvert;
2578                                 bezt= icu->bezt;
2579                                 while(b--) {
2580                                         if(bezt->f2 & 1) tot++;
2581                                         bezt++;
2582                                 }
2583                                 
2584                                 if(tot) {
2585                                         icu->totvert+= tot;
2586                                         newb= beztn= MEM_mallocN(icu->totvert*sizeof(BezTriple), "bezt");
2587                                         bezt= icu->bezt;
2588                                         b= icu->totvert-tot;
2589                                         while(b--) {
2590                                                 *beztn= *bezt;
2591                                                 if(bezt->f2 & 1) {
2592                                                         beztn->f1= beztn->f2= beztn->f3= 0;
2593                                                         beztn++;
2594                                                         *beztn= *bezt;
2595                                                 }
2596                                                 beztn++;
2597                                                 bezt++;
2598                                         }
2599                                         MEM_freeN(icu->bezt);
2600                                         icu->bezt= newb;
2601                                         
2602                                         calchandles_ipocurve(icu);
2603                                 }
2604                         }
2605                 }
2606         }
2607         
2608         if(G.sipo->showkey) {
2609                 make_ipokey();
2610                 if(G.sipo->blocktype==ID_OB) {
2611                         ob= OBACT;
2612                         if(ob && (ob->ipoflag & OB_DRAWKEY)) allqueue(REDRAWVIEW3D, 0);
2613                 }
2614         }
2615         BIF_undo_push("Duplicate Ipo");
2616         transform_ipo('g');
2617 }
2618
2619 void remove_doubles_ipo(void)
2620 {
2621         EditIpo *ei;
2622         IpoKey *ik, *ikn;
2623         BezTriple *bezt, *newb, *new1;
2624         float val;
2625         int mode, a, b;
2626         
2627         ei= G.sipo->editipo;
2628         for(a=0; a<G.sipo->totipo; a++, ei++) {
2629                 if (ISPOIN3(ei, flag & IPO_VISIBLE, icu, icu->bezt)) {
2630                         
2631                         /* OR the curve is selected OR in editmode OR in keymode */
2632                         mode= 0;
2633                         if(G.sipo->showkey || (ei->flag & IPO_EDIT)) mode= 1;
2634                         else if(ei->flag & IPO_SELECT) mode= 2;
2635                         
2636                         if(mode) {
2637                                 bezt= ei->icu->bezt;
2638                                 newb= new1= MEM_mallocN(ei->icu->totvert*sizeof(BezTriple), "newbezt");
2639                                 *newb= *bezt;
2640                                 b= ei->icu->totvert-1;
2641                                 bezt++;
2642                                 while(b--) {
2643                                         
2644                                         /* can we remove? */
2645                                         if(mode==2 || (bezt->f2 & 1)) {
2646                                         
2647                                                 /* are the points different? */
2648                                                 if( fabs( bezt->vec[1][0]-newb->vec[1][0] ) > 0.9 ) {
2649                                                         newb++;
2650                                                         *newb= *bezt;
2651                                                 }
2652                                                 else {
2653                                                         /* median */
2654                                                         VecMidf(newb->vec[0], newb->vec[0], bezt->vec[0]);
2655                                                         VecMidf(newb->vec[1], newb->vec[1], bezt->vec[1]);
2656                                                         VecMidf(newb->vec[2], newb->vec[2], bezt->vec[2]);
2657                                                         
2658                                                         newb->h1= newb->h2= HD_FREE;
2659                                                         
2660                                                         ei->icu->totvert--;
2661                                                 }
2662                                                 
2663                                         }
2664                                         else {
2665                                                 newb++;
2666                                                 *newb= *bezt;
2667                                         }
2668                                         bezt++;
2669                                 }
2670                                 
2671                                 MEM_freeN(ei->icu->bezt);
2672                                 ei->icu->bezt= new1;
2673                                 
2674                                 calchandles_ipocurve(ei->icu);                          
2675                         }
2676                 }
2677         }
2678         
2679         editipo_changed(G.sipo, 1);     /* makes ipokeys again! */
2680
2681         /* remove double keys */
2682         if(G.sipo->showkey) {
2683                 ik= G.sipo->ipokey.first;
2684                 ikn= ik->next;
2685                 
2686                 while(ik && ikn) {
2687                         if( (ik->flag & 1) && (ikn->flag & 1) ) {
2688                                 if( fabs(ik->val-ikn->val) < 0.9 ) {
2689                                         val= (float)((ik->val + ikn->val)/2.0);
2690                                         
2691                                         for(a=0; a<G.sipo->totipo; a++) {
2692                                                 if(ik->data[a]) ik->data[a]->vec[1][0]= val;
2693                                                 if(ikn->data[a]) ikn->data[a]->vec[1][0]= val;                                          
2694                                         }
2695                                 }
2696                         }
2697                         ik= ikn;
2698                         ikn= ikn->next;
2699
2700                 }
2701                 
2702                 editipo_changed(G.sipo, 1);     /* makes ipokeys agian! */
2703
2704         }
2705         deselectall_editipo();
2706 }
2707
2708 void join_ipo_menu(void)
2709 {
2710         int mode = 0;
2711         mode= pupmenu("Join %t|All Selected %x1|Selected Doubles %x2");
2712         
2713         if (mode == -1) return;
2714         
2715         join_ipo(mode);
2716 }
2717
2718 void join_ipo(int mode)
2719 {
2720         EditIpo *ei;
2721         IpoKey *ik;
2722         IpoCurve *icu;
2723         BezTriple *bezt, *beztn, *newb;
2724         float val;
2725         int tot, a, b;
2726         
2727         get_status_editipo();
2728         
2729         /* Mode events:
2730          * All Selected: 1
2731          * Selected Doubles: 2
2732          */
2733         
2734         if( mode==2 ) {
2735                 remove_doubles_ipo();
2736                 return;
2737         }
2738         
2739         /* first: multiple selected verts in 1 curve */
2740         ei= G.sipo->editipo;
2741         for(a=0; a<G.sipo->totipo; a++, ei++) {
2742                 if (ISPOIN3(ei, flag & IPO_VISIBLE, icu, icu->bezt)) {
2743                         if(G.sipo->showkey || (ei->flag & IPO_EDIT)) {
2744                                 icu= ei->icu;
2745                                 
2746                                 /* how many points */
2747                                 tot= 0;
2748                                 b= icu->totvert;
2749                                 bezt= icu->bezt;
2750                                 while(b--) {
2751                                         if(bezt->f2 & 1) tot++;
2752                                         bezt++;
2753                                 }
2754                                 
2755                                 if(tot>1) {
2756                                         tot--;
2757                                         icu->totvert-= tot;
2758                                         
2759                                         newb= MEM_mallocN(icu->totvert*sizeof(BezTriple), "bezt");
2760                                         /* the first point is the new one */
2761                                         beztn= newb+1;
2762                                         tot= 0;
2763                                         
2764                                         bezt= icu->bezt;
2765                                         b= icu->totvert+tot+1;
2766                                         while(b--) {
2767                                                 
2768                                                 if(bezt->f2 & 1) {
2769                                                         if(tot==0) *newb= *bezt;
2770                                                         else {
2771                                                                 VecAddf(newb->vec[0], newb->vec[0], bezt->vec[0]);
2772                                                                 VecAddf(newb->vec[1], newb->vec[1], bezt->vec[1]);
2773                                                                 VecAddf(newb->vec[2], newb->vec[2], bezt->vec[2]);
2774                                                         }
2775                                                         tot++;
2776                                                 }
2777                                                 else {
2778                                                         *beztn= *bezt;
2779                                                         beztn++;
2780                                                 }
2781                                                 bezt++;
2782                                         }
2783                                         
2784                                         VecMulf(newb->vec[0], (float)(1.0/((float)tot)));
2785                                         VecMulf(newb->vec[1], (float)(1.0/((float)tot)));
2786                                         VecMulf(newb->vec[2], (float)(1.0/((float)tot)));
2787                                         
2788                                         MEM_freeN(icu->bezt);
2789                                         icu->bezt= newb;
2790                                         
2791                                         sort_time_ipocurve(icu);
2792                                         calchandles_ipocurve(icu);
2793                                 }
2794                         }
2795                 }
2796         }
2797         
2798         /* next: in keymode: join multiple selected keys */
2799         
2800         editipo_changed(G.sipo, 1);     /* makes ipokeys again! */
2801         
2802         if(G.sipo->showkey) {
2803                 ik= G.sipo->ipokey.first;
2804                 val= 0.0;
2805                 tot= 0;
2806                 while(ik) {
2807                         if(ik->flag & 1) {
2808                                 for(a=0; a<G.sipo->totipo; a++) {
2809                                         if(ik->data[a]) {
2810                                                 val+= ik->data[a]->vec[1][0];
2811                                                 break;
2812                                         }
2813                                 }
2814                                 tot++;
2815                         }
2816                         ik= ik->next;
2817                 }
2818                 if(tot>1) {
2819                         val/= (float)tot;
2820                         
2821                         ik= G.sipo->ipokey.first;
2822                         while(ik) {
2823                                 if(ik->flag & 1) {
2824                                         for(a=0; a<G.sipo->totipo; a++) {
2825                                                 if(ik->data[a]) {
2826                                                         ik->data[a]->vec[1][0]= val;
2827                                                 }
2828                                         }
2829                                 }
2830                                 ik= ik->next;
2831                         }
2832                         editipo_changed(G.sipo, 0);
2833                 }
2834         }
2835         deselectall_editipo();
2836         BIF_undo_push("Join Ipo");
2837 }
2838
2839 void ipo_snap_menu(void)
2840 {
2841         short event;
2842         
2843         event= pupmenu("Snap %t|Horizontal %x1|To Next %x2|To Frame %x3|To Current Frame%x4");
2844         if(event < 1) return;
2845
2846         ipo_snap(event);
2847</