397a884e20a9b1a7b080744a32bc146c8b202e36
[blender.git] / source / blender / editors / space_graph / graph_ops.c
1 /*
2  * ***** BEGIN GPL LICENSE BLOCK *****
3  *
4  * This program is free software; you can redistribute it and/or
5  * modify it under the terms of the GNU General Public License
6  * as published by the Free Software Foundation; either version 2
7  * of the License, or (at your option) any later version. 
8  *
9  * This program is distributed in the hope that it will be useful,
10  * but WITHOUT ANY WARRANTY; without even the implied warranty of
11  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
12  * GNU General Public License for more details.
13  *
14  * You should have received a copy of the GNU General Public License
15  * along with this program; if not, write to the Free Software Foundation,
16  * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
17  *
18  * The Original Code is Copyright (C) 2008 Blender Foundation.
19  * All rights reserved.
20  *
21  * 
22  * Contributor(s): Blender Foundation
23  *
24  * ***** END GPL LICENSE BLOCK *****
25  */
26
27 /** \file blender/editors/space_graph/graph_ops.c
28  *  \ingroup spgraph
29  */
30
31
32 #include <stdlib.h>
33 #include <math.h>
34
35 #include "DNA_scene_types.h"
36
37 #include "BLI_blenlib.h"
38 #include "BLI_utildefines.h"
39 #include "BLI_math_base.h"
40
41 #include "BKE_context.h"
42 #include "BKE_global.h"
43 #include "BKE_main.h"
44 #include "BKE_sound.h"
45
46 #include "UI_view2d.h"
47
48 #include "ED_anim_api.h"
49 #include "ED_markers.h"
50 #include "ED_screen.h"
51 #include "ED_transform.h"
52
53 #include "graph_intern.h"
54
55 #include "RNA_access.h"
56 #include "RNA_define.h"
57
58 #include "WM_api.h"
59 #include "WM_types.h"
60
61 /* ************************** view-based operators **********************************/
62 // XXX should these really be here?
63
64 /* Set Cursor --------------------------------------------------------------------- */
65 /* The 'cursor' in the Graph Editor consists of two parts:
66  *      1) Current Frame Indicator (as per ANIM_OT_change_frame)
67  *      2) Value Indicator (stored per Graph Editor instance)
68  */
69
70 static int graphview_cursor_poll(bContext *C)
71 {
72         /* prevent changes during render */
73         if (G.is_rendering)
74                 return 0;
75
76         return ED_operator_graphedit_active(C);
77 }
78
79 /* Set the new frame number */
80 static void graphview_cursor_apply(bContext *C, wmOperator *op)
81 {
82         Main *bmain = CTX_data_main(C);
83         Scene *scene = CTX_data_scene(C);
84         SpaceIpo *sipo = CTX_wm_space_graph(C);
85         float frame = RNA_float_get(op->ptr, "frame"); /* this isn't technically "frame", but it'll do... */
86         
87         /* adjust the frame or the cursor x-value */
88         if (sipo->mode == SIPO_MODE_DRIVERS) {
89                 /* adjust cursor x-value */
90                 sipo->cursorTime = frame;
91         }
92         else {
93                 /* adjust the frame 
94                  * NOTE: sync this part of the code with ANIM_OT_change_frame
95                  */
96                 /* 1) frame is rounded to the nearest int, since frames are ints */
97                 CFRA = iroundf(frame);
98                 
99                 if (scene->r.flag & SCER_LOCK_FRAME_SELECTION) {
100                         /* Clip to preview range
101                          * NOTE: Preview range won't go into negative values,
102                          *       so only clamping once should be fine.
103                          */
104                         CLAMP(CFRA, PSFRA, PEFRA);
105                 }
106                 else {
107                         /* Prevent negative frames */
108                         FRAMENUMBER_MIN_CLAMP(CFRA);
109                 }
110                 
111                 SUBFRA = 0.0f;
112                 BKE_sound_seek_scene(bmain, scene);
113         }
114         
115         /* set the cursor value */
116         sipo->cursorVal = RNA_float_get(op->ptr, "value");
117         
118         /* send notifiers - notifiers for frame should force an update for both vars ok... */
119         WM_event_add_notifier(C, NC_SCENE | ND_FRAME, scene);
120 }
121
122 /* ... */
123
124 /* Non-modal callback for running operator without user input */
125 static int graphview_cursor_exec(bContext *C, wmOperator *op)
126 {
127         graphview_cursor_apply(C, op);
128         return OPERATOR_FINISHED;
129 }
130
131 /* ... */
132
133 /* set the operator properties from the initial event */
134 static void graphview_cursor_setprops(bContext *C, wmOperator *op, const wmEvent *event)
135 {
136         Scene *scene = CTX_data_scene(C);
137         ARegion *ar = CTX_wm_region(C);
138         float viewx, viewy;
139         
140         /* abort if not active region (should not really be possible) */
141         if (ar == NULL)
142                 return;
143         
144         /* convert from region coordinates to View2D 'tot' space */
145         UI_view2d_region_to_view(&ar->v2d, event->mval[0], event->mval[1], &viewx, &viewy);
146         
147         /* store the values in the operator properties */
148         /* NOTE: we don't clamp frame here, as it might be used for the drivers cursor */
149         RNA_float_set(op->ptr, "frame", viewx);
150         RNA_float_set(op->ptr, "value", viewy);
151 }
152
153 /* Modal Operator init */
154 static int graphview_cursor_invoke(bContext *C, wmOperator *op, const wmEvent *event)
155 {
156         bScreen *screen = CTX_wm_screen(C);
157         
158         /* Change to frame that mouse is over before adding modal handler,
159          * as user could click on a single frame (jump to frame) as well as
160          * click-dragging over a range (modal scrubbing). Apply this change.
161          */
162         graphview_cursor_setprops(C, op, event);
163         graphview_cursor_apply(C, op);
164         
165         /* Signal that a scrubbing operating is starting */
166         if (screen)
167                 screen->scrubbing = true;
168         
169         /* add temp handler */
170         WM_event_add_modal_handler(C, op);
171         return OPERATOR_RUNNING_MODAL;
172 }
173
174 /* Modal event handling of cursor changing */
175 static int graphview_cursor_modal(bContext *C, wmOperator *op, const wmEvent *event)
176 {
177         bScreen *screen = CTX_wm_screen(C);
178         Scene *scene = CTX_data_scene(C);
179         
180         /* execute the events */
181         switch (event->type) {
182                 case ESCKEY:
183                         if (screen)
184                                 screen->scrubbing = false;
185                         
186                         WM_event_add_notifier(C, NC_SCENE | ND_FRAME, scene);
187                         return OPERATOR_FINISHED;
188                 
189                 case MOUSEMOVE:
190                         /* set the new values */
191                         graphview_cursor_setprops(C, op, event);
192                         graphview_cursor_apply(C, op);
193                         break;
194                 
195                 case LEFTMOUSE: 
196                 case RIGHTMOUSE:
197                 case MIDDLEMOUSE:
198                         /* we check for either mouse-button to end, as checking for ACTIONMOUSE (which is used to init 
199                          * the modal op) doesn't work for some reason
200                          */
201                         if (event->val == KM_RELEASE) {
202                                 if (screen)
203                                         screen->scrubbing = false;
204                                 
205                                 WM_event_add_notifier(C, NC_SCENE | ND_FRAME, scene);
206                                 return OPERATOR_FINISHED;
207                         }
208                         break;
209         }
210
211         return OPERATOR_RUNNING_MODAL;
212 }
213
214 static void GRAPH_OT_cursor_set(wmOperatorType *ot)
215 {
216         /* identifiers */
217         ot->name = "Set Cursor";
218         ot->idname = "GRAPH_OT_cursor_set";
219         ot->description = "Interactively set the current frame and value cursor";
220         
221         /* api callbacks */
222         ot->exec = graphview_cursor_exec;
223         ot->invoke = graphview_cursor_invoke;
224         ot->modal = graphview_cursor_modal;
225         ot->poll = graphview_cursor_poll;
226         
227         /* flags */
228         ot->flag = OPTYPE_BLOCKING | OPTYPE_UNDO;
229
230         /* rna */
231         RNA_def_float(ot->srna, "frame", 0, MINAFRAMEF, MAXFRAMEF, "Frame", "", MINAFRAMEF, MAXFRAMEF);
232         RNA_def_float(ot->srna, "value", 0, -FLT_MAX, FLT_MAX, "Value", "", -100.0f, 100.0f);
233 }
234
235 /* Hide/Reveal ------------------------------------------------------------ */
236
237 static int graphview_curves_hide_exec(bContext *C, wmOperator *op)
238 {
239         bAnimContext ac;
240         ListBase anim_data = {NULL, NULL};
241         ListBase all_data = {NULL, NULL};
242         bAnimListElem *ale;
243         int filter;
244         const bool unselected = RNA_boolean_get(op->ptr, "unselected");
245         
246         /* get editor data */
247         if (ANIM_animdata_get_context(C, &ac) == 0)
248                 return OPERATOR_CANCELLED;
249                 
250         /* get list of all channels that selection may need to be flushed to 
251          * - hierarchy must not affect what we have access to here...
252          */
253         filter = (ANIMFILTER_DATA_VISIBLE | ANIMFILTER_LIST_CHANNELS | ANIMFILTER_NODUPLIS);
254         ANIM_animdata_filter(&ac, &all_data, filter, ac.data, ac.datatype);
255         
256         /* filter data
257          * - of the remaining visible curves, we want to hide the ones that are 
258          *   selected/unselected (depending on "unselected" prop) 
259          */
260         filter = (ANIMFILTER_DATA_VISIBLE | ANIMFILTER_CURVE_VISIBLE | ANIMFILTER_NODUPLIS);
261         if (unselected)
262                 filter |= ANIMFILTER_UNSEL;
263         else
264                 filter |= ANIMFILTER_SEL;
265         
266         ANIM_animdata_filter(&ac, &anim_data, filter, ac.data, ac.datatype);
267         
268         for (ale = anim_data.first; ale; ale = ale->next) {
269                 /* hack: skip object channels for now, since flushing those will always flush everything, but they are always included */
270                 /* TODO: find out why this is the case, and fix that */
271                 if (ale->type == ANIMTYPE_OBJECT)
272                         continue;
273                 
274                 /* change the hide setting, and unselect it... */
275                 ANIM_channel_setting_set(&ac, ale, ACHANNEL_SETTING_VISIBLE, ACHANNEL_SETFLAG_CLEAR);
276                 ANIM_channel_setting_set(&ac, ale, ACHANNEL_SETTING_SELECT,  ACHANNEL_SETFLAG_CLEAR);
277                 
278                 /* now, also flush selection status up/down as appropriate */
279                 ANIM_flush_setting_anim_channels(&ac, &all_data, ale, ACHANNEL_SETTING_VISIBLE, ACHANNEL_SETFLAG_CLEAR);
280         }
281
282         /* cleanup */
283         ANIM_animdata_freelist(&anim_data);
284         BLI_freelistN(&all_data);
285         
286         /* unhide selected */
287         if (unselected) {
288                 /* turn off requirement for visible */
289                 filter = ANIMFILTER_SEL | ANIMFILTER_NODUPLIS | ANIMFILTER_LIST_CHANNELS;
290
291                 /* flushing has been done */
292                 ANIM_animdata_filter(&ac, &anim_data, filter, ac.data, ac.datatype);
293
294                 for (ale = anim_data.first; ale; ale = ale->next) {
295                         /* hack: skip object channels for now, since flushing those will always flush everything, but they are always included */
296                         /* TODO: find out why this is the case, and fix that */
297                         if (ale->type == ANIMTYPE_OBJECT)
298                                 continue;
299                         
300                         /* change the hide setting, and unselect it... */
301                         ANIM_channel_setting_set(&ac, ale, ACHANNEL_SETTING_VISIBLE, ACHANNEL_SETFLAG_ADD);
302                         ANIM_channel_setting_set(&ac, ale, ACHANNEL_SETTING_SELECT,  ACHANNEL_SETFLAG_ADD);
303                         
304                         /* now, also flush selection status up/down as appropriate */
305                         ANIM_flush_setting_anim_channels(&ac, &anim_data, ale, ACHANNEL_SETTING_VISIBLE, ACHANNEL_SETFLAG_ADD);
306                 }
307                 ANIM_animdata_freelist(&anim_data);     
308         }
309         
310         
311         /* send notifier that things have changed */
312         WM_event_add_notifier(C, NC_ANIMATION | ND_ANIMCHAN | NA_EDITED, NULL);
313         
314         return OPERATOR_FINISHED;
315 }
316
317 static void GRAPH_OT_hide(wmOperatorType *ot)
318 {
319         /* identifiers */
320         ot->name = "Hide Curves";
321         ot->idname = "GRAPH_OT_hide";
322         ot->description = "Hide selected curves from Graph Editor view";
323         
324         /* api callbacks */
325         ot->exec = graphview_curves_hide_exec;
326         ot->poll = ED_operator_graphedit_active;
327         
328         /* flags */
329         ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
330         
331         /* props */
332         RNA_def_boolean(ot->srna, "unselected", 0, "Unselected", "Hide unselected rather than selected curves");
333 }
334
335 /* ........ */
336
337 static int graphview_curves_reveal_exec(bContext *C, wmOperator *UNUSED(op))
338 {
339         bAnimContext ac;
340         ListBase anim_data = {NULL, NULL};
341         ListBase all_data = {NULL, NULL};
342         bAnimListElem *ale;
343         int filter;
344         
345         /* get editor data */
346         if (ANIM_animdata_get_context(C, &ac) == 0)
347                 return OPERATOR_CANCELLED;
348                 
349         /* get list of all channels that selection may need to be flushed to 
350          * - hierarchy must not affect what we have access to here...
351          */
352         filter = (ANIMFILTER_DATA_VISIBLE | ANIMFILTER_LIST_CHANNELS | ANIMFILTER_NODUPLIS);
353         ANIM_animdata_filter(&ac, &all_data, filter, ac.data, ac.datatype);
354         
355         /* filter data
356          * - just go through all visible channels, ensuring that everything is set to be curve-visible
357          */
358         filter = (ANIMFILTER_DATA_VISIBLE | ANIMFILTER_LIST_VISIBLE | ANIMFILTER_NODUPLIS);
359         ANIM_animdata_filter(&ac, &anim_data, filter, ac.data, ac.datatype);
360         
361         for (ale = anim_data.first; ale; ale = ale->next) {
362                 /* hack: skip object channels for now, since flushing those will always flush everything, but they are always included */
363                 /* TODO: find out why this is the case, and fix that */
364                 if (ale->type == ANIMTYPE_OBJECT)
365                         continue;
366                 
367                 /* select if it is not visible */
368                 if (ANIM_channel_setting_get(&ac, ale, ACHANNEL_SETTING_VISIBLE) == 0)
369                         ANIM_channel_setting_set(&ac, ale, ACHANNEL_SETTING_SELECT, ACHANNEL_SETFLAG_ADD);
370                 
371                 /* change the visibility setting */
372                 ANIM_channel_setting_set(&ac, ale, ACHANNEL_SETTING_VISIBLE, ACHANNEL_SETFLAG_ADD);
373                 
374                 /* now, also flush selection status up/down as appropriate */
375                 ANIM_flush_setting_anim_channels(&ac, &all_data, ale, ACHANNEL_SETTING_VISIBLE, true);
376         }
377         
378         /* cleanup */
379         ANIM_animdata_freelist(&anim_data);
380         BLI_freelistN(&all_data);
381         
382         /* send notifier that things have changed */
383         WM_event_add_notifier(C, NC_ANIMATION | ND_ANIMCHAN | NA_EDITED, NULL);
384         
385         return OPERATOR_FINISHED;
386 }
387
388 static void GRAPH_OT_reveal(wmOperatorType *ot)
389 {
390         /* identifiers */
391         ot->name = "Reveal Curves";
392         ot->idname = "GRAPH_OT_reveal";
393         ot->description = "Make previously hidden curves visible again in Graph Editor view";
394         
395         /* api callbacks */
396         ot->exec = graphview_curves_reveal_exec;
397         ot->poll = ED_operator_graphedit_active;
398         
399         /* flags */
400         ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
401 }
402
403 /* ************************** registration - operator types **********************************/
404
405 void graphedit_operatortypes(void)
406 {
407         /* view */
408         WM_operatortype_append(GRAPH_OT_cursor_set);
409         
410         WM_operatortype_append(GRAPH_OT_previewrange_set);
411         WM_operatortype_append(GRAPH_OT_view_all);
412         WM_operatortype_append(GRAPH_OT_view_selected);
413         WM_operatortype_append(GRAPH_OT_properties);
414         WM_operatortype_append(GRAPH_OT_view_frame);
415         
416         WM_operatortype_append(GRAPH_OT_ghost_curves_create);
417         WM_operatortype_append(GRAPH_OT_ghost_curves_clear);
418         
419         WM_operatortype_append(GRAPH_OT_hide);
420         WM_operatortype_append(GRAPH_OT_reveal);
421         
422         /* keyframes */
423         /* selection */
424         WM_operatortype_append(GRAPH_OT_clickselect);
425         WM_operatortype_append(GRAPH_OT_select_all_toggle);
426         WM_operatortype_append(GRAPH_OT_select_border);
427         WM_operatortype_append(GRAPH_OT_select_lasso);
428         WM_operatortype_append(GRAPH_OT_select_circle);
429         WM_operatortype_append(GRAPH_OT_select_column);
430         WM_operatortype_append(GRAPH_OT_select_linked);
431         WM_operatortype_append(GRAPH_OT_select_more);
432         WM_operatortype_append(GRAPH_OT_select_less);
433         WM_operatortype_append(GRAPH_OT_select_leftright);
434         
435         /* editing */
436         WM_operatortype_append(GRAPH_OT_snap);
437         WM_operatortype_append(GRAPH_OT_mirror);
438         WM_operatortype_append(GRAPH_OT_frame_jump);
439         WM_operatortype_append(GRAPH_OT_handle_type);
440         WM_operatortype_append(GRAPH_OT_interpolation_type);
441         WM_operatortype_append(GRAPH_OT_extrapolation_type);
442         WM_operatortype_append(GRAPH_OT_easing_type);
443         WM_operatortype_append(GRAPH_OT_sample);
444         WM_operatortype_append(GRAPH_OT_bake);
445         WM_operatortype_append(GRAPH_OT_sound_bake);
446         WM_operatortype_append(GRAPH_OT_smooth);
447         WM_operatortype_append(GRAPH_OT_clean);
448         WM_operatortype_append(GRAPH_OT_euler_filter);
449         WM_operatortype_append(GRAPH_OT_delete);
450         WM_operatortype_append(GRAPH_OT_duplicate);
451         
452         WM_operatortype_append(GRAPH_OT_copy);
453         WM_operatortype_append(GRAPH_OT_paste);
454         
455         WM_operatortype_append(GRAPH_OT_keyframe_insert);
456         WM_operatortype_append(GRAPH_OT_click_insert);
457         
458         /* F-Curve Modifiers */
459         WM_operatortype_append(GRAPH_OT_fmodifier_add);
460         WM_operatortype_append(GRAPH_OT_fmodifier_copy);
461         WM_operatortype_append(GRAPH_OT_fmodifier_paste);
462 }
463
464 void ED_operatormacros_graph(void)
465 {
466         wmOperatorType *ot;
467         wmOperatorTypeMacro *otmacro;
468         
469         ot = WM_operatortype_append_macro("GRAPH_OT_duplicate_move", "Duplicate",
470                                           "Make a copy of all selected keyframes and move them",
471                                           OPTYPE_UNDO | OPTYPE_REGISTER);
472         WM_operatortype_macro_define(ot, "GRAPH_OT_duplicate");
473         otmacro = WM_operatortype_macro_define(ot, "TRANSFORM_OT_transform");
474         RNA_enum_set(otmacro->ptr, "mode", TFM_TIME_DUPLICATE);
475         RNA_enum_set(otmacro->ptr, "proportional", PROP_EDIT_OFF);
476 }
477
478
479 /* ************************** registration - keymaps **********************************/
480
481 static void graphedit_keymap_keyframes(wmKeyConfig *keyconf, wmKeyMap *keymap)
482 {
483         wmKeyMapItem *kmi;
484         
485         /* view */
486         kmi = WM_keymap_add_item(keymap, "WM_OT_context_toggle", HKEY, KM_PRESS, KM_CTRL, 0);
487         RNA_string_set(kmi->ptr, "data_path", "space_data.show_handles");
488
489         /* NOTE: 'ACTIONMOUSE' not 'LEFTMOUSE', as user may have swapped mouse-buttons
490          * This keymap is supposed to override ANIM_OT_change_frame, which does the same except it doesn't do y-values
491          */
492         WM_keymap_add_item(keymap, "GRAPH_OT_cursor_set", ACTIONMOUSE, KM_PRESS, 0, 0);
493         
494         
495         /* graph_select.c - selection tools */
496         /* click-select: keyframe (replace)  */
497         kmi = WM_keymap_add_item(keymap, "GRAPH_OT_clickselect", SELECTMOUSE, KM_PRESS, 0, 0);
498         RNA_boolean_set(kmi->ptr, "extend", false);
499         RNA_boolean_set(kmi->ptr, "curves", false);
500         RNA_boolean_set(kmi->ptr, "column", false);
501         /* click-select: all keyframes on same frame (replace) */
502         kmi = WM_keymap_add_item(keymap, "GRAPH_OT_clickselect", SELECTMOUSE, KM_PRESS, KM_ALT, 0);
503         RNA_boolean_set(kmi->ptr, "extend", false);
504         RNA_boolean_set(kmi->ptr, "curves", false);
505         RNA_boolean_set(kmi->ptr, "column", true);
506         /* click-select: keyframe (add) */
507         kmi = WM_keymap_add_item(keymap, "GRAPH_OT_clickselect", SELECTMOUSE, KM_PRESS, KM_SHIFT, 0);
508         RNA_boolean_set(kmi->ptr, "extend", true);
509         RNA_boolean_set(kmi->ptr, "curves", false);
510         RNA_boolean_set(kmi->ptr, "column", false);
511         /* click-select: all keyframes on same frame (add) */
512         kmi = WM_keymap_add_item(keymap, "GRAPH_OT_clickselect", SELECTMOUSE, KM_PRESS, KM_ALT | KM_SHIFT, 0);
513         RNA_boolean_set(kmi->ptr, "extend", true);
514         RNA_boolean_set(kmi->ptr, "curves", false);
515         RNA_boolean_set(kmi->ptr, "column", true);
516         /* click-select: all keyframes in same curve (replace) */
517         kmi = WM_keymap_add_item(keymap, "GRAPH_OT_clickselect", SELECTMOUSE, KM_PRESS, KM_CTRL | KM_ALT, 0);
518         RNA_boolean_set(kmi->ptr, "extend", false);
519         RNA_boolean_set(kmi->ptr, "curves", true);
520         RNA_boolean_set(kmi->ptr, "column", false);
521         /* click-select: all keyframes in same curve (add) */
522         kmi = WM_keymap_add_item(keymap, "GRAPH_OT_clickselect", SELECTMOUSE, KM_PRESS, KM_CTRL | KM_ALT | KM_SHIFT, 0);
523         RNA_boolean_set(kmi->ptr, "extend", true);
524         RNA_boolean_set(kmi->ptr, "curves", true);
525         RNA_boolean_set(kmi->ptr, "column", false);
526         
527         /* click-select left/right */
528         kmi = WM_keymap_add_item(keymap, "GRAPH_OT_select_leftright", SELECTMOUSE, KM_PRESS, KM_CTRL, 0);
529         RNA_boolean_set(kmi->ptr, "extend", false);
530         RNA_enum_set(kmi->ptr, "mode", GRAPHKEYS_LRSEL_TEST);
531         kmi = WM_keymap_add_item(keymap, "GRAPH_OT_select_leftright", SELECTMOUSE, KM_PRESS, KM_CTRL | KM_SHIFT, 0);
532         RNA_boolean_set(kmi->ptr, "extend", true);
533         RNA_enum_set(kmi->ptr, "mode", GRAPHKEYS_LRSEL_TEST);
534         
535         kmi = WM_keymap_add_item(keymap, "GRAPH_OT_select_leftright", LEFTBRACKETKEY, KM_PRESS, 0, 0);
536         RNA_boolean_set(kmi->ptr, "extend", false);
537         RNA_enum_set(kmi->ptr, "mode", GRAPHKEYS_LRSEL_LEFT);
538         kmi = WM_keymap_add_item(keymap, "GRAPH_OT_select_leftright", RIGHTBRACKETKEY, KM_PRESS, 0, 0);
539         RNA_boolean_set(kmi->ptr, "extend", false);
540         RNA_enum_set(kmi->ptr, "mode", GRAPHKEYS_LRSEL_RIGHT);
541         
542         /* deselect all */
543         kmi = WM_keymap_add_item(keymap, "GRAPH_OT_select_all_toggle", AKEY, KM_PRESS, 0, 0);
544         RNA_boolean_set(kmi->ptr, "invert", false);
545         kmi = WM_keymap_add_item(keymap, "GRAPH_OT_select_all_toggle", IKEY, KM_PRESS, KM_CTRL, 0);
546         RNA_boolean_set(kmi->ptr, "invert", true);
547         
548         /* borderselect */
549         kmi = WM_keymap_add_item(keymap, "GRAPH_OT_select_border", BKEY, KM_PRESS, 0, 0);
550         RNA_boolean_set(kmi->ptr, "axis_range", false);
551         RNA_boolean_set(kmi->ptr, "include_handles", false);
552         kmi = WM_keymap_add_item(keymap, "GRAPH_OT_select_border", BKEY, KM_PRESS, KM_ALT, 0);
553         RNA_boolean_set(kmi->ptr, "axis_range", true);
554         RNA_boolean_set(kmi->ptr, "include_handles", false);
555                 
556         kmi = WM_keymap_add_item(keymap, "GRAPH_OT_select_border", BKEY, KM_PRESS, KM_CTRL, 0);
557         RNA_boolean_set(kmi->ptr, "axis_range", false);
558         RNA_boolean_set(kmi->ptr, "include_handles", true);
559         kmi = WM_keymap_add_item(keymap, "GRAPH_OT_select_border", BKEY, KM_PRESS, KM_CTRL | KM_ALT, 0);
560         RNA_boolean_set(kmi->ptr, "axis_range", true);
561         RNA_boolean_set(kmi->ptr, "include_handles", true);
562
563         kmi = WM_keymap_add_item(keymap, "GRAPH_OT_select_lasso", EVT_TWEAK_A, KM_ANY, KM_CTRL, 0);
564         RNA_boolean_set(kmi->ptr, "deselect", false);
565         kmi = WM_keymap_add_item(keymap, "GRAPH_OT_select_lasso", EVT_TWEAK_A, KM_ANY, KM_CTRL | KM_SHIFT, 0);
566         RNA_boolean_set(kmi->ptr, "deselect", true);
567
568         WM_keymap_add_item(keymap, "GRAPH_OT_select_circle", CKEY, KM_PRESS, 0, 0);
569         
570         /* column select */
571         RNA_enum_set(WM_keymap_add_item(keymap, "GRAPH_OT_select_column", KKEY, KM_PRESS, 0, 0)->ptr, "mode", GRAPHKEYS_COLUMNSEL_KEYS);
572         RNA_enum_set(WM_keymap_add_item(keymap, "GRAPH_OT_select_column", KKEY, KM_PRESS, KM_CTRL, 0)->ptr, "mode", GRAPHKEYS_COLUMNSEL_CFRA);
573         RNA_enum_set(WM_keymap_add_item(keymap, "GRAPH_OT_select_column", KKEY, KM_PRESS, KM_SHIFT, 0)->ptr, "mode", GRAPHKEYS_COLUMNSEL_MARKERS_COLUMN);
574         RNA_enum_set(WM_keymap_add_item(keymap, "GRAPH_OT_select_column", KKEY, KM_PRESS, KM_ALT, 0)->ptr, "mode", GRAPHKEYS_COLUMNSEL_MARKERS_BETWEEN);
575         
576         /* select more/less */
577         WM_keymap_add_item(keymap, "GRAPH_OT_select_more", PADPLUSKEY, KM_PRESS, KM_CTRL, 0);
578         WM_keymap_add_item(keymap, "GRAPH_OT_select_less", PADMINUS, KM_PRESS, KM_CTRL, 0);
579         
580         /* select linked */
581         WM_keymap_add_item(keymap, "GRAPH_OT_select_linked", LKEY, KM_PRESS, 0, 0);
582         
583         
584         /* graph_edit.c */
585         /* jump to selected keyframes */
586         WM_keymap_add_item(keymap, "GRAPH_OT_frame_jump", GKEY, KM_PRESS, KM_CTRL, 0);
587                 
588         /* menu + single-step transform */
589         WM_keymap_add_item(keymap, "GRAPH_OT_snap", SKEY, KM_PRESS, KM_SHIFT, 0);
590         WM_keymap_add_item(keymap, "GRAPH_OT_mirror", MKEY, KM_PRESS, KM_SHIFT, 0);
591         
592         WM_keymap_add_item(keymap, "GRAPH_OT_handle_type", VKEY, KM_PRESS, 0, 0);
593
594         WM_keymap_add_item(keymap, "GRAPH_OT_interpolation_type", TKEY, KM_PRESS, 0, 0);
595         WM_keymap_add_item(keymap, "GRAPH_OT_easing_type", EKEY, KM_PRESS, KM_CTRL, 0);
596         
597         /* destructive */
598         WM_keymap_add_item(keymap, "GRAPH_OT_smooth", OKEY, KM_PRESS, KM_ALT, 0);
599         WM_keymap_add_item(keymap, "GRAPH_OT_sample", OKEY, KM_PRESS, KM_SHIFT, 0);
600         
601         WM_keymap_add_item(keymap, "GRAPH_OT_bake", CKEY, KM_PRESS, KM_ALT, 0);
602         
603         WM_keymap_add_menu(keymap, "GRAPH_MT_delete", XKEY, KM_PRESS, 0, 0);
604         WM_keymap_add_menu(keymap, "GRAPH_MT_delete", DELKEY, KM_PRESS, 0, 0);
605
606         WM_keymap_add_item(keymap, "GRAPH_OT_duplicate_move", DKEY, KM_PRESS, KM_SHIFT, 0);
607         
608         /* insertkey */
609         WM_keymap_add_item(keymap, "GRAPH_OT_keyframe_insert", IKEY, KM_PRESS, 0, 0);
610         WM_keymap_add_item(keymap, "GRAPH_OT_click_insert", ACTIONMOUSE, KM_CLICK, KM_CTRL, 0);
611         
612         /* copy/paste */
613         WM_keymap_add_item(keymap, "GRAPH_OT_copy", CKEY, KM_PRESS, KM_CTRL, 0);
614         WM_keymap_add_item(keymap, "GRAPH_OT_paste", VKEY, KM_PRESS, KM_CTRL, 0);
615         kmi = WM_keymap_add_item(keymap, "GRAPH_OT_paste", VKEY, KM_PRESS, KM_CTRL | KM_SHIFT, 0);
616         RNA_boolean_set(kmi->ptr, "flipped", true);
617 #ifdef __APPLE__
618         WM_keymap_add_item(keymap, "GRAPH_OT_copy", CKEY, KM_PRESS, KM_OSKEY, 0);
619         WM_keymap_add_item(keymap, "GRAPH_OT_paste", VKEY, KM_PRESS, KM_OSKEY, 0);
620         kmi = WM_keymap_add_item(keymap, "GRAPH_OT_paste", VKEY, KM_PRESS, KM_OSKEY | KM_SHIFT, 0);
621         RNA_boolean_set(kmi->ptr, "flipped", true);
622 #endif
623
624         /* auto-set range */
625         WM_keymap_add_item(keymap, "GRAPH_OT_previewrange_set", PKEY, KM_PRESS, KM_CTRL | KM_ALT, 0);
626         WM_keymap_add_item(keymap, "GRAPH_OT_view_all", HOMEKEY, KM_PRESS, 0, 0);
627         WM_keymap_add_item(keymap, "GRAPH_OT_view_all", NDOF_BUTTON_FIT, KM_PRESS, 0, 0);
628         WM_keymap_add_item(keymap, "GRAPH_OT_view_selected", PADPERIOD, KM_PRESS, 0, 0);
629         WM_keymap_add_item(keymap, "GRAPH_OT_view_frame", PAD0, KM_PRESS, 0, 0);
630
631         /* F-Modifiers */
632         kmi = WM_keymap_add_item(keymap, "GRAPH_OT_fmodifier_add", MKEY, KM_PRESS, KM_CTRL | KM_SHIFT, 0);
633         RNA_boolean_set(kmi->ptr, "only_active", false);
634         
635         /* animation module */
636         /* channels list
637          * NOTE: these operators were originally for the channels list, but are added here too for convenience...
638          */
639         WM_keymap_add_item(keymap, "ANIM_OT_channels_editable_toggle", TABKEY, KM_PRESS, 0, 0);
640         
641         /* transform system */
642         transform_keymap_for_space(keyconf, keymap, SPACE_IPO);
643         
644         kmi = WM_keymap_add_item(keymap, "WM_OT_context_toggle", OKEY, KM_PRESS, 0, 0);
645         RNA_string_set(kmi->ptr, "data_path", "tool_settings.use_proportional_fcurve");
646
647         /* pivot point settings */
648         kmi = WM_keymap_add_item(keymap, "WM_OT_context_set_enum", COMMAKEY, KM_PRESS, 0, 0);
649         RNA_string_set(kmi->ptr, "data_path", "space_data.pivot_point");
650         RNA_string_set(kmi->ptr, "value", "BOUNDING_BOX_CENTER");
651         
652         kmi = WM_keymap_add_item(keymap, "WM_OT_context_set_enum", PERIODKEY, KM_PRESS, 0, 0);
653         RNA_string_set(kmi->ptr, "data_path", "space_data.pivot_point");
654         RNA_string_set(kmi->ptr, "value", "CURSOR");
655         
656         kmi = WM_keymap_add_item(keymap, "WM_OT_context_set_enum", PERIODKEY, KM_PRESS, KM_CTRL, 0);
657         RNA_string_set(kmi->ptr, "data_path", "space_data.pivot_point");
658         RNA_string_set(kmi->ptr, "value", "INDIVIDUAL_ORIGINS");
659                 
660         /* special markers hotkeys for anim editors: see note in definition of this function */
661         ED_marker_keymap_animedit_conflictfree(keymap);
662 }
663
664 /* --------------- */
665
666 void graphedit_keymap(wmKeyConfig *keyconf)
667 {
668         wmKeyMap *keymap;
669         wmKeyMapItem *kmi;
670         
671         /* keymap for all regions */
672         keymap = WM_keymap_find(keyconf, "Graph Editor Generic", SPACE_IPO, 0);
673         WM_keymap_add_item(keymap, "GRAPH_OT_properties", NKEY, KM_PRESS, 0, 0);
674         
675         /* extrapolation works on channels, not keys */
676         WM_keymap_add_item(keymap, "GRAPH_OT_extrapolation_type", EKEY, KM_PRESS, KM_SHIFT, 0);
677         
678         /* find (i.e. a shortcut for setting the name filter) */
679         WM_keymap_add_item(keymap, "ANIM_OT_channels_find", FKEY, KM_PRESS, KM_CTRL, 0);
680         
681         /* hide/reveal selected curves */
682         kmi = WM_keymap_add_item(keymap, "GRAPH_OT_hide", HKEY, KM_PRESS, 0, 0);
683         RNA_boolean_set(kmi->ptr, "unselected", false);
684         
685         kmi = WM_keymap_add_item(keymap, "GRAPH_OT_hide", HKEY, KM_PRESS, KM_SHIFT, 0);
686         RNA_boolean_set(kmi->ptr, "unselected", true);
687         
688         WM_keymap_add_item(keymap, "GRAPH_OT_reveal", HKEY, KM_PRESS, KM_ALT, 0);
689         
690         
691         /* channels */
692         /* Channels are not directly handled by the Graph Editor module, but are inherited from the Animation module. 
693          * All the relevant operations, keymaps, drawing, etc. can therefore all be found in that module instead, as these
694          * are all used for the Graph Editor too.
695          */
696         
697         /* keyframes */
698         keymap = WM_keymap_find(keyconf, "Graph Editor", SPACE_IPO, 0);
699         graphedit_keymap_keyframes(keyconf, keymap);
700 }
701