Cleanup: warning & whitespace
[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         ARegion *ar = CTX_wm_region(C);
137         float viewx, viewy;
138         
139         /* abort if not active region (should not really be possible) */
140         if (ar == NULL)
141                 return;
142         
143         /* convert from region coordinates to View2D 'tot' space */
144         UI_view2d_region_to_view(&ar->v2d, event->mval[0], event->mval[1], &viewx, &viewy);
145         
146         /* store the values in the operator properties */
147         /* NOTE: we don't clamp frame here, as it might be used for the drivers cursor */
148         RNA_float_set(op->ptr, "frame", viewx);
149         RNA_float_set(op->ptr, "value", viewy);
150 }
151
152 /* Modal Operator init */
153 static int graphview_cursor_invoke(bContext *C, wmOperator *op, const wmEvent *event)
154 {
155         bScreen *screen = CTX_wm_screen(C);
156         
157         /* Change to frame that mouse is over before adding modal handler,
158          * as user could click on a single frame (jump to frame) as well as
159          * click-dragging over a range (modal scrubbing). Apply this change.
160          */
161         graphview_cursor_setprops(C, op, event);
162         graphview_cursor_apply(C, op);
163         
164         /* Signal that a scrubbing operating is starting */
165         if (screen)
166                 screen->scrubbing = true;
167         
168         /* add temp handler */
169         WM_event_add_modal_handler(C, op);
170         return OPERATOR_RUNNING_MODAL;
171 }
172
173 /* Modal event handling of cursor changing */
174 static int graphview_cursor_modal(bContext *C, wmOperator *op, const wmEvent *event)
175 {
176         bScreen *screen = CTX_wm_screen(C);
177         Scene *scene = CTX_data_scene(C);
178         
179         /* execute the events */
180         switch (event->type) {
181                 case ESCKEY:
182                         if (screen)
183                                 screen->scrubbing = false;
184                         
185                         WM_event_add_notifier(C, NC_SCENE | ND_FRAME, scene);
186                         return OPERATOR_FINISHED;
187                 
188                 case MOUSEMOVE:
189                         /* set the new values */
190                         graphview_cursor_setprops(C, op, event);
191                         graphview_cursor_apply(C, op);
192                         break;
193                 
194                 case LEFTMOUSE: 
195                 case RIGHTMOUSE:
196                 case MIDDLEMOUSE:
197                         /* we check for either mouse-button to end, as checking for ACTIONMOUSE (which is used to init 
198                          * the modal op) doesn't work for some reason
199                          */
200                         if (event->val == KM_RELEASE) {
201                                 if (screen)
202                                         screen->scrubbing = false;
203                                 
204                                 WM_event_add_notifier(C, NC_SCENE | ND_FRAME, scene);
205                                 return OPERATOR_FINISHED;
206                         }
207                         break;
208         }
209
210         return OPERATOR_RUNNING_MODAL;
211 }
212
213 static void GRAPH_OT_cursor_set(wmOperatorType *ot)
214 {
215         /* identifiers */
216         ot->name = "Set Cursor";
217         ot->idname = "GRAPH_OT_cursor_set";
218         ot->description = "Interactively set the current frame and value cursor";
219         
220         /* api callbacks */
221         ot->exec = graphview_cursor_exec;
222         ot->invoke = graphview_cursor_invoke;
223         ot->modal = graphview_cursor_modal;
224         ot->poll = graphview_cursor_poll;
225         
226         /* flags */
227         ot->flag = OPTYPE_BLOCKING | OPTYPE_UNDO;
228
229         /* rna */
230         RNA_def_float(ot->srna, "frame", 0, MINAFRAMEF, MAXFRAMEF, "Frame", "", MINAFRAMEF, MAXFRAMEF);
231         RNA_def_float(ot->srna, "value", 0, -FLT_MAX, FLT_MAX, "Value", "", -100.0f, 100.0f);
232 }
233
234 /* Hide/Reveal ------------------------------------------------------------ */
235
236 static int graphview_curves_hide_exec(bContext *C, wmOperator *op)
237 {
238         bAnimContext ac;
239         ListBase anim_data = {NULL, NULL};
240         ListBase all_data = {NULL, NULL};
241         bAnimListElem *ale;
242         int filter;
243         const bool unselected = RNA_boolean_get(op->ptr, "unselected");
244         
245         /* get editor data */
246         if (ANIM_animdata_get_context(C, &ac) == 0)
247                 return OPERATOR_CANCELLED;
248                 
249         /* get list of all channels that selection may need to be flushed to 
250          * - hierarchy must not affect what we have access to here...
251          */
252         filter = (ANIMFILTER_DATA_VISIBLE | ANIMFILTER_LIST_CHANNELS | ANIMFILTER_NODUPLIS);
253         ANIM_animdata_filter(&ac, &all_data, filter, ac.data, ac.datatype);
254         
255         /* filter data
256          * - of the remaining visible curves, we want to hide the ones that are 
257          *   selected/unselected (depending on "unselected" prop) 
258          */
259         filter = (ANIMFILTER_DATA_VISIBLE | ANIMFILTER_CURVE_VISIBLE | ANIMFILTER_NODUPLIS);
260         if (unselected)
261                 filter |= ANIMFILTER_UNSEL;
262         else
263                 filter |= ANIMFILTER_SEL;
264         
265         ANIM_animdata_filter(&ac, &anim_data, filter, ac.data, ac.datatype);
266         
267         for (ale = anim_data.first; ale; ale = ale->next) {
268                 /* hack: skip object channels for now, since flushing those will always flush everything, but they are always included */
269                 /* TODO: find out why this is the case, and fix that */
270                 if (ale->type == ANIMTYPE_OBJECT)
271                         continue;
272                 
273                 /* change the hide setting, and unselect it... */
274                 ANIM_channel_setting_set(&ac, ale, ACHANNEL_SETTING_VISIBLE, ACHANNEL_SETFLAG_CLEAR);
275                 ANIM_channel_setting_set(&ac, ale, ACHANNEL_SETTING_SELECT,  ACHANNEL_SETFLAG_CLEAR);
276                 
277                 /* now, also flush selection status up/down as appropriate */
278                 ANIM_flush_setting_anim_channels(&ac, &all_data, ale, ACHANNEL_SETTING_VISIBLE, ACHANNEL_SETFLAG_CLEAR);
279         }
280
281         /* cleanup */
282         ANIM_animdata_freelist(&anim_data);
283         BLI_freelistN(&all_data);
284         
285         /* unhide selected */
286         if (unselected) {
287                 /* turn off requirement for visible */
288                 filter = ANIMFILTER_SEL | ANIMFILTER_NODUPLIS | ANIMFILTER_LIST_CHANNELS;
289
290                 /* flushing has been done */
291                 ANIM_animdata_filter(&ac, &anim_data, filter, ac.data, ac.datatype);
292
293                 for (ale = anim_data.first; ale; ale = ale->next) {
294                         /* hack: skip object channels for now, since flushing those will always flush everything, but they are always included */
295                         /* TODO: find out why this is the case, and fix that */
296                         if (ale->type == ANIMTYPE_OBJECT)
297                                 continue;
298                         
299                         /* change the hide setting, and unselect it... */
300                         ANIM_channel_setting_set(&ac, ale, ACHANNEL_SETTING_VISIBLE, ACHANNEL_SETFLAG_ADD);
301                         ANIM_channel_setting_set(&ac, ale, ACHANNEL_SETTING_SELECT,  ACHANNEL_SETFLAG_ADD);
302                         
303                         /* now, also flush selection status up/down as appropriate */
304                         ANIM_flush_setting_anim_channels(&ac, &anim_data, ale, ACHANNEL_SETTING_VISIBLE, ACHANNEL_SETFLAG_ADD);
305                 }
306                 ANIM_animdata_freelist(&anim_data);     
307         }
308         
309         
310         /* send notifier that things have changed */
311         WM_event_add_notifier(C, NC_ANIMATION | ND_ANIMCHAN | NA_EDITED, NULL);
312         
313         return OPERATOR_FINISHED;
314 }
315
316 static void GRAPH_OT_hide(wmOperatorType *ot)
317 {
318         /* identifiers */
319         ot->name = "Hide Curves";
320         ot->idname = "GRAPH_OT_hide";
321         ot->description = "Hide selected curves from Graph Editor view";
322         
323         /* api callbacks */
324         ot->exec = graphview_curves_hide_exec;
325         ot->poll = ED_operator_graphedit_active;
326         
327         /* flags */
328         ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
329         
330         /* props */
331         RNA_def_boolean(ot->srna, "unselected", 0, "Unselected", "Hide unselected rather than selected curves");
332 }
333
334 /* ........ */
335
336 static int graphview_curves_reveal_exec(bContext *C, wmOperator *UNUSED(op))
337 {
338         bAnimContext ac;
339         ListBase anim_data = {NULL, NULL};
340         ListBase all_data = {NULL, NULL};
341         bAnimListElem *ale;
342         int filter;
343         
344         /* get editor data */
345         if (ANIM_animdata_get_context(C, &ac) == 0)
346                 return OPERATOR_CANCELLED;
347                 
348         /* get list of all channels that selection may need to be flushed to 
349          * - hierarchy must not affect what we have access to here...
350          */
351         filter = (ANIMFILTER_DATA_VISIBLE | ANIMFILTER_LIST_CHANNELS | ANIMFILTER_NODUPLIS);
352         ANIM_animdata_filter(&ac, &all_data, filter, ac.data, ac.datatype);
353         
354         /* filter data
355          * - just go through all visible channels, ensuring that everything is set to be curve-visible
356          */
357         filter = (ANIMFILTER_DATA_VISIBLE | ANIMFILTER_LIST_VISIBLE | ANIMFILTER_NODUPLIS);
358         ANIM_animdata_filter(&ac, &anim_data, filter, ac.data, ac.datatype);
359         
360         for (ale = anim_data.first; ale; ale = ale->next) {
361                 /* hack: skip object channels for now, since flushing those will always flush everything, but they are always included */
362                 /* TODO: find out why this is the case, and fix that */
363                 if (ale->type == ANIMTYPE_OBJECT)
364                         continue;
365                 
366                 /* select if it is not visible */
367                 if (ANIM_channel_setting_get(&ac, ale, ACHANNEL_SETTING_VISIBLE) == 0)
368                         ANIM_channel_setting_set(&ac, ale, ACHANNEL_SETTING_SELECT, ACHANNEL_SETFLAG_ADD);
369                 
370                 /* change the visibility setting */
371                 ANIM_channel_setting_set(&ac, ale, ACHANNEL_SETTING_VISIBLE, ACHANNEL_SETFLAG_ADD);
372                 
373                 /* now, also flush selection status up/down as appropriate */
374                 ANIM_flush_setting_anim_channels(&ac, &all_data, ale, ACHANNEL_SETTING_VISIBLE, true);
375         }
376         
377         /* cleanup */
378         ANIM_animdata_freelist(&anim_data);
379         BLI_freelistN(&all_data);
380         
381         /* send notifier that things have changed */
382         WM_event_add_notifier(C, NC_ANIMATION | ND_ANIMCHAN | NA_EDITED, NULL);
383         
384         return OPERATOR_FINISHED;
385 }
386
387 static void GRAPH_OT_reveal(wmOperatorType *ot)
388 {
389         /* identifiers */
390         ot->name = "Reveal Curves";
391         ot->idname = "GRAPH_OT_reveal";
392         ot->description = "Make previously hidden curves visible again in Graph Editor view";
393         
394         /* api callbacks */
395         ot->exec = graphview_curves_reveal_exec;
396         ot->poll = ED_operator_graphedit_active;
397         
398         /* flags */
399         ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
400 }
401
402 /* ************************** registration - operator types **********************************/
403
404 void graphedit_operatortypes(void)
405 {
406         /* view */
407         WM_operatortype_append(GRAPH_OT_cursor_set);
408         
409         WM_operatortype_append(GRAPH_OT_previewrange_set);
410         WM_operatortype_append(GRAPH_OT_view_all);
411         WM_operatortype_append(GRAPH_OT_view_selected);
412         WM_operatortype_append(GRAPH_OT_properties);
413         WM_operatortype_append(GRAPH_OT_view_frame);
414         
415         WM_operatortype_append(GRAPH_OT_ghost_curves_create);
416         WM_operatortype_append(GRAPH_OT_ghost_curves_clear);
417         
418         WM_operatortype_append(GRAPH_OT_hide);
419         WM_operatortype_append(GRAPH_OT_reveal);
420         
421         /* keyframes */
422         /* selection */
423         WM_operatortype_append(GRAPH_OT_clickselect);
424         WM_operatortype_append(GRAPH_OT_select_all_toggle);
425         WM_operatortype_append(GRAPH_OT_select_border);
426         WM_operatortype_append(GRAPH_OT_select_lasso);
427         WM_operatortype_append(GRAPH_OT_select_circle);
428         WM_operatortype_append(GRAPH_OT_select_column);
429         WM_operatortype_append(GRAPH_OT_select_linked);
430         WM_operatortype_append(GRAPH_OT_select_more);
431         WM_operatortype_append(GRAPH_OT_select_less);
432         WM_operatortype_append(GRAPH_OT_select_leftright);
433         
434         /* editing */
435         WM_operatortype_append(GRAPH_OT_snap);
436         WM_operatortype_append(GRAPH_OT_mirror);
437         WM_operatortype_append(GRAPH_OT_frame_jump);
438         WM_operatortype_append(GRAPH_OT_handle_type);
439         WM_operatortype_append(GRAPH_OT_interpolation_type);
440         WM_operatortype_append(GRAPH_OT_extrapolation_type);
441         WM_operatortype_append(GRAPH_OT_easing_type);
442         WM_operatortype_append(GRAPH_OT_sample);
443         WM_operatortype_append(GRAPH_OT_bake);
444         WM_operatortype_append(GRAPH_OT_sound_bake);
445         WM_operatortype_append(GRAPH_OT_smooth);
446         WM_operatortype_append(GRAPH_OT_clean);
447         WM_operatortype_append(GRAPH_OT_euler_filter);
448         WM_operatortype_append(GRAPH_OT_delete);
449         WM_operatortype_append(GRAPH_OT_duplicate);
450         
451         WM_operatortype_append(GRAPH_OT_copy);
452         WM_operatortype_append(GRAPH_OT_paste);
453         
454         WM_operatortype_append(GRAPH_OT_keyframe_insert);
455         WM_operatortype_append(GRAPH_OT_click_insert);
456         
457         /* F-Curve Modifiers */
458         WM_operatortype_append(GRAPH_OT_fmodifier_add);
459         WM_operatortype_append(GRAPH_OT_fmodifier_copy);
460         WM_operatortype_append(GRAPH_OT_fmodifier_paste);
461 }
462
463 void ED_operatormacros_graph(void)
464 {
465         wmOperatorType *ot;
466         wmOperatorTypeMacro *otmacro;
467         
468         ot = WM_operatortype_append_macro("GRAPH_OT_duplicate_move", "Duplicate",
469                                           "Make a copy of all selected keyframes and move them",
470                                           OPTYPE_UNDO | OPTYPE_REGISTER);
471         WM_operatortype_macro_define(ot, "GRAPH_OT_duplicate");
472         otmacro = WM_operatortype_macro_define(ot, "TRANSFORM_OT_transform");
473         RNA_enum_set(otmacro->ptr, "mode", TFM_TIME_DUPLICATE);
474         RNA_enum_set(otmacro->ptr, "proportional", PROP_EDIT_OFF);
475 }
476
477
478 /* ************************** registration - keymaps **********************************/
479
480 static void graphedit_keymap_keyframes(wmKeyConfig *keyconf, wmKeyMap *keymap)
481 {
482         wmKeyMapItem *kmi;
483         
484         /* view */
485         kmi = WM_keymap_add_item(keymap, "WM_OT_context_toggle", HKEY, KM_PRESS, KM_CTRL, 0);
486         RNA_string_set(kmi->ptr, "data_path", "space_data.show_handles");
487
488         /* NOTE: 'ACTIONMOUSE' not 'LEFTMOUSE', as user may have swapped mouse-buttons
489          * This keymap is supposed to override ANIM_OT_change_frame, which does the same except it doesn't do y-values
490          */
491         WM_keymap_add_item(keymap, "GRAPH_OT_cursor_set", ACTIONMOUSE, KM_PRESS, 0, 0);
492         
493         
494         /* graph_select.c - selection tools */
495         /* click-select: keyframe (replace)  */
496         kmi = WM_keymap_add_item(keymap, "GRAPH_OT_clickselect", SELECTMOUSE, KM_PRESS, 0, 0);
497         RNA_boolean_set(kmi->ptr, "extend", false);
498         RNA_boolean_set(kmi->ptr, "curves", false);
499         RNA_boolean_set(kmi->ptr, "column", false);
500         /* click-select: all keyframes on same frame (replace) */
501         kmi = WM_keymap_add_item(keymap, "GRAPH_OT_clickselect", SELECTMOUSE, KM_PRESS, KM_ALT, 0);
502         RNA_boolean_set(kmi->ptr, "extend", false);
503         RNA_boolean_set(kmi->ptr, "curves", false);
504         RNA_boolean_set(kmi->ptr, "column", true);
505         /* click-select: keyframe (add) */
506         kmi = WM_keymap_add_item(keymap, "GRAPH_OT_clickselect", SELECTMOUSE, KM_PRESS, KM_SHIFT, 0);
507         RNA_boolean_set(kmi->ptr, "extend", true);
508         RNA_boolean_set(kmi->ptr, "curves", false);
509         RNA_boolean_set(kmi->ptr, "column", false);
510         /* click-select: all keyframes on same frame (add) */
511         kmi = WM_keymap_add_item(keymap, "GRAPH_OT_clickselect", SELECTMOUSE, KM_PRESS, KM_ALT | KM_SHIFT, 0);
512         RNA_boolean_set(kmi->ptr, "extend", true);
513         RNA_boolean_set(kmi->ptr, "curves", false);
514         RNA_boolean_set(kmi->ptr, "column", true);
515         /* click-select: all keyframes in same curve (replace) */
516         kmi = WM_keymap_add_item(keymap, "GRAPH_OT_clickselect", SELECTMOUSE, KM_PRESS, KM_CTRL | KM_ALT, 0);
517         RNA_boolean_set(kmi->ptr, "extend", false);
518         RNA_boolean_set(kmi->ptr, "curves", true);
519         RNA_boolean_set(kmi->ptr, "column", false);
520         /* click-select: all keyframes in same curve (add) */
521         kmi = WM_keymap_add_item(keymap, "GRAPH_OT_clickselect", SELECTMOUSE, KM_PRESS, KM_CTRL | KM_ALT | KM_SHIFT, 0);
522         RNA_boolean_set(kmi->ptr, "extend", true);
523         RNA_boolean_set(kmi->ptr, "curves", true);
524         RNA_boolean_set(kmi->ptr, "column", false);
525         
526         /* click-select left/right */
527         kmi = WM_keymap_add_item(keymap, "GRAPH_OT_select_leftright", SELECTMOUSE, KM_PRESS, KM_CTRL, 0);
528         RNA_boolean_set(kmi->ptr, "extend", false);
529         RNA_enum_set(kmi->ptr, "mode", GRAPHKEYS_LRSEL_TEST);
530         kmi = WM_keymap_add_item(keymap, "GRAPH_OT_select_leftright", SELECTMOUSE, KM_PRESS, KM_CTRL | KM_SHIFT, 0);
531         RNA_boolean_set(kmi->ptr, "extend", true);
532         RNA_enum_set(kmi->ptr, "mode", GRAPHKEYS_LRSEL_TEST);
533         
534         kmi = WM_keymap_add_item(keymap, "GRAPH_OT_select_leftright", LEFTBRACKETKEY, KM_PRESS, 0, 0);
535         RNA_boolean_set(kmi->ptr, "extend", false);
536         RNA_enum_set(kmi->ptr, "mode", GRAPHKEYS_LRSEL_LEFT);
537         kmi = WM_keymap_add_item(keymap, "GRAPH_OT_select_leftright", RIGHTBRACKETKEY, KM_PRESS, 0, 0);
538         RNA_boolean_set(kmi->ptr, "extend", false);
539         RNA_enum_set(kmi->ptr, "mode", GRAPHKEYS_LRSEL_RIGHT);
540         
541         /* deselect all */
542         kmi = WM_keymap_add_item(keymap, "GRAPH_OT_select_all_toggle", AKEY, KM_PRESS, 0, 0);
543         RNA_boolean_set(kmi->ptr, "invert", false);
544         kmi = WM_keymap_add_item(keymap, "GRAPH_OT_select_all_toggle", IKEY, KM_PRESS, KM_CTRL, 0);
545         RNA_boolean_set(kmi->ptr, "invert", true);
546         
547         /* borderselect */
548         kmi = WM_keymap_add_item(keymap, "GRAPH_OT_select_border", BKEY, KM_PRESS, 0, 0);
549         RNA_boolean_set(kmi->ptr, "axis_range", false);
550         RNA_boolean_set(kmi->ptr, "include_handles", false);
551         kmi = WM_keymap_add_item(keymap, "GRAPH_OT_select_border", BKEY, KM_PRESS, KM_ALT, 0);
552         RNA_boolean_set(kmi->ptr, "axis_range", true);
553         RNA_boolean_set(kmi->ptr, "include_handles", false);
554                 
555         kmi = WM_keymap_add_item(keymap, "GRAPH_OT_select_border", BKEY, KM_PRESS, KM_CTRL, 0);
556         RNA_boolean_set(kmi->ptr, "axis_range", false);
557         RNA_boolean_set(kmi->ptr, "include_handles", true);
558         kmi = WM_keymap_add_item(keymap, "GRAPH_OT_select_border", BKEY, KM_PRESS, KM_CTRL | KM_ALT, 0);
559         RNA_boolean_set(kmi->ptr, "axis_range", true);
560         RNA_boolean_set(kmi->ptr, "include_handles", true);
561
562         kmi = WM_keymap_add_item(keymap, "GRAPH_OT_select_lasso", EVT_TWEAK_A, KM_ANY, KM_CTRL, 0);
563         RNA_boolean_set(kmi->ptr, "deselect", false);
564         kmi = WM_keymap_add_item(keymap, "GRAPH_OT_select_lasso", EVT_TWEAK_A, KM_ANY, KM_CTRL | KM_SHIFT, 0);
565         RNA_boolean_set(kmi->ptr, "deselect", true);
566
567         WM_keymap_add_item(keymap, "GRAPH_OT_select_circle", CKEY, KM_PRESS, 0, 0);
568         
569         /* column select */
570         RNA_enum_set(WM_keymap_add_item(keymap, "GRAPH_OT_select_column", KKEY, KM_PRESS, 0, 0)->ptr, "mode", GRAPHKEYS_COLUMNSEL_KEYS);
571         RNA_enum_set(WM_keymap_add_item(keymap, "GRAPH_OT_select_column", KKEY, KM_PRESS, KM_CTRL, 0)->ptr, "mode", GRAPHKEYS_COLUMNSEL_CFRA);
572         RNA_enum_set(WM_keymap_add_item(keymap, "GRAPH_OT_select_column", KKEY, KM_PRESS, KM_SHIFT, 0)->ptr, "mode", GRAPHKEYS_COLUMNSEL_MARKERS_COLUMN);
573         RNA_enum_set(WM_keymap_add_item(keymap, "GRAPH_OT_select_column", KKEY, KM_PRESS, KM_ALT, 0)->ptr, "mode", GRAPHKEYS_COLUMNSEL_MARKERS_BETWEEN);
574         
575         /* select more/less */
576         WM_keymap_add_item(keymap, "GRAPH_OT_select_more", PADPLUSKEY, KM_PRESS, KM_CTRL, 0);
577         WM_keymap_add_item(keymap, "GRAPH_OT_select_less", PADMINUS, KM_PRESS, KM_CTRL, 0);
578         
579         /* select linked */
580         WM_keymap_add_item(keymap, "GRAPH_OT_select_linked", LKEY, KM_PRESS, 0, 0);
581         
582         
583         /* graph_edit.c */
584         /* jump to selected keyframes */
585         WM_keymap_add_item(keymap, "GRAPH_OT_frame_jump", GKEY, KM_PRESS, KM_CTRL, 0);
586                 
587         /* menu + single-step transform */
588         WM_keymap_add_item(keymap, "GRAPH_OT_snap", SKEY, KM_PRESS, KM_SHIFT, 0);
589         WM_keymap_add_item(keymap, "GRAPH_OT_mirror", MKEY, KM_PRESS, KM_SHIFT, 0);
590         
591         WM_keymap_add_item(keymap, "GRAPH_OT_handle_type", VKEY, KM_PRESS, 0, 0);
592
593         WM_keymap_add_item(keymap, "GRAPH_OT_interpolation_type", TKEY, KM_PRESS, 0, 0);
594         WM_keymap_add_item(keymap, "GRAPH_OT_easing_type", EKEY, KM_PRESS, KM_CTRL, 0);
595         
596         /* destructive */
597         WM_keymap_add_item(keymap, "GRAPH_OT_smooth", OKEY, KM_PRESS, KM_ALT, 0);
598         WM_keymap_add_item(keymap, "GRAPH_OT_sample", OKEY, KM_PRESS, KM_SHIFT, 0);
599         
600         WM_keymap_add_item(keymap, "GRAPH_OT_bake", CKEY, KM_PRESS, KM_ALT, 0);
601         
602         WM_keymap_add_menu(keymap, "GRAPH_MT_delete", XKEY, KM_PRESS, 0, 0);
603         WM_keymap_add_menu(keymap, "GRAPH_MT_delete", DELKEY, KM_PRESS, 0, 0);
604
605         WM_keymap_add_item(keymap, "GRAPH_OT_duplicate_move", DKEY, KM_PRESS, KM_SHIFT, 0);
606         
607         /* insertkey */
608         WM_keymap_add_item(keymap, "GRAPH_OT_keyframe_insert", IKEY, KM_PRESS, 0, 0);
609         WM_keymap_add_item(keymap, "GRAPH_OT_click_insert", ACTIONMOUSE, KM_CLICK, KM_CTRL, 0);
610         
611         /* copy/paste */
612         WM_keymap_add_item(keymap, "GRAPH_OT_copy", CKEY, KM_PRESS, KM_CTRL, 0);
613         WM_keymap_add_item(keymap, "GRAPH_OT_paste", VKEY, KM_PRESS, KM_CTRL, 0);
614         kmi = WM_keymap_add_item(keymap, "GRAPH_OT_paste", VKEY, KM_PRESS, KM_CTRL | KM_SHIFT, 0);
615         RNA_boolean_set(kmi->ptr, "flipped", true);
616 #ifdef __APPLE__
617         WM_keymap_add_item(keymap, "GRAPH_OT_copy", CKEY, KM_PRESS, KM_OSKEY, 0);
618         WM_keymap_add_item(keymap, "GRAPH_OT_paste", VKEY, KM_PRESS, KM_OSKEY, 0);
619         kmi = WM_keymap_add_item(keymap, "GRAPH_OT_paste", VKEY, KM_PRESS, KM_OSKEY | KM_SHIFT, 0);
620         RNA_boolean_set(kmi->ptr, "flipped", true);
621 #endif
622
623         /* auto-set range */
624         WM_keymap_add_item(keymap, "GRAPH_OT_previewrange_set", PKEY, KM_PRESS, KM_CTRL | KM_ALT, 0);
625         WM_keymap_add_item(keymap, "GRAPH_OT_view_all", HOMEKEY, KM_PRESS, 0, 0);
626         WM_keymap_add_item(keymap, "GRAPH_OT_view_all", NDOF_BUTTON_FIT, KM_PRESS, 0, 0);
627         WM_keymap_add_item(keymap, "GRAPH_OT_view_selected", PADPERIOD, KM_PRESS, 0, 0);
628         WM_keymap_add_item(keymap, "GRAPH_OT_view_frame", PAD0, KM_PRESS, 0, 0);
629
630         /* F-Modifiers */
631         kmi = WM_keymap_add_item(keymap, "GRAPH_OT_fmodifier_add", MKEY, KM_PRESS, KM_CTRL | KM_SHIFT, 0);
632         RNA_boolean_set(kmi->ptr, "only_active", false);
633         
634         /* animation module */
635         /* channels list
636          * NOTE: these operators were originally for the channels list, but are added here too for convenience...
637          */
638         WM_keymap_add_item(keymap, "ANIM_OT_channels_editable_toggle", TABKEY, KM_PRESS, 0, 0);
639         
640         /* transform system */
641         transform_keymap_for_space(keyconf, keymap, SPACE_IPO);
642         
643         kmi = WM_keymap_add_item(keymap, "WM_OT_context_toggle", OKEY, KM_PRESS, 0, 0);
644         RNA_string_set(kmi->ptr, "data_path", "tool_settings.use_proportional_fcurve");
645
646         /* pivot point settings */
647         kmi = WM_keymap_add_item(keymap, "WM_OT_context_set_enum", COMMAKEY, KM_PRESS, 0, 0);
648         RNA_string_set(kmi->ptr, "data_path", "space_data.pivot_point");
649         RNA_string_set(kmi->ptr, "value", "BOUNDING_BOX_CENTER");
650         
651         kmi = WM_keymap_add_item(keymap, "WM_OT_context_set_enum", PERIODKEY, KM_PRESS, 0, 0);
652         RNA_string_set(kmi->ptr, "data_path", "space_data.pivot_point");
653         RNA_string_set(kmi->ptr, "value", "CURSOR");
654         
655         kmi = WM_keymap_add_item(keymap, "WM_OT_context_set_enum", PERIODKEY, KM_PRESS, KM_CTRL, 0);
656         RNA_string_set(kmi->ptr, "data_path", "space_data.pivot_point");
657         RNA_string_set(kmi->ptr, "value", "INDIVIDUAL_ORIGINS");
658                 
659         /* special markers hotkeys for anim editors: see note in definition of this function */
660         ED_marker_keymap_animedit_conflictfree(keymap);
661 }
662
663 /* --------------- */
664
665 void graphedit_keymap(wmKeyConfig *keyconf)
666 {
667         wmKeyMap *keymap;
668         wmKeyMapItem *kmi;
669         
670         /* keymap for all regions */
671         keymap = WM_keymap_find(keyconf, "Graph Editor Generic", SPACE_IPO, 0);
672         WM_keymap_add_item(keymap, "GRAPH_OT_properties", NKEY, KM_PRESS, 0, 0);
673         
674         /* extrapolation works on channels, not keys */
675         WM_keymap_add_item(keymap, "GRAPH_OT_extrapolation_type", EKEY, KM_PRESS, KM_SHIFT, 0);
676         
677         /* find (i.e. a shortcut for setting the name filter) */
678         WM_keymap_add_item(keymap, "ANIM_OT_channels_find", FKEY, KM_PRESS, KM_CTRL, 0);
679         
680         /* hide/reveal selected curves */
681         kmi = WM_keymap_add_item(keymap, "GRAPH_OT_hide", HKEY, KM_PRESS, 0, 0);
682         RNA_boolean_set(kmi->ptr, "unselected", false);
683         
684         kmi = WM_keymap_add_item(keymap, "GRAPH_OT_hide", HKEY, KM_PRESS, KM_SHIFT, 0);
685         RNA_boolean_set(kmi->ptr, "unselected", true);
686         
687         WM_keymap_add_item(keymap, "GRAPH_OT_reveal", HKEY, KM_PRESS, KM_ALT, 0);
688         
689         
690         /* channels */
691         /* Channels are not directly handled by the Graph Editor module, but are inherited from the Animation module. 
692          * All the relevant operations, keymaps, drawing, etc. can therefore all be found in that module instead, as these
693          * are all used for the Graph Editor too.
694          */
695         
696         /* keyframes */
697         keymap = WM_keymap_find(keyconf, "Graph Editor", SPACE_IPO, 0);
698         graphedit_keymap_keyframes(keyconf, keymap);
699 }
700