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