2.5 - Action Editor / Animation Stuff:
[blender-staging.git] / source / blender / editors / space_action / action_header.c
1 /**
2  * $Id$
3  *
4  * ***** BEGIN GPL LICENSE BLOCK *****
5  *
6  * This program is free software; you can redistribute it and/or
7  * modify it under the terms of the GNU General Public License
8  * as published by the Free Software Foundation; either version 2
9  * of the License, or (at your option) any later version. 
10  *
11  * This program is distributed in the hope that it will be useful,
12  * but WITHOUT ANY WARRANTY; without even the implied warranty of
13  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14  * GNU General Public License for more details.
15  *
16  * You should have received a copy of the GNU General Public License
17  * along with this program; if not, write to the Free Software Foundation,
18  * Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
19  *
20  * The Original Code is Copyright (C) 2008 Blender Foundation.
21  * All rights reserved.
22  *
23  * 
24  * Contributor(s): Blender Foundation
25  *
26  * ***** END GPL LICENSE BLOCK *****
27  */
28
29 #include <string.h>
30 #include <stdio.h>
31
32 #include "DNA_action_types.h"
33 #include "DNA_space_types.h"
34 #include "DNA_scene_types.h"
35 #include "DNA_screen_types.h"
36 #include "DNA_windowmanager_types.h"
37
38 #include "MEM_guardedalloc.h"
39
40 #include "BLI_blenlib.h"
41
42 #include "BKE_context.h"
43 #include "BKE_screen.h"
44
45 #include "ED_anim_api.h"
46 #include "ED_screen.h"
47 #include "ED_types.h"
48 #include "ED_util.h"
49
50 #include "WM_api.h"
51 #include "WM_types.h"
52
53 #include "BIF_gl.h"
54 #include "BIF_glutil.h"
55
56 #include "UI_interface.h"
57 #include "UI_resources.h"
58 #include "UI_view2d.h"
59
60 #include "action_intern.h"
61
62 /* ********************************************************* */
63 /* Menu Defines... */
64
65 /* button events */
66 enum {
67         B_REDR  = 0,
68         B_ACTCOPYKEYS,
69         B_ACTPASTEKEYS,
70 } eActHeader_ButEvents;
71
72 /* ------------------------------- */
73 /* enums declaring constants that are used as menu event codes  */
74
75 enum {
76         ACTMENU_VIEW_CENTERVIEW= 0,
77         ACTMENU_VIEW_AUTOUPDATE,
78         ACTMENU_VIEW_PLAY3D,
79         ACTMENU_VIEW_PLAYALL,
80         ACTMENU_VIEW_ALL,
81         ACTMENU_VIEW_MAXIMIZE,
82         ACTMENU_VIEW_LOCK,
83         ACTMENU_VIEW_SLIDERS,
84         ACTMENU_VIEW_NEXTMARKER,
85         ACTMENU_VIEW_PREVMARKER,
86         ACTMENU_VIEW_NEXTKEYFRAME,
87         ACTMENU_VIEW_PREVKEYFRAME,
88         ACTMENU_VIEW_TIME,
89         ACTMENU_VIEW_NOHIDE,
90         ACTMENU_VIEW_FRANUM,
91         ACTMENU_VIEW_TRANSDELDUPS,
92         ACTMENU_VIEW_HORIZOPTIMISE,
93         ACTMENU_VIEW_GCOLORS,
94         ACTMENU_VIEW_PREVRANGESET,
95         ACTMENU_VIEW_PREVRANGECLEAR,
96         ACTMENU_VIEW_PREVRANGEAUTO
97 };
98
99 enum {
100         ACTMENU_SEL_BORDER = 0,
101         ACTMENU_SEL_BORDERC,
102         ACTMENU_SEL_BORDERM,
103         ACTMENU_SEL_ALL_KEYS,
104         ACTMENU_SEL_ALL_CHAN,
105         ACTMENU_SEL_ALL_MARKERS,
106         ACTMENU_SEL_INVERSE_KEYS,
107         ACTMENU_SEL_INVERSE_MARKERS,
108         ACTMENU_SEL_INVERSE_CHANNELS,
109         ACTMENU_SEL_LEFTKEYS,
110         ACTMENU_SEL_RIGHTKEYS
111 };
112
113 enum {
114         ACTMENU_SEL_COLUMN_KEYS = 1,
115         ACTMENU_SEL_COLUMN_CFRA,
116         ACTMENU_SEL_COLUMN_MARKERSCOLUMN,
117         ACTMENU_SEL_COLUMN_MARKERSBETWEEN 
118 };
119
120 enum {
121         ACTMENU_CHANNELS_OPENLEVELS = 0,
122         ACTMENU_CHANNELS_CLOSELEVELS,
123         ACTMENU_CHANNELS_EXPANDALL,
124         ACTMENU_CHANNELS_SHOWACHANS,
125         ACTMENU_CHANNELS_DELETE
126 };
127
128 enum {
129         ACTMENU_CHANNELS_CHANPOS_MOVE_CHANNEL_UP        = 0,
130         ACTMENU_CHANNELS_CHANPOS_MOVE_CHANNEL_DOWN,
131         ACTMENU_CHANNELS_CHANPOS_MOVE_CHANNEL_TOP,
132         ACTMENU_CHANNELS_CHANPOS_MOVE_CHANNEL_BOTTOM
133 };
134
135 enum {
136         ACTMENU_CHANNELS_GROUP_ADD_TOACTIVE     = 0,
137         ACTMENU_CHANNELS_GROUP_ADD_TONEW,
138         ACTMENU_CHANNELS_GROUP_REMOVE,
139         ACTMENU_CHANNELS_GROUP_SYNCPOSE
140 };
141
142 enum {
143         ACTMENU_CHANNELS_SETTINGS_TOGGLE = 0,
144         ACTMENU_CHANNELS_SETTINGS_ENABLE,
145         ACTMENU_CHANNELS_SETTINGS_DISABLE,
146 };
147
148 enum {
149         ACTMENU_KEY_DUPLICATE = 0,
150         ACTMENU_KEY_DELETE,
151         ACTMENU_KEY_CLEAN,
152         ACTMENU_KEY_SAMPLEKEYS,
153         ACTMENU_KEY_INSERTKEY
154 };
155
156 enum {
157         ACTMENU_KEY_TRANSFORM_MOVE  = 0,
158         ACTMENU_KEY_TRANSFORM_SCALE,
159         ACTMENU_KEY_TRANSFORM_SLIDE,
160         ACTMENU_KEY_TRANSFORM_EXTEND
161 };
162
163 enum {
164         ACTMENU_KEY_HANDLE_AUTO = 0,
165         ACTMENU_KEY_HANDLE_ALIGN,
166         ACTMENU_KEY_HANDLE_FREE,
167         ACTMENU_KEY_HANDLE_VECTOR
168 };
169
170 enum {
171         ACTMENU_KEY_INTERP_CONST = 0,
172         ACTMENU_KEY_INTERP_LINEAR,
173         ACTMENU_KEY_INTERP_BEZIER
174 };
175
176 enum {
177         ACTMENU_KEY_EXTEND_CONST = 0,
178         ACTMENU_KEY_EXTEND_EXTRAPOLATION,
179         ACTMENU_KEY_EXTEND_CYCLIC,
180         ACTMENU_KEY_EXTEND_CYCLICEXTRAPOLATION
181 };
182
183 enum {
184         ACTMENU_KEY_SNAP_NEARFRAME = 1,
185         ACTMENU_KEY_SNAP_CURFRAME,
186         ACTMENU_KEY_SNAP_NEARMARK,
187         ACTMENU_KEY_SNAP_NEARTIME,
188         ACTMENU_KEY_SNAP_CFRA2KEY,
189 };
190
191 enum {
192         ACTMENU_KEY_MIRROR_CURFRAME = 1,
193         ACTMENU_KEY_MIRROR_YAXIS,
194         ACTMENU_KEY_MIRROR_XAXIS,
195         ACTMENU_KEY_MIRROR_MARKER
196 };
197
198 enum {
199         ACTMENU_MARKERS_ADD = 0,
200         ACTMENU_MARKERS_DUPLICATE,
201         ACTMENU_MARKERS_DELETE,
202         ACTMENU_MARKERS_NAME,
203         ACTMENU_MARKERS_MOVE,
204         ACTMENU_MARKERS_LOCALADD,
205         ACTMENU_MARKERS_LOCALRENAME,
206         ACTMENU_MARKERS_LOCALDELETE,
207         ACTMENU_MARKERS_LOCALMOVE
208 };
209
210 /* ------------------------------- */
211 /* macros for easier state testing (only for use here) */
212
213 /* test if active action editor is showing any markers */
214 #if 0
215         #define G_SACTION_HASMARKERS \
216                 ((G.saction->action && G.saction->action->markers.first) \
217                  || (G.scene->markers.first))
218 #endif
219
220 /* ------------------------------- */
221
222 /* *************************************************************** */
223 /* menus */
224
225 /* Key menu ---------------------------  */
226
227 static void do_keymenu(bContext *C, void *arg, int event)
228 {
229         
230 }
231
232 static uiBlock *action_keymenu(bContext *C, uiMenuBlockHandle *handle, void *arg_unused)
233 {
234         ScrArea *curarea= CTX_wm_area(C);
235         uiBlock *block;
236         short yco= 0, menuwidth=120;
237         
238         block= uiBeginBlock(C, handle->region, "dummy_keymenu", UI_EMBOSSP, UI_HELV);
239         uiBlockSetButmFunc(block, do_keymenu, NULL);
240         
241         uiDefIconTextBut(block, BUTM, 1, ICON_BLANK1, "Nothing yet", 0, yco-=20, 
242                                          menuwidth, 19, NULL, 0.0, 0.0, 1, 3, "");
243         
244         if(curarea->headertype==HEADERTOP) {
245                 uiBlockSetDirection(block, UI_DOWN);
246         }
247         else {
248                 uiBlockSetDirection(block, UI_TOP);
249                 uiBlockFlipOrder(block);
250         }
251         
252         uiTextBoundsBlock(block, 50);
253         uiEndBlock(C, block);
254         
255         return block;
256 }
257
258 /* Frame menu ---------------------------  */
259
260 static void do_framemenu(bContext *C, void *arg, int event)
261 {
262         
263 }
264
265 static uiBlock *action_framemenu(bContext *C, uiMenuBlockHandle *handle, void *arg_unused)
266 {
267         ScrArea *curarea= CTX_wm_area(C);
268         uiBlock *block;
269         short yco= 0, menuwidth=120;
270         
271         block= uiBeginBlock(C, handle->region, "dummy_framemenu", UI_EMBOSSP, UI_HELV);
272         uiBlockSetButmFunc(block, do_framemenu, NULL);
273         
274         uiDefIconTextBut(block, BUTM, 1, ICON_BLANK1, "Nothing yet", 0, yco-=20, 
275                                          menuwidth, 19, NULL, 0.0, 0.0, 1, 3, "");
276         
277         if(curarea->headertype==HEADERTOP) {
278                 uiBlockSetDirection(block, UI_DOWN);
279         }
280         else {
281                 uiBlockSetDirection(block, UI_TOP);
282                 uiBlockFlipOrder(block);
283         }
284         
285         uiTextBoundsBlock(block, 50);
286         uiEndBlock(C, block);
287         
288         return block;
289 }
290
291 /* Marker menu ---------------------------  */
292
293 static void do_markermenu(bContext *C, void *arg, int event)
294 {
295         
296 }
297
298 static uiBlock *action_markermenu(bContext *C, uiMenuBlockHandle *handle, void *arg_unused)
299 {
300         ScrArea *curarea= CTX_wm_area(C);
301         uiBlock *block;
302         short yco= 0, menuwidth=120;
303         
304         block= uiBeginBlock(C, handle->region, "dummy_markermenu", UI_EMBOSSP, UI_HELV);
305         uiBlockSetButmFunc(block, do_markermenu, NULL);
306         
307         uiDefIconTextBut(block, BUTM, 1, ICON_BLANK1, "Nothing yet", 0, yco-=20, 
308                                          menuwidth, 19, NULL, 0.0, 0.0, 1, 3, "");
309         
310         if(curarea->headertype==HEADERTOP) {
311                 uiBlockSetDirection(block, UI_DOWN);
312         }
313         else {
314                 uiBlockSetDirection(block, UI_TOP);
315                 uiBlockFlipOrder(block);
316         }
317         
318         uiTextBoundsBlock(block, 50);
319         uiEndBlock(C, block);
320         
321         return block;
322 }
323
324 /* Grease Pencil ---------------------------  */
325
326 static void do_gplayermenu(bContext *C, void *arg, int event)
327 {
328         
329 }
330
331 static uiBlock *action_gplayermenu(bContext *C, uiMenuBlockHandle *handle, void *arg_unused)
332 {
333         ScrArea *curarea= CTX_wm_area(C);
334         uiBlock *block;
335         short yco= 0, menuwidth=120;
336         
337         block= uiBeginBlock(C, handle->region, "dummy_gplayermenu", UI_EMBOSSP, UI_HELV);
338         uiBlockSetButmFunc(block, do_gplayermenu, NULL);
339         
340         uiDefIconTextBut(block, BUTM, 1, ICON_BLANK1, "Nothing yet", 0, yco-=20, 
341                                          menuwidth, 19, NULL, 0.0, 0.0, 1, 3, "");
342         
343         if(curarea->headertype==HEADERTOP) {
344                 uiBlockSetDirection(block, UI_DOWN);
345         }
346         else {
347                 uiBlockSetDirection(block, UI_TOP);
348                 uiBlockFlipOrder(block);
349         }
350         
351         uiTextBoundsBlock(block, 50);
352         uiEndBlock(C, block);
353         
354         return block;
355 }
356
357 /* Channel menu ---------------------------  */
358
359 static void do_channelmenu(bContext *C, void *arg, int event)
360 {
361         
362 }
363
364 static uiBlock *action_channelmenu(bContext *C, uiMenuBlockHandle *handle, void *arg_unused)
365 {
366         ScrArea *curarea= CTX_wm_area(C);
367         uiBlock *block;
368         short yco= 0, menuwidth=120;
369         
370         block= uiBeginBlock(C, handle->region, "dummy_channelmenu", UI_EMBOSSP, UI_HELV);
371         uiBlockSetButmFunc(block, do_channelmenu, NULL);
372         
373         uiDefIconTextBut(block, BUTM, 1, ICON_BLANK1, "Nothing yet", 0, yco-=20, 
374                                          menuwidth, 19, NULL, 0.0, 0.0, 1, 3, "");
375         
376         if(curarea->headertype==HEADERTOP) {
377                 uiBlockSetDirection(block, UI_DOWN);
378         }
379         else {
380                 uiBlockSetDirection(block, UI_TOP);
381                 uiBlockFlipOrder(block);
382         }
383         
384         uiTextBoundsBlock(block, 50);
385         uiEndBlock(C, block);
386         
387         return block;
388 }
389
390 /* Select menu ---------------------------  */
391
392 static void do_selectmenu(bContext *C, void *arg, int event)
393 {
394         
395 }
396
397 static uiBlock *action_selectmenu(bContext *C, uiMenuBlockHandle *handle, void *arg_unused)
398 {
399         ScrArea *curarea= CTX_wm_area(C);
400         uiBlock *block;
401         short yco= 0, menuwidth=120;
402         
403         block= uiBeginBlock(C, handle->region, "dummy_selectmenu", UI_EMBOSSP, UI_HELV);
404         uiBlockSetButmFunc(block, do_selectmenu, NULL);
405         
406         uiDefIconTextBut(block, BUTM, 1, ICON_BLANK1, "Nothing yet", 0, yco-=20, 
407                                          menuwidth, 19, NULL, 0.0, 0.0, 1, 3, "");
408         
409         if(curarea->headertype==HEADERTOP) {
410                 uiBlockSetDirection(block, UI_DOWN);
411         }
412         else {
413                 uiBlockSetDirection(block, UI_TOP);
414                 uiBlockFlipOrder(block);
415         }
416         
417         uiTextBoundsBlock(block, 50);
418         uiEndBlock(C, block);
419         
420         return block;
421 }
422
423 /* View menu ---------------------------  */
424
425 static void do_viewmenu(bContext *C, void *arg, int event)
426 {
427         
428 }
429
430 static uiBlock *action_viewmenu(bContext *C, uiMenuBlockHandle *handle, void *arg_unused)
431 {
432         ScrArea *curarea= CTX_wm_area(C);
433         uiBlock *block;
434         short yco= 0, menuwidth=120;
435         
436         block= uiBeginBlock(C, handle->region, "dummy_viewmenu", UI_EMBOSSP, UI_HELV);
437         uiBlockSetButmFunc(block, do_viewmenu, NULL);
438         
439         uiDefIconTextBut(block, BUTM, 1, ICON_BLANK1, "Nothing yet", 0, yco-=20, 
440                                          menuwidth, 19, NULL, 0.0, 0.0, 1, 3, "");
441         
442         if (curarea->headertype==HEADERTOP) {
443                 uiBlockSetDirection(block, UI_DOWN);
444         }
445         else {
446                 uiBlockSetDirection(block, UI_TOP);
447                 uiBlockFlipOrder(block);
448         }
449         
450         uiTextBoundsBlock(block, 50);
451         uiEndBlock(C, block);
452         
453         return block;
454 }
455
456 /* ************************ header area region *********************** */
457
458 static void do_action_buttons(bContext *C, void *arg, int event)
459 {
460         switch(event) {
461                 case B_REDR:
462                         ED_region_tag_redraw(CTX_wm_region(C));
463                         break;
464         }
465 }
466
467 void action_header_buttons(const bContext *C, ARegion *ar)
468 {
469         ScrArea *sa= CTX_wm_area(C);
470         SpaceAction *saction= (SpaceAction *)CTX_wm_space_data(C);
471         bAnimContext ac;
472         uiBlock *block;
473         int xco, yco= 3, xmax;
474         
475         block= uiBeginBlock(C, ar, "header buttons", UI_EMBOSS, UI_HELV);
476         uiBlockSetHandleFunc(block, do_action_buttons, NULL);
477         
478         xco= ED_area_header_standardbuttons(C, block, yco);
479         
480         uiBlockSetEmboss(block, UI_EMBOSS);
481         
482         /* get context... (also syncs data) */
483         ANIM_animdata_get_context(C, &ac);
484         
485         if ((sa->flag & HEADER_NO_PULLDOWN)==0) {
486                 /* pull down menus */
487                 uiBlockSetEmboss(block, UI_EMBOSSP);
488                 
489                 xmax= GetButStringLength("View");
490                 uiDefPulldownBut(block, action_viewmenu, CTX_wm_area(C), 
491                                           "View", xco, yco, xmax-3, 24, "");
492                 xco+= xmax;
493                 
494                 xmax= GetButStringLength("Select");
495                 uiDefPulldownBut(block, action_selectmenu, CTX_wm_area(C), 
496                                           "Select", xco, yco, xmax-3, 24, "");
497                 xco+= xmax;
498                 
499                 if ( (saction->mode == SACTCONT_DOPESHEET) ||
500                          ((saction->action) && (saction->mode==SACTCONT_ACTION)) ) 
501                 {
502                         xmax= GetButStringLength("Channel");
503                         uiDefPulldownBut(block, action_channelmenu, CTX_wm_area(C), 
504                                                   "Channel", xco, yco, xmax-3, 24, "");
505                         xco+= xmax;
506                 }
507                 else if (saction->mode==SACTCONT_GPENCIL) {
508                         xmax= GetButStringLength("Channel");
509                         uiDefPulldownBut(block, action_gplayermenu, CTX_wm_area(C), 
510                                                   "Channel", xco, yco, xmax-3, 24, "");
511                         xco+= xmax;
512                 }
513                 
514                 xmax= GetButStringLength("Marker");
515                 uiDefPulldownBut(block, action_markermenu, CTX_wm_area(C), 
516                                           "Marker", xco, yco, xmax-3, 24, "");
517                 xco+= xmax;
518                 
519                 if (saction->mode == SACTCONT_GPENCIL) {
520                         xmax= GetButStringLength("Frame");
521                         uiDefPulldownBut(block, action_framemenu, CTX_wm_area(C), 
522                                                   "Frame", xco, yco, xmax-3, 24, "");
523                         xco+= xmax;
524                 }
525                 else {
526                         xmax= GetButStringLength("Key");
527                         uiDefPulldownBut(block, action_keymenu, CTX_wm_area(C), 
528                                                   "Key", xco, yco, xmax-3, 24, "");
529                         xco+= xmax;
530                 }
531         }
532
533         uiBlockSetEmboss(block, UI_EMBOSS);
534         
535         /* MODE SELECTOR */
536         uiDefButC(block, MENU, B_REDR, 
537                         "Editor Mode %t|DopeSheet %x3|Action Editor %x0|ShapeKey Editor %x1|Grease Pencil %x2", 
538                         xco,yco,90,YIC, &saction->mode, 0, 1, 0, 0, 
539                         "Editing modes for this editor");
540         
541         
542         xco += (90 + 8);
543         
544         if (ac.data) {
545                 /* MODE-DEPENDENT DRAWING */
546                 if (saction->mode == SACTCONT_DOPESHEET) {
547                         /* FILTERING OPTIONS */
548                         xco -= 10;
549                         
550                         //uiBlockBeginAlign(block);
551                                 uiDefIconButBitI(block, TOG, ADS_FILTER_ONLYSEL, B_REDR, ICON_RESTRICT_SELECT_OFF,      (short)(xco+=XIC),yco,XIC,YIC, &(saction->ads.filterflag), 0, 0, 0, 0, "Only display selected Objects");
552                         //uiBlockEndAlign(block);
553                         xco += 5;
554                         
555                         uiBlockBeginAlign(block);
556                                 uiDefIconButBitI(block, TOGN, ADS_FILTER_NOOBJ, B_REDR, ICON_OBJECT,    (short)(xco+=XIC),yco,XIC,YIC, &(saction->ads.filterflag), 0, 0, 0, 0, "Display Non-Armature Objects");
557                                 uiDefIconButBitI(block, TOGN, ADS_FILTER_NOARM, B_REDR, ICON_ARMATURE,  (short)(xco+=XIC),yco,XIC,YIC, &(saction->ads.filterflag), 0, 0, 0, 0, "Display Armature Objects");
558                                 uiDefIconButBitI(block, TOGN, ADS_FILTER_NOSHAPEKEYS, B_REDR, ICON_EDIT,        (short)(xco+=XIC),yco,XIC,YIC, &(saction->ads.filterflag), 0, 0, 0, 0, "Display ShapeKeys");
559                                 uiDefIconButBitI(block, TOGN, ADS_FILTER_NOMAT, B_REDR, ICON_MATERIAL,  (short)(xco+=XIC),yco,XIC,YIC, &(saction->ads.filterflag), 0, 0, 0, 0, "Display Materials");
560                                 uiDefIconButBitI(block, TOGN, ADS_FILTER_NOLAM, B_REDR, ICON_LAMP,      (short)(xco+=XIC),yco,XIC,YIC, &(saction->ads.filterflag), 0, 0, 0, 0, "Display Lamps");
561                                 uiDefIconButBitI(block, TOGN, ADS_FILTER_NOCAM, B_REDR, ICON_CAMERA,    (short)(xco+=XIC),yco,XIC,YIC, &(saction->ads.filterflag), 0, 0, 0, 0, "Display Cameras");
562                                 uiDefIconButBitI(block, TOGN, ADS_FILTER_NOCUR, B_REDR, ICON_CURVE,     (short)(xco+=XIC),yco,XIC,YIC, &(saction->ads.filterflag), 0, 0, 0, 0, "Display Curves");
563                         uiBlockEndAlign(block);
564                         xco += 5;
565                         
566                         uiBlockBeginAlign(block);               
567                                 uiDefIconButBitI(block, TOGN, ADS_FILTER_NOIPOS, B_REDR, ICON_IPO,      (short)(xco+=XIC),yco,XIC,YIC, &(saction->ads.filterflag), 0, 0, 0, 0, "Display Object IPO's");
568                                 uiDefIconButBitI(block, TOGN, ADS_FILTER_NOACTS, B_REDR, ICON_ACTION,   (short)(xco+=XIC),yco,XIC,YIC, &(saction->ads.filterflag), 0, 0, 0, 0, "Display Actions");
569                                 uiDefIconButBitI(block, TOGN, ADS_FILTER_NOCONSTRAINTS, B_REDR, ICON_CONSTRAINT,        (short)(xco+=XIC),yco,XIC,YIC, &(saction->ads.filterflag), 0, 0, 0, 0, "Display Object Constraints");
570                         uiBlockEndAlign(block);
571                         xco += 30;
572                 }
573                 else if (saction->mode == SACTCONT_ACTION) { // not too appropriate for shapekeys atm...
574                         /* NAME ETC */
575                                 // XXX missing stuff here!
576                         //ob= OBACT;
577                         //from = (ID *)ob;
578                         
579                         //xco= std_libbuttons(block, xco, 0, B_ACTPIN, saction->pin, 
580                         //                                      B_ACTIONBROWSE, ID_AC, 0, (ID*)saction->action, 
581                         //                                      from, &(saction->actnr), B_ACTALONE, 
582                         //                                      B_ACTLOCAL, B_ACTIONDELETE, 0, B_KEEPDATA);     
583                         
584                         //uiClearButLock();
585                         
586                         xco += 8;
587                 }
588                 
589                 /* COPY PASTE */
590                 uiBlockBeginAlign(block);
591                 uiDefIconBut(block, BUT, B_ACTCOPYKEYS, ICON_COPYDOWN,  xco,yco,XIC,YIC, 0, 0, 0, 0, 0, "Copies the selected keyframes from the selected channel(s) to the buffer");
592                 uiDefIconBut(block, BUT, B_ACTPASTEKEYS, ICON_PASTEDOWN,        xco+=XIC,yco,XIC,YIC, 0, 0, 0, 0, 0, "Pastes the keyframes from the buffer");
593                 uiBlockEndAlign(block);
594                 xco += (XIC + 8);
595                 
596                 /* draw AUTOSNAP */
597                 if (saction->mode != SACTCONT_GPENCIL) {
598                         if (saction->flag & SACTION_DRAWTIME) {
599                                 uiDefButC(block, MENU, B_REDR,
600                                                 "Auto-Snap Keyframes %t|No Snap %x0|Second Step %x1|Nearest Second %x2|Nearest Marker %x3", 
601                                                 xco,yco,70,YIC, &(saction->autosnap), 0, 1, 0, 0, 
602                                                 "Auto-snapping mode for keyframes when transforming");
603                         }
604                         else {
605                                 uiDefButC(block, MENU, B_REDR, 
606                                                 "Auto-Snap Keyframes %t|No Snap %x0|Frame Step %x1|Nearest Frame %x2|Nearest Marker %x3", 
607                                                 xco,yco,70,YIC, &(saction->autosnap), 0, 1, 0, 0, 
608                                                 "Auto-snapping mode for keyframes when transforming");
609                         }
610                         
611                         xco += (70 + 8);
612                 }
613                 
614                 /* draw LOCK */
615                 uiDefIconButS(block, ICONTOG, 1, ICON_UNLOCKED, xco, yco, XIC, YIC, 
616                                           &(saction->lock), 0, 0, 0, 0, 
617                                           "Updates other affected window spaces automatically "
618                                           "to reflect changes in real time");
619         }
620
621         /* always as last  */
622         UI_view2d_totRect_set(&ar->v2d, xco+XIC+80, ar->v2d.tot.ymax-ar->v2d.tot.ymin);
623         
624         uiEndBlock(C, block);
625         uiDrawBlock(C, block);
626 }
627
628