91cbc2ff3e00dd097657e7d366af4bc181652ecd
[blender.git] / source / blender / editors / animation / anim_ops.c
1 /*
2  * This program is free software; you can redistribute it and/or
3  * modify it under the terms of the GNU General Public License
4  * as published by the Free Software Foundation; either version 2
5  * of the License, or (at your option) any later version.
6  *
7  * This program is distributed in the hope that it will be useful,
8  * but WITHOUT ANY WARRANTY; without even the implied warranty of
9  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
10  * GNU General Public License for more details.
11  *
12  * You should have received a copy of the GNU General Public License
13  * along with this program; if not, write to the Free Software Foundation,
14  * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
15  *
16  * The Original Code is Copyright (C) 2008 Blender Foundation.
17  * All rights reserved.
18  */
19
20 /** \file
21  * \ingroup edanimation
22  */
23
24 #include <stdlib.h>
25 #include <math.h>
26
27 #include "BLI_sys_types.h"
28
29 #include "BLI_utildefines.h"
30 #include "BLI_math_base.h"
31
32 #include "DNA_anim_types.h"
33 #include "DNA_scene_types.h"
34
35 #include "BKE_context.h"
36 #include "BKE_sequencer.h"
37 #include "BKE_global.h"
38 #include "BKE_main.h"
39 #include "BKE_sound.h"
40 #include "BKE_scene.h"
41
42 #include "UI_view2d.h"
43
44 #include "RNA_access.h"
45 #include "RNA_define.h"
46
47 #include "WM_api.h"
48 #include "WM_types.h"
49
50 #include "ED_anim_api.h"
51 #include "ED_screen.h"
52 #include "ED_sequencer.h"
53 #include "ED_util.h"
54
55 #include "anim_intern.h"
56
57 /* ********************** frame change operator ***************************/
58
59 /* Check if the operator can be run from the current context */
60 static bool change_frame_poll(bContext *C)
61 {
62   ScrArea *sa = CTX_wm_area(C);
63
64   /* XXX temp? prevent changes during render */
65   if (G.is_rendering)
66     return false;
67
68   /* although it's only included in keymaps for regions using ED_KEYMAP_ANIMATION,
69    * this shouldn't show up in 3D editor (or others without 2D timeline view) via search
70    */
71   if (sa) {
72     if (ELEM(sa->spacetype, SPACE_ACTION, SPACE_NLA, SPACE_SEQ, SPACE_CLIP)) {
73       return true;
74     }
75     else if (sa->spacetype == SPACE_GRAPH) {
76       /* NOTE: Graph Editor has special version which does some extra stuff.
77        * No need to show the generic error message for that case though!
78        */
79       return false;
80     }
81   }
82
83   CTX_wm_operator_poll_msg_set(C, "Expected an animation area to be active");
84   return false;
85 }
86
87 /* Set the new frame number */
88 static void change_frame_apply(bContext *C, wmOperator *op)
89 {
90   Main *bmain = CTX_data_main(C);
91   Scene *scene = CTX_data_scene(C);
92   float frame = RNA_float_get(op->ptr, "frame");
93   bool do_snap = RNA_boolean_get(op->ptr, "snap");
94
95   if (do_snap) {
96     if (CTX_wm_space_seq(C)) {
97       frame = BKE_sequencer_find_next_prev_edit(scene, frame, SEQ_SIDE_BOTH, true, false, false);
98     }
99     else {
100       frame = BKE_scene_frame_snap_by_seconds(scene, 1.0, frame);
101     }
102   }
103
104   /* set the new frame number */
105   if (scene->r.flag & SCER_SHOW_SUBFRAME) {
106     CFRA = (int)frame;
107     SUBFRA = frame - (int)frame;
108   }
109   else {
110     CFRA = round_fl_to_int(frame);
111     SUBFRA = 0.0f;
112   }
113   FRAMENUMBER_MIN_CLAMP(CFRA);
114
115   /* do updates */
116   BKE_sound_seek_scene(bmain, scene);
117   WM_event_add_notifier(C, NC_SCENE | ND_FRAME, scene);
118 }
119
120 /* ---- */
121
122 /* Non-modal callback for running operator without user input */
123 static int change_frame_exec(bContext *C, wmOperator *op)
124 {
125   change_frame_apply(C, op);
126
127   return OPERATOR_FINISHED;
128 }
129
130 /* ---- */
131
132 /* Get frame from mouse coordinates */
133 static float frame_from_event(bContext *C, const wmEvent *event)
134 {
135   ARegion *region = CTX_wm_region(C);
136   Scene *scene = CTX_data_scene(C);
137   float frame;
138
139   /* convert from region coordinates to View2D 'tot' space */
140   frame = UI_view2d_region_to_view_x(&region->v2d, event->mval[0]);
141
142   /* respect preview range restrictions (if only allowed to move around within that range) */
143   if (scene->r.flag & SCER_LOCK_FRAME_SELECTION) {
144     CLAMP(frame, PSFRA, PEFRA);
145   }
146
147   return frame;
148 }
149
150 static void change_frame_seq_preview_begin(bContext *C, const wmEvent *event)
151 {
152   ScrArea *sa = CTX_wm_area(C);
153   bScreen *screen = CTX_wm_screen(C);
154   if (sa && sa->spacetype == SPACE_SEQ) {
155     SpaceSeq *sseq = sa->spacedata.first;
156     if (ED_space_sequencer_check_show_strip(sseq)) {
157       ED_sequencer_special_preview_set(C, event->mval);
158     }
159   }
160   if (screen)
161     screen->scrubbing = true;
162 }
163
164 static void change_frame_seq_preview_end(bContext *C)
165 {
166   bScreen *screen = CTX_wm_screen(C);
167   bool notify = false;
168
169   if (screen->scrubbing) {
170     screen->scrubbing = false;
171     notify = true;
172   }
173
174   if (ED_sequencer_special_preview_get() != NULL) {
175     ED_sequencer_special_preview_clear();
176     notify = true;
177   }
178
179   if (notify) {
180     Scene *scene = CTX_data_scene(C);
181     WM_event_add_notifier(C, NC_SCENE | ND_FRAME, scene);
182   }
183 }
184
185 /* Modal Operator init */
186 static int change_frame_invoke(bContext *C, wmOperator *op, const wmEvent *event)
187 {
188   /* Change to frame that mouse is over before adding modal handler,
189    * as user could click on a single frame (jump to frame) as well as
190    * click-dragging over a range (modal scrubbing).
191    */
192   RNA_float_set(op->ptr, "frame", frame_from_event(C, event));
193
194   change_frame_seq_preview_begin(C, event);
195
196   change_frame_apply(C, op);
197
198   /* add temp handler */
199   WM_event_add_modal_handler(C, op);
200
201   return OPERATOR_RUNNING_MODAL;
202 }
203
204 static void change_frame_cancel(bContext *C, wmOperator *UNUSED(op))
205 {
206   change_frame_seq_preview_end(C);
207 }
208
209 /* Modal event handling of frame changing */
210 static int change_frame_modal(bContext *C, wmOperator *op, const wmEvent *event)
211 {
212   int ret = OPERATOR_RUNNING_MODAL;
213   /* execute the events */
214   switch (event->type) {
215     case ESCKEY:
216       ret = OPERATOR_FINISHED;
217       break;
218
219     case MOUSEMOVE:
220       RNA_float_set(op->ptr, "frame", frame_from_event(C, event));
221       change_frame_apply(C, op);
222       break;
223
224     case LEFTMOUSE:
225     case RIGHTMOUSE:
226     case MIDDLEMOUSE:
227       /* We check for either mouse-button to end, to work with all user keymaps. */
228       if (event->val == KM_RELEASE)
229         ret = OPERATOR_FINISHED;
230       break;
231
232     case LEFTCTRLKEY:
233     case RIGHTCTRLKEY:
234       if (event->val == KM_RELEASE) {
235         RNA_boolean_set(op->ptr, "snap", false);
236       }
237       else if (event->val == KM_PRESS) {
238         RNA_boolean_set(op->ptr, "snap", true);
239       }
240       break;
241   }
242
243   if (ret != OPERATOR_RUNNING_MODAL) {
244     change_frame_seq_preview_end(C);
245   }
246
247   return ret;
248 }
249
250 static void ANIM_OT_change_frame(wmOperatorType *ot)
251 {
252   PropertyRNA *prop;
253
254   /* identifiers */
255   ot->name = "Change Frame";
256   ot->idname = "ANIM_OT_change_frame";
257   ot->description = "Interactively change the current frame number";
258
259   /* api callbacks */
260   ot->exec = change_frame_exec;
261   ot->invoke = change_frame_invoke;
262   ot->cancel = change_frame_cancel;
263   ot->modal = change_frame_modal;
264   ot->poll = change_frame_poll;
265
266   /* flags */
267   ot->flag = OPTYPE_BLOCKING | OPTYPE_GRAB_CURSOR | OPTYPE_UNDO_GROUPED;
268   ot->undo_group = "Frame Change";
269
270   /* rna */
271   ot->prop = RNA_def_float(
272       ot->srna, "frame", 0, MINAFRAME, MAXFRAME, "Frame", "", MINAFRAME, MAXFRAME);
273   prop = RNA_def_boolean(ot->srna, "snap", false, "Snap", "");
274   RNA_def_property_flag(prop, PROP_SKIP_SAVE);
275 }
276
277 /* ****************** Start/End Frame Operators *******************************/
278
279 static bool anim_set_end_frames_poll(bContext *C)
280 {
281   ScrArea *sa = CTX_wm_area(C);
282
283   /* XXX temp? prevent changes during render */
284   if (G.is_rendering)
285     return false;
286
287   /* although it's only included in keymaps for regions using ED_KEYMAP_ANIMATION,
288    * this shouldn't show up in 3D editor (or others without 2D timeline view) via search
289    */
290   if (sa) {
291     if (ELEM(sa->spacetype, SPACE_ACTION, SPACE_GRAPH, SPACE_NLA, SPACE_SEQ, SPACE_CLIP)) {
292       return true;
293     }
294   }
295
296   CTX_wm_operator_poll_msg_set(C, "Expected an animation area to be active");
297   return false;
298 }
299
300 static int anim_set_sfra_exec(bContext *C, wmOperator *UNUSED(op))
301 {
302   Scene *scene = CTX_data_scene(C);
303   int frame;
304
305   if (scene == NULL)
306     return OPERATOR_CANCELLED;
307
308   frame = CFRA;
309
310   /* if Preview Range is defined, set the 'start' frame for that */
311   if (PRVRANGEON)
312     scene->r.psfra = frame;
313   else
314     scene->r.sfra = frame;
315
316   if (PEFRA < frame) {
317     if (PRVRANGEON)
318       scene->r.pefra = frame;
319     else
320       scene->r.efra = frame;
321   }
322
323   WM_event_add_notifier(C, NC_SCENE | ND_FRAME, scene);
324
325   return OPERATOR_FINISHED;
326 }
327
328 static void ANIM_OT_start_frame_set(wmOperatorType *ot)
329 {
330   /* identifiers */
331   ot->name = "Set Start Frame";
332   ot->idname = "ANIM_OT_start_frame_set";
333   ot->description = "Set the current frame as the preview or scene start frame";
334
335   /* api callbacks */
336   ot->exec = anim_set_sfra_exec;
337   ot->poll = anim_set_end_frames_poll;
338
339   /* flags */
340   ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
341 }
342
343 static int anim_set_efra_exec(bContext *C, wmOperator *UNUSED(op))
344 {
345   Scene *scene = CTX_data_scene(C);
346   int frame;
347
348   if (scene == NULL)
349     return OPERATOR_CANCELLED;
350
351   frame = CFRA;
352
353   /* if Preview Range is defined, set the 'end' frame for that */
354   if (PRVRANGEON)
355     scene->r.pefra = frame;
356   else
357     scene->r.efra = frame;
358
359   if (PSFRA > frame) {
360     if (PRVRANGEON)
361       scene->r.psfra = frame;
362     else
363       scene->r.sfra = frame;
364   }
365
366   WM_event_add_notifier(C, NC_SCENE | ND_FRAME, scene);
367
368   return OPERATOR_FINISHED;
369 }
370
371 static void ANIM_OT_end_frame_set(wmOperatorType *ot)
372 {
373   /* identifiers */
374   ot->name = "Set End Frame";
375   ot->idname = "ANIM_OT_end_frame_set";
376   ot->description = "Set the current frame as the preview or scene end frame";
377
378   /* api callbacks */
379   ot->exec = anim_set_efra_exec;
380   ot->poll = anim_set_end_frames_poll;
381
382   /* flags */
383   ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
384 }
385
386 /* ****************** set preview range operator ****************************/
387
388 static int previewrange_define_exec(bContext *C, wmOperator *op)
389 {
390   Scene *scene = CTX_data_scene(C);
391   ARegion *ar = CTX_wm_region(C);
392   float sfra, efra;
393   rcti rect;
394
395   /* get min/max values from box select rect (already in region coordinates, not screen) */
396   WM_operator_properties_border_to_rcti(op, &rect);
397
398   /* convert min/max values to frames (i.e. region to 'tot' rect) */
399   sfra = UI_view2d_region_to_view_x(&ar->v2d, rect.xmin);
400   efra = UI_view2d_region_to_view_x(&ar->v2d, rect.xmax);
401
402   /* set start/end frames for preview-range
403    * - must clamp within allowable limits
404    * - end must not be before start (though this won't occur most of the time)
405    */
406   FRAMENUMBER_MIN_CLAMP(sfra);
407   FRAMENUMBER_MIN_CLAMP(efra);
408   if (efra < sfra)
409     efra = sfra;
410
411   scene->r.flag |= SCER_PRV_RANGE;
412   scene->r.psfra = round_fl_to_int(sfra);
413   scene->r.pefra = round_fl_to_int(efra);
414
415   /* send notifiers */
416   WM_event_add_notifier(C, NC_SCENE | ND_FRAME, scene);
417
418   return OPERATOR_FINISHED;
419 }
420
421 static void ANIM_OT_previewrange_set(wmOperatorType *ot)
422 {
423   /* identifiers */
424   ot->name = "Set Preview Range";
425   ot->idname = "ANIM_OT_previewrange_set";
426   ot->description = "Interactively define frame range used for playback";
427
428   /* api callbacks */
429   ot->invoke = WM_gesture_box_invoke;
430   ot->exec = previewrange_define_exec;
431   ot->modal = WM_gesture_box_modal;
432   ot->cancel = WM_gesture_box_cancel;
433
434   ot->poll = ED_operator_animview_active;
435
436   /* flags */
437   ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
438
439   /* rna */
440   /* used to define frame range.
441    *
442    * note: border Y values are not used,
443    * but are needed by box_select gesture operator stuff */
444   WM_operator_properties_border(ot);
445 }
446
447 /* ****************** clear preview range operator ****************************/
448
449 static int previewrange_clear_exec(bContext *C, wmOperator *UNUSED(op))
450 {
451   Scene *scene = CTX_data_scene(C);
452   ScrArea *curarea = CTX_wm_area(C);
453
454   /* sanity checks */
455   if (ELEM(NULL, scene, curarea))
456     return OPERATOR_CANCELLED;
457
458   /* simply clear values */
459   scene->r.flag &= ~SCER_PRV_RANGE;
460   scene->r.psfra = 0;
461   scene->r.pefra = 0;
462
463   ED_area_tag_redraw(curarea);
464
465   /* send notifiers */
466   WM_event_add_notifier(C, NC_SCENE | ND_FRAME, scene);
467
468   return OPERATOR_FINISHED;
469 }
470
471 static void ANIM_OT_previewrange_clear(wmOperatorType *ot)
472 {
473   /* identifiers */
474   ot->name = "Clear Preview Range";
475   ot->idname = "ANIM_OT_previewrange_clear";
476   ot->description = "Clear Preview Range";
477
478   /* api callbacks */
479   ot->exec = previewrange_clear_exec;
480
481   ot->poll = ED_operator_animview_active;
482
483   /* flags */
484   ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
485 }
486
487 /* ************************** registration **********************************/
488
489 void ED_operatortypes_anim(void)
490 {
491   /* Animation Editors only -------------------------- */
492   WM_operatortype_append(ANIM_OT_change_frame);
493
494   WM_operatortype_append(ANIM_OT_start_frame_set);
495   WM_operatortype_append(ANIM_OT_end_frame_set);
496
497   WM_operatortype_append(ANIM_OT_previewrange_set);
498   WM_operatortype_append(ANIM_OT_previewrange_clear);
499
500   /* Entire UI --------------------------------------- */
501   WM_operatortype_append(ANIM_OT_keyframe_insert);
502   WM_operatortype_append(ANIM_OT_keyframe_delete);
503   WM_operatortype_append(ANIM_OT_keyframe_insert_menu);
504   WM_operatortype_append(ANIM_OT_keyframe_delete_v3d);
505   WM_operatortype_append(ANIM_OT_keyframe_clear_v3d);
506   WM_operatortype_append(ANIM_OT_keyframe_insert_button);
507   WM_operatortype_append(ANIM_OT_keyframe_delete_button);
508   WM_operatortype_append(ANIM_OT_keyframe_clear_button);
509   WM_operatortype_append(ANIM_OT_keyframe_insert_by_name);
510   WM_operatortype_append(ANIM_OT_keyframe_delete_by_name);
511
512   WM_operatortype_append(ANIM_OT_driver_button_add);
513   WM_operatortype_append(ANIM_OT_driver_button_remove);
514   WM_operatortype_append(ANIM_OT_driver_button_edit);
515   WM_operatortype_append(ANIM_OT_copy_driver_button);
516   WM_operatortype_append(ANIM_OT_paste_driver_button);
517
518   WM_operatortype_append(ANIM_OT_keyingset_button_add);
519   WM_operatortype_append(ANIM_OT_keyingset_button_remove);
520
521   WM_operatortype_append(ANIM_OT_keying_set_add);
522   WM_operatortype_append(ANIM_OT_keying_set_remove);
523   WM_operatortype_append(ANIM_OT_keying_set_path_add);
524   WM_operatortype_append(ANIM_OT_keying_set_path_remove);
525
526   WM_operatortype_append(ANIM_OT_keying_set_active_set);
527 }
528
529 void ED_keymap_anim(wmKeyConfig *keyconf)
530 {
531   WM_keymap_ensure(keyconf, "Animation", 0, 0);
532 }