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