49f5ee3fd0d74c1d8c542b51056a486863bfbde2
[blender.git] / source / blender / src / header_action.c
1 /**
2  * header_action.c oct-2003
3  *
4  * Functions to draw the "Action 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_curve_types.h"
48 #include "DNA_ID.h"
49 #include "DNA_ipo_types.h"
50 #include "DNA_key_types.h"
51 #include "DNA_object_types.h"
52 #include "DNA_scene_types.h"
53 #include "DNA_screen_types.h"
54 #include "DNA_space_types.h"
55
56 #include "BIF_editaction.h"
57 #include "BIF_interface.h"
58 #include "BIF_poseobject.h"
59 #include "BIF_resources.h"
60 #include "BIF_screen.h"
61 #include "BIF_space.h"
62
63 #include "BKE_action.h"
64 #include "BKE_armature.h"
65 #include "BKE_constraint.h"
66 #include "BKE_depsgraph.h"
67 #include "BKE_global.h"
68 #include "BKE_main.h"
69 #include "BKE_utildefines.h"
70
71 #include "BSE_drawipo.h"
72 #include "BSE_headerbuttons.h"
73
74 #include "nla.h"
75
76 #include "blendef.h"
77 #include "mydevice.h"
78
79 #define ACTMENU_VIEW_CENTERVIEW 0
80 #define ACTMENU_VIEW_AUTOUPDATE 1
81 #define ACTMENU_VIEW_PLAY3D     2
82 #define ACTMENU_VIEW_PLAYALL    3
83 #define ACTMENU_VIEW_ALL        4
84 #define ACTMENU_VIEW_MAXIMIZE   5
85
86 #define ACTMENU_SEL_BORDER      0
87 #define ACTMENU_SEL_ALL_KEYS    1
88 #define ACTMENU_SEL_ALL_CHAN    2
89
90 #define ACTMENU_KEY_DUPLICATE     0
91 #define ACTMENU_KEY_DELETE        1
92 #define ACTMENU_KEY_BAKE          2
93
94 #define ACTMENU_KEY_TRANSFORM_MOVE      0
95 #define ACTMENU_KEY_TRANSFORM_SCALE     1
96
97 #define ACTMENU_KEY_HANDLE_AUTO   0
98 #define ACTMENU_KEY_HANDLE_ALIGN  1
99 #define ACTMENU_KEY_HANDLE_FREE   2
100 #define ACTMENU_KEY_HANDLE_VECTOR 3
101
102 #define ACTMENU_KEY_INTERP_CONST  0
103 #define ACTMENU_KEY_INTERP_LINEAR 1
104 #define ACTMENU_KEY_INTERP_BEZIER 2
105
106 void do_action_buttons(unsigned short event)
107 {
108         Object *ob= OBACT;
109
110         switch(event){
111                 case B_ACTBAKE:
112                         bake_action_with_client (G.saction->action, ob, 0.01);
113                         break;
114                 case B_ACTCONT:
115                         set_exprap_action(IPO_HORIZ);
116                         break;
117 //      case B_ACTEXTRAP:
118 //              set_exprap_ipo(IPO_DIR);
119 //              break;
120                 case B_ACTCYCLIC:
121                         set_exprap_action(IPO_CYCL);
122                         break;
123 //      case B_ACTCYCLICX:
124 //              set_exprap_ipo(IPO_CYCLX);
125 //              break;
126                 case B_ACTHOME:
127                         //      Find X extents
128                         //v2d= &(G.saction->v2d);
129
130                         G.v2d->cur.xmin = 0;
131                         G.v2d->cur.ymin=-SCROLLB;
132
133                         if (!G.saction->action){        // here the mesh rvk?
134                                 G.v2d->cur.xmax= -5;
135                                 G.v2d->cur.xmax= 100;
136                         }
137                         else {
138                                 float extra;
139                                 G.v2d->cur.xmin= calc_action_start(G.saction->action);
140                                 G.v2d->cur.xmax= calc_action_end(G.saction->action);
141                                 extra= 0.05*(G.v2d->cur.xmax - G.v2d->cur.xmin);
142                                 G.v2d->cur.xmin-= extra;
143                                 G.v2d->cur.xmax+= extra;
144                                 
145                                 if(G.v2d->cur.xmin==G.v2d->cur.xmax) {
146                                         G.v2d->cur.xmax= -5;
147                                         G.v2d->cur.xmax= 100;
148                                 }
149                         }
150                         G.v2d->cur.ymin= 0.0f;
151                         G.v2d->cur.ymax= 1000.0f;
152                         
153                         G.v2d->tot= G.v2d->cur;
154                         test_view2d(G.v2d, curarea->winx, curarea->winy);
155
156
157                         addqueue (curarea->win, REDRAW, 1);
158
159                         break;
160                 case B_ACTCOPY:
161                         copy_posebuf();
162                         allqueue(REDRAWVIEW3D, 1);
163                         break;
164                 case B_ACTPASTE:
165                         paste_posebuf(0);
166                         allqueue(REDRAWVIEW3D, 1);
167                         break;
168                 case B_ACTPASTEFLIP:
169                         paste_posebuf(1);
170                         allqueue(REDRAWVIEW3D, 1);
171                         break;
172
173                 case B_ACTPIN:  /* __PINFAKE */
174 /*              if (G.saction->flag & SACTION_PIN){
175                 if (G.saction->action)
176                 G.saction->action->id.us ++;
177                 
178                 }
179                 else {
180                         if (G.saction->action)
181                                 G.saction->action->id.us --;
182                                 }
183 */              /* end PINFAKE */
184                         allqueue(REDRAWACTION, 1);
185                         break;
186
187         }
188 }
189
190 static void do_action_viewmenu(void *arg, int event)
191 {
192         extern int play_anim(int mode);
193
194         switch(event) {
195                 case ACTMENU_VIEW_CENTERVIEW: /* Center View to Current Frame */
196                         center_currframe();
197                         break;
198                 case ACTMENU_VIEW_AUTOUPDATE: /* Update Automatically */
199                         if (BTST(G.saction->lock, 0)) 
200                                 G.saction->lock = BCLR(G.saction->lock, 0);
201                         else 
202                                 G.saction->lock = BSET(G.saction->lock, 0);
203                         break;
204                 case ACTMENU_VIEW_PLAY3D: /* Play Back Animation */
205                         play_anim(0);
206                         break;
207                 case ACTMENU_VIEW_PLAYALL: /* Play Back Animation in All */
208                         play_anim(1);
209                         break;  
210                 case ACTMENU_VIEW_ALL: /* View All */
211                         do_action_buttons(B_ACTHOME);
212                         break;
213                 case ACTMENU_VIEW_MAXIMIZE: /* Maximize Window */
214                         /* using event B_FULL */
215                         break;
216         }
217         allqueue(REDRAWVIEW3D, 0);
218 }
219
220 static uiBlock *action_viewmenu(void *arg_unused)
221 {
222         uiBlock *block;
223         short yco= 0, menuwidth=120;
224         
225         block= uiNewBlock(&curarea->uiblocks, "action_viewmenu", 
226                                           UI_EMBOSSP, UI_HELV, curarea->headwin);
227         uiBlockSetButmFunc(block, do_action_viewmenu, NULL);
228         
229         uiDefIconTextBut(block, BUTM, 1, ICON_BLANK1, 
230                                          "Center View to Current Frame|C", 0, yco-=20, 
231                                          menuwidth, 19, NULL, 0.0, 0.0, 1, 
232                                          ACTMENU_VIEW_CENTERVIEW, "");
233         
234         uiDefBut(block, SEPR, 0, "", 0, yco-=6, 
235                          menuwidth, 6, NULL, 0.0, 0.0, 0, 0, "");
236         
237         if(BTST(G.saction->lock, 0)) {
238                 uiDefIconTextBut(block, BUTM, 1, ICON_CHECKBOX_HLT, 
239                                                  "Update Automatically|", 0, yco-=20, 
240                                                  menuwidth, 19, NULL, 0.0, 0.0, 1, 
241                                                  ACTMENU_VIEW_AUTOUPDATE, "");
242         } 
243         else {
244                 uiDefIconTextBut(block, BUTM, 1, ICON_CHECKBOX_DEHLT, 
245                                                  "Update Automatically|", 0, yco-=20, 
246                                                  menuwidth, 19, NULL, 0.0, 0.0, 1, 
247                                                  ACTMENU_VIEW_AUTOUPDATE, "");
248         }
249
250         uiDefBut(block, SEPR, 0, "", 0, yco-=6, 
251                          menuwidth, 6, NULL, 0.0, 0.0, 0, 0, "");
252         
253         uiDefIconTextBut(block, BUTM, 1, ICON_BLANK1, 
254                                          "Play Back Animation|Alt A", 0, yco-=20, 
255                                          menuwidth, 19, NULL, 0.0, 0.0, 1, 
256                                          ACTMENU_VIEW_PLAY3D, "");
257         uiDefIconTextBut(block, BUTM, 1, ICON_BLANK1, 
258                                          "Play Back Animation in 3D View|Alt Shift A", 0, yco-=20,
259                                          menuwidth, 19, NULL, 0.0, 0.0, 1, 
260                                          ACTMENU_VIEW_PLAYALL, "");
261
262         uiDefBut(block, SEPR, 0, "", 0, yco-=6, 
263                          menuwidth, 6, NULL, 0.0, 0.0, 0, 0, "");
264         
265         uiDefIconTextBut(block, BUTM, 1, ICON_BLANK1, 
266                                          "View All|Home", 0, yco-=20, 
267                                          menuwidth, 19, NULL, 0.0, 0.0, 1, 
268                                          ACTMENU_VIEW_ALL, "");
269                 
270         if (!curarea->full) 
271                 uiDefIconTextBut(block, BUTM, B_FULL, ICON_BLANK1, 
272                                                  "Maximize Window|Ctrl UpArrow", 0, yco-=20, 
273                                                  menuwidth, 19, NULL, 0.0, 0.0, 0, 
274                                                  ACTMENU_VIEW_MAXIMIZE, "");
275         else 
276                 uiDefIconTextBut(block, BUTM, B_FULL, ICON_BLANK1, 
277                                                  "Tile Window|Ctrl DownArrow", 0, yco-=20, 
278                                                  menuwidth, 19, NULL, 0.0, 0.0, 0, 
279                                                  ACTMENU_VIEW_MAXIMIZE, "");
280         
281         if(curarea->headertype==HEADERTOP) {
282                 uiBlockSetDirection(block, UI_DOWN);
283         }
284         else {
285                 uiBlockSetDirection(block, UI_TOP);
286                 uiBlockFlipOrder(block);
287         }
288
289         uiTextBoundsBlock(block, 50);
290         
291         return block;
292 }
293
294 static void do_action_selectmenu(void *arg, int event)
295 {       
296         SpaceAction *saction;
297         bAction *act;
298         Key *key;
299         
300         saction = curarea->spacedata.first;
301         if (!saction)
302                 return;
303
304         act = saction->action;
305         key = get_action_mesh_key();
306         
307         switch(event)
308         {
309                 case ACTMENU_SEL_BORDER: /* Border Select */
310                         if (key) {
311                                 borderselect_mesh(key);
312                         }
313                         else {
314                                 borderselect_action();
315                         }
316                         break;
317
318                 case ACTMENU_SEL_ALL_KEYS: /* Select/Deselect All Keys */
319                         if (key) {
320                                 deselect_meshchannel_keys(key, 1);
321                                 allqueue (REDRAWACTION, 0);
322                                 allqueue(REDRAWNLA, 0);
323                                 allqueue (REDRAWIPO, 0);
324                         }
325                         else {
326                                 deselect_actionchannel_keys (act, 1);
327                                 allqueue (REDRAWACTION, 0);
328                                 allqueue(REDRAWNLA, 0);
329                                 allqueue (REDRAWIPO, 0);
330                         }
331                         break;
332
333                 case ACTMENU_SEL_ALL_CHAN: /* Select/Deselect All Channels */
334                         deselect_actionchannels (act, 1);
335                         allqueue (REDRAWVIEW3D, 0);
336                         allqueue (REDRAWACTION, 0);
337                         allqueue(REDRAWNLA, 0);
338                         allqueue (REDRAWIPO, 0);
339                         break;
340         }
341 }
342
343 static uiBlock *action_selectmenu(void *arg_unused)
344 {
345         uiBlock *block;
346         short yco= 0, menuwidth=120;
347
348         block= uiNewBlock(&curarea->uiblocks, "action_selectmenu", 
349                                           UI_EMBOSSP, UI_HELV, curarea->headwin);
350         uiBlockSetButmFunc(block, do_action_selectmenu, NULL);
351
352         uiDefIconTextBut(block, BUTM, 1, ICON_BLANK1, 
353                                          "Border Select|B", 0, yco-=20, 
354                                          menuwidth, 19, NULL, 0.0, 0.0, 0, 
355                                          ACTMENU_SEL_BORDER, "");
356         uiDefBut(block, SEPR, 0, "", 0, yco-=6, 
357                          menuwidth, 6, NULL, 0.0, 0.0, 0, 0, "");
358         uiDefIconTextBut(block, BUTM, 1, ICON_BLANK1, 
359                                          "Select/Deselect All Keys|A", 0, yco-=20, 
360                                          menuwidth, 19, NULL, 0.0, 0.0, 0, 
361                                          ACTMENU_SEL_ALL_KEYS, "");
362         uiDefIconTextBut(block, BUTM, 1, ICON_BLANK1, 
363                                          "Select/Deselect All Channels", 0, yco-=20, 
364                                          menuwidth, 19, NULL, 0.0, 0.0, 0, 
365                                          ACTMENU_SEL_ALL_CHAN, "");
366
367         if(curarea->headertype==HEADERTOP) {
368                 uiBlockSetDirection(block, UI_DOWN);
369         }
370         else {
371                 uiBlockSetDirection(block, UI_TOP);
372                 uiBlockFlipOrder(block);
373         }
374
375         uiTextBoundsBlock(block, 50);
376
377         return block;
378 }
379
380 static void do_action_keymenu_transformmenu(void *arg, int event)
381 {
382         SpaceAction *saction;
383         bAction *act;
384         Key *key;
385         
386         key = get_action_mesh_key();
387         saction= curarea->spacedata.first;
388         
389         act=saction->action;
390         
391         switch(event)
392         {
393                 case ACTMENU_KEY_TRANSFORM_MOVE:
394                         if (key) {
395                                 transform_meshchannel_keys('g', key);
396                         } 
397                         else if (act) { 
398                                 transform_actionchannel_keys ('g', 0);
399                         }
400                         break;
401                 case ACTMENU_KEY_TRANSFORM_SCALE:
402                         if (key) {
403                                 transform_meshchannel_keys('s', key);
404                         } 
405                         else if (act) {
406                                 transform_actionchannel_keys ('s', 0);
407                         }
408                         break;
409         }
410
411         scrarea_queue_winredraw(curarea);
412 }
413
414 static uiBlock *action_keymenu_transformmenu(void *arg_unused)
415 {
416         uiBlock *block;
417         short yco= 0, menuwidth=120;
418
419         block= uiNewBlock(&curarea->uiblocks, "action_keymenu_transformmenu", 
420                                           UI_EMBOSSP, UI_HELV, G.curscreen->mainwin);
421         uiBlockSetButmFunc(block, do_action_keymenu_transformmenu, NULL);
422
423         uiDefIconTextBut(block, BUTM, 1, ICON_BLANK1, 
424                                          "Grab/Move|G", 0, yco-=20, 
425                                          menuwidth, 19, NULL, 0.0, 0.0, 0, 
426                                          ACTMENU_KEY_TRANSFORM_MOVE, "");
427         uiDefIconTextBut(block, BUTM, 1, ICON_BLANK1, 
428                                          "Scale|S", 0, yco-=20, 
429                                          menuwidth, 19, NULL, 0.0, 0.0, 0, 
430                                          ACTMENU_KEY_TRANSFORM_SCALE, "");
431
432         uiBlockSetDirection(block, UI_RIGHT);
433         uiTextBoundsBlock(block, 60);
434
435         return block;
436 }
437
438 static void do_action_keymenu_handlemenu(void *arg, int event)
439 {
440         Key *key;
441         
442         key = get_action_mesh_key();
443
444         switch (event){
445                 case ACTMENU_KEY_HANDLE_AUTO:
446                         if (key) {
447                                 sethandles_meshchannel_keys(HD_AUTO, key);
448                         } else {
449                                 sethandles_actionchannel_keys(HD_AUTO);
450                         }
451                         break;
452
453                 case ACTMENU_KEY_HANDLE_ALIGN:
454                 case ACTMENU_KEY_HANDLE_FREE:
455                         /* OK, this is kinda dumb, need to fix the
456                          * toggle crap in sethandles_ipo_keys() 
457                          */
458                         if (key) {
459                                 sethandles_meshchannel_keys(HD_ALIGN, key);
460                         } else {
461                                 sethandles_actionchannel_keys(HD_ALIGN);
462                         }
463                         break;
464
465                 case ACTMENU_KEY_HANDLE_VECTOR:
466                         if (key) {
467                                 sethandles_meshchannel_keys(HD_VECT, key);
468                         } else {
469                                 sethandles_actionchannel_keys(HD_VECT);
470                         }
471                         break;
472         }
473 }
474
475 static uiBlock *action_keymenu_handlemenu(void *arg_unused)
476 {
477         uiBlock *block;
478         short yco= 0, menuwidth=120;
479
480         block= uiNewBlock(&curarea->uiblocks, "action_keymenu_handlemenu", UI_EMBOSSP, UI_HELV, G.curscreen->mainwin);
481         uiBlockSetButmFunc(block, do_action_keymenu_handlemenu, NULL);
482
483         uiDefIconTextBut(block, BUTM, 1, ICON_BLANK1, 
484                                          "Auto|Shift H", 0, yco-=20, 
485                                          menuwidth, 19, NULL, 0.0, 0.0, 0, 
486                                          ACTMENU_KEY_HANDLE_AUTO, "");
487         uiDefIconTextBut(block, BUTM, 1, ICON_BLANK1, 
488                                          "Aligned|H", 0, yco-=20, 
489                                          menuwidth, 19, NULL, 0.0, 0.0, 0, 
490                                          ACTMENU_KEY_HANDLE_ALIGN, "");
491         uiDefIconTextBut(block, BUTM, 1, ICON_BLANK1, 
492                                          "Free|H", 0, yco-=20, menuwidth, 
493                                          19, NULL, 0.0, 0.0, 0, 
494                                          ACTMENU_KEY_HANDLE_FREE, "");
495         uiDefIconTextBut(block, BUTM, 1, ICON_BLANK1, 
496                                          "Vector|V", 0, yco-=20, 
497                                          menuwidth, 19, NULL, 0.0, 0.0, 0, 
498                                          ACTMENU_KEY_HANDLE_VECTOR, "");
499
500         uiBlockSetDirection(block, UI_RIGHT);
501         uiTextBoundsBlock(block, 60);
502
503         return block;
504 }
505
506 static void do_action_keymenu_intpolmenu(void *arg, int event)
507 {
508         Key *key;
509
510         key = get_action_mesh_key();
511
512         switch(event)
513         {
514                 case ACTMENU_KEY_INTERP_CONST:
515                         if (key) {
516                                 /* to do */
517                         }
518                         else {
519                                 set_ipotype_actionchannels(SET_IPO_CONSTANT);
520                         }
521                         break;
522                 case ACTMENU_KEY_INTERP_LINEAR:
523                         if (key) {
524                                 /* to do */
525                         }
526                         else {
527                                 set_ipotype_actionchannels(SET_IPO_LINEAR);
528                         }
529                         break;
530                 case ACTMENU_KEY_INTERP_BEZIER:
531                         if (key) {
532                                 /* to do */
533                         }
534                         else {
535                                 set_ipotype_actionchannels(SET_IPO_BEZIER);
536                         }
537                         break;
538         }
539
540         scrarea_queue_winredraw(curarea);
541 }
542
543 static uiBlock *action_keymenu_intpolmenu(void *arg_unused)
544 {
545         uiBlock *block;
546         short yco= 0, menuwidth=120;
547
548         block= uiNewBlock(&curarea->uiblocks, "action_keymenu_intpolmenu", 
549                                           UI_EMBOSSP, UI_HELV, G.curscreen->mainwin);
550         uiBlockSetButmFunc(block, do_action_keymenu_intpolmenu, NULL);
551
552         uiDefIconTextBut(block, BUTM, 1, ICON_BLANK1, 
553                                          "Constant", 0, yco-=20, 
554                                          menuwidth, 19, NULL, 0.0, 0.0, 0, 
555                                          ACTMENU_KEY_INTERP_CONST, "");
556         uiDefIconTextBut(block, BUTM, 1, ICON_BLANK1, 
557                                          "Linear", 0, yco-=20, 
558                                          menuwidth, 19, NULL, 0.0, 0.0, 0, 
559                                          ACTMENU_KEY_INTERP_LINEAR, "");
560         uiDefIconTextBut(block, BUTM, 1, ICON_BLANK1, 
561                                          "Bezier", 0, yco-=20, 
562                                          menuwidth, 19, NULL, 0.0, 0.0, 0, 
563                                          ACTMENU_KEY_INTERP_BEZIER, "");
564
565         uiBlockSetDirection(block, UI_RIGHT);
566         uiTextBoundsBlock(block, 60);
567
568         return block;
569 }
570
571 static void do_action_keymenu(void *arg, int event)
572 {       
573         SpaceAction *saction;
574         bAction *act;
575         Key *key;
576         
577         saction= curarea->spacedata.first;
578         if (!saction)
579                 return;
580
581         act = saction->action;
582         key = get_action_mesh_key();
583
584         switch(event)
585         {
586                 case ACTMENU_KEY_DUPLICATE:
587                         if (key) {
588                                 duplicate_meshchannel_keys(key);
589                         }
590                         else if (act) {
591                                 duplicate_actionchannel_keys();
592                                 remake_action_ipos(act);
593                         }
594                         break;
595
596                 case ACTMENU_KEY_DELETE:
597                         if (key) {
598                                 delete_meshchannel_keys(key);
599                         }
600                         else if (act) {
601                                 delete_actionchannel_keys ();
602                         }
603                         break;
604                 case ACTMENU_KEY_BAKE:
605                         bake_action_with_client (G.saction->action, OBACT, 0.01);
606                         break;
607         }
608 }
609
610 static uiBlock *action_keymenu(void *arg_unused)
611 {
612         uiBlock *block;
613         short yco= 0, menuwidth=120;
614
615         block= uiNewBlock(&curarea->uiblocks, "action_keymenu", 
616                                           UI_EMBOSSP, UI_HELV, curarea->headwin);
617         uiBlockSetButmFunc(block, do_action_keymenu, NULL);
618         
619         uiDefIconTextBlockBut(block, action_keymenu_transformmenu, 
620                                         NULL, ICON_RIGHTARROW_THIN, 
621                                         "Transform", 0, yco-=20, 120, 20, "");
622                                                   
623         uiDefBut(block, SEPR, 0, "", 0, yco-=6, 
624                                         menuwidth, 6, NULL, 0.0, 0.0, 0, 0, "");
625
626         uiDefIconTextBut(block, BUTM, 1, ICON_BLANK1, 
627                                         "Duplicate|Shift D", 0, yco-=20, 
628                                         menuwidth, 19, NULL, 0.0, 0.0, 0, 
629                                         ACTMENU_KEY_DUPLICATE, "");
630         uiDefIconTextBut(block, BUTM, 1, ICON_BLANK1, 
631                                         "Delete|X", 0, yco-=20, 
632                                         menuwidth, 19, NULL, 0.0, 0.0, 0, 
633                                         ACTMENU_KEY_DELETE, "");
634
635         uiDefBut(block, SEPR, 0, "", 0, yco-=6, 
636                          menuwidth, 6, NULL, 0.0, 0.0, 0, 0, "");
637
638         uiDefIconTextBut(block, BUTM, 1, ICON_BLANK1, 
639                                          "Bake Action to Ipo Keys", 0, yco-=20, 
640                                          menuwidth, 19, NULL, 0.0, 0.0, 0, 
641                                          ACTMENU_KEY_BAKE, "");
642
643         uiDefBut(block, SEPR, 0, "", 0, yco-=6, 
644                          menuwidth, 6, NULL, 0.0, 0.0, 0, 0, "");
645
646         uiDefIconTextBlockBut(block, action_keymenu_intpolmenu, 
647                                                   NULL, ICON_RIGHTARROW_THIN, 
648                                                   "Interpolation Mode", 0, yco-=20, 120, 20, "");
649         uiDefIconTextBlockBut(block, action_keymenu_handlemenu, 
650                                                   NULL, ICON_RIGHTARROW_THIN, 
651                                                   "Handle Type", 0, yco-=20, 120, 20, "");
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 void action_buttons(void)
667 {
668         uiBlock *block;
669         short xco, xmax;
670         char naam[256];
671         Object *ob;
672         ID *from;
673
674         if (!G.saction)
675                 return;
676
677         // copy from drawactionspace....
678         if (!G.saction->pin) {
679                 if (OBACT)
680                         G.saction->action = OBACT->action;
681                 else
682                         G.saction->action=NULL;
683         }
684
685         sprintf(naam, "header %d", curarea->headwin);
686         block= uiNewBlock(&curarea->uiblocks, naam, 
687                                           UI_EMBOSS, UI_HELV, curarea->headwin);
688
689         if (area_is_active_area(curarea)) 
690                 uiBlockSetCol(block, TH_HEADER);
691         else 
692                 uiBlockSetCol(block, TH_HEADERDESEL);
693
694         curarea->butspacetype= SPACE_ACTION;
695         
696         xco = 8;
697         
698         uiDefIconTextButC(block, ICONTEXTROW,B_NEWSPACE, ICON_VIEW3D, 
699                                           windowtype_pup(), xco, 0, XIC+10, YIC, 
700                                           &(curarea->butspacetype), 1.0, SPACEICONMAX, 0, 0, 
701                                           "Displays Current Window Type. "
702                                           "Click for menu of available types.");
703
704         xco += XIC + 14;
705
706         uiBlockSetEmboss(block, UI_EMBOSSN);
707         if (curarea->flag & HEADER_NO_PULLDOWN) {
708                 uiDefIconButBitS(block, TOG, HEADER_NO_PULLDOWN, B_FLIPINFOMENU, 
709                                           ICON_DISCLOSURE_TRI_RIGHT,
710                                           xco,2,XIC,YIC-2,
711                                           &(curarea->flag), 0, 0, 0, 0, 
712                                           "Show pulldown menus");
713         }
714         else {
715                 uiDefIconButBitS(block, TOG, HEADER_NO_PULLDOWN, B_FLIPINFOMENU, 
716                                           ICON_DISCLOSURE_TRI_DOWN,
717                                           xco,2,XIC,YIC-2,
718                                           &(curarea->flag), 0, 0, 0, 0, 
719                                           "Hide pulldown menus");
720         }
721         uiBlockSetEmboss(block, UI_EMBOSS);
722         xco+=XIC;
723
724         if((curarea->flag & HEADER_NO_PULLDOWN)==0) {
725                 /* pull down menus */
726                 uiBlockSetEmboss(block, UI_EMBOSSP);
727         
728                 xmax= GetButStringLength("View");
729                 uiDefPulldownBut(block, action_viewmenu, NULL, 
730                                           "View", xco, -2, xmax-3, 24, "");
731                 xco+= xmax;
732                 
733                 xmax= GetButStringLength("Select");
734                 uiDefPulldownBut(block, action_selectmenu, NULL, 
735                                           "Select", xco, -2, xmax-3, 24, "");
736                 xco+= xmax;
737         
738                 xmax= GetButStringLength("Key");
739                 uiDefPulldownBut(block, action_keymenu, NULL, 
740                                           "Key", xco, -2, xmax-3, 24, "");
741                 xco+= xmax;
742         }
743
744         uiBlockSetEmboss(block, UI_EMBOSS);
745         
746         /* NAME ETC */
747         ob=OBACT;
748         from = (ID*) ob;
749
750         xco= std_libbuttons(block, xco, 0, B_ACTPIN, &G.saction->pin, 
751                                                 B_ACTIONBROWSE, (ID*)G.saction->action, 
752                                                 from, &(G.saction->actnr), B_ACTALONE, 
753                                                 B_ACTLOCAL, B_ACTIONDELETE, 0, 0);      
754
755         /* Draw action baker */
756         xco+= 8;
757         
758         uiDefBut(block, BUT, B_ACTBAKE, 
759                          "Bake", xco, 0, 64, YIC, 0, 0, 0, 0, 0, 
760                          "Create an action with the constraint effects "
761                          "converted into Ipo keys");
762         xco+=64;
763
764         uiClearButLock();
765
766         /* draw LOCK */
767         xco+= 8;
768         uiDefIconButS(block, ICONTOG, 1, ICON_UNLOCKED, xco, 0, XIC, YIC, 
769                                   &(G.saction->lock), 0, 0, 0, 0, 
770                                   "Updates other affected window spaces automatically "
771                                   "to reflect changes in real time");
772
773
774         /* always as last  */
775         curarea->headbutlen = xco + 2*XIC;
776
777         uiDrawBlock(block);
778 }