61854556ae83f454a5d5432686b46c2b910d3ca6
[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/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
83 #include "BIF_editaction.h"
84 #include "BIF_interface.h"
85 #include "BIF_mainqueue.h"
86 #include "BIF_resources.h"
87 #include "BIF_screen.h"
88 #include "BIF_space.h"
89 #include "BIF_toolbox.h"
90
91 #include "nla.h"
92
93 #include "blendef.h"
94 #include "mydevice.h"
95
96 static int viewmovetemp = 0;
97 extern int totipo_edit, totipo_sel;
98
99 /* headerbutton call, assuming full context is set */
100 /* it aligns with editipo.c, verify_ipo */
101 void spaceipo_assign_ipo(SpaceIpo *si, Ipo *ipo)
102 {
103         if(si->from==NULL || si->from->lib) return;
104         
105         if(ipo) ipo->id.us++;
106
107         /* first check action ipos */
108         if(si->actname && si->actname[0]) {
109                 Object *ob= (Object *)si->from;
110                 bActionChannel *achan;
111                 
112                 if(ob->action) {
113                         achan= get_action_channel(ob->action, si->actname);
114                 
115                         if(achan) {
116                                 /* constraint exception */
117                                 if(si->blocktype==ID_CO) {
118                                         bConstraintChannel *conchan= get_constraint_channel(&achan->constraintChannels, si->constname);
119                                         if(conchan) {
120                                                 if(conchan->ipo)
121                                                         conchan->ipo->id.us--;
122                                                 conchan->ipo= ipo;
123                                         }
124                                 }
125                                 else {
126                                         if(achan->ipo)
127                                                 achan->ipo->id.us--;
128                                         achan->ipo= ipo;
129                                 }
130                         }
131                 }
132         }
133         else {
134                 switch(GS(si->from->name)) {
135                         case ID_OB:
136                         {
137                                 Object *ob= (Object *)si->from;
138                                 /* constraint exception */
139                                 if(si->blocktype==ID_CO) {
140                                         bConstraintChannel *conchan= get_constraint_channel(&ob->constraintChannels, si->constname);
141                                         if(conchan) {
142                                                 if(conchan->ipo)
143                                                         conchan->ipo->id.us--;
144                                                 conchan->ipo= ipo;
145                                         }
146                                 }
147                                 else if(si->blocktype==ID_FLUIDSIM) { // NT
148                                         if( (ob->fluidsimSettings) && 
149                                             (ob->fluidsimSettings->ipo) ) {
150                                                 // decrement users counter
151                                                 ob->fluidsimSettings->ipo->id.us--; 
152                                         }
153                                         ob->fluidsimSettings->ipo = ipo;
154                                 } 
155                                 else if(si->blocktype==ID_OB) {
156                                         if(ob->ipo)
157                                                 ob->ipo->id.us--;
158                                         ob->ipo= ipo;
159                                 }
160                         }
161                                 break;
162                         case ID_MA:
163                         {
164                                 Material *ma= (Material *)si->from;
165                                 
166                                 if(ma->ipo)
167                                         ma->ipo->id.us--;
168                                 ma->ipo= ipo;
169                         }
170                                 break;
171                         case ID_TE:
172                         {
173                                 Tex *tex= (Tex *)si->from;
174                                 
175                                 if(tex->ipo)
176                                         tex->ipo->id.us--;
177                                 tex->ipo= ipo;
178                         }
179                                 break;
180                         case ID_SEQ:
181                         {
182                                 Sequence *seq= (Sequence *)si->from;    /* note, sequence is mimicing Id */
183                                 
184                                 if((seq->type & SEQ_EFFECT)
185                                    || (seq->type == SEQ_RAM_SOUND)
186                                    || (seq->type == SEQ_HD_SOUND)) {
187                                         if(seq->ipo)
188                                                 seq->ipo->id.us--;
189                                         seq->ipo= ipo;
190                                 }
191                         }
192                                 break;
193                         case ID_CU:
194                         {
195                                 Curve *cu= (Curve *)si->from;
196                                 
197                                 if(cu->ipo)
198                                         cu->ipo->id.us--;
199                                 cu->ipo= ipo;
200                         }
201                                 break;
202                         case ID_KE:
203                         {
204                                 Key *key= (Key *)si->from;
205                                 
206                                 if(key->ipo)
207                                         key->ipo->id.us--;
208                                 key->ipo= ipo;
209                         }
210                                 break;
211                         case ID_WO:
212                         {
213                                 World *wo= (World *)si->from;
214                                 
215                                 if(wo->ipo)
216                                         wo->ipo->id.us--;
217                                 wo->ipo= ipo;
218                         }
219                                 break;
220                         case ID_LA:
221                         {
222                                 Lamp *la= (Lamp *)si->from;
223                                 
224                                 if(la->ipo)
225                                         la->ipo->id.us--;
226                                 la->ipo= ipo;
227                         }
228                                 break;
229                         case ID_CA:
230                         {
231                                 Camera *ca= (Camera *)si->from;
232                                 
233                                 if(ca->ipo)
234                                         ca->ipo->id.us--;
235                                 ca->ipo= ipo;
236                         }
237                                 break;
238                         case ID_SO:
239                         {
240                                 bSound *snd= (bSound *)si->from;
241                                 
242                                 if(snd->ipo)
243                                         snd->ipo->id.us--;
244                                 snd->ipo= ipo;
245                         }
246                 }
247         }
248         
249         allqueue(REDRAWVIEW3D, 0);
250         allqueue(REDRAWIPO, 0);
251         allqueue(REDRAWACTION, 0);
252         allqueue(REDRAWNLA, 0);
253         allqueue(REDRAWBUTSALL, 0);
254         
255 }
256
257
258 static void do_ipo_editmenu_transformmenu(void *arg, int event)
259 {
260         switch(event)
261         {
262         case 0: /* grab/move */
263                 transform_ipo('g');
264                 break;
265         case 1: /* scale */
266                 transform_ipo('s');
267                 break;
268         }
269 }
270
271 static uiBlock *ipo_editmenu_transformmenu(void *arg_unused)
272 {
273         uiBlock *block;
274         short yco= 0, menuwidth=120;
275
276         block= uiNewBlock(&curarea->uiblocks, "ipo_editmenu_transformmenu", UI_EMBOSSP, UI_HELV, G.curscreen->mainwin);
277         uiBlockSetButmFunc(block, do_ipo_editmenu_transformmenu, NULL);
278
279         uiDefIconTextBut(block, BUTM, 1, ICON_BLANK1, "Grab/Move|G", 0, yco-=20, menuwidth, 19, NULL, 0.0, 0.0, 0, 0, "");
280         uiDefIconTextBut(block, BUTM, 1, ICON_BLANK1, "Scale|S", 0, yco-=20, menuwidth, 19, NULL, 0.0, 0.0, 0, 1, "");
281
282         uiBlockSetDirection(block, UI_RIGHT);
283         uiTextBoundsBlock(block, 60);
284
285         return block;
286 }
287
288 static void do_ipo_editmenu_snapmenu(void *arg, int event)
289 {
290         switch(event) {
291         case 1: /* Horizontal */
292         case 2: /* To Next */
293         case 3: /* To Frame */
294         case 4: /* To Current Frame */
295                 ipo_snap(event);
296             break;
297         }
298         allqueue(REDRAWVIEW3D, 0);
299 }
300
301 static uiBlock *ipo_editmenu_snapmenu(void *arg_unused)
302 {
303         uiBlock *block;
304         short yco = 20, menuwidth = 120;
305
306         block= uiNewBlock(&curarea->uiblocks, "ipo_editmenu_snapmenu", UI_EMBOSSP, UI_HELV, G.curscreen->mainwin);
307         uiBlockSetButmFunc(block, do_ipo_editmenu_snapmenu, NULL);
308         
309         uiDefIconTextBut(block, BUTM, 1, ICON_BLANK1, "Horizontal|Shift S, 1",                  0, yco-=20, menuwidth, 19, NULL, 0.0, 0.0, 1, 1, "");
310         uiDefIconTextBut(block, BUTM, 1, ICON_BLANK1, "To Next|Shift S, 2",                     0, yco-=20, menuwidth, 19, NULL, 0.0, 0.0, 1, 2, "");
311         uiDefIconTextBut(block, BUTM, 1, ICON_BLANK1, "To Frame|Shift S, 3",                    0, yco-=20, menuwidth, 19, NULL, 0.0, 0.0, 1, 3, "");
312         uiDefIconTextBut(block, BUTM, 1, ICON_BLANK1, "To Current Frame|Shift S, 4",                    0, yco-=20, menuwidth, 19, NULL, 0.0, 0.0, 1, 4, "");   
313         
314         uiBlockSetDirection(block, UI_RIGHT);
315         uiTextBoundsBlock(block, 60);
316         return block;
317 }
318
319 static void do_ipo_editmenu_joinmenu(void *arg, int event)
320 {
321         switch(event) {
322         case 1: /* All Selected */
323         case 2: /* Selected Doubles */
324                 join_ipo(event);
325             break;
326         }
327         allqueue(REDRAWVIEW3D, 0);
328 }
329
330 static uiBlock *ipo_editmenu_joinmenu(void *arg_unused)
331 {
332         uiBlock *block;
333         short yco = 20, menuwidth = 120;
334
335         block= uiNewBlock(&curarea->uiblocks, "ipo_editmenu_joinmenu", UI_EMBOSSP, UI_HELV, G.curscreen->mainwin);
336         uiBlockSetButmFunc(block, do_ipo_editmenu_joinmenu, NULL);
337         
338         uiDefIconTextBut(block, BUTM, 1, ICON_BLANK1, "All Selected|Ctrl J, 1",                 0, yco-=20, menuwidth, 19, NULL, 0.0, 0.0, 1, 1, "");
339         uiDefIconTextBut(block, BUTM, 1, ICON_BLANK1, "Selected Doubles|Ctrl J, 2",                     0, yco-=20, menuwidth, 19, NULL, 0.0, 0.0, 1, 2, "");
340
341         uiBlockSetDirection(block, UI_RIGHT);
342         uiTextBoundsBlock(block, 60);
343         return block;
344 }
345
346 static void do_ipo_editmenu_keymenu(void *arg, int event)
347 {
348         Key *key;
349         KeyBlock *kb;
350         Object *ob= OBACT;
351
352         if(G.sipo->blocktype==ID_KE && totipo_edit==0 && totipo_sel==0) {
353                 key= ob_get_key((Object *)G.sipo->from);
354                 if(key==NULL) return;
355
356                 kb= BLI_findlink(&key->block, ob->shapenr-1);
357                 kb->type= 0;
358                 switch(event){
359                         case 0:
360                                 kb->type= KEY_LINEAR;
361                                 break;
362                         case 1:
363                                 kb->type= KEY_CARDINAL;
364                                 break;
365                         case 2:
366                                 kb->type= KEY_BSPLINE;
367                                 break;
368                 }
369         }
370 }
371
372 static uiBlock *ipo_editmenu_keymenu(void *arg_unused)
373 {
374         uiBlock *block;
375         short yco= 0, menuwidth=120;
376
377         block= uiNewBlock(&curarea->uiblocks, "ipo_editmenu_keymenu", UI_EMBOSSP, UI_HELV, G.curscreen->mainwin);
378         uiBlockSetButmFunc(block, do_ipo_editmenu_keymenu, NULL);
379
380         uiDefIconTextBut(block, BUTM, 1, ICON_BLANK1, "Linear|T, 1", 0, yco-=20, menuwidth, 19, NULL, 0.0, 0.0, 0, 0, "");
381         uiDefIconTextBut(block, BUTM, 1, ICON_BLANK1, "Cardinal|T, 2", 0, yco-=20, menuwidth, 19, NULL, 0.0, 0.0, 0, 1, "");
382         uiDefIconTextBut(block, BUTM, 1, ICON_BLANK1, "BSpline|T, 3", 0, yco-=20, menuwidth, 19, NULL, 0.0, 0.0, 0, 2, "");
383
384         uiBlockSetDirection(block, UI_RIGHT);
385         uiTextBoundsBlock(block, 60);
386
387         return block;
388
389 }
390
391 static void do_ipo_editmenu_handlemenu(void *arg, int event)
392 {
393         switch(event){
394         case 0:
395                 sethandles_ipo(HD_AUTO);
396                 break;
397         case 1:
398         case 2:
399                 sethandles_ipo(HD_ALIGN);
400                 break;
401         case 3:
402                 sethandles_ipo(HD_VECT);
403                 break;
404         case 4:
405                 sethandles_ipo(HD_AUTO_ANIM);
406                 break;
407         }
408 }
409
410 static uiBlock *ipo_editmenu_handlemenu(void *arg_unused)
411 {
412         uiBlock *block;
413         short yco= 0, menuwidth=120;
414
415         block= uiNewBlock(&curarea->uiblocks, "ipo_editmenu_handlemenu", UI_EMBOSSP, UI_HELV, G.curscreen->mainwin);
416         uiBlockSetButmFunc(block, do_ipo_editmenu_handlemenu, NULL);
417
418         uiDefIconTextBut(block, BUTM, 1, ICON_BLANK1, "Auto|Shift H", 0, yco-=20, menuwidth, 19, NULL, 0.0, 0.0, 0, 0, "");
419         uiDefIconTextBut(block, BUTM, 1, ICON_BLANK1, "Auto Clamped|Alt H", 0, yco-=20, menuwidth, 19, NULL, 0.0, 0.0, 0, 4, "");
420         uiDefIconTextBut(block, BUTM, 1, ICON_BLANK1, "Aligned|H", 0, yco-=20, menuwidth, 19, NULL, 0.0, 0.0, 0, 1, "");
421         uiDefIconTextBut(block, BUTM, 1, ICON_BLANK1, "Free|H", 0, yco-=20, menuwidth, 19, NULL, 0.0, 0.0, 0, 2, "");
422         uiDefIconTextBut(block, BUTM, 1, ICON_BLANK1, "Vector|V", 0, yco-=20, menuwidth, 19, NULL, 0.0, 0.0, 0, 3, "");
423
424         uiBlockSetDirection(block, UI_RIGHT);
425         uiTextBoundsBlock(block, 60);
426
427         return block;
428 }
429
430 static void do_ipo_editmenu_intpolmenu(void *arg, int event)
431 {
432         EditIpo *ei;
433         int a;
434
435         get_status_editipo();
436
437         ei = G.sipo->editipo;
438
439         switch(event)
440         {
441         case 0:
442                 for(a=0; a<G.sipo->totipo; a++, ei++) {
443                         if ISPOIN3(ei, flag & IPO_VISIBLE, flag & IPO_SELECT, icu) {
444                                 ei->icu->ipo= IPO_CONST;
445                         }
446                 }
447                 break;
448         case 1:
449                 for(a=0; a<G.sipo->totipo; a++, ei++) {
450                         if ISPOIN3(ei, flag & IPO_VISIBLE, flag & IPO_SELECT, icu) {
451                                 ei->icu->ipo= IPO_LIN;
452                         }
453                 }
454                 break;
455         case 2:
456                 for(a=0; a<G.sipo->totipo; a++, ei++) {
457                         if ISPOIN3(ei, flag & IPO_VISIBLE, flag & IPO_SELECT, icu) {
458                                 ei->icu->ipo= IPO_BEZ;
459                         }
460                 }
461                 break;
462         }
463
464         scrarea_queue_winredraw(curarea);
465 }
466
467 static uiBlock *ipo_editmenu_intpolmenu(void *arg_unused)
468 {
469         uiBlock *block;
470         short yco= 0, menuwidth=120;
471
472         block= uiNewBlock(&curarea->uiblocks, "ipo_editmenu_intpolmenu", UI_EMBOSSP, UI_HELV, G.curscreen->mainwin);
473         uiBlockSetButmFunc(block, do_ipo_editmenu_intpolmenu, NULL);
474
475         uiDefIconTextBut(block, BUTM, 1, ICON_BLANK1, "Constant|T, 1", 0, yco-=20, menuwidth, 19, NULL, 0.0, 0.0, 0, 0, "");
476         uiDefIconTextBut(block, BUTM, 1, ICON_BLANK1, "Linear|T, 2", 0, yco-=20, menuwidth, 19, NULL, 0.0, 0.0, 0, 1, "");
477         uiDefIconTextBut(block, BUTM, 1, ICON_BLANK1, "Bezier|T, 3", 0, yco-=20, menuwidth, 19, NULL, 0.0, 0.0, 0, 2, "");
478
479         uiBlockSetDirection(block, UI_RIGHT);
480         uiTextBoundsBlock(block, 60);
481
482         return block;
483 }
484
485 static void do_ipo_editmenu_extendmenu(void *arg, int event)
486 {
487         switch(event)
488         {
489         case 0:
490                 do_ipo_buttons(B_IPOCONT);
491                 break;
492         case 1:
493                 do_ipo_buttons(B_IPOEXTRAP);
494                 break;
495         case 2:
496                 do_ipo_buttons(B_IPOCYCLIC);
497                 break;
498         case 3:
499                 do_ipo_buttons(B_IPOCYCLICX);
500                 break;
501         }
502 }
503
504 static uiBlock *ipo_editmenu_extendmenu(void *arg_unused)
505 {
506         uiBlock *block;
507         short yco= 0, menuwidth=120;
508
509         block= uiNewBlock(&curarea->uiblocks, "ipo_editmenu_extendmenu", UI_EMBOSSP, UI_HELV, G.curscreen->mainwin);
510         uiBlockSetButmFunc(block, do_ipo_editmenu_extendmenu, NULL);
511
512         uiDefIconTextBut(block, BUTM, 1, ICON_BLANK1, "Constant", 0, yco-=20, menuwidth, 19, NULL, 0.0, 0.0, 0, 0, "");
513         uiDefIconTextBut(block, BUTM, 1, ICON_BLANK1, "Extrapolation", 0, yco-=20, menuwidth, 19, NULL, 0.0, 0.0, 0, 1, "");
514         uiDefIconTextBut(block, BUTM, 1, ICON_BLANK1, "Cyclic", 0, yco-=20, menuwidth, 19, NULL, 0.0, 0.0, 0, 2, "");
515         uiDefIconTextBut(block, BUTM, 1, ICON_BLANK1, "Cyclic Extrapolation", 0, yco-=20, menuwidth, 19, NULL, 0.0, 0.0, 0, 3, "");
516
517         uiBlockSetDirection(block, UI_RIGHT);
518         uiTextBoundsBlock(block, 60);
519
520         return block;
521 }
522
523
524 static void do_ipo_editmenu(void *arg, int event)
525 {
526         switch(event)
527         {
528         case 0:
529                 del_ipo();
530                 break;
531         case 1:
532                 add_duplicate_editipo();
533                 break;
534         case 2:
535                 ipo_record();
536                 break;
537         case 3:
538                 mainqenter(IKEY, 1);
539                 break;
540         case 4 :
541                 add_blockhandler(curarea, IPO_HANDLER_PROPERTIES, UI_PNL_UNSTOW);
542                 break;
543         case 5:
544                 //join_ipo();
545                 break;
546         case 6:
547                 /*IPO Editmode*/
548                 set_editflag_editipo();
549                 break;
550         case 7:
551                 sethandles_ipo(HD_AUTO_ANIM);
552                 break;
553         }
554 }
555
556 static uiBlock *ipo_editmenu(void *arg_unused)
557 {
558         uiBlock *block;
559         EditIpo *ei;
560         short yco= 0, menuwidth=120;
561         int a,isedit = 0;
562
563         get_status_editipo();
564
565         ei = G.sipo->editipo;
566
567         block= uiNewBlock(&curarea->uiblocks, "ipo_editmenu", UI_EMBOSSP, UI_HELV, curarea->headwin);
568         uiBlockSetButmFunc(block, do_ipo_editmenu, NULL);
569
570         uiDefIconTextBut(block, BUTM, 1, ICON_MENU_PANEL, "Transform Properties|N", 0, yco-=20, menuwidth, 19, NULL, 0.0, 0.0, 0, 4, "");
571         
572         uiDefIconTextBlockBut(block, ipo_editmenu_transformmenu, NULL, ICON_RIGHTARROW_THIN, "Transform", 0, yco-=20, 120, 19, "");     
573         
574         uiDefIconTextBlockBut(block, ipo_editmenu_snapmenu, NULL, ICON_RIGHTARROW_THIN, "Snap", 0, yco-=20, 120, 19, "");       
575
576         uiDefBut(block, SEPR, 0, "",        0, yco-=6, menuwidth, 6, NULL, 0.0, 0.0, 0, 0, ""); 
577
578         /*Look to see if any ipos are being edited, so there can be a check next to the menu option*/
579         for(a=0; a<G.sipo->totipo; a++, ei++) {         
580                 if(ei->icu) {
581                         if(ei->flag & IPO_VISIBLE) {
582                                 if(totipo_edit && (ei->flag & IPO_EDIT)) {
583                                         isedit = 1;
584                                         break;
585                                 }
586                         }
587                 }
588         }
589         if(isedit)
590                 uiDefIconTextBut(block, BUTM, 1, ICON_CHECKBOX_HLT,   "Edit Selected|TAB", 0, yco-=20, menuwidth, 19, NULL, 0.0, 0.0, 0, 6, "");                
591         else
592                 uiDefIconTextBut(block, BUTM, 1, ICON_CHECKBOX_DEHLT, "Edit Selected|TAB", 0, yco-=20, menuwidth, 19, NULL, 0.0, 0.0, 0, 6, "");
593         
594         ei = get_active_editipo();
595         uiDefBut(block, SEPR, 0, "",        0, yco-=6, menuwidth, 6, NULL, 0.0, 0.0, 0, 0, "");
596         
597         if(ei && ei->icu && ei->icu->driver)
598                 uiDefIconTextBut(block, BUTM, 1, ICON_BLANK1, "Insert 1:1 Curve...|I", 0, yco-=20, menuwidth, 19, NULL, 0.0, 0.0, 0, 3, "");
599         else
600                 uiDefIconTextBut(block, BUTM, 1, ICON_BLANK1, "Insert Keyframe...|I", 0, yco-=20, menuwidth, 19, NULL, 0.0, 0.0, 0, 3, "");
601         
602         uiDefBut(block, SEPR, 0, "",        0, yco-=6, menuwidth, 6, NULL, 0.0, 0.0, 0, 0, "");
603
604         uiDefIconTextBut(block, BUTM, 1, ICON_BLANK1, "Duplicate|Shift D", 0, yco-=20, menuwidth, 19, NULL, 0.0, 0.0, 0, 1, "");
605         uiDefIconTextBut(block, BUTM, 1, ICON_BLANK1, "Record Mouse Movement|R", 0, yco-=20, menuwidth, 19, NULL, 0.0, 0.0, 0, 2, "");
606         uiDefIconTextBut(block, BUTM, 1, ICON_BLANK1, "Delete|X", 0, yco-=20, menuwidth, 19, NULL, 0.0, 0.0, 0, 0, "");
607         uiDefIconTextBlockBut(block, ipo_editmenu_joinmenu, NULL, ICON_RIGHTARROW_THIN, "Join", 0, yco-=20, 120, 19, "");       
608
609         uiDefBut(block, SEPR, 0, "",        0, yco-=6, menuwidth, 6, NULL, 0.0, 0.0, 0, 0, "");
610         uiDefIconTextBut(block, BUTM, 1, ICON_BLANK1, "Auto Clamped Handles|Alt H", 0, yco-=20, menuwidth, 19, NULL, 0.0, 0.0, 0, 7, "");
611         
612         if (!G.sipo->showkey){
613                 uiDefIconTextBlockBut(block, ipo_editmenu_extendmenu, NULL, ICON_RIGHTARROW_THIN, "Extend Mode", 0, yco-=20, 120, 19, "");      
614                 uiDefIconTextBlockBut(block, ipo_editmenu_intpolmenu, NULL, ICON_RIGHTARROW_THIN, "Interpolation Mode   ", 0, yco-=20, 120, 20, "");
615                 if(ei != NULL && (ei->flag & IPO_EDIT))
616                         uiDefIconTextBlockBut(block, ipo_editmenu_handlemenu, NULL, ICON_RIGHTARROW_THIN, "Handle Type", 0, yco-=20, 120, 19, "");
617                 if(G.sipo->blocktype==ID_KE && totipo_edit==0 && totipo_sel==0)
618                         uiDefIconTextBlockBut(block, ipo_editmenu_keymenu, NULL, ICON_RIGHTARROW_THIN, "Key Type", 0, yco-=20, 120, 19, "");
619         }
620         
621
622         if(curarea->headertype==HEADERTOP) {
623                 uiBlockSetDirection(block, UI_DOWN);
624         }
625         else {
626                 uiBlockSetDirection(block, UI_TOP);
627                 uiBlockFlipOrder(block);
628         }
629
630         uiTextBoundsBlock(block, 50);
631
632         return block;
633 }
634
635 static void do_ipo_viewmenu(void *arg, int event)
636 {
637         extern int play_anim(int mode);
638         
639         switch(event)
640         {
641         case 1:
642                 do_ipo_buttons(B_IPOHOME);
643                 break;
644         case 2:
645                 ipo_toggle_showkey();
646                 scrarea_queue_headredraw(curarea);
647                 scrarea_queue_winredraw(curarea);
648                 allqueue(REDRAWVIEW3D, 0);
649                 break;
650         case 3:
651                 move_to_frame();
652                 break;
653         case 4:
654                 mainqenter(PADPLUSKEY,1);
655                 break;
656         case 5:
657                 mainqenter(PADMINUS,1);
658                 break;
659         case 6: /* Play Animation */
660                 play_anim(0);
661                 break;
662         case 7: /* Play Animation in All */
663                 play_anim(1);
664                 break;  
665         case 8:
666                 add_blockhandler(curarea, IPO_HANDLER_PROPERTIES, UI_PNL_UNSTOW);
667                 break;  
668         case 9:
669                 G.v2d->flag ^= V2D_VIEWLOCK;
670                 if(G.v2d->flag & V2D_VIEWLOCK)
671                         view2d_do_locks(curarea, 0);
672                 break;                  
673         }
674 }
675
676 static uiBlock *ipo_viewmenu(void *arg_unused)
677 {
678         uiBlock *block;
679         EditIpo *ei;
680         short yco= 0, menuwidth=120;
681
682         ei = get_active_editipo();
683
684         block= uiNewBlock(&curarea->uiblocks, "ipo_viewmenu", UI_EMBOSSP, UI_HELV, curarea->headwin);
685         uiBlockSetButmFunc(block, do_ipo_viewmenu, NULL);
686
687         uiDefIconTextBut(block, BUTM, 1, ICON_MENU_PANEL, "Channel Properties|N", 0, yco-=20, menuwidth, 19, NULL, 0.0, 0.0, 0, 8, "");
688         
689         if (G.sipo->showkey)
690                 uiDefIconTextBut(block, BUTM, 1, ICON_CHECKBOX_HLT, "Show Keys|K", 0, yco-=20, menuwidth, 19, NULL, 0.0, 0.0, 0, 2, "");
691         else
692                 uiDefIconTextBut(block, BUTM, 1, ICON_CHECKBOX_DEHLT, "Show Keys|K", 0, yco-=20, menuwidth, 19, NULL, 0.0, 0.0, 0, 2, "");
693
694         uiDefBut(block, SEPR, 0, "",        0, yco-=6, menuwidth, 6, NULL, 0.0, 0.0, 0, 0, "");
695
696         uiDefIconTextBut(block, BUTM, 1, ICON_BLANK1, "Zoom Out|NumPad -", 0, yco-=20, menuwidth, 19, NULL, 0.0, 0.0, 0, 5, "");
697         uiDefIconTextBut(block, BUTM, 1, ICON_BLANK1, "Zoom In|NumPad +", 0, yco-=20, menuwidth, 19, NULL, 0.0, 0.0, 0, 4, "");
698
699         uiDefBut(block, SEPR, 0, "", 0, yco-=6, menuwidth, 6, NULL, 0.0, 0.0, 0, 0, "");
700         
701         uiDefIconTextBut(block, BUTM, 1, ICON_BLANK1, "Play Animation|Alt A", 0, yco-=20, 
702                                          menuwidth, 19, NULL, 0.0, 0.0, 1, 6, "");
703         uiDefIconTextBut(block, BUTM, 1, ICON_BLANK1, "Play Animation in 3D View|Alt Shift A", 0, yco-=20,
704                                          menuwidth, 19, NULL, 0.0, 0.0, 1, 7, "");
705
706         uiDefBut(block, SEPR, 0, "",        0, yco-=6, menuwidth, 6, NULL, 0.0, 0.0, 0, 0, "");
707
708         uiDefIconTextBut(block, BUTM, 1, ICON_BLANK1, "View All|Home", 0, yco-=20, menuwidth, 19, NULL, 0.0, 0.0, 0, 1, "");
709         uiDefIconTextBut(block, BUTM, 1, (G.v2d->flag & V2D_VIEWLOCK)?ICON_CHECKBOX_HLT:ICON_CHECKBOX_DEHLT, 
710                                          "Lock Time to Other Windows|", 0, yco-=20, menuwidth, 19, NULL, 0.0, 0.0, 1, 9, "");
711
712         if (ei != NULL && (ei->flag & IPO_EDIT)) {
713                 uiDefIconTextBut(block, BUTM, 1, ICON_BLANK1, "Move Current Frame to Selected|C", 0, yco-=20, menuwidth, 19, NULL, 0.0, 0.0, 0, 3, "");
714         }
715
716         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, "");
717         else uiDefIconTextBut(block, BUTM, B_FULL, ICON_BLANK1, "Tile Window|Ctrl DownArrow", 0, yco-=20, menuwidth, 19, NULL, 0.0, 0.0, 0, 20, "");
718
719         if(curarea->headertype==HEADERTOP) {
720                 uiBlockSetDirection(block, UI_DOWN);
721         }
722         else {
723                 uiBlockSetDirection(block, UI_TOP);
724                 uiBlockFlipOrder(block);
725         }
726
727         uiTextBoundsBlock(block, 50);
728
729         return block;
730 }
731
732 static void do_ipo_selectmenu(void *arg, int event)
733 {
734         switch(event)
735         {
736         case 0:
737                 borderselect_ipo();
738                 break;
739         case 1:
740                 swap_selectall_editipo();
741                 break;
742         }
743 }
744
745 static uiBlock *ipo_selectmenu(void *arg_unused)
746 {
747         uiBlock *block;
748         short yco= 0, menuwidth=120;
749
750         block= uiNewBlock(&curarea->uiblocks, "ipo_selectmenu", UI_EMBOSSP, UI_HELV, curarea->headwin);
751         uiBlockSetButmFunc(block, do_ipo_selectmenu, NULL);
752
753         uiDefIconTextBut(block, BUTM, 1, ICON_BLANK1, "Border Select|B", 0, yco-=20, menuwidth, 19, NULL, 0.0, 0.0, 0, 0, "");
754         uiDefBut(block, SEPR, 0, "",        0, yco-=6, menuwidth, 6, NULL, 0.0, 0.0, 0, 0, "");
755         uiDefIconTextBut(block, BUTM, 1, ICON_BLANK1, "Select/Deselect All|A", 0, yco-=20, menuwidth, 19, NULL, 0.0, 0.0, 0, 1, "");
756
757         if(curarea->headertype==HEADERTOP) {
758                 uiBlockSetDirection(block, UI_DOWN);
759         }
760         else {
761                 uiBlockSetDirection(block, UI_TOP);
762                 uiBlockFlipOrder(block);
763         }
764
765         uiTextBoundsBlock(block, 50);
766
767         return block;
768 }
769
770
771 static char *ipo_modeselect_pup(void)
772 {
773         Object *ob= OBACT;
774         static char formatstring[] = "|%s %%x%d %%i%d";
775         static char string[1024];
776         char *str = string;
777         
778         str += sprintf(str, "Ipo type: %%t");
779
780         if(ob)
781                 str += sprintf(str,formatstring, "Object",ID_OB, ICON_OBJECT);
782
783         if(ob && give_current_material(ob, ob->actcol)) // check for material
784                 str += sprintf(str,formatstring, "Material",ID_MA, ICON_MATERIAL);
785
786         if(G.scene->world)
787                 str += sprintf(str,formatstring, "World",ID_WO, ICON_WORLD);
788
789         if(ob && ob->type==OB_CURVE)
790                 str += sprintf(str,formatstring, "Path",ID_CU, ICON_CURVE);
791
792         if(ob && ob->type==OB_CAMERA)
793                 str += sprintf(str,formatstring, "Camera",ID_CA, ICON_CAMERA);
794         
795         if(ob && ob->type==OB_LAMP)
796                 str += sprintf(str,formatstring, "Lamp",ID_LA, ICON_LAMP);
797
798         if(ob && give_current_texture(ob, ob->actcol))
799                 str += sprintf(str,formatstring, "Texture",ID_TE, ICON_TEXTURE);
800
801         if(ob){
802                 if ELEM4(ob->type, OB_MESH, OB_CURVE, OB_SURF, OB_LATTICE)
803                         str += sprintf(str,formatstring, "Shape",ID_KE, ICON_EDIT);
804                 if (ob->type==OB_ARMATURE)
805                         str += sprintf(str,formatstring, "Pose",ID_PO, ICON_POSE_HLT);
806 #ifdef __CON_IPO
807                 str += sprintf(str,formatstring, "Constraint",ID_CO, ICON_CONSTRAINT);
808 #endif
809                 if(ob->fluidsimFlag & OB_FLUIDSIM_ENABLE) {
810                         str += sprintf(str,formatstring,"Fluidsim",ID_FLUIDSIM, ICON_WORLD);
811                 }
812         }
813
814         str += sprintf(str,formatstring, "Sequence",ID_SEQ, ICON_SEQUENCE);
815
816         return (string);
817 }
818
819 void do_ipo_buttons(short event)
820 {
821         EditIpo *ei;
822         View2D *v2d;
823         rcti rect;
824         Object *ob= OBACT;
825         float xmin, ymin, dx, dy;
826         int a, val, first;
827         short mval[2];
828
829         if(curarea->win==0) return;
830
831         switch(event) {
832         case B_IPOHOME:
833
834                 /* boundbox */
835
836                 v2d= &(G.sipo->v2d);
837                 first= 1;
838
839                 ei= G.sipo->editipo;
840                 if(ei==0) return;
841                 for(a=0; a<G.sipo->totipo; a++, ei++) {
842                         if ISPOIN(ei, flag & IPO_VISIBLE, icu) {
843                         
844                                 boundbox_ipocurve(ei->icu);
845                                 
846                                 if(first) {
847                                         v2d->tot= ei->icu->totrct;
848                                         first= 0;
849                                 }
850                                 else BLI_union_rctf(&(v2d->tot), &(ei->icu->totrct));
851                         }
852                 }
853
854                 /* speciale home */
855                 if(G.qual & LR_SHIFTKEY) {
856                         v2d->tot.xmin= SFRA;
857                         v2d->tot.xmax= EFRA;
858                 }
859
860                 /* zoom out a bit */
861                 dx= 0.10*(v2d->tot.xmax-v2d->tot.xmin);
862                 dy= 0.10*(v2d->tot.ymax-v2d->tot.ymin);
863                 
864                 if(dx<v2d->min[0]) dx= v2d->min[0];
865                 if(dy<v2d->min[1]) dy= v2d->min[1];
866                 
867                 v2d->cur.xmin= v2d->tot.xmin- dx;
868                 v2d->cur.xmax= v2d->tot.xmax+ dx;
869                 v2d->cur.ymin= v2d->tot.ymin- dy;
870                 v2d->cur.ymax= v2d->tot.ymax+ dy;
871
872                 test_view2d(G.v2d, curarea->winx, curarea->winy);
873                 view2d_do_locks(curarea, V2D_LOCK_COPY);
874                 if(G.sipo->ipo) G.sipo->ipo->cur = G.v2d->cur;
875                 
876                 scrarea_queue_winredraw(curarea);
877                 break;
878         case B_IPOBORDER:
879                 val= get_border(&rect, 3);
880                 if(val) {
881                         mval[0]= rect.xmin;
882                         mval[1]= rect.ymin;
883                         areamouseco_to_ipoco(G.v2d, mval, &xmin, &ymin);
884                         mval[0]= rect.xmax;
885                         mval[1]= rect.ymax;
886                         areamouseco_to_ipoco(G.v2d, mval, &(G.v2d->cur.xmax), &(G.v2d->cur.ymax));
887                         G.v2d->cur.xmin= xmin;
888                         G.v2d->cur.ymin= ymin;
889                         
890                         test_view2d(G.v2d, curarea->winx, curarea->winy);
891                         view2d_do_locks(curarea, V2D_LOCK_COPY);
892                         scrarea_queue_winredraw(curarea);
893                 }
894                 break;
895
896         case B_IPOPIN:
897                 allqueue (REDRAWIPO, 0);
898                 break;
899
900         case B_IPOCOPY:
901                 copy_editipo();
902                 break;
903         case B_IPOPASTE:
904                 paste_editipo();
905                 break;
906         case B_IPOCONT:
907                 set_exprap_ipo(IPO_HORIZ);
908                 break;
909         case B_IPOEXTRAP:
910                 set_exprap_ipo(IPO_DIR);
911                 break;
912         case B_IPOCYCLIC:
913                 set_exprap_ipo(IPO_CYCL);
914                 break;
915         case B_IPOCYCLICX:
916                 set_exprap_ipo(IPO_CYCLX);
917                 break;
918         case B_IPOMAIN:
919                 /* pass 1 to enforce a refresh when there's no Ipo */
920                 test_editipo(1);
921                 scrarea_queue_winredraw(curarea);
922                 scrarea_queue_headredraw(curarea);
923                 if(ob) ob->ipowin= G.sipo->blocktype;
924                 break;
925         case B_IPOSHOWKEY:
926                 /* reverse value because of winqread */
927                 G.sipo->showkey= 1-G.sipo->showkey;
928                 ipo_toggle_showkey();
929                 scrarea_queue_headredraw(curarea);
930                 scrarea_queue_winredraw(curarea);
931                 allqueue(REDRAWVIEW3D, 0);
932                 break;
933         case B_VIEW2DZOOM:
934                 viewmovetemp= 0;
935                 view2dzoom(event);
936                 scrarea_queue_headredraw(curarea);
937                 break;
938         case B_IPO_ACTION_OB:
939                 if(ob && G.sipo->from && G.sipo->pin==0) {
940                         if(ob->ipoflag & OB_ACTION_OB) {        /* check if channel exists, and flip ipo link */
941                                 bActionChannel *achan;
942                                 
943                                 if(has_ipo_code(ob->ipo, OB_LAY))
944                                         notice("Note: Layer Ipo doesn't work in Actions");
945                                 
946                                 if(ob->action==NULL) 
947                                         ob->action= add_empty_action(ID_OB);
948                                 achan= verify_action_channel(ob->action, "Object");
949                                 if(achan->ipo==NULL && ob->ipo) {
950                                         achan->ipo= ob->ipo;
951                                         ob->ipo= NULL;
952                                 }
953                                 
954                                 /* object constraints */
955                                 if(ob->constraintChannels.first) {
956                                         free_constraint_channels(&achan->constraintChannels);
957                                         achan->constraintChannels= ob->constraintChannels;
958                                         ob->constraintChannels.first= ob->constraintChannels.last= NULL;
959                                 }
960                         }
961                         else if(ob->action) {
962                                 bActionChannel *achan= get_action_channel(ob->action, "Object");
963                                 if(achan) {
964                                         
965                                         if(achan->ipo && ob->ipo==NULL) {
966                                                 ob->ipo= achan->ipo;
967                                                 achan->ipo= NULL;
968                                         }
969                                         
970                                         /* object constraints */
971                                         if(achan->constraintChannels.first) {
972                                                 free_constraint_channels(&ob->constraintChannels);
973                                                 ob->constraintChannels= achan->constraintChannels;
974                                                 achan->constraintChannels.first= achan->constraintChannels.last= NULL;
975                                         }
976                                 }
977                         }
978                         allqueue(REDRAWVIEW3D, 0);
979                         allqueue(REDRAWIPO, 0);
980                         allqueue(REDRAWACTION, 0);
981                         allqueue(REDRAWOOPS, 0);
982                         allqueue(REDRAWNLA, 0);
983                 }
984                 break;
985                 
986         case B_IPO_ACTION_KEY:
987                 if(ob && G.sipo->from && G.sipo->pin==0) {
988                         Key *key= ob_get_key(ob);
989                         if(key) {
990                                 if(ob->ipoflag & OB_ACTION_KEY) {       /* check if channel exists, and flip ipo link */
991                                         bActionChannel *achan;
992                                         
993                                         if(ob->action==NULL) 
994                                                 ob->action= add_empty_action(ID_KE);
995                                         achan= verify_action_channel(ob->action, "Shape");
996                                         if(achan->ipo==NULL && key->ipo) {
997                                                 achan->ipo= key->ipo;
998                                                 key->ipo= NULL;
999                                         }
1000                                 }
1001                                 else if(ob->action) {
1002                                         bActionChannel *achan= get_action_channel(ob->action, "Shape");
1003                                         if(achan) {
1004                                                 if(achan->ipo && key->ipo==NULL) {
1005                                                         key->ipo= achan->ipo;
1006                                                         achan->ipo= NULL;
1007                                                 }
1008                                         }
1009                                 }
1010                                 allqueue(REDRAWVIEW3D, 0);
1011                                 allqueue(REDRAWIPO, 0);
1012                                 allqueue(REDRAWACTION, 0);
1013                                 allqueue(REDRAWOOPS, 0);
1014                                 allqueue(REDRAWNLA, 0);
1015                         }
1016                 }
1017                 break;
1018         } 
1019 }
1020
1021 void ipo_buttons(void)
1022 {
1023         Object *ob;
1024         EditIpo *ei;
1025         uiBlock *block;
1026         short xco,xmax;
1027         char naam[20];
1028         int icon=0, allow_pin= B_IPOPIN;
1029
1030         sprintf(naam, "header %d", curarea->headwin);
1031         block= uiNewBlock(&curarea->uiblocks, naam, UI_EMBOSS, UI_HELV, curarea->headwin);
1032
1033         if(area_is_active_area(curarea)) uiBlockSetCol(block, TH_HEADER);
1034         else uiBlockSetCol(block, TH_HEADERDESEL);
1035
1036         curarea->butspacetype= SPACE_IPO;
1037
1038         xco = 8;
1039         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.");
1040         xco+= XIC+14;
1041         
1042         test_editipo(0);        /* test if current editipo is OK, make_editipo sets v2d->cur */
1043
1044         uiBlockSetEmboss(block, UI_EMBOSSN);
1045         if(curarea->flag & HEADER_NO_PULLDOWN) {
1046                 uiDefIconButBitS(block, TOG, HEADER_NO_PULLDOWN, B_FLIPINFOMENU, ICON_DISCLOSURE_TRI_RIGHT,
1047                                 xco,2,XIC,YIC-2,
1048                                 &(curarea->flag), 0, 0, 0, 0, "Enables display of pulldown menus");
1049         } else {
1050                 uiDefIconButBitS(block, TOG, HEADER_NO_PULLDOWN, B_FLIPINFOMENU, ICON_DISCLOSURE_TRI_DOWN,
1051                                 xco,2,XIC,YIC-2,
1052                                 &(curarea->flag), 0, 0, 0, 0, "Hides pulldown menus");
1053         }
1054         uiBlockSetEmboss(block, UI_EMBOSS);
1055         xco+=XIC;
1056
1057         /* pull down menus */
1058         if((curarea->flag & HEADER_NO_PULLDOWN)==0) {
1059                 uiBlockSetEmboss(block, UI_EMBOSSP);
1060         
1061                 ei = get_active_editipo();
1062         
1063                 xmax= GetButStringLength("View");
1064                 uiDefPulldownBut(block,ipo_viewmenu, NULL, "View", xco, -2, xmax-3, 24, "");
1065                 xco+=xmax;
1066         
1067                 xmax= GetButStringLength("Select");
1068                 uiDefPulldownBut(block,ipo_selectmenu, NULL, "Select", xco, -2, xmax-3, 24, "");
1069                 xco+=xmax;
1070         
1071                 if (G.sipo->showkey) {
1072                         xmax= GetButStringLength("Key");
1073                         uiDefPulldownBut(block,ipo_editmenu, NULL, "Key", xco, -2, xmax-3, 24, "");
1074                 }
1075                 else if(ei != NULL && (ei->flag & IPO_EDIT)) {
1076                         xmax= GetButStringLength("Point");
1077                         uiDefPulldownBut(block,ipo_editmenu, NULL, "Point", xco, -2, xmax-3, 24, "");
1078                 }
1079                 else {
1080                         xmax= GetButStringLength("Curve");
1081                         uiDefPulldownBut(block,ipo_editmenu, NULL, "Curve", xco, -2, xmax-3, 24, "");
1082                 }
1083                         
1084                 xco+=xmax;
1085         }
1086
1087         /* end of pull down menus */
1088         uiBlockSetEmboss(block, UI_EMBOSS);
1089
1090         ob= OBACT;
1091         
1092         /* action switch option, only when active object is there and no pin */
1093         uiSetButLock(G.sipo->pin, "Can't change because of pinned data");
1094         
1095         /* define whether ipos are on Object or on action */
1096         if(ob) {
1097                 static short fake1= 1;
1098                 
1099                 uiBlockBeginAlign(block);
1100                 
1101                 if(G.sipo->blocktype==ID_OB) {
1102                         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");
1103                         xco+= XIC;
1104                 }
1105                 else if(G.sipo->blocktype==ID_KE) {
1106                         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");
1107                         xco+= XIC;
1108                 }
1109                 else if(G.sipo->blocktype==ID_CO) {
1110                         
1111                         if(G.sipo->from && G.sipo->actname[0]==0)
1112                                 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");
1113                         else {
1114                                 uiSetButLock(1, "Pose Constraint Ipo cannot be switched");
1115                                 uiDefIconButS(block, TOG, 1, ICON_ACTION,       xco,0,XIC,YIC, &fake1, 0, 0, 0, 0, "Ipo is connected to Pose Action");
1116                         }
1117                         xco+= XIC;
1118                 }
1119                 else if(G.sipo->blocktype==ID_PO) {     /* only to indicate we have action ipos */
1120                         uiSetButLock(1, "Pose Action Ipo cannot be switched");
1121                         uiDefIconButS(block, TOG, 1, ICON_ACTION,       xco,0,XIC,YIC, &fake1, 0, 0, 0, 0, "Ipo is connected to Pose Action");
1122                         xco+= XIC;
1123                 }
1124                 uiClearButLock();
1125         }
1126         
1127         /* mainmenu, only when data is there and no pin */
1128         uiSetButLock(G.sipo->pin, "Can't change because of pinned data");
1129
1130         if (G.sipo->blocktype == ID_OB)
1131                 icon = ICON_OBJECT;
1132         else if (G.sipo->blocktype == ID_MA)
1133                 icon = ICON_MATERIAL;
1134         else if (G.sipo->blocktype == ID_WO)
1135                 icon = ICON_WORLD;
1136         else if (G.sipo->blocktype == ID_CU)
1137                 icon = ICON_ANIM;
1138         else if (G.sipo->blocktype == ID_CA)
1139                 icon = ICON_CAMERA;
1140         else if (G.sipo->blocktype == ID_LA)
1141                 icon = ICON_LAMP;
1142         else if (G.sipo->blocktype == ID_KE)
1143                 icon = ICON_EDIT;
1144         else if (G.sipo->blocktype == ID_PO)
1145                 icon = ICON_POSE_HLT;
1146         else if (G.sipo->blocktype == ID_CO)
1147                 icon = ICON_CONSTRAINT;
1148         else if (G.sipo->blocktype == ID_SEQ)
1149                 icon = ICON_SEQUENCE;
1150         else if(G.sipo->blocktype == ID_TE)
1151                 icon = ICON_TEXTURE;
1152         else if(G.sipo->blocktype == ID_FLUIDSIM)
1153                 icon = ICON_WORLD;
1154
1155         uiDefIconTextButS(block, MENU, B_IPOMAIN, icon, ipo_modeselect_pup(), xco,0,100,20, &(G.sipo->blocktype), 0, 0, 0, 0, "Show IPO type");
1156
1157         xco += 85;
1158
1159         if(G.sipo->blocktype==ID_MA) {
1160                 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.");
1161                 xco-= 4;
1162         }
1163         if(G.sipo->blocktype==ID_WO) {
1164                 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.");
1165                 xco-= 4;
1166         }
1167         
1168         if(G.sipo->blocktype==ID_LA) {
1169                 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. ");
1170                 xco-= 4;
1171         }
1172         
1173         uiBlockEndAlign(block);
1174         
1175         uiClearButLock();
1176
1177         /* if(G.sipo->blocktype==ID_SEQ)
1178            allow_pin= 0; */
1179         xco= std_libbuttons(block, (short)(xco+1.5*XIC), 0, allow_pin, &G.sipo->pin, B_IPOBROWSE, ID_IP, 
1180                                                 G.sipo->blocktype, (ID*)G.sipo->ipo, G.sipo->from, &(G.sipo->menunr), B_IPOALONE, B_IPOLOCAL, B_IPODELETE, 0, B_KEEPDATA);
1181
1182         /* COPY PASTE */
1183         xco-= XIC/2;
1184         uiBlockBeginAlign(block);
1185         if(curarea->headertype==HEADERTOP) {
1186                 uiDefIconBut(block, BUT, B_IPOCOPY, ICON_COPYUP,        xco+=XIC,0,XIC,YIC, 0, 0, 0, 0, 0, "Copies the selected curves to the buffer");
1187                 uiSetButLock(G.sipo->ipo && G.sipo->ipo->id.lib, "Can't edit library data");
1188                 uiDefIconBut(block, BUT, B_IPOPASTE, ICON_PASTEUP,      xco+=XIC,0,XIC,YIC, 0, 0, 0, 0, 0, "Pastes the curves from the buffer");
1189         }
1190         else {
1191                 uiDefIconBut(block, BUT, B_IPOCOPY, ICON_COPYDOWN,      xco+=XIC,0,XIC,YIC, 0, 0, 0, 0, 0, "Copies the selected curves to the buffer");
1192                 uiSetButLock(G.sipo->ipo && G.sipo->ipo->id.lib, "Can't edit library data");
1193                 uiDefIconBut(block, BUT, B_IPOPASTE, ICON_PASTEDOWN,    xco+=XIC,0,XIC,YIC, 0, 0, 0, 0, 0, "Pastes the curves from the buffer");
1194         }
1195         uiBlockEndAlign(block);
1196         xco+=XIC/2;
1197         
1198         uiClearButLock();
1199
1200         /* ZOOMBORDER */
1201         uiDefIconBut(block, BUT, B_IPOBORDER, ICON_BORDERMOVE,  xco+=XIC,0,XIC,YIC, 0, 0, 0, 0, 0, "Zooms view to area");
1202         
1203         xco+=XIC/2;
1204         
1205         /* draw LOCK */
1206         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");
1207         
1208         /* always do as last */
1209         curarea->headbutlen= xco+2*XIC;
1210
1211         uiDrawBlock(block);
1212 }