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