NLA and IPO now have the "AfterTrans Keyframe" option that prevents the creation...
[blender.git] / source / blender / src / header_ipo.c
1 /**
2  * header_ipo.c oct-2003
3  *
4  * Functions to draw the "Ipo Curve Editor" window header
5  * and handle user events sent to it.
6  * 
7  * $Id$
8  *
9  * ***** BEGIN GPL LICENSE BLOCK *****
10  *
11  * This program is free software; you can redistribute it and/or
12  * modify it under the terms of the GNU General Public License
13  * as published by the Free Software Foundation; either version 2
14  * of the License, or (at your option) any later version.
15  *
16  * This program is distributed in the hope that it will be useful,
17  * but WITHOUT ANY WARRANTY; without even the implied warranty of
18  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
19  * GNU General Public License for more details.
20  *
21  * You should have received a copy of the GNU General Public License
22  * along with this program; if not, write to the Free Software Foundation,
23  * Inc., 59 Temple Place - Suite 330, Boston, MA        02111-1307, USA.
24  *
25  * The Original Code is Copyright (C) 2001-2002 by NaN Holding BV.
26  * All rights reserved.
27  *
28  * The Original Code is: all of this file.
29  *
30  * Contributor(s): none yet.
31  *
32  * ***** END GPL LICENSE BLOCK *****
33  */
34
35 #include <stdlib.h>
36 #include <string.h>
37 #include <stdio.h>
38
39 #ifdef HAVE_CONFIG_H
40 #include <config.h>
41 #endif
42
43 #include "DNA_action_types.h"
44 #include "DNA_camera_types.h"
45 #include "DNA_curve_types.h"
46 #include "DNA_constraint_types.h"
47 #include "DNA_ID.h"
48 #include "DNA_ipo_types.h"
49 #include "DNA_key_types.h"
50 #include "DNA_lamp_types.h"
51 #include "DNA_material_types.h"
52 #include "DNA_object_types.h"
53 #include "DNA_object_fluidsim.h"
54 #include "DNA_particle_types.h"
55 #include "DNA_scene_types.h"
56 #include "DNA_screen_types.h"
57 #include "DNA_texture_types.h"
58 #include "DNA_space_types.h"
59 #include "DNA_sequence_types.h"
60 #include "DNA_sound_types.h"
61 #include "DNA_world_types.h"
62
63 #include "BKE_action.h"
64 #include "BKE_constraint.h"
65 #include "BKE_depsgraph.h"
66 #include "BKE_global.h"
67 #include "BKE_ipo.h"
68 #include "BKE_key.h"
69 #include "BKE_main.h"
70 #include "BKE_material.h"
71 #include "BKE_particle.h"
72 #include "BKE_texture.h"
73 #include "BKE_utildefines.h"
74
75 #include "BLI_blenlib.h"
76
77 #include "BSE_drawipo.h"
78 #include "BSE_editipo_types.h"
79 #include "BSE_edit.h"
80 #include "BSE_editipo.h"
81 #include "BSE_headerbuttons.h"
82 #include "BSE_time.h"
83
84 #include "BIF_editaction.h"
85 #include "BIF_editconstraint.h"
86 #include "BIF_interface.h"
87 #include "BIF_mainqueue.h"
88 #include "BIF_resources.h"
89 #include "BIF_screen.h"
90 #include "BIF_space.h"
91 #include "BIF_toolbox.h"
92
93 #include "nla.h"
94
95 #include "blendef.h"
96 #include "mydevice.h"
97
98 extern int totipo_edit, totipo_sel;
99
100 /* headerbutton call, assuming full context is set */
101 /* it aligns with editipo.c, verify_ipo */
102 void spaceipo_assign_ipo(SpaceIpo *si, Ipo *ipo)
103 {
104         if(si->from==NULL || si->from->lib) return;
105         
106         if(ipo) ipo->id.us++;
107
108         /* first check action ipos */
109         if(si->actname && si->actname[0]) {
110                 Object *ob= (Object *)si->from;
111                 bActionChannel *achan;
112                 
113                 if(ob->action) {
114                         achan= verify_action_channel(ob->action, si->actname);
115                 
116                         if(achan) {
117                                 /* constraint exception */
118                                 if(si->blocktype==ID_CO) {
119                                         bConstraintChannel *conchan= get_constraint_channel(&achan->constraintChannels, si->constname);
120                                         if(conchan) {
121                                                 if(conchan->ipo)
122                                                         conchan->ipo->id.us--;
123                                                 conchan->ipo= ipo;
124                                         }
125                                 }
126                                 else {
127                                         if(achan->ipo)
128                                                 achan->ipo->id.us--;
129                                         achan->ipo= ipo;
130                                 }
131                         }
132                 }
133         }
134         else {
135                 switch(GS(si->from->name)) {
136                         case ID_OB:
137                         {
138                                 Object *ob= (Object *)si->from;
139                                 /* constraint exception */
140                                 if(si->blocktype==ID_CO) {
141                                         /* check the local constraint ipo */
142                                         if(si->bonename && si->bonename[0] && ob->pose) {
143                                                 bPoseChannel *pchan= get_pose_channel(ob->pose, si->bonename);
144                                                 bConstraint *con;
145
146                                                 for(con= pchan->constraints.first; con; con= con->next)
147                                                         if(strcmp(con->name, si->constname)==0)
148                                                                 break;
149                                                 if(con) {
150                                                         if(con->ipo)
151                                                                 con->ipo->id.us--;
152                                                         con->ipo= ipo;
153                                                 }
154                                         }
155                                         else {
156                                                 bConstraintChannel *conchan= get_constraint_channel(&ob->constraintChannels, si->constname);
157                                                 if(conchan) {
158                                                         if(conchan->ipo)
159                                                                 conchan->ipo->id.us--;
160                                                         conchan->ipo= ipo;
161                                                 }
162                                         }
163                                 }
164                                 else if(si->blocktype==ID_FLUIDSIM) { // NT
165                                         if( (ob->fluidsimSettings) && 
166                                             (ob->fluidsimSettings->ipo) ) {
167                                                 // decrement users counter
168                                                 ob->fluidsimSettings->ipo->id.us--; 
169                                         }
170                                         ob->fluidsimSettings->ipo = ipo;
171                                 } 
172                                 else if(si->blocktype==ID_PA) {
173                                         ParticleSystem *psys=psys_get_current(ob);
174                                         if(psys){
175                                                 if(psys->part->ipo){
176                                                         psys->part->ipo->id.us--;
177                                                 }
178                                                 psys->part->ipo = ipo;
179                                         }
180                                 }
181                                 else if(si->blocktype==ID_OB) {
182                                         if(ob->ipo)
183                                                 ob->ipo->id.us--;
184                                         ob->ipo= ipo;
185                                 }
186                         }
187                                 break;
188                         case ID_MA:
189                         {
190                                 Material *ma= (Material *)si->from;
191                                 
192                                 if(ma->ipo)
193                                         ma->ipo->id.us--;
194                                 ma->ipo= ipo;
195                         }
196                                 break;
197                         case ID_TE:
198                         {
199                                 Tex *tex= (Tex *)si->from;
200                                 
201                                 if(tex->ipo)
202                                         tex->ipo->id.us--;
203                                 tex->ipo= ipo;
204                         }
205                                 break;
206                         case ID_SEQ:
207                         {
208                                 Sequence *seq= (Sequence *)si->from;    /* note, sequence is mimicing Id */
209                                 
210                                 if(seq->ipo)
211                                         seq->ipo->id.us--;
212                                 seq->ipo= ipo;
213                         }
214                                 break;
215                         case ID_CU:
216                         {
217                                 Curve *cu= (Curve *)si->from;
218                                 
219                                 if(cu->ipo)
220                                         cu->ipo->id.us--;
221                                 cu->ipo= ipo;
222                         }
223                                 break;
224                         case ID_KE:
225                         {
226                                 Key *key= (Key *)si->from;
227                                 
228                                 if(key->ipo)
229                                         key->ipo->id.us--;
230                                 key->ipo= ipo;
231                         }
232                                 break;
233                         case ID_WO:
234                         {
235                                 World *wo= (World *)si->from;
236                                 
237                                 if(wo->ipo)
238                                         wo->ipo->id.us--;
239                                 wo->ipo= ipo;
240                         }
241                                 break;
242                         case ID_LA:
243                         {
244                                 Lamp *la= (Lamp *)si->from;
245                                 
246                                 if(la->ipo)
247                                         la->ipo->id.us--;
248                                 la->ipo= ipo;
249                         }
250                                 break;
251                         case ID_CA:
252                         {
253                                 Camera *ca= (Camera *)si->from;
254                                 
255                                 if(ca->ipo)
256                                         ca->ipo->id.us--;
257                                 ca->ipo= ipo;
258                         }
259                                 break;
260                         case ID_SO:
261                         {
262                                 bSound *snd= (bSound *)si->from;
263                                 
264                                 if(snd->ipo)
265                                         snd->ipo->id.us--;
266                                 snd->ipo= ipo;
267                         }
268                 }
269         }
270         
271         allqueue(REDRAWVIEW3D, 0);
272         allqueue(REDRAWIPO, 0);
273         allqueue(REDRAWACTION, 0);
274         allqueue(REDRAWNLA, 0);
275         allqueue(REDRAWBUTSALL, 0);
276         
277 }
278
279
280 static void do_ipo_editmenu_transformmenu(void *arg, int event)
281 {
282         switch(event)
283         {
284         case 0: /* grab/move */
285                 transform_ipo('g');
286                 break;
287         case 1: /* rotate */
288                 transform_ipo('r');
289                 break;
290         case 2: /* scale */
291                 transform_ipo('s');
292                 break;
293         }
294 }
295
296 static uiBlock *ipo_editmenu_transformmenu(void *arg_unused)
297 {
298         uiBlock *block;
299         short yco= 0, menuwidth=120;
300
301         block= uiNewBlock(&curarea->uiblocks, "ipo_editmenu_transformmenu", UI_EMBOSSP, UI_HELV, G.curscreen->mainwin);
302         uiBlockSetButmFunc(block, do_ipo_editmenu_transformmenu, NULL);
303
304         uiDefIconTextBut(block, BUTM, 1, ICON_BLANK1, "Grab/Move|G", 0, yco-=20, menuwidth, 19, NULL, 0.0, 0.0, 0, 0, "");
305         uiDefIconTextBut(block, BUTM, 1, ICON_BLANK1, "Rotate|R", 0, yco-=20, menuwidth, 19, NULL, 0.0, 0.0, 0, 1, "");
306         uiDefIconTextBut(block, BUTM, 1, ICON_BLANK1, "Scale|S", 0, yco-=20, menuwidth, 19, NULL, 0.0, 0.0, 0, 2, "");
307
308         uiBlockSetDirection(block, UI_RIGHT);
309         uiTextBoundsBlock(block, 60);
310
311         return block;
312 }
313
314 static void do_ipo_editmenu_snapmenu(void *arg, int event)
315 {
316         switch(event) {
317         case 1: /* Horizontal */
318         case 2: /* To Next */
319         case 3: /* To Frame */
320         case 4: /* To Current Frame */
321                 ipo_snap(event);
322             break;
323         }
324         allqueue(REDRAWVIEW3D, 0);
325 }
326
327 static uiBlock *ipo_editmenu_snapmenu(void *arg_unused)
328 {
329         uiBlock *block;
330         short yco = 20, menuwidth = 120;
331
332         block= uiNewBlock(&curarea->uiblocks, "ipo_editmenu_snapmenu", UI_EMBOSSP, UI_HELV, G.curscreen->mainwin);
333         uiBlockSetButmFunc(block, do_ipo_editmenu_snapmenu, NULL);
334         
335         uiDefIconTextBut(block, BUTM, 1, ICON_BLANK1, "Horizontal|Shift S, 1",                  0, yco-=20, menuwidth, 19, NULL, 0.0, 0.0, 1, 1, "");
336         uiDefIconTextBut(block, BUTM, 1, ICON_BLANK1, "To Next|Shift S, 2",                     0, yco-=20, menuwidth, 19, NULL, 0.0, 0.0, 1, 2, "");
337         uiDefIconTextBut(block, BUTM, 1, ICON_BLANK1, "To Frame|Shift S, 3",                    0, yco-=20, menuwidth, 19, NULL, 0.0, 0.0, 1, 3, "");
338         uiDefIconTextBut(block, BUTM, 1, ICON_BLANK1, "To Current Frame|Shift S, 4",                    0, yco-=20, menuwidth, 19, NULL, 0.0, 0.0, 1, 4, "");   
339         
340         uiBlockSetDirection(block, UI_RIGHT);
341         uiTextBoundsBlock(block, 60);
342         return block;
343 }
344
345 static void do_ipo_editmenu_mirrormenu(void *arg, int event)
346 {
347         switch(event) {
348                 case 1: /* mirror over current frame */
349                 case 2: /* mirror over frame 0 */
350                 case 3: /* mirror over horizontal axis */
351                         ipo_mirror(event);
352                         break;
353         }
354         allqueue(REDRAWVIEW3D, 0);
355 }
356
357 static uiBlock *ipo_editmenu_mirrormenu(void *arg_unused)
358 {
359         uiBlock *block;
360         short yco = 20, menuwidth = 120;
361
362         block= uiNewBlock(&curarea->uiblocks, "ipo_editmenu_mirrormenu", UI_EMBOSSP, UI_HELV, G.curscreen->mainwin);
363         uiBlockSetButmFunc(block, do_ipo_editmenu_mirrormenu, NULL);
364         
365         uiDefIconTextBut(block, BUTM, 1, ICON_BLANK1, "Over Current Frame|Shift M, 1",                  0, yco-=20, menuwidth, 19, NULL, 0.0, 0.0, 1, 1, "");
366         uiDefIconTextBut(block, BUTM, 1, ICON_BLANK1, "Over Vertical Axis|Shift M, 2",                  0, yco-=20, menuwidth, 19, NULL, 0.0, 0.0, 1, 2, "");
367         uiDefIconTextBut(block, BUTM, 1, ICON_BLANK1, "Over Horizontal Axis|Shift M, 3",                        0, yco-=20, menuwidth, 19, NULL, 0.0, 0.0, 1, 3, "");   
368         
369         uiBlockSetDirection(block, UI_RIGHT);
370         uiTextBoundsBlock(block, 60);
371         return block;
372
373
374 static void do_ipo_editmenu_joinmenu(void *arg, int event)
375 {
376         switch(event) {
377         case 1: /* All Selected */
378         case 2: /* Selected Doubles */
379                 join_ipo(event);
380             break;
381         }
382         allqueue(REDRAWVIEW3D, 0);
383 }
384
385 static uiBlock *ipo_editmenu_joinmenu(void *arg_unused)
386 {
387         uiBlock *block;
388         short yco = 20, menuwidth = 120;
389
390         block= uiNewBlock(&curarea->uiblocks, "ipo_editmenu_joinmenu", UI_EMBOSSP, UI_HELV, G.curscreen->mainwin);
391         uiBlockSetButmFunc(block, do_ipo_editmenu_joinmenu, NULL);
392         
393         uiDefIconTextBut(block, BUTM, 1, ICON_BLANK1, "All Selected|Ctrl J, 1",                 0, yco-=20, menuwidth, 19, NULL, 0.0, 0.0, 1, 1, "");
394         uiDefIconTextBut(block, BUTM, 1, ICON_BLANK1, "Selected Doubles|Ctrl J, 2",                     0, yco-=20, menuwidth, 19, NULL, 0.0, 0.0, 1, 2, "");
395
396         uiBlockSetDirection(block, UI_RIGHT);
397         uiTextBoundsBlock(block, 60);
398         return block;
399 }
400
401 static void do_ipo_editmenu_keymenu(void *arg, int event)
402 {
403         Key *key;
404         KeyBlock *kb;
405         Object *ob= OBACT;
406
407         if(G.sipo->blocktype==ID_KE && totipo_edit==0 && totipo_sel==0) {
408                 key= ob_get_key((Object *)G.sipo->from);
409                 if(key==NULL) return;
410
411                 kb= BLI_findlink(&key->block, ob->shapenr-1);
412                 kb->type= 0;
413                 switch(event){
414                         case 0:
415                                 kb->type= KEY_LINEAR;
416                                 break;
417                         case 1:
418                                 kb->type= KEY_CARDINAL;
419                                 break;
420                         case 2:
421                                 kb->type= KEY_BSPLINE;
422                                 break;
423                 }
424         }
425 }
426
427 static uiBlock *ipo_editmenu_keymenu(void *arg_unused)
428 {
429         uiBlock *block;
430         short yco= 0, menuwidth=120;
431
432         block= uiNewBlock(&curarea->uiblocks, "ipo_editmenu_keymenu", UI_EMBOSSP, UI_HELV, G.curscreen->mainwin);
433         uiBlockSetButmFunc(block, do_ipo_editmenu_keymenu, NULL);
434
435         uiDefIconTextBut(block, BUTM, 1, ICON_BLANK1, "Linear|T, 1", 0, yco-=20, menuwidth, 19, NULL, 0.0, 0.0, 0, 0, "");
436         uiDefIconTextBut(block, BUTM, 1, ICON_BLANK1, "Cardinal|T, 2", 0, yco-=20, menuwidth, 19, NULL, 0.0, 0.0, 0, 1, "");
437         uiDefIconTextBut(block, BUTM, 1, ICON_BLANK1, "BSpline|T, 3", 0, yco-=20, menuwidth, 19, NULL, 0.0, 0.0, 0, 2, "");
438
439         uiBlockSetDirection(block, UI_RIGHT);
440         uiTextBoundsBlock(block, 60);
441
442         return block;
443
444 }
445
446 static void do_ipo_editmenu_handlemenu(void *arg, int event)
447 {
448         switch(event){
449         case 0:
450                 sethandles_ipo(HD_AUTO);
451                 break;
452         case 1:
453         case 2:
454                 sethandles_ipo(HD_ALIGN);
455                 break;
456         case 3:
457                 sethandles_ipo(HD_VECT);
458                 break;
459         case 4:
460                 sethandles_ipo(HD_AUTO_ANIM);
461                 break;
462         }
463 }
464
465 static uiBlock *ipo_editmenu_handlemenu(void *arg_unused)
466 {
467         uiBlock *block;
468         short yco= 0, menuwidth=120;
469
470         block= uiNewBlock(&curarea->uiblocks, "ipo_editmenu_handlemenu", UI_EMBOSSP, UI_HELV, G.curscreen->mainwin);
471         uiBlockSetButmFunc(block, do_ipo_editmenu_handlemenu, NULL);
472
473         uiDefIconTextBut(block, BUTM, 1, ICON_BLANK1, "Auto|Shift H", 0, yco-=20, menuwidth, 19, NULL, 0.0, 0.0, 0, 0, "");
474         uiDefIconTextBut(block, BUTM, 1, ICON_BLANK1, "Auto Clamped|Alt H", 0, yco-=20, menuwidth, 19, NULL, 0.0, 0.0, 0, 4, "");
475         uiDefIconTextBut(block, BUTM, 1, ICON_BLANK1, "Aligned|H", 0, yco-=20, menuwidth, 19, NULL, 0.0, 0.0, 0, 1, "");
476         uiDefIconTextBut(block, BUTM, 1, ICON_BLANK1, "Free|H", 0, yco-=20, menuwidth, 19, NULL, 0.0, 0.0, 0, 2, "");
477         uiDefIconTextBut(block, BUTM, 1, ICON_BLANK1, "Vector|V", 0, yco-=20, menuwidth, 19, NULL, 0.0, 0.0, 0, 3, "");
478
479         uiBlockSetDirection(block, UI_RIGHT);
480         uiTextBoundsBlock(block, 60);
481
482         return block;
483 }
484
485 static void do_ipo_editmenu_intpolmenu(void *arg, int event)
486 {
487         EditIpo *ei;
488         int a;
489
490         get_status_editipo();
491
492         ei = G.sipo->editipo;
493
494         switch(event)
495         {
496         case 0:
497                 for(a=0; a<G.sipo->totipo; a++, ei++) {
498                         if ISPOIN3(ei, flag & IPO_VISIBLE, flag & IPO_SELECT, icu) {
499                                 ei->icu->ipo= IPO_CONST;
500                         }
501                 }
502                 break;
503         case 1:
504                 for(a=0; a<G.sipo->totipo; a++, ei++) {
505                         if ISPOIN3(ei, flag & IPO_VISIBLE, flag & IPO_SELECT, icu) {
506                                 ei->icu->ipo= IPO_LIN;
507                         }
508                 }
509                 break;
510         case 2:
511                 for(a=0; a<G.sipo->totipo; a++, ei++) {
512                         if ISPOIN3(ei, flag & IPO_VISIBLE, flag & IPO_SELECT, icu) {
513                                 ei->icu->ipo= IPO_BEZ;
514                         }
515                 }
516                 break;
517         }
518
519         scrarea_queue_winredraw(curarea);
520 }
521
522 static uiBlock *ipo_editmenu_intpolmenu(void *arg_unused)
523 {
524         uiBlock *block;
525         short yco= 0, menuwidth=120;
526
527         block= uiNewBlock(&curarea->uiblocks, "ipo_editmenu_intpolmenu", UI_EMBOSSP, UI_HELV, G.curscreen->mainwin);
528         uiBlockSetButmFunc(block, do_ipo_editmenu_intpolmenu, NULL);
529
530         uiDefIconTextBut(block, BUTM, 1, ICON_BLANK1, "Constant|T, 1", 0, yco-=20, menuwidth, 19, NULL, 0.0, 0.0, 0, 0, "");
531         uiDefIconTextBut(block, BUTM, 1, ICON_BLANK1, "Linear|T, 2", 0, yco-=20, menuwidth, 19, NULL, 0.0, 0.0, 0, 1, "");
532         uiDefIconTextBut(block, BUTM, 1, ICON_BLANK1, "Bezier|T, 3", 0, yco-=20, menuwidth, 19, NULL, 0.0, 0.0, 0, 2, "");
533
534         uiBlockSetDirection(block, UI_RIGHT);
535         uiTextBoundsBlock(block, 60);
536
537         return block;
538 }
539
540 static void do_ipo_editmenu_extendmenu(void *arg, int event)
541 {
542         switch(event)
543         {
544         case 0:
545                 do_ipo_buttons(B_IPOCONT);
546                 break;
547         case 1:
548                 do_ipo_buttons(B_IPOEXTRAP);
549                 break;
550         case 2:
551                 do_ipo_buttons(B_IPOCYCLIC);
552                 break;
553         case 3:
554                 do_ipo_buttons(B_IPOCYCLICX);
555                 break;
556         }
557 }
558
559 static uiBlock *ipo_editmenu_extendmenu(void *arg_unused)
560 {
561         uiBlock *block;
562         short yco= 0, menuwidth=120;
563
564         block= uiNewBlock(&curarea->uiblocks, "ipo_editmenu_extendmenu", UI_EMBOSSP, UI_HELV, G.curscreen->mainwin);
565         uiBlockSetButmFunc(block, do_ipo_editmenu_extendmenu, NULL);
566
567         uiDefIconTextBut(block, BUTM, 1, ICON_BLANK1, "Constant|E, 1", 0, yco-=20, menuwidth, 19, NULL, 0.0, 0.0, 0, 0, "");
568         uiDefIconTextBut(block, BUTM, 1, ICON_BLANK1, "Extrapolation|E, 2", 0, yco-=20, menuwidth, 19, NULL, 0.0, 0.0, 0, 1, "");
569         uiDefIconTextBut(block, BUTM, 1, ICON_BLANK1, "Cyclic|E, 3", 0, yco-=20, menuwidth, 19, NULL, 0.0, 0.0, 0, 2, "");
570         uiDefIconTextBut(block, BUTM, 1, ICON_BLANK1, "Cyclic Extrapolation|E, 4", 0, yco-=20, menuwidth, 19, NULL, 0.0, 0.0, 0, 3, "");
571
572         uiBlockSetDirection(block, UI_RIGHT);
573         uiTextBoundsBlock(block, 60);
574
575         return block;
576 }
577
578
579 static void do_ipo_editmenu(void *arg, int event)
580 {
581         switch(event)
582         {
583         case 0:
584                 del_ipo(1);
585                 break;
586         case 1:
587                 add_duplicate_editipo();
588                 break;
589         case 2:
590                 ipo_record();
591                 break;
592         case 3:
593                 mainqenter(IKEY, 1);
594                 break;
595         case 4 :
596                 add_blockhandler(curarea, IPO_HANDLER_PROPERTIES, UI_PNL_UNSTOW);
597                 break;
598         case 5:
599                 //join_ipo();
600                 break;
601         case 6:
602                 /*IPO Editmode*/
603                 set_editflag_editipo();
604                 break;
605         case 7:
606                 sethandles_ipo(HD_AUTO_ANIM);
607                 break;
608         case 8: /* clean ipo */
609                 clean_ipo();
610                 break;
611         case 9: /* smooth ipo */
612                 smooth_ipo();
613                 break;
614         }
615 }
616
617 static uiBlock *ipo_editmenu(void *arg_unused)
618 {
619         uiBlock *block;
620         EditIpo *ei;
621         short yco= 0, menuwidth=120;
622         int a,isedit = 0;
623
624         get_status_editipo();
625
626         ei = G.sipo->editipo;
627
628         block= uiNewBlock(&curarea->uiblocks, "ipo_editmenu", UI_EMBOSSP, UI_HELV, curarea->headwin);
629         uiBlockSetButmFunc(block, do_ipo_editmenu, NULL);
630
631         uiDefIconTextBut(block, BUTM, 1, ICON_MENU_PANEL, "Transform Properties|N", 0, yco-=20, menuwidth, 19, NULL, 0.0, 0.0, 0, 4, "");
632         
633         uiDefIconTextBlockBut(block, ipo_editmenu_transformmenu, NULL, ICON_RIGHTARROW_THIN, "Transform", 0, yco-=20, 120, 19, "");     
634         
635         uiDefIconTextBlockBut(block, ipo_editmenu_snapmenu, NULL, ICON_RIGHTARROW_THIN, "Snap", 0, yco-=20, 120, 19, "");       
636
637         uiDefIconTextBlockBut(block, ipo_editmenu_mirrormenu, NULL, ICON_RIGHTARROW_THIN, "Mirror", 0, yco-=20, 120, 19, "");   
638         
639         uiDefBut(block, SEPR, 0, "",        0, yco-=6, menuwidth, 6, NULL, 0.0, 0.0, 0, 0, ""); 
640
641         /*Look to see if any ipos are being edited, so there can be a check next to the menu option*/
642         for(a=0; a<G.sipo->totipo; a++, ei++) {         
643                 if(ei->icu) {
644                         if(ei->flag & IPO_VISIBLE) {
645                                 if(totipo_edit && (ei->flag & IPO_EDIT)) {
646                                         isedit = 1;
647                                         break;
648                                 }
649                         }
650                 }
651         }
652         if(isedit)
653                 uiDefIconTextBut(block, BUTM, 1, ICON_CHECKBOX_HLT,   "Edit Selected|TAB", 0, yco-=20, menuwidth, 19, NULL, 0.0, 0.0, 0, 6, "");                
654         else
655                 uiDefIconTextBut(block, BUTM, 1, ICON_CHECKBOX_DEHLT, "Edit Selected|TAB", 0, yco-=20, menuwidth, 19, NULL, 0.0, 0.0, 0, 6, "");
656         
657         ei = get_active_editipo();
658         uiDefBut(block, SEPR, 0, "",        0, yco-=6, menuwidth, 6, NULL, 0.0, 0.0, 0, 0, "");
659         
660         if(ei && ei->icu && ei->icu->driver)
661                 uiDefIconTextBut(block, BUTM, 1, ICON_BLANK1, "Insert 1:1 Curve...|I", 0, yco-=20, menuwidth, 19, NULL, 0.0, 0.0, 0, 3, "");
662         else
663                 uiDefIconTextBut(block, BUTM, 1, ICON_BLANK1, "Insert Keyframe...|I", 0, yco-=20, menuwidth, 19, NULL, 0.0, 0.0, 0, 3, "");
664         
665         uiDefBut(block, SEPR, 0, "",        0, yco-=6, menuwidth, 6, NULL, 0.0, 0.0, 0, 0, "");
666
667         uiDefIconTextBut(block, BUTM, 1, ICON_BLANK1, "Duplicate|Shift D", 0, yco-=20, menuwidth, 19, NULL, 0.0, 0.0, 0, 1, "");
668         uiDefIconTextBut(block, BUTM, 1, ICON_BLANK1, "Record Mouse Movement|Ctrl R", 0, yco-=20, menuwidth, 19, NULL, 0.0, 0.0, 0, 2, "");
669         uiDefIconTextBut(block, BUTM, 1, ICON_BLANK1, "Clean IPO Curves|O", 0, yco-=20, menuwidth, 19, NULL, 0.0, 0.0, 0, 8, "");
670         uiDefIconTextBut(block, BUTM, 1, ICON_BLANK1, "Smooth IPO Curves|Shift O", 0, yco-=20, menuwidth, 19, NULL, 0.0, 0.0, 0, 9, "");
671         uiDefIconTextBut(block, BUTM, 1, ICON_BLANK1, "Delete|X", 0, yco-=20, menuwidth, 19, NULL, 0.0, 0.0, 0, 0, "");
672         uiDefIconTextBlockBut(block, ipo_editmenu_joinmenu, NULL, ICON_RIGHTARROW_THIN, "Join", 0, yco-=20, 120, 19, "");       
673
674         uiDefBut(block, SEPR, 0, "",        0, yco-=6, menuwidth, 6, NULL, 0.0, 0.0, 0, 0, "");
675         uiDefIconTextBut(block, BUTM, 1, ICON_BLANK1, "Auto Clamped Handles|Alt H", 0, yco-=20, menuwidth, 19, NULL, 0.0, 0.0, 0, 7, "");
676         
677         if (!G.sipo->showkey){
678                 uiDefIconTextBlockBut(block, ipo_editmenu_extendmenu, NULL, ICON_RIGHTARROW_THIN, "Extend Mode", 0, yco-=20, 120, 19, "");      
679                 uiDefIconTextBlockBut(block, ipo_editmenu_intpolmenu, NULL, ICON_RIGHTARROW_THIN, "Interpolation Mode   ", 0, yco-=20, 120, 20, "");
680                 if(ei != NULL && (ei->flag & IPO_EDIT))
681                         uiDefIconTextBlockBut(block, ipo_editmenu_handlemenu, NULL, ICON_RIGHTARROW_THIN, "Handle Type", 0, yco-=20, 120, 19, "");
682                 if(G.sipo->blocktype==ID_KE && totipo_edit==0 && totipo_sel==0)
683                         uiDefIconTextBlockBut(block, ipo_editmenu_keymenu, NULL, ICON_RIGHTARROW_THIN, "Key Type", 0, yco-=20, 120, 19, "");
684         }
685         
686
687         if(curarea->headertype==HEADERTOP) {
688                 uiBlockSetDirection(block, UI_DOWN);
689         }
690         else {
691                 uiBlockSetDirection(block, UI_TOP);
692                 uiBlockFlipOrder(block);
693         }
694
695         uiTextBoundsBlock(block, 50);
696
697         return block;
698 }
699
700 static void do_ipo_viewmenu(void *arg, int event)
701 {
702         extern int play_anim(int mode);
703         
704         switch(event)
705         {
706         case 1:
707                 do_ipo_buttons(B_IPOHOME);
708                 break;
709         case 2:
710                 ipo_toggle_showkey();
711                 scrarea_queue_headredraw(curarea);
712                 scrarea_queue_winredraw(curarea);
713                 allqueue(REDRAWVIEW3D, 0);
714                 break;
715         case 3:
716                 move_to_frame();
717                 break;
718         case 4:
719                 mainqenter(PADPLUSKEY,1);
720                 break;
721         case 5:
722                 mainqenter(PADMINUS,1);
723                 break;
724         case 6: /* Play Animation */
725                 play_anim(0);
726                 break;
727         case 7: /* Play Animation in All */
728                 play_anim(1);
729                 break;  
730         case 8:
731                 add_blockhandler(curarea, IPO_HANDLER_PROPERTIES, UI_PNL_UNSTOW);
732                 break;  
733         case 9:
734                 G.v2d->flag ^= V2D_VIEWLOCK;
735                 if(G.v2d->flag & V2D_VIEWLOCK)
736                         view2d_do_locks(curarea, 0);
737                 break;  
738         case 10: /* center view to current frame */
739                 center_currframe();
740                 scrarea_queue_winredraw(curarea);
741                 break;
742         case 11:
743                 do_ipo_buttons(B_IPOVIEWCENTER);
744                 break;
745         case 12:        
746                 G.sipo->flag ^= SIPO_LOCK_VIEW;
747                 break;
748         case 13: /* Set Preview Range */
749                 anim_previewrange_set();
750                 break;
751         case 14: /* Clear Preview Range */
752                 anim_previewrange_clear();
753                 break;
754         case 15: /* AutoMerge Keyframes */
755                 G.sipo->flag ^= SIPO_NOTRANSKEYCULL;
756                 break;
757         }
758 }
759
760 static uiBlock *ipo_viewmenu(void *arg_unused)
761 {
762         uiBlock *block;
763         EditIpo *ei;
764         short yco= 0, menuwidth=120;
765
766         ei = get_active_editipo();
767
768         block= uiNewBlock(&curarea->uiblocks, "ipo_viewmenu", UI_EMBOSSP, UI_HELV, curarea->headwin);
769         uiBlockSetButmFunc(block, do_ipo_viewmenu, NULL);
770
771         uiDefIconTextBut(block, BUTM, 1, ICON_MENU_PANEL, "Channel Properties|N", 0, yco-=20, menuwidth, 19, NULL, 0.0, 0.0, 0, 8, "");
772         
773         if (G.sipo->showkey)
774                 uiDefIconTextBut(block, BUTM, 1, ICON_CHECKBOX_HLT, "Show Keys|K", 0, yco-=20, menuwidth, 19, NULL, 0.0, 0.0, 0, 2, "");
775         else
776                 uiDefIconTextBut(block, BUTM, 1, ICON_CHECKBOX_DEHLT, "Show Keys|K", 0, yco-=20, menuwidth, 19, NULL, 0.0, 0.0, 0, 2, "");
777         
778         uiDefIconTextBut(block, BUTM, 1, (G.sipo->flag & SIPO_NOTRANSKEYCULL)?ICON_CHECKBOX_DEHLT:ICON_CHECKBOX_HLT, 
779                                          "AutoMerge Keyframes|", 0, yco-=20, menuwidth, 19, NULL, 0.0, 0.0, 1, 15, "");
780         
781         uiDefBut(block, SEPR, 0, "",        0, yco-=6, menuwidth, 6, NULL, 0.0, 0.0, 0, 0, "");
782
783         uiDefIconTextBut(block, BUTM, 1, ICON_BLANK1, "Zoom Out|NumPad -", 0, yco-=20, menuwidth, 19, NULL, 0.0, 0.0, 0, 5, "");
784         uiDefIconTextBut(block, BUTM, 1, ICON_BLANK1, "Zoom In|NumPad +", 0, yco-=20, menuwidth, 19, NULL, 0.0, 0.0, 0, 4, "");
785
786         uiDefBut(block, SEPR, 0, "", 0, yco-=6, menuwidth, 6, NULL, 0.0, 0.0, 0, 0, "");
787         
788         uiDefIconTextBut(block, BUTM, 1, ICON_BLANK1, "Play Animation|Alt A", 0, yco-=20, 
789                                          menuwidth, 19, NULL, 0.0, 0.0, 1, 6, "");
790         //uiDefIconTextBut(block, BUTM, 1, ICON_BLANK1, "Play Animation in 3D View|Alt Shift A", 0, yco-=20,
791         //                               menuwidth, 19, NULL, 0.0, 0.0, 1, 7, "");
792
793         uiDefBut(block, SEPR, 0, "",        0, yco-=6, menuwidth, 6, NULL, 0.0, 0.0, 0, 0, "");
794         
795         uiDefIconTextBut(block, BUTM, 1, ICON_BLANK1, "Set Preview Range|Ctrl P", 0, yco-=20, 
796                                          menuwidth, 19, NULL, 0.0, 0.0, 1, 13, "");
797         uiDefIconTextBut(block, BUTM, 1, ICON_BLANK1, "Clear Preview Range|Alt P", 0, yco-=20,
798                                          menuwidth, 19, NULL, 0.0, 0.0, 1, 14, "");
799         
800         uiDefBut(block, SEPR, 0, "",        0, yco-=6, menuwidth, 6, NULL, 0.0, 0.0, 0, 0, "");
801
802
803         uiDefIconTextBut(block, BUTM, 1, ICON_BLANK1, "Center on Current Frame|Shift C", 0, yco-=20, menuwidth, 19, NULL, 0.0, 0.0, 0, 10, "");
804         uiDefIconTextBut(block, BUTM, 1, (G.v2d->flag & V2D_VIEWLOCK)?ICON_CHECKBOX_HLT:ICON_CHECKBOX_DEHLT, 
805                                          "Lock Time to Other Windows|", 0, yco-=20, menuwidth, 19, NULL, 0.0, 0.0, 1, 9, "");
806         
807         if (G.sipo->flag & SIPO_LOCK_VIEW)
808                 uiDefIconTextBut(block, BUTM, 1, ICON_CHECKBOX_HLT, "Lock View Area", 0, yco-=20, menuwidth, 19, NULL, 0.0, 0.0, 0, 12, "");
809         else
810                 uiDefIconTextBut(block, BUTM, 1, ICON_CHECKBOX_DEHLT, "Lock View Area", 0, yco-=20, menuwidth, 19, NULL, 0.0, 0.0, 0, 12, "");
811
812         if (ei != NULL && (ei->flag & IPO_EDIT)) {
813                 uiDefIconTextBut(block, BUTM, 1, ICON_BLANK1, "Move Current Frame to Selected|C", 0, yco-=20, menuwidth, 19, NULL, 0.0, 0.0, 0, 3, "");
814         }
815
816         uiDefBut(block, SEPR, 0, "",        0, yco-=6, menuwidth, 6, NULL, 0.0, 0.0, 0, 0, "");
817
818         uiDefIconTextBut(block, BUTM, 1, ICON_BLANK1, "View Selected|NumPad .",                 0, yco-=20, menuwidth, 19, NULL, 0.0, 0.0, 0, 11, "");
819         uiDefIconTextBut(block, BUTM, 1, ICON_BLANK1, "View All|Home", 0, yco-=20, menuwidth, 19, NULL, 0.0, 0.0, 0, 1, "");
820         if(!curarea->full) uiDefIconTextBut(block, BUTM, B_FULL, ICON_BLANK1, "Maximize Window|Ctrl UpArrow", 0, yco-=20, menuwidth, 19, NULL, 0.0, 0.0, 0,20, "");
821         else uiDefIconTextBut(block, BUTM, B_FULL, ICON_BLANK1, "Tile Window|Ctrl DownArrow", 0, yco-=20, menuwidth, 19, NULL, 0.0, 0.0, 0, 20, "");
822
823         if(curarea->headertype==HEADERTOP) {
824                 uiBlockSetDirection(block, UI_DOWN);
825         }
826         else {
827                 uiBlockSetDirection(block, UI_TOP);
828                 uiBlockFlipOrder(block);
829         }
830
831         uiTextBoundsBlock(block, 50);
832
833         return block;
834 }
835
836 static void do_ipo_selectmenu(void *arg, int event)
837 {
838         switch(event)
839         {
840         case 0:
841                 borderselect_ipo();
842                 break;
843         case 1:
844                 swap_selectall_editipo();
845                 break;
846         case 2:
847                 borderselect_markers();
848                 allqueue(REDRAWMARKER, 0);
849                 break;
850         case 3:
851                 deselect_markers(1, 0);
852                 allqueue(REDRAWMARKER, 0);
853                 break;
854         }
855 }
856
857 static uiBlock *ipo_selectmenu(void *arg_unused)
858 {
859         uiBlock *block;
860         short yco= 0, menuwidth=120;
861
862         block= uiNewBlock(&curarea->uiblocks, "ipo_selectmenu", UI_EMBOSSP, UI_HELV, curarea->headwin);
863         uiBlockSetButmFunc(block, do_ipo_selectmenu, NULL);
864
865         uiDefIconTextBut(block, BUTM, 1, ICON_BLANK1, "Border Select|B", 0, yco-=20, menuwidth, 19, NULL, 0.0, 0.0, 0, 0, "");
866         uiDefIconTextBut(block, BUTM, 1, ICON_BLANK1, "Border Select Markers|Ctrl B", 0, yco-=20, menuwidth, 19, NULL, 0.0, 0.0, 0, 2, "");
867         
868         uiDefBut(block, SEPR, 0, "",        0, yco-=6, menuwidth, 6, NULL, 0.0, 0.0, 0, 0, "");
869         
870         uiDefIconTextBut(block, BUTM, 1, ICON_BLANK1, "Select/Deselect All|A", 0, yco-=20, menuwidth, 19, NULL, 0.0, 0.0, 0, 1, "");
871         uiDefIconTextBut(block, BUTM, 1, ICON_BLANK1, "Select/Deselect All Markers|Ctrl A", 0, yco-=20, menuwidth, 19, NULL, 0.0, 0.0, 0, 3, "");
872
873         if(curarea->headertype==HEADERTOP) {
874                 uiBlockSetDirection(block, UI_DOWN);
875         }
876         else {
877                 uiBlockSetDirection(block, UI_TOP);
878                 uiBlockFlipOrder(block);
879         }
880
881         uiTextBoundsBlock(block, 50);
882
883         return block;
884 }
885
886 static void do_ipo_markermenu(void *arg, int event)
887 {       
888         switch(event)
889         {
890                 case 1:
891                         add_marker(CFRA);
892                         break;
893                 case 2:
894                         duplicate_marker();
895                         break;
896                 case 3:
897                         remove_marker();
898                         break;
899                 case 4:
900                         rename_marker();
901                         break;
902                 case 5:
903                         transform_markers('g', 0);
904                         break;
905         }
906         
907         allqueue(REDRAWMARKER, 0);
908 }
909
910 static uiBlock *ipo_markermenu(void *arg_unused)
911 {
912         uiBlock *block;
913         short yco= 0, menuwidth=120;
914
915         block= uiNewBlock(&curarea->uiblocks, "ipo_markermenu", 
916                                           UI_EMBOSSP, UI_HELV, curarea->headwin);
917         uiBlockSetButmFunc(block, do_ipo_markermenu, NULL);
918
919         uiDefIconTextBut(block, BUTM, 1, ICON_BLANK1, "Add Marker|M", 0, yco-=20, 
920                                          menuwidth, 19, NULL, 0.0, 0.0, 1, 1, "");
921         uiDefIconTextBut(block, BUTM, 1, ICON_BLANK1, "Duplicate Marker|Ctrl Shift D", 0, yco-=20, 
922                                          menuwidth, 19, NULL, 0.0, 0.0, 1, 2, "");
923         uiDefIconTextBut(block, BUTM, 1, ICON_BLANK1, "Delete Marker|X", 0, yco-=20,
924                                          menuwidth, 19, NULL, 0.0, 0.0, 1, 3, "");
925                                          
926         uiDefBut(block, SEPR, 0, "",        0, yco-=6, menuwidth, 6, NULL, 0.0, 0.0, 0, 0, "");
927
928         uiDefIconTextBut(block, BUTM, 1, ICON_BLANK1, "(Re)Name Marker|Ctrl M", 0, yco-=20,
929                                          menuwidth, 19, NULL, 0.0, 0.0, 1, 4, "");
930         uiDefIconTextBut(block, BUTM, 1, ICON_BLANK1, "Grab/Move Marker|Ctrl G", 0, yco-=20,
931                                          menuwidth, 19, NULL, 0.0, 0.0, 1, 5, "");
932         
933         if(curarea->headertype==HEADERTOP) {
934                 uiBlockSetDirection(block, UI_DOWN);
935         }
936         else {
937                 uiBlockSetDirection(block, UI_TOP);
938                 uiBlockFlipOrder(block);
939         }
940
941         uiTextBoundsBlock(block, 50);
942
943         return block;
944 }
945
946 static char *ipo_modeselect_pup(void)
947 {
948         Object *ob= OBACT;
949         static char formatstring[] = "|%s %%x%d %%i%d";
950         static char string[1024];
951         char *str = string;
952         
953         str += sprintf(str, "Ipo type: %%t");
954
955         if(ob)
956                 str += sprintf(str,formatstring, "Object",ID_OB, ICON_OBJECT);
957
958         if(ob && give_current_material(ob, ob->actcol)) // check for material
959                 str += sprintf(str,formatstring, "Material",ID_MA, ICON_MATERIAL);
960
961         if(G.scene->world)
962                 str += sprintf(str,formatstring, "World",ID_WO, ICON_WORLD);
963
964         if(ob && ob->type==OB_CURVE)
965                 str += sprintf(str,formatstring, "Path",ID_CU, ICON_CURVE);
966
967         if(ob && ob->type==OB_CAMERA)
968                 str += sprintf(str,formatstring, "Camera",ID_CA, ICON_CAMERA);
969         
970         if(ob && ob->type==OB_LAMP)
971                 str += sprintf(str,formatstring, "Lamp",ID_LA, ICON_LAMP);
972
973         if(ob && give_current_texture(ob, ob->actcol))
974                 str += sprintf(str,formatstring, "Texture",ID_TE, ICON_TEXTURE);
975
976         if(ob){
977                 if ELEM4(ob->type, OB_MESH, OB_CURVE, OB_SURF, OB_LATTICE)
978                         str += sprintf(str,formatstring, "Shape",ID_KE, ICON_EDIT);
979                 if (ob->type==OB_ARMATURE)
980                         str += sprintf(str,formatstring, "Pose",ID_PO, ICON_POSE_HLT);
981 #ifdef __CON_IPO
982                 str += sprintf(str,formatstring, "Constraint",ID_CO, ICON_CONSTRAINT);
983 #endif
984                 if(ob->fluidsimFlag & OB_FLUIDSIM_ENABLE) {
985                         str += sprintf(str,formatstring,"Fluidsim",ID_FLUIDSIM, ICON_WORLD);
986                 }
987
988                 if(ob->particlesystem.first) {
989                         str += sprintf(str,formatstring,"Particles",ID_PA, ICON_PARTICLES);
990                 }
991         }
992
993         str += sprintf(str,formatstring, "Sequence",ID_SEQ, ICON_SEQUENCE);
994
995         return (string);
996 }
997
998 void do_ipo_buttons(short event)
999 {
1000         EditIpo *ei;
1001         View2D *v2d;
1002         rcti rect;
1003         Object *ob= OBACT;
1004         float xmin, ymin, dx, dy;
1005         int a, val, first;
1006         short mval[2];
1007
1008         if(curarea->win==0) return;
1009
1010         switch(event) {
1011         case B_IPOVIEWCENTER:
1012         case B_IPOHOME:
1013
1014                 /* boundbox */
1015
1016                 v2d= &(G.sipo->v2d);
1017                 first= 1;
1018
1019                 ei= G.sipo->editipo;
1020                 if(ei==0) return;
1021                 
1022                 /* map ipo-points for drawing if scaled ipo */
1023                 if (OBACT && OBACT->action && G.sipo->pin==0 && G.sipo->actname) {
1024                         actstrip_map_ipo_keys(OBACT, G.sipo->ipo, 0, 0);
1025                 }
1026                 
1027                 for(a=0; a<G.sipo->totipo; a++, ei++) {
1028                         if ISPOIN(ei, flag & IPO_VISIBLE, icu) {
1029                         
1030                                 boundbox_ipocurve(ei->icu, (event==B_IPOVIEWCENTER));
1031                                 
1032                                 if(first) {
1033                                         v2d->tot= ei->icu->totrct;
1034                                         first= 0;
1035                                 }
1036                                 else BLI_union_rctf(&(v2d->tot), &(ei->icu->totrct));
1037                         }
1038                 }
1039                 
1040                 /* undo mapping of ipo-points for drawing if scaled ipo */
1041                 if (OBACT && OBACT->action && G.sipo->pin==0 && G.sipo->actname) {
1042                         actstrip_map_ipo_keys(OBACT, G.sipo->ipo, 1, 0);
1043                 }
1044
1045                 /* speciale home */
1046                 if(G.qual & LR_SHIFTKEY) {
1047                         v2d->tot.xmin= SFRA;
1048                         v2d->tot.xmax= EFRA;
1049                 }
1050
1051                 /* zoom out a bit */
1052                 dx= 0.10*(v2d->tot.xmax-v2d->tot.xmin);
1053                 dy= 0.10*(v2d->tot.ymax-v2d->tot.ymin);
1054                 
1055                 if(dx<v2d->min[0]) dx= v2d->min[0];
1056                 if(dy<v2d->min[1]) dy= v2d->min[1];
1057                 
1058                 v2d->cur.xmin= v2d->tot.xmin- dx;
1059                 v2d->cur.xmax= v2d->tot.xmax+ dx;
1060                 v2d->cur.ymin= v2d->tot.ymin- dy;
1061                 v2d->cur.ymax= v2d->tot.ymax+ dy;
1062
1063                 test_view2d(G.v2d, curarea->winx, curarea->winy);
1064                 view2d_do_locks(curarea, V2D_LOCK_COPY);
1065                 if(G.sipo->ipo) G.sipo->ipo->cur = G.v2d->cur;
1066                 
1067                 scrarea_queue_winredraw(curarea);
1068                 break;
1069         case B_IPOBORDER:
1070                 val= get_border(&rect, 3);
1071                 if(val) {
1072                         mval[0]= rect.xmin;
1073                         mval[1]= rect.ymin;
1074                         areamouseco_to_ipoco(G.v2d, mval, &xmin, &ymin);
1075                         mval[0]= rect.xmax;
1076                         mval[1]= rect.ymax;
1077                         areamouseco_to_ipoco(G.v2d, mval, &(G.v2d->cur.xmax), &(G.v2d->cur.ymax));
1078                         G.v2d->cur.xmin= xmin;
1079                         G.v2d->cur.ymin= ymin;
1080                         
1081                         test_view2d(G.v2d, curarea->winx, curarea->winy);
1082                         view2d_do_locks(curarea, V2D_LOCK_COPY);
1083                         scrarea_queue_winredraw(curarea);
1084                 }
1085                 break;
1086
1087         case B_IPOPIN:
1088                 allqueue (REDRAWIPO, 0);
1089                 break;
1090
1091         case B_IPOCOPY:
1092                 copy_editipo();
1093                 break;
1094         case B_IPOPASTE:
1095                 paste_editipo();
1096                 break;
1097         case B_IPOCONT:
1098                 set_exprap_ipo(IPO_HORIZ);
1099                 break;
1100         case B_IPOEXTRAP:
1101                 set_exprap_ipo(IPO_DIR);
1102                 break;
1103         case B_IPOCYCLIC:
1104                 set_exprap_ipo(IPO_CYCL);
1105                 break;
1106         case B_IPOCYCLICX:
1107                 set_exprap_ipo(IPO_CYCLX);
1108                 break;
1109         case B_IPOMAIN:
1110                 /* pass 1 to enforce a refresh when there's no Ipo */
1111                 test_editipo(1);
1112                 scrarea_queue_winredraw(curarea);
1113                 scrarea_queue_headredraw(curarea);
1114                 if(ob) ob->ipowin= G.sipo->blocktype;
1115                 break;
1116         case B_IPOSHOWKEY:
1117                 /* reverse value because of winqread */
1118                 G.sipo->showkey= 1-G.sipo->showkey;
1119                 ipo_toggle_showkey();
1120                 scrarea_queue_headredraw(curarea);
1121                 scrarea_queue_winredraw(curarea);
1122                 allqueue(REDRAWVIEW3D, 0);
1123                 break;
1124         case B_VIEW2DZOOM:
1125                 view2dzoom(event);
1126                 scrarea_queue_headredraw(curarea);
1127                 break;
1128         case B_IPO_ACTION_OB:
1129                 if(ob && G.sipo->from && G.sipo->pin==0) {
1130                         if(ob->ipoflag & OB_ACTION_OB) {        /* check if channel exists, and flip ipo link */
1131                                 bActionChannel *achan;
1132                                 
1133                                 if(has_ipo_code(ob->ipo, OB_LAY))
1134                                         notice("Note: Layer Ipo doesn't work in Actions");
1135                                 
1136                                 if(ob->action==NULL) 
1137                                         ob->action= add_empty_action("ObAction");
1138                                 achan= verify_action_channel(ob->action, "Object");
1139                                 if(achan->ipo==NULL && ob->ipo) {
1140                                         achan->ipo= ob->ipo;
1141                                         ob->ipo= NULL;
1142                                 }
1143                                 
1144                                 /* object constraints */
1145                                 if(ob->constraintChannels.first) {
1146                                         free_constraint_channels(&achan->constraintChannels);
1147                                         achan->constraintChannels= ob->constraintChannels;
1148                                         ob->constraintChannels.first= ob->constraintChannels.last= NULL;
1149                                 }
1150                         }
1151                         else if(ob->action) {
1152                                 bActionChannel *achan= get_action_channel(ob->action, "Object");
1153                                 if(achan) {
1154                                         
1155                                         if(achan->ipo && ob->ipo==NULL) {
1156                                                 ob->ipo= achan->ipo;
1157                                                 achan->ipo= NULL;
1158                                         }
1159                                         
1160                                         /* object constraints */
1161                                         if(achan->constraintChannels.first) {
1162                                                 free_constraint_channels(&ob->constraintChannels);
1163                                                 ob->constraintChannels= achan->constraintChannels;
1164                                                 achan->constraintChannels.first= achan->constraintChannels.last= NULL;
1165                                         }
1166                                 }
1167                         }
1168                         allqueue(REDRAWVIEW3D, 0);
1169                         allqueue(REDRAWIPO, 0);
1170                         allqueue(REDRAWACTION, 0);
1171                         allqueue(REDRAWOOPS, 0);
1172                         allqueue(REDRAWNLA, 0);
1173                 }
1174                 break;
1175                 
1176         case B_IPO_ACTION_KEY:
1177                 if(ob && G.sipo->from && G.sipo->pin==0) {
1178                         Key *key= ob_get_key(ob);
1179                         if(key) {
1180                                 if(ob->ipoflag & OB_ACTION_KEY) {       /* check if channel exists, and flip ipo link */
1181                                         bActionChannel *achan;
1182                                         
1183                                         if(ob->action==NULL) 
1184                                                 ob->action= add_empty_action("ShapeAction");
1185                                         achan= verify_action_channel(ob->action, "Shape");
1186                                         if(achan->ipo==NULL && key->ipo) {
1187                                                 achan->ipo= key->ipo;
1188                                                 key->ipo= NULL;
1189                                         }
1190                                 }
1191                                 else if(ob->action) {
1192                                         bActionChannel *achan= get_action_channel(ob->action, "Shape");
1193                                         if(achan) {
1194                                                 if(achan->ipo && key->ipo==NULL) {
1195                                                         key->ipo= achan->ipo;
1196                                                         achan->ipo= NULL;
1197                                                 }
1198                                         }
1199                                 }
1200                                 allqueue(REDRAWVIEW3D, 0);
1201                                 allqueue(REDRAWIPO, 0);
1202                                 allqueue(REDRAWACTION, 0);
1203                                 allqueue(REDRAWOOPS, 0);
1204                                 allqueue(REDRAWNLA, 0);
1205                         }
1206                 }
1207                 break;
1208         case B_IPOVIEWALL:
1209                 /* set visible active */
1210                 for(a=0, ei=G.sipo->editipo; a<G.sipo->totipo; a++, ei++) {
1211                         if (ei->icu)    ei->flag |= IPO_VISIBLE;
1212                         else                    ei->flag &= ~IPO_VISIBLE;
1213                 }
1214                 break;
1215         case B_IPOREDRAW:
1216                 DAG_object_flush_update(G.scene, ob, OB_RECALC);
1217                 allqueue(REDRAWVIEW3D, 0);
1218                 allqueue(REDRAWIPO, 0);
1219                 break;
1220         }
1221 }
1222
1223 void ipo_buttons(void)
1224 {
1225         Object *ob;
1226         EditIpo *ei;
1227         uiBlock *block;
1228         short xco,xmax;
1229         char naam[20];
1230         int icon=0, allow_pin= B_IPOPIN;
1231
1232         sprintf(naam, "header %d", curarea->headwin);
1233         block= uiNewBlock(&curarea->uiblocks, naam, UI_EMBOSS, UI_HELV, curarea->headwin);
1234
1235         if(area_is_active_area(curarea)) uiBlockSetCol(block, TH_HEADER);
1236         else uiBlockSetCol(block, TH_HEADERDESEL);
1237
1238         curarea->butspacetype= SPACE_IPO;
1239
1240         xco = 8;
1241         uiDefIconTextButC(block, ICONTEXTROW,B_NEWSPACE, ICON_VIEW3D, windowtype_pup(), xco,0,XIC+10,YIC, &(curarea->butspacetype), 1.0, SPACEICONMAX, 0, 0, "Displays Current Window Type. Click for menu of available types.");
1242         xco+= XIC+14;
1243         
1244         test_editipo(0);        /* test if current editipo is OK, make_editipo sets v2d->cur */
1245
1246         uiBlockSetEmboss(block, UI_EMBOSSN);
1247         if(curarea->flag & HEADER_NO_PULLDOWN) {
1248                 uiDefIconButBitS(block, TOG, HEADER_NO_PULLDOWN, B_FLIPINFOMENU, ICON_DISCLOSURE_TRI_RIGHT,
1249                                 xco,2,XIC,YIC-2,
1250                                 &(curarea->flag), 0, 0, 0, 0, "Enables display of pulldown menus");
1251         } else {
1252                 uiDefIconButBitS(block, TOG, HEADER_NO_PULLDOWN, B_FLIPINFOMENU, ICON_DISCLOSURE_TRI_DOWN,
1253                                 xco,2,XIC,YIC-2,
1254                                 &(curarea->flag), 0, 0, 0, 0, "Hides pulldown menus");
1255         }
1256         uiBlockSetEmboss(block, UI_EMBOSS);
1257         xco+=XIC;
1258
1259         /* pull down menus */
1260         if((curarea->flag & HEADER_NO_PULLDOWN)==0) {
1261                 uiBlockSetEmboss(block, UI_EMBOSSP);
1262         
1263                 ei = get_active_editipo();
1264         
1265                 xmax= GetButStringLength("View");
1266                 uiDefPulldownBut(block,ipo_viewmenu, NULL, "View", xco, -2, xmax-3, 24, "");
1267                 xco+=xmax;
1268         
1269                 xmax= GetButStringLength("Select");
1270                 uiDefPulldownBut(block,ipo_selectmenu, NULL, "Select", xco, -2, xmax-3, 24, "");
1271                 xco+=xmax;
1272                 
1273                 xmax= GetButStringLength("Marker");
1274                 uiDefPulldownBut(block,ipo_markermenu, NULL, "Marker", xco, -2, xmax-3, 24, "");
1275                 xco+=xmax;
1276                 
1277                 if (G.sipo->showkey) {
1278                         xmax= GetButStringLength("Key");
1279                         uiDefPulldownBut(block,ipo_editmenu, NULL, "Key", xco, -2, xmax-3, 24, "");
1280                 }
1281                 else if(ei != NULL && (ei->flag & IPO_EDIT)) {
1282                         xmax= GetButStringLength("Point");
1283                         uiDefPulldownBut(block,ipo_editmenu, NULL, "Point", xco, -2, xmax-3, 24, "");
1284                 }
1285                 else {
1286                         xmax= GetButStringLength("Curve");
1287                         uiDefPulldownBut(block,ipo_editmenu, NULL, "Curve", xco, -2, xmax-3, 24, "");
1288                 }
1289                 xco+=xmax;
1290         }
1291
1292         /* end of pull down menus */
1293         uiBlockSetEmboss(block, UI_EMBOSS);
1294
1295         ob= OBACT;
1296         
1297         /* action switch option, only when active object is there and no pin */
1298         uiSetButLock(G.sipo->pin, "Can't change because of pinned data");
1299         
1300         /* define whether ipos are on Object or on action */
1301         if(ob) {
1302                 static short fake1= 1;
1303                 
1304                 uiBlockBeginAlign(block);
1305                 
1306                 if(G.sipo->blocktype==ID_OB) {
1307                         uiDefIconButBitS(block, TOG, OB_ACTION_OB, B_IPO_ACTION_OB, ICON_ACTION,        xco,0,XIC,YIC, &(ob->ipoflag), 0, 0, 0, 0, "Sets Ipo to be included in an Action or not");
1308                         xco+= XIC;
1309                 }
1310                 else if(G.sipo->blocktype==ID_KE) {
1311                         uiDefIconButBitS(block, TOG, OB_ACTION_KEY, B_IPO_ACTION_KEY, ICON_ACTION,      xco,0,XIC,YIC, &(ob->ipoflag), 0, 0, 0, 0, "Sets Ipo to be included in an Action or not");
1312                         xco+= XIC;
1313                 }
1314                 else if(G.sipo->blocktype==ID_CO) {
1315                         
1316                         if(ob->pose==NULL)
1317                                 uiDefIconButBitS(block, TOG, OB_ACTION_OB, B_IPO_ACTION_OB, ICON_ACTION,        xco,0,XIC,YIC, &(ob->ipoflag), 0, 0, 0, 0, "Sets Ipo to be included in an Action or not");
1318                         else {
1319                                 bConstraint *con= get_active_constraint(ob);
1320                                 if(con)
1321                                         uiDefIconButBitS(block, TOGN, CONSTRAINT_OWN_IPO, B_IPOREDRAW, ICON_ACTION,     xco,0,XIC,YIC, &con->flag, 0, 0, 0, 0, 
1322                                                                          (con->flag & CONSTRAINT_OWN_IPO)?"Ipo is connected to Constraint itself":"Ipo is connected to Pose Action"
1323                                                                          );
1324                         }
1325                         xco+= XIC;
1326                 }
1327                 else if(G.sipo->blocktype==ID_PO) {     /* only to indicate we have action ipos */
1328                         uiSetButLock(1, "Pose Action Ipo cannot be switched");
1329                         uiDefIconButS(block, TOG, 1, ICON_ACTION,       xco,0,XIC,YIC, &fake1, 0, 0, 0, 0, "Ipo is connected to Pose Action");
1330                         xco+= XIC;
1331                 }
1332                 uiClearButLock();
1333         }
1334         
1335         /* ipo muting */
1336         if (G.sipo->ipo) {
1337                 uiDefIconButS(block, ICONTOG, 1, ICON_MUTE_IPO_OFF, xco,0,XIC,YIC, &(G.sipo->ipo->muteipo), 0, 0, 0, 0, "Mute IPO-block");
1338                 xco += XIC;
1339         }
1340         
1341         /* mainmenu, only when data is there and no pin */
1342         uiSetButLock(G.sipo->pin, "Can't change because of pinned data");
1343
1344         if (G.sipo->blocktype == ID_OB)
1345                 icon = ICON_OBJECT;
1346         else if (G.sipo->blocktype == ID_MA)
1347                 icon = ICON_MATERIAL;
1348         else if (G.sipo->blocktype == ID_WO)
1349                 icon = ICON_WORLD;
1350         else if (G.sipo->blocktype == ID_CU)
1351                 icon = ICON_ANIM;
1352         else if (G.sipo->blocktype == ID_CA)
1353                 icon = ICON_CAMERA;
1354         else if (G.sipo->blocktype == ID_LA)
1355                 icon = ICON_LAMP;
1356         else if (G.sipo->blocktype == ID_KE)
1357                 icon = ICON_EDIT;
1358         else if (G.sipo->blocktype == ID_PO)
1359                 icon = ICON_POSE_HLT;
1360         else if (G.sipo->blocktype == ID_CO)
1361                 icon = ICON_CONSTRAINT;
1362         else if (G.sipo->blocktype == ID_SEQ)
1363                 icon = ICON_SEQUENCE;
1364         else if(G.sipo->blocktype == ID_TE)
1365                 icon = ICON_TEXTURE;
1366         else if(G.sipo->blocktype == ID_FLUIDSIM)
1367                 icon = ICON_WORLD;
1368         else if(G.sipo->blocktype == ID_PA)
1369                 icon = ICON_PARTICLES;
1370
1371         uiDefIconTextButS(block, MENU, B_IPOMAIN, icon, ipo_modeselect_pup(), xco,0,100,20, &(G.sipo->blocktype), 0, 0, 0, 0, "Show IPO type");
1372
1373         xco += 85;
1374
1375         if(G.sipo->blocktype==ID_MA) {
1376                 uiDefButS(block, NUM, B_IPOMAIN, "",    xco+=XIC,0,XIC-4,YIC, &G.sipo->channel, 0.0, MAX_MTEX-1.0, 0, 0, "Channel Number of the active Material texture.");
1377                 xco-= 4;
1378         }
1379         if(G.sipo->blocktype==ID_WO) {
1380                 uiDefButS(block, NUM, B_IPOMAIN, "",    xco+=XIC,0,XIC-4,YIC, &G.sipo->channel, 0.0, MAX_MTEX-1.0, 0, 0, "Channel Number of the active World texture.");
1381                 xco-= 4;
1382         }
1383         
1384         if(G.sipo->blocktype==ID_LA) {
1385                 uiDefButS(block, NUM, B_IPOMAIN, "",    xco+=XIC,0,XIC-4,YIC, &G.sipo->channel, 0.0, MAX_MTEX-1.0, 0, 0, "Channel Number of the active Lamp texture. ");
1386                 xco-= 4;
1387         }
1388         
1389         uiBlockEndAlign(block);
1390         
1391         uiClearButLock();
1392
1393         /* if(G.sipo->blocktype==ID_SEQ)
1394            allow_pin= 0; */
1395         xco= std_libbuttons(block, (short)(xco+1.5*XIC), 0, allow_pin, &G.sipo->pin, B_IPOBROWSE, ID_IP, 
1396                                                 G.sipo->blocktype, (ID*)G.sipo->ipo, G.sipo->from, &(G.sipo->menunr), B_IPOALONE, B_IPOLOCAL, B_IPODELETE, 0, B_KEEPDATA);
1397
1398         /* COPY PASTE */
1399         xco-= XIC/2;
1400         uiBlockBeginAlign(block);
1401         if(curarea->headertype==HEADERTOP) {
1402                 uiDefIconBut(block, BUT, B_IPOCOPY, ICON_COPYUP,        xco+=XIC,0,XIC,YIC, 0, 0, 0, 0, 0, "Copies the selected curves to the buffer");
1403                 uiSetButLock(G.sipo->ipo && G.sipo->ipo->id.lib, ERROR_LIBDATA_MESSAGE);
1404                 uiDefIconBut(block, BUT, B_IPOPASTE, ICON_PASTEUP,      xco+=XIC,0,XIC,YIC, 0, 0, 0, 0, 0, "Pastes the curves from the buffer");
1405         }
1406         else {
1407                 uiDefIconBut(block, BUT, B_IPOCOPY, ICON_COPYDOWN,      xco+=XIC,0,XIC,YIC, 0, 0, 0, 0, 0, "Copies the selected curves to the buffer");
1408                 uiSetButLock(G.sipo->ipo && G.sipo->ipo->id.lib, ERROR_LIBDATA_MESSAGE);
1409                 uiDefIconBut(block, BUT, B_IPOPASTE, ICON_PASTEDOWN,    xco+=XIC,0,XIC,YIC, 0, 0, 0, 0, 0, "Pastes the curves from the buffer");
1410         }
1411         uiBlockEndAlign(block);
1412         xco+=XIC/2;
1413         
1414         uiClearButLock();
1415
1416         /* ZOOMBORDER */
1417         uiDefIconBut(block, BUT, B_IPOBORDER, ICON_BORDERMOVE,  xco+=XIC,0,XIC,YIC, 0, 0, 0, 0, 0, "Zooms view to area");
1418         
1419         xco+=XIC/2;
1420         
1421         /* draw LOCK */
1422         uiDefIconButS(block, ICONTOG, 1, ICON_UNLOCKED, xco+=XIC,0,XIC,YIC, &(G.sipo->lock), 0, 0, 0, 0, "Toggles forced redraw of other windows to reflect changes in real time");
1423         
1424         /* always do as last */
1425         curarea->headbutlen= xco+2*XIC;
1426
1427         uiDrawBlock(block);
1428 }