Blender V5.0
anim_ops.cc
Go to the documentation of this file.
1/* SPDX-FileCopyrightText: 2008 Blender Authors
2 *
3 * SPDX-License-Identifier: GPL-2.0-or-later */
4
8
9#include <algorithm>
10#include <cmath>
11#include <cstdlib>
12
13#include "BLI_listbase.h"
14#include "BLI_math_base.h"
15#include "BLI_utildefines.h"
16#include "BLI_vector.hh"
17
18#include "DNA_scene_types.h"
19
20#include "BKE_anim_data.hh"
21#include "BKE_context.hh"
22#include "BKE_global.hh"
23#include "BKE_lib_id.hh"
24#include "BKE_lib_query.hh"
25#include "BKE_report.hh"
26#include "BKE_scene.hh"
27
28#include "BLT_translation.hh"
29
30#include "UI_resources.hh"
31#include "UI_view2d.hh"
32
33#include "RNA_access.hh"
34#include "RNA_define.hh"
35
36#include "WM_api.hh"
37#include "WM_types.hh"
38
39#include "ED_anim_api.hh"
41#include "ED_markers.hh"
42#include "ED_screen.hh"
43#include "ED_sequencer.hh"
44#include "ED_space_graph.hh"
45#include "ED_time_scrub_ui.hh"
46
47#include "DEG_depsgraph.hh"
49
50#include "SEQ_iterator.hh"
51#include "SEQ_retiming.hh"
52#include "SEQ_sequencer.hh"
53#include "SEQ_time.hh"
54
55#include "ANIM_action.hh"
56#include "ANIM_animdata.hh"
57
58#include "anim_intern.hh"
59
60/* -------------------------------------------------------------------- */
63
70 public:
72
74 {
75 keylist = nullptr;
76 }
77
79 {
80 if (keylist) {
82 }
83 }
84};
85
87struct SnapTarget {
88 float pos;
94};
95
96/* Check if the operator can be run from the current context */
98{
99 ScrArea *area = CTX_wm_area(C);
100
101 /* XXX temp? prevent changes during render */
102 if (G.is_rendering) {
103 return false;
104 }
105
106 /* although it's only included in keymaps for regions using ED_KEYMAP_ANIMATION,
107 * this shouldn't show up in 3D editor (or others without 2D timeline view) via search
108 */
109 if (area) {
111 return true;
112 }
113 if (area->spacetype == SPACE_SEQ) {
115 return false;
116 }
117 /* Check the region type so tools (which are shared between preview/strip view)
118 * don't conflict with actions which can have the same key bound (2D cursor for example). */
119 const ARegion *region = CTX_wm_region(C);
120 if (region && region->regiontype == RGN_TYPE_WINDOW) {
121 return true;
122 }
123 }
124 if (area->spacetype == SPACE_GRAPH) {
125 const SpaceGraph *sipo = static_cast<const SpaceGraph *>(area->spacedata.first);
126 /* Driver Editor's X axis is not time. */
127 if (sipo->mode != SIPO_MODE_DRIVERS) {
128 return true;
129 }
130 }
131 }
132
133 CTX_wm_operator_poll_msg_set(C, "Expected an animation area to be active");
134 return false;
135}
136
137/* Returns the playhead snap threshold in frames. Of course that depends on the zoom level of the
138 * editor. */
139static float get_snap_threshold(const ToolSettings *tool_settings, const ARegion *region)
140{
141 const int snap_threshold = tool_settings->playhead_snap_distance;
142 return UI_view2d_region_to_view_x(&region->v2d, snap_threshold) -
143 UI_view2d_region_to_view_x(&region->v2d, 0);
144}
145
147{
148 /* Only populate data once. */
149 if (op_data.keylist != nullptr) {
150 return;
151 }
152
153 ScrArea *area = CTX_wm_area(C);
154
155 if (area->spacetype == SPACE_SEQ) {
156 /* Special case for the sequencer since it has retiming keys, but those have no bAnimListElem
157 * representation. Need to manually add entries to keylist. */
158 op_data.keylist = ED_keylist_create();
160 if (!scene) {
161 return;
162 }
163
165 LISTBASE_FOREACH (Strip *, strip, seqbase) {
166 sequencer_strip_to_keylist(*strip, *op_data.keylist, *scene);
167 }
169 return;
170 }
171
172 op_data.keylist = ED_keylist_create();
173
174 bAnimContext ac;
175 if (!ANIM_animdata_get_context(C, &ac)) {
176 /* If there is no action, getting the anim context fails in the action editor. */
178 return;
179 }
180
181 ListBase anim_data = {nullptr, nullptr};
182
183 switch (area->spacetype) {
184 case SPACE_ACTION: {
186 ANIM_animdata_filter(&ac, &anim_data, filter, ac.data, ac.datatype);
187 break;
188 }
189
190 case SPACE_GRAPH:
192 break;
193
194 default:
196 break;
197 }
198
199 LISTBASE_FOREACH (bAnimListElem *, ale, &anim_data) {
200 switch (ale->datatype) {
201 case ALE_FCURVE: {
202 FCurve *fcurve = static_cast<FCurve *>(ale->data);
203 fcurve_to_keylist(ale->adt, fcurve, op_data.keylist, 0, {-FLT_MAX, FLT_MAX}, true);
204 break;
205 }
206
207 case ALE_GPFRAME: {
208 gpl_to_keylist(nullptr, static_cast<bGPDlayer *>(ale->data), op_data.keylist);
209 break;
210 }
211
214 ale->adt, static_cast<const GreasePencilLayer *>(ale->data), op_data.keylist, 0);
215 break;
216 }
217
218 default:
219 break;
220 }
221 }
222 ANIM_animdata_freelist(&anim_data);
223
225}
226
228 FrameChangeModalData &op_data,
229 const float timeline_frame,
231{
233 const ActKeyColumn *closest_column = ED_keylist_find_closest(op_data.keylist, timeline_frame);
234 if (!closest_column) {
235 return;
236 }
237 r_targets.append({closest_column->cfra, true});
238}
239
241 const float timeline_frame,
243{
244 if (BLI_listbase_is_empty(&scene->markers)) {
245 /* This check needs to be here because #ED_markers_find_nearest_marker_time returns the
246 * current frame if there are no markers. */
247 return;
248 }
249 const float nearest_marker = ED_markers_find_nearest_marker_time(&scene->markers,
250 timeline_frame);
251 r_targets.append({nearest_marker, true});
252}
253
255 const float timeline_frame,
256 const int step,
258{
259 const int start_frame = scene->r.sfra;
260 const float snap_frame = BKE_scene_frame_snap_by_seconds(
261 scene, step, timeline_frame - start_frame) +
262 start_frame;
263 r_targets.append({snap_frame, false});
264}
265
266static void append_frame_snap_target(const Scene *scene,
267 const float timeline_frame,
268 const int step,
270{
271 const int start_frame = scene->r.sfra;
272 const float snap_frame = (round((timeline_frame - start_frame) / float(step)) * step) +
273 start_frame;
274 r_targets.append({snap_frame, false});
275}
276
277static void seq_frame_snap_update_best(const float position,
278 const float timeline_frame,
279 float *r_best_frame,
280 float *r_best_distance)
281{
282 if (abs(position - timeline_frame) < *r_best_distance) {
283 *r_best_distance = abs(position - timeline_frame);
284 *r_best_frame = position;
285 }
286}
287
289 const Scene *scene,
290 const float timeline_frame,
292{
293 float best_frame = FLT_MAX;
294 float best_distance = FLT_MAX;
295
296 for (Strip *strip : strips) {
298 timeline_frame,
299 &best_frame,
300 &best_distance);
302 timeline_frame,
303 &best_frame,
304 &best_distance);
305 }
306
307 /* best_frame will be FLT_MAX if no target was found. */
308 if (best_distance != FLT_MAX) {
309 r_targets.append({best_frame, true});
310 }
311}
312
314 const float timeline_frame,
316{
317
318 bAnimContext ac;
319 if (!ANIM_animdata_get_context(C, &ac)) {
321 }
322
323 ListBase anim_data = {nullptr, nullptr};
326 ANIM_animdata_filter(&ac, &anim_data, filter, ac.data, eAnimCont_Types(ac.datatype));
327
328 float best_frame = FLT_MAX;
329 float best_distance = FLT_MAX;
330
331 LISTBASE_FOREACH (bAnimListElem *, ale, &anim_data) {
332 if (ale->type != ANIMTYPE_NLATRACK) {
333 continue;
334 }
335 NlaTrack *track = static_cast<NlaTrack *>(ale->data);
336 LISTBASE_FOREACH (NlaStrip *, strip, &track->strips) {
337 if (abs(strip->start - timeline_frame) < best_distance) {
338 best_distance = abs(strip->start - timeline_frame);
339 best_frame = strip->start;
340 }
341 if (abs(strip->end - timeline_frame) < best_distance) {
342 best_distance = abs(strip->end - timeline_frame);
343 best_frame = strip->end;
344 }
345 }
346 }
347 ANIM_animdata_freelist(&anim_data);
348
349 /* If no strip was found, best_frame will be FLT_MAX. */
350 if (best_frame != FLT_MAX) {
351 r_targets.append({best_frame, true});
352 }
353}
354
355/* ---- */
356
358 FrameChangeModalData &op_data,
359 const float timeline_frame)
360{
362 if (!scene) {
363 return {};
364 }
365
366 ToolSettings *tool_settings = scene->toolsettings;
368
369 if (ed == nullptr) {
370 return {};
371 }
372
374
375 if (tool_settings->snap_playhead_mode & SCE_SNAP_TO_STRIPS) {
378 blender::seq::query_all_strips(seqbase), scene, timeline_frame, targets);
379 }
380
381 if (tool_settings->snap_playhead_mode & SCE_SNAP_TO_MARKERS) {
382 append_marker_snap_target(scene, timeline_frame, targets);
383 }
384
385 if (tool_settings->snap_playhead_mode & SCE_SNAP_TO_KEYS) {
386 append_keyframe_snap_target(C, op_data, timeline_frame, targets);
387 }
388
389 if (tool_settings->snap_playhead_mode & SCE_SNAP_TO_SECOND) {
390 append_second_snap_target(scene, timeline_frame, tool_settings->snap_step_seconds, targets);
391 }
392
393 if (tool_settings->snap_playhead_mode & SCE_SNAP_TO_FRAME) {
394 append_frame_snap_target(scene, timeline_frame, tool_settings->snap_step_frames, targets);
395 }
396
397 return targets;
398}
399
400static blender::Vector<SnapTarget> nla_get_snap_targets(bContext *C, const float timeline_frame)
401{
402 Scene *scene = CTX_data_scene(C);
403 ToolSettings *tool_settings = scene->toolsettings;
404
406
407 if (tool_settings->snap_playhead_mode & SCE_SNAP_TO_STRIPS) {
408 append_nla_strip_snap_target(C, timeline_frame, targets);
409 }
410
411 if (tool_settings->snap_playhead_mode & SCE_SNAP_TO_MARKERS) {
412 append_marker_snap_target(scene, timeline_frame, targets);
413 }
414
415 if (tool_settings->snap_playhead_mode & SCE_SNAP_TO_SECOND) {
416 append_second_snap_target(scene, timeline_frame, tool_settings->snap_step_seconds, targets);
417 }
418
419 if (tool_settings->snap_playhead_mode & SCE_SNAP_TO_FRAME) {
420 append_frame_snap_target(scene, timeline_frame, tool_settings->snap_step_frames, targets);
421 }
422
423 return targets;
424}
425
427 FrameChangeModalData &op_data,
428 const float timeline_frame)
429{
430 Scene *scene = CTX_data_scene(C);
431 ToolSettings *tool_settings = scene->toolsettings;
432
434
435 if (tool_settings->snap_playhead_mode & SCE_SNAP_TO_MARKERS) {
436 append_marker_snap_target(scene, timeline_frame, targets);
437 }
438
439 if (tool_settings->snap_playhead_mode & SCE_SNAP_TO_KEYS) {
440 append_keyframe_snap_target(C, op_data, timeline_frame, targets);
441 }
442
443 if (tool_settings->snap_playhead_mode & SCE_SNAP_TO_SECOND) {
444 append_second_snap_target(scene, timeline_frame, tool_settings->snap_step_seconds, targets);
445 }
446
447 if (tool_settings->snap_playhead_mode & SCE_SNAP_TO_FRAME) {
448 append_frame_snap_target(scene, timeline_frame, tool_settings->snap_step_frames, targets);
449 }
450
451 return targets;
452}
453
455 FrameChangeModalData &op_data,
456 const float timeline_frame)
457{
458 Scene *scene = CTX_data_scene(C);
459 ToolSettings *tool_settings = scene->toolsettings;
460
462
463 if (tool_settings->snap_playhead_mode & SCE_SNAP_TO_MARKERS) {
464 append_marker_snap_target(scene, timeline_frame, targets);
465 }
466
467 if (tool_settings->snap_playhead_mode & SCE_SNAP_TO_KEYS) {
468 append_keyframe_snap_target(C, op_data, timeline_frame, targets);
469 }
470
471 if (tool_settings->snap_playhead_mode & SCE_SNAP_TO_SECOND) {
472 append_second_snap_target(scene, timeline_frame, tool_settings->snap_step_seconds, targets);
473 }
474
475 if (tool_settings->snap_playhead_mode & SCE_SNAP_TO_FRAME) {
476 append_frame_snap_target(scene, timeline_frame, tool_settings->snap_step_frames, targets);
477 }
478
479 return targets;
480}
481
482/* ---- */
483
484/* Returns a frame that is snapped to the closest point of interest defined by the area. If no
485 * point of interest is nearby, the frame is returned unmodified. */
486static float apply_frame_snap(bContext *C, FrameChangeModalData &op_data, const float frame)
487{
488 ScrArea *area = CTX_wm_area(C);
489
491 const bool is_sequencer = CTX_wm_space_seq(C) != nullptr;
492 Scene *scene = is_sequencer ? CTX_data_sequencer_scene(C) : CTX_data_scene(C);
493 if (!scene) {
494 return frame;
495 }
496
497 switch (area->spacetype) {
498 case SPACE_SEQ:
499 targets = seq_get_snap_targets(C, op_data, frame);
500 break;
501 case SPACE_ACTION:
502 targets = action_get_snap_targets(C, op_data, frame);
503 break;
504 case SPACE_GRAPH:
505 targets = graph_get_snap_targets(C, op_data, frame);
506 break;
507 case SPACE_NLA:
508 targets = nla_get_snap_targets(C, frame);
509 break;
510
511 default:
512 break;
513 }
514
515 float snap_frame = FLT_MAX;
516
517 /* Find closest frame of all targets. */
518 for (const SnapTarget &target : targets) {
519 if (abs(target.pos - frame) < abs(snap_frame - frame)) {
520 snap_frame = target.pos;
521 }
522 }
523
524 const ARegion *region = CTX_wm_region(C);
525 if (abs(snap_frame - frame) < get_snap_threshold(scene->toolsettings, region)) {
526 return snap_frame;
527 }
528
529 snap_frame = FLT_MAX;
530 /* No frame is close enough to the snap threshold. Hard snap to targets without a threshold. */
531 for (const SnapTarget &target : targets) {
532 if (target.use_snap_treshold) {
533 continue;
534 }
535 if (abs(target.pos - frame) < abs(snap_frame - frame)) {
536 snap_frame = target.pos;
537 }
538 }
539
540 if (snap_frame != FLT_MAX) {
541 return snap_frame;
542 }
543
544 return frame;
545}
546
547/* Set the new frame number */
548static void change_frame_apply(bContext *C, wmOperator *op, const bool always_update)
549{
550 const bool is_sequencer = CTX_wm_space_seq(C) != nullptr;
551 Scene *scene = is_sequencer ? CTX_data_sequencer_scene(C) : CTX_data_scene(C);
552 if (!scene) {
553 return;
554 }
555 float frame = RNA_float_get(op->ptr, "frame");
556 bool do_snap = RNA_boolean_get(op->ptr, "snap");
557
558 const int old_frame = scene->r.cfra;
559 const float old_subframe = scene->r.subframe;
560
561 if (do_snap) {
562 FrameChangeModalData *op_data = static_cast<FrameChangeModalData *>(op->customdata);
563 frame = apply_frame_snap(C, *op_data, frame);
564 }
565
566 /* set the new frame number */
567 if (scene->r.flag & SCER_SHOW_SUBFRAME) {
568 scene->r.cfra = int(frame);
569 scene->r.subframe = frame - int(frame);
570 }
571 else {
572 scene->r.cfra = round_fl_to_int(frame);
573 scene->r.subframe = 0.0f;
574 }
576
578
579 /* do updates */
580 const bool frame_changed = (old_frame != scene->r.cfra) || (old_subframe != scene->r.subframe);
581 if (frame_changed || always_update) {
584 }
585}
586
587/* ---- */
588
589/* Non-modal callback for running operator without user input */
591{
592 change_frame_apply(C, op, true);
593
594 return OPERATOR_FINISHED;
595}
596
597/* ---- */
598
599/* Get frame from mouse coordinates */
600static float frame_from_event(bContext *C, const wmEvent *event)
601{
602 ARegion *region = CTX_wm_region(C);
603 const bool is_sequencer = CTX_wm_space_seq(C) != nullptr;
604 Scene *scene = is_sequencer ? CTX_data_sequencer_scene(C) : CTX_data_scene(C);
605 float frame;
606
607 /* convert from region coordinates to View2D 'tot' space */
608 frame = UI_view2d_region_to_view_x(&region->v2d, event->mval[0]);
609
610 /* respect preview range restrictions (if only allowed to move around within that range) */
611 if (scene->r.flag & SCER_LOCK_FRAME_SELECTION) {
612 CLAMP(frame, PSFRA, PEFRA);
613 }
614
615 return frame;
616}
617
618static void change_frame_seq_preview_begin(bContext *C, const wmEvent *event, SpaceSeq *sseq)
619{
620 BLI_assert(sseq != nullptr);
621 ARegion *region = CTX_wm_region(C);
624 }
625}
626
628{
629 BLI_assert(sseq != nullptr);
630 UNUSED_VARS_NDEBUG(sseq);
631 if (blender::ed::vse::special_preview_get() != nullptr) {
633 }
634}
635
637{
638 const bool is_sequencer = CTX_wm_space_seq(C) != nullptr;
639 Scene *scene = is_sequencer ? CTX_data_sequencer_scene(C) : CTX_data_scene(C);
640 if (!scene) {
641 return false;
642 }
643
644 ScrArea *area = CTX_wm_area(C);
645
646 if (area->spacetype == SPACE_GRAPH) {
647 SpaceGraph *graph_editor = static_cast<SpaceGraph *>(area->spacedata.first);
648 /* Snapping is disabled for driver mode. Need to evaluate if it makes sense there and what form
649 * it should take. */
650 if (graph_editor->mode == SIPO_MODE_DRIVERS) {
651 return false;
652 }
653 }
654
656}
657
658static bool sequencer_skip_for_handle_tweak(const bContext *C, const wmEvent *event)
659{
661 if (!blender::seq::editing_get(scene)) {
662 return false;
663 }
664
665 const View2D *v2d = UI_view2d_fromcontext(C);
666
667 float mouse_co[2];
668 UI_view2d_region_to_view(v2d, event->mval[0], event->mval[1], &mouse_co[0], &mouse_co[1]);
669
671 scene, v2d, mouse_co);
672
674}
675
676/* Modal Operator init */
678{
679 bScreen *screen = CTX_wm_screen(C);
680 FrameChangeModalData *op_data = MEM_new<FrameChangeModalData>(__func__);
681 op->customdata = op_data;
682
683 /* This check is done in case scrubbing and strip tweaking in the sequencer are bound to the same
684 * event (e.g. RCS keymap where both are activated on left mouse press). Tweaking should take
685 * precedence. */
688 }
689
690 /* Change to frame that mouse is over before adding modal handler,
691 * as user could click on a single frame (jump to frame) as well as
692 * click-dragging over a range (modal scrubbing).
693 */
694 RNA_float_set(op->ptr, "frame", frame_from_event(C, event));
695
697 RNA_boolean_set(op->ptr, "snap", true);
698 }
699
700 screen->scrubbing = true;
701
702 if (RNA_boolean_get(op->ptr, "seq_solo_preview")) {
703 SpaceSeq *sseq = CTX_wm_space_seq(C);
704 if (sseq) {
705 change_frame_seq_preview_begin(C, event, sseq);
706 }
707 }
708
709 change_frame_apply(C, op, true);
710
711 /* add temp handler */
713
715}
716
718{
719 if (CTX_wm_space_seq(C)) {
720 /* During scrubbing in the sequencer, a preview of the final video might be drawn. After
721 * scrubbing, the actual result should be shown again. */
722 return true;
723 }
724 Scene *scene = CTX_data_scene(C);
725 if (scene->eevee.taa_samples != 1) {
726 return true;
727 }
728 return false;
729}
730
732{
733 bScreen *screen = CTX_wm_screen(C);
734 screen->scrubbing = false;
735
736 if (RNA_boolean_get(op->ptr, "seq_solo_preview")) {
737 SpaceSeq *sseq = CTX_wm_space_seq(C);
738 if (sseq != nullptr) {
740 }
741 }
742
744 Scene *scene = CTX_data_scene(C);
746 }
747}
748
749/* Modal event handling of frame changing */
751{
753 /* execute the events */
754 switch (event->type) {
755 case EVT_ESCKEY:
757 break;
758
759 case MOUSEMOVE:
760 RNA_float_set(op->ptr, "frame", frame_from_event(C, event));
761 change_frame_apply(C, op, false);
762 break;
763
764 case LEFTMOUSE:
765 case RIGHTMOUSE:
766 case MIDDLEMOUSE:
767 /* We check for either mouse-button to end, to work with all user keymaps. */
768 if (event->val == KM_RELEASE) {
770 }
771 break;
772
773 case EVT_LEFTCTRLKEY:
774 case EVT_RIGHTCTRLKEY:
775 /* Use Ctrl key to invert snapping in sequencer. */
777 if (event->val == KM_RELEASE) {
778 RNA_boolean_set(op->ptr, "snap", true);
779 }
780 else if (event->val == KM_PRESS) {
781 RNA_boolean_set(op->ptr, "snap", false);
782 }
783 }
784 else {
785 if (event->val == KM_RELEASE) {
786 RNA_boolean_set(op->ptr, "snap", false);
787 }
788 else if (event->val == KM_PRESS) {
789 RNA_boolean_set(op->ptr, "snap", true);
790 }
791 }
792 break;
793 default: {
794 break;
795 }
796 }
797
799 status.item(IFACE_("Toggle Snapping"), ICON_EVENT_CTRL);
800
802 ED_workspace_status_text(C, nullptr);
803 bScreen *screen = CTX_wm_screen(C);
804 screen->scrubbing = false;
805
806 FrameChangeModalData *op_data = static_cast<FrameChangeModalData *>(op->customdata);
807 MEM_delete(op_data);
808 op->customdata = nullptr;
809
810 if (RNA_boolean_get(op->ptr, "seq_solo_preview")) {
811 SpaceSeq *sseq = CTX_wm_space_seq(C);
812 if (sseq != nullptr) {
814 }
815 }
816
818 Scene *scene = CTX_data_scene(C);
820 }
821 }
822
823 return ret;
824}
825
827{
828 if (RNA_boolean_get(ptr, "seq_solo_preview")) {
829 return CTX_IFACE_(BLT_I18NCONTEXT_OPERATOR_DEFAULT, "Set Frame (Strip Preview)");
830 }
831
832 return {};
833}
834
836{
837 PropertyRNA *prop;
838
839 /* identifiers */
840 ot->name = "Change Frame";
841 ot->idname = "ANIM_OT_change_frame";
842 ot->description = "Interactively change the current frame number";
843
844 /* API callbacks. */
845 ot->exec = change_frame_exec;
846 ot->invoke = change_frame_invoke;
847 ot->cancel = change_frame_cancel;
848 ot->modal = change_frame_modal;
849 ot->poll = change_frame_poll;
850 ot->get_name = change_frame_get_name;
851
852 /* flags */
854 ot->undo_group = "Frame Change";
855
856 /* rna */
857 ot->prop = RNA_def_float(
858 ot->srna, "frame", 0, MINAFRAME, MAXFRAME, "Frame", "", MINAFRAME, MAXFRAME);
859 prop = RNA_def_boolean(ot->srna, "snap", false, "Snap", "");
861 prop = RNA_def_boolean(ot->srna, "seq_solo_preview", false, "Strip Preview", "");
862}
863
865
866/* -------------------------------------------------------------------- */
869
871{
872 ScrArea *area = CTX_wm_area(C);
873
874 /* XXX temp? prevent changes during render */
875 if (G.is_rendering) {
876 return false;
877 }
878
879 /* although it's only included in keymaps for regions using ED_KEYMAP_ANIMATION,
880 * this shouldn't show up in 3D editor (or others without 2D timeline view) via search
881 */
882 if (area) {
884 return true;
885 }
886 }
887
888 CTX_wm_operator_poll_msg_set(C, "Expected an animation area to be active");
889 return false;
890}
891
893{
894 const bool is_sequencer = CTX_wm_space_seq(C) != nullptr;
895 Scene *scene = is_sequencer ? CTX_data_sequencer_scene(C) : CTX_data_scene(C);
896 int frame;
897
898 if (scene == nullptr) {
899 return OPERATOR_CANCELLED;
900 }
901
902 frame = scene->r.cfra;
903
904 /* if Preview Range is defined, set the 'start' frame for that */
905 if (PRVRANGEON) {
906 scene->r.psfra = frame;
907 }
908 else {
909 /* Clamping should be in sync with 'rna_Scene_start_frame_set()'. */
910 int frame_clamped = frame;
911 CLAMP(frame_clamped, MINFRAME, MAXFRAME);
912 if (frame_clamped != frame) {
913 BKE_report(op->reports, RPT_WARNING, "Start frame clamped to valid rendering range");
914 }
915 frame = frame_clamped;
916 scene->r.sfra = frame;
917 }
918
919 if (PEFRA < frame) {
920 if (PRVRANGEON) {
921 scene->r.pefra = frame;
922 }
923 else {
924 scene->r.efra = frame;
925 }
926 }
927
929
930 return OPERATOR_FINISHED;
931}
932
934{
935 /* identifiers */
936 ot->name = "Set Start Frame";
937 ot->idname = "ANIM_OT_start_frame_set";
938 ot->description = "Set the current frame as the preview or scene start frame";
939
940 /* API callbacks. */
941 ot->exec = anim_set_sfra_exec;
943
944 /* flags */
946}
947
949{
950 const bool is_sequencer = CTX_wm_space_seq(C) != nullptr;
951 Scene *scene = is_sequencer ? CTX_data_sequencer_scene(C) : CTX_data_scene(C);
952 int frame;
953
954 if (scene == nullptr) {
955 return OPERATOR_CANCELLED;
956 }
957
958 frame = scene->r.cfra;
959
960 /* if Preview Range is defined, set the 'end' frame for that */
961 if (PRVRANGEON) {
962 scene->r.pefra = frame;
963 }
964 else {
965 /* Clamping should be in sync with 'rna_Scene_end_frame_set()'. */
966 int frame_clamped = frame;
967 CLAMP(frame_clamped, MINFRAME, MAXFRAME);
968 if (frame_clamped != frame) {
969 BKE_report(op->reports, RPT_WARNING, "End frame clamped to valid rendering range");
970 }
971 frame = frame_clamped;
972 scene->r.efra = frame;
973 }
974
975 if (PSFRA > frame) {
976 if (PRVRANGEON) {
977 scene->r.psfra = frame;
978 }
979 else {
980 scene->r.sfra = frame;
981 }
982 }
983
985
986 return OPERATOR_FINISHED;
987}
988
990{
991 /* identifiers */
992 ot->name = "Set End Frame";
993 ot->idname = "ANIM_OT_end_frame_set";
994 ot->description = "Set the current frame as the preview or scene end frame";
995
996 /* API callbacks. */
997 ot->exec = anim_set_efra_exec;
999
1000 /* flags */
1001 ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
1002}
1003
1005
1006/* -------------------------------------------------------------------- */
1009
1011{
1012 const bool is_sequencer = CTX_wm_space_seq(C) != nullptr;
1013 Scene *scene = is_sequencer ? CTX_data_sequencer_scene(C) : CTX_data_scene(C);
1014 if (!scene) {
1015 return OPERATOR_CANCELLED;
1016 }
1017 ARegion *region = CTX_wm_region(C);
1018 float sfra, efra;
1019 rcti rect;
1020
1021 /* get min/max values from box select rect (already in region coordinates, not screen) */
1023
1024 /* convert min/max values to frames (i.e. region to 'tot' rect) */
1025 sfra = UI_view2d_region_to_view_x(&region->v2d, rect.xmin);
1026 efra = UI_view2d_region_to_view_x(&region->v2d, rect.xmax);
1027
1028 /* set start/end frames for preview-range
1029 * - must clamp within allowable limits
1030 * - end must not be before start (though this won't occur most of the time)
1031 */
1034 efra = std::max(efra, sfra);
1035
1036 scene->r.flag |= SCER_PRV_RANGE;
1037 scene->r.psfra = round_fl_to_int(sfra);
1038 scene->r.pefra = round_fl_to_int(efra);
1039
1040 /* send notifiers */
1042
1043 return OPERATOR_FINISHED;
1044}
1045
1047{
1048 /* identifiers */
1049 ot->name = "Set Preview Range";
1050 ot->idname = "ANIM_OT_previewrange_set";
1051 ot->description = "Interactively define frame range used for playback";
1052
1053 /* API callbacks. */
1054 ot->invoke = WM_gesture_box_invoke;
1056 ot->modal = WM_gesture_box_modal;
1057 ot->cancel = WM_gesture_box_cancel;
1058
1060
1061 /* flags */
1062 ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
1063
1064 /* rna */
1065 /* used to define frame range.
1066 *
1067 * NOTE: border Y values are not used,
1068 * but are needed by box_select gesture operator stuff */
1070}
1071
1073
1074/* -------------------------------------------------------------------- */
1077
1079{
1080 const bool is_sequencer = CTX_wm_space_seq(C) != nullptr;
1081 Scene *scene = is_sequencer ? CTX_data_sequencer_scene(C) : CTX_data_scene(C);
1082 ScrArea *curarea = CTX_wm_area(C);
1083
1084 /* sanity checks */
1085 if (ELEM(nullptr, scene, curarea)) {
1086 return OPERATOR_CANCELLED;
1087 }
1088
1089 /* simply clear values */
1090 scene->r.flag &= ~SCER_PRV_RANGE;
1091 scene->r.psfra = 0;
1092 scene->r.pefra = 0;
1093
1094 ED_area_tag_redraw(curarea);
1095
1096 /* send notifiers */
1098
1099 return OPERATOR_FINISHED;
1100}
1101
1103{
1104 /* identifiers */
1105 ot->name = "Clear Preview Range";
1106 ot->idname = "ANIM_OT_previewrange_clear";
1107 ot->description = "Clear preview range";
1108
1109 /* API callbacks. */
1111
1113
1114 /* flags */
1115 ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
1116}
1117
1119
1120/* -------------------------------------------------------------------- */
1123
1124#ifndef NDEBUG
1126{
1127 bAnimContext ac;
1128 if (ANIM_animdata_get_context(C, &ac) == 0) {
1129 return OPERATOR_CANCELLED;
1130 }
1131
1132 ListBase anim_data = {nullptr, nullptr};
1133 /* Same filter flags as in action_channel_region_draw() in
1134 * `source/blender/editors/space_action/space_action.cc`. */
1137 ANIM_animdata_filter(&ac, &anim_data, filter, ac.data, eAnimCont_Types(ac.datatype));
1138
1139 printf("==============================================\n");
1140 printf("Animation Channel List:\n");
1141 printf("----------------------------------------------\n");
1142
1143 LISTBASE_FOREACH (bAnimListElem *, ale, &anim_data) {
1145 }
1146
1147 printf("==============================================\n");
1148
1149 ANIM_animdata_freelist(&anim_data);
1150 return OPERATOR_FINISHED;
1151}
1152
1154{
1155 ot->name = "Debug Channel List";
1156 ot->idname = "ANIM_OT_debug_channel_list";
1157 ot->description =
1158 "Log the channel list info in the terminal. This operator is only available in debug builds "
1159 "of Blender";
1160
1163
1164 ot->flag = OPTYPE_REGISTER;
1165}
1166#endif /* !NDEBUG */
1167
1169
1170/* -------------------------------------------------------------------- */
1173
1175{
1176 const bool is_sequencer = CTX_wm_space_seq(C) != nullptr;
1177 const Scene *scene = is_sequencer ? CTX_data_sequencer_scene(C) : CTX_data_scene(C);
1178 if (!scene) {
1179 return OPERATOR_CANCELLED;
1180 }
1181 ARegion *region = CTX_wm_region(C);
1182 BLI_assert(region);
1183
1184 View2D &v2d = region->v2d;
1185 v2d.cur.xmin = PSFRA;
1186 v2d.cur.xmax = PEFRA;
1187
1189
1192
1193 return OPERATOR_FINISHED;
1194}
1195
1197{
1198 ot->name = "Frame Scene/Preview Range";
1199 ot->idname = "ANIM_OT_scene_range_frame";
1200 ot->description =
1201 "Reset the horizontal view to the current scene frame range, taking the preview range into "
1202 "account if it is active";
1203
1204 ot->exec = scene_range_frame_exec;
1206
1207 ot->flag = OPTYPE_REGISTER;
1208}
1209
1211
1212/* -------------------------------------------------------------------- */
1215
1217{
1218 using namespace blender;
1219
1220 Object *object = CTX_data_active_object(C);
1221 AnimData *adt = BKE_animdata_from_id(&object->id);
1222 BLI_assert(adt != nullptr);
1223 BLI_assert(adt->action != nullptr);
1224
1225 animrig::Action &legacy_action = adt->action->wrap();
1226 Main *bmain = CTX_data_main(C);
1227
1228 animrig::Action *layered_action = animrig::convert_to_layered_action(*bmain, legacy_action);
1229 /* We did already check if the action can be converted. */
1230 BLI_assert(layered_action != nullptr);
1231 const bool assign_ok = animrig::assign_action(layered_action, object->id);
1232 BLI_assert_msg(assign_ok, "Expecting assigning a layered Action to always work");
1233 UNUSED_VARS_NDEBUG(assign_ok);
1234
1235 BLI_assert(layered_action->slots().size() == 1);
1236 animrig::Slot *slot = layered_action->slot(0);
1237 layered_action->slot_identifier_set(*bmain, *slot, object->id.name);
1238
1242
1243 ANIM_id_update(bmain, &object->id);
1246
1247 return OPERATOR_FINISHED;
1248}
1249
1251{
1252 Object *object = CTX_data_active_object(C);
1253 if (!object) {
1254 return false;
1255 }
1256
1257 AnimData *adt = BKE_animdata_from_id(&object->id);
1258 if (!adt || !adt->action) {
1259 return false;
1260 }
1261
1262 /* This will also convert empty actions to layered by just adding an empty slot. */
1263 if (!adt->action->wrap().is_action_legacy()) {
1264 CTX_wm_operator_poll_msg_set(C, "Action is already layered");
1265 return false;
1266 }
1267
1268 return true;
1269}
1270
1272{
1273 /* identifiers */
1274 ot->name = "Convert Legacy Action";
1275 ot->idname = "ANIM_OT_convert_legacy_action";
1276 ot->description = "Convert a legacy Action to a layered Action on the active object";
1277
1278 /* API callbacks. */
1279 ot->exec = convert_action_exec;
1280 ot->poll = convert_action_poll;
1281
1282 /* flags */
1283 ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
1284}
1285
1287{
1288 Object *object = CTX_data_active_object(C);
1289 if (!object) {
1290 CTX_wm_operator_poll_msg_set(C, "No active object");
1291 return false;
1292 }
1294 if (!action) {
1295 CTX_wm_operator_poll_msg_set(C, "Active object has no action");
1296 return false;
1297 }
1298 if (!BKE_id_is_editable(CTX_data_main(C), &action->id)) {
1299 return false;
1300 }
1301 return true;
1302}
1303
1305{
1306 using namespace blender::animrig;
1307 Object *active_object = CTX_data_active_object(C);
1308 /* Those cases are caught by the poll. */
1309 BLI_assert(active_object != nullptr);
1310 BLI_assert(active_object->adt->action != nullptr);
1311
1312 Action &active_action = active_object->adt->action->wrap();
1313
1315 if (!CTX_data_selected_objects(C, &selection)) {
1316 return OPERATOR_CANCELLED;
1317 }
1318
1319 Main *bmain = CTX_data_main(C);
1320 int moved_slots_count = 0;
1321 for (const PointerRNA &ptr : selection) {
1322 blender::Vector<ID *> related_ids = find_related_ids(*bmain, *ptr.owner_id);
1323 for (ID *related_id : related_ids) {
1324 Action *action = get_action(*related_id);
1325 if (!action) {
1326 continue;
1327 }
1328 if (action == &active_action) {
1329 /* Object is already animated by the same action, no point in moving. */
1330 continue;
1331 }
1332 if (action->is_action_legacy()) {
1333 continue;
1334 }
1335 if (!BKE_id_is_editable(bmain, &action->id)) {
1336 BKE_reportf(op->reports, RPT_WARNING, "The action %s is not editable", action->id.name);
1337 continue;
1338 }
1339 AnimData *id_anim_data = BKE_animdata_ensure_id(related_id);
1340 /* Since we already get an action from the ID the animdata has to exist. */
1341 BLI_assert(id_anim_data);
1342 Slot *slot = action->slot_for_handle(id_anim_data->slot_handle);
1343 if (!slot) {
1344 continue;
1345 }
1346 blender::animrig::move_slot(*bmain, *slot, *action, active_action);
1347 moved_slots_count++;
1348 ANIM_id_update(bmain, related_id);
1350 }
1351 }
1352
1353 if (moved_slots_count > 0) {
1354 BKE_reportf(op->reports,
1355 RPT_INFO,
1356 "Moved %i slot(s) into the action of the active object",
1357 moved_slots_count);
1358 }
1359 else {
1360 BKE_reportf(op->reports,
1361 RPT_ERROR,
1362 "Failed to merge any animation. Note that NLA strips cannot be merged");
1363 }
1364
1365 /* `ID_RECALC_ANIMATION_NO_FLUSH` is used here (and above), as the actual animation values do not
1366 * change, so there is no need to flush to the animated IDs. The Action itself does need to be
1367 * re-evaluated to get an up-to-date evaluated copy with the new slots & channelbags. Without
1368 * this, future animation evaluation will break. */
1370
1373
1374 return OPERATOR_FINISHED;
1375}
1376
1378{
1379 ot->name = "Merge Animation";
1380 ot->idname = "ANIM_OT_merge_animation";
1381 ot->description =
1382 "Merge the animation of the selected objects into the action of the active object. Actions "
1383 "are not deleted by this, but might end up with zero users";
1384
1387
1388 ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
1389}
1390
1392
1393/* -------------------------------------------------------------------- */
1396
1398{
1399 /* Animation Editors only -------------------------- */
1401
1404
1407
1409
1410#ifndef NDEBUG
1412#endif
1413
1414 /* Entire UI --------------------------------------- */
1427
1433
1436
1441
1443
1446
1450}
1451
1453{
1454 WM_keymap_ensure(keyconf, "Animation", SPACE_EMPTY, RGN_TYPE_WINDOW);
1455}
1456
Functions and classes to work with Actions.
Functions to work with AnimData.
AnimData * BKE_animdata_ensure_id(ID *id)
Definition anim_data.cc:97
AnimData * BKE_animdata_from_id(const ID *id)
Definition anim_data.cc:83
bScreen * CTX_wm_screen(const bContext *C)
void CTX_wm_operator_poll_msg_set(bContext *C, const char *msg)
ScrArea * CTX_wm_area(const bContext *C)
Object * CTX_data_active_object(const bContext *C)
Scene * CTX_data_scene(const bContext *C)
SpaceSeq * CTX_wm_space_seq(const bContext *C)
bool CTX_data_selected_objects(const bContext *C, blender::Vector< PointerRNA > *list)
Main * CTX_data_main(const bContext *C)
ARegion * CTX_wm_region(const bContext *C)
Scene * CTX_data_sequencer_scene(const bContext *C)
bool BKE_id_is_editable(const Main *bmain, const ID *id)
Definition lib_id.cc:2523
void BKE_reportf(ReportList *reports, eReportType type, const char *format,...) ATTR_PRINTF_FORMAT(3
@ RPT_INFO
Definition BKE_report.hh:35
@ RPT_ERROR
Definition BKE_report.hh:39
@ RPT_WARNING
Definition BKE_report.hh:38
void BKE_report(ReportList *reports, eReportType type, const char *message)
Definition report.cc:153
float BKE_scene_frame_snap_by_seconds(const Scene *scene, double interval_in_seconds, float frame)
Definition scene.cc:2321
#define BLI_assert_unreachable()
Definition BLI_assert.h:93
#define BLI_assert(a)
Definition BLI_assert.h:46
#define BLI_assert_msg(a, msg)
Definition BLI_assert.h:53
#define LISTBASE_FOREACH(type, var, list)
BLI_INLINE bool BLI_listbase_is_empty(const ListBase *lb)
MINLINE int round_fl_to_int(float a)
#define CLAMP(a, b, c)
#define UNUSED_VARS_NDEBUG(...)
#define ELEM(...)
#define CTX_IFACE_(context, msgid)
#define BLT_I18NCONTEXT_OPERATOR_DEFAULT
#define IFACE_(msgid)
void DEG_id_tag_update(ID *id, unsigned int flags)
void DEG_relations_tag_update(Main *bmain)
@ ID_RECALC_FRAME_CHANGE
Definition DNA_ID.h:1125
@ ID_RECALC_ANIMATION_NO_FLUSH
Definition DNA_ID.h:1176
#define MINFRAME
#define MINAFRAME
#define PSFRA
@ SCE_SNAP
@ SCER_SHOW_SUBFRAME
@ SCER_PRV_RANGE
@ SCER_LOCK_FRAME_SELECTION
#define PRVRANGEON
#define PEFRA
@ SCE_SNAP_TO_KEYS
@ SCE_SNAP_TO_MARKERS
@ SCE_SNAP_TO_FRAME
@ SCE_SNAP_TO_SECOND
@ SCE_SNAP_TO_STRIPS
#define MAXFRAME
@ RGN_TYPE_WINDOW
@ SPACE_CLIP
@ SPACE_ACTION
@ SPACE_NLA
@ SPACE_SEQ
@ SPACE_EMPTY
@ SPACE_GRAPH
@ SIPO_MODE_DRIVERS
#define FRAMENUMBER_MIN_CLAMP(cfra)
@ OPERATOR_CANCELLED
@ OPERATOR_FINISHED
@ OPERATOR_RUNNING_MODAL
@ OPERATOR_PASS_THROUGH
@ ANIMTYPE_NLATRACK
@ ALE_GREASE_PENCIL_CEL
@ ALE_GPFRAME
@ ALE_FCURVE
eAnimCont_Types
eAnimFilter_Flags
@ ANIMFILTER_DATA_VISIBLE
@ ANIMFILTER_LIST_VISIBLE
@ ANIMFILTER_LIST_CHANNELS
@ ANIMFILTER_FCURVESONLY
void ED_area_tag_redraw(ScrArea *area)
Definition area.cc:693
bool ED_operator_animview_active(bContext *C)
void ED_workspace_status_text(bContext *C, const char *str)
Definition area.cc:1024
@ PROP_SKIP_SAVE
Definition RNA_types.hh:344
#define C
Definition RandGen.cpp:29
void UI_view2d_sync(bScreen *screen, ScrArea *area, View2D *v2dcur, int flag)
Definition view2d.cc:865
#define V2D_LOCK_COPY
Definition UI_view2d.hh:85
View2D * UI_view2d_fromcontext(const bContext *C)
Definition view2d.cc:1855
void UI_view2d_region_to_view(const View2D *v2d, float x, float y, float *r_view_x, float *r_view_y) ATTR_NONNULL()
Definition view2d.cc:1668
float UI_view2d_region_to_view_x(const View2D *v2d, float x)
Definition view2d.cc:1657
#define ND_NLA_ACTCHANGE
Definition WM_types.hh:498
@ KM_PRESS
Definition WM_types.hh:311
@ KM_RELEASE
Definition WM_types.hh:312
#define NC_ANIMATION
Definition WM_types.hh:388
#define NC_SCENE
Definition WM_types.hh:378
@ OPTYPE_BLOCKING
Definition WM_types.hh:184
@ OPTYPE_UNDO_GROUPED
Definition WM_types.hh:207
@ OPTYPE_UNDO
Definition WM_types.hh:182
@ OPTYPE_REGISTER
Definition WM_types.hh:180
@ OPTYPE_GRAB_CURSOR_X
Definition WM_types.hh:190
#define ND_FRAME
Definition WM_types.hh:434
void ANIM_channel_debug_print_info(bAnimContext &ac, bAnimListElem *ale, short indent_level)
void ANIM_animdata_freelist(ListBase *anim_data)
Definition anim_deps.cc:463
void ANIM_id_update(Main *bmain, ID *id)
Definition anim_deps.cc:103
rctf ANIM_frame_range_view2d_add_xmargin(const View2D &view_2d, const rctf view_rect)
Definition anim_draw.cc:811
bool ANIM_animdata_get_context(const bContext *C, bAnimContext *ac)
size_t ANIM_animdata_filter(bAnimContext *ac, ListBase *anim_data, const eAnimFilter_Flags filter_mode, void *data, const eAnimCont_Types datatype)
void ANIM_OT_keyframe_insert_menu(wmOperatorType *ot)
void ANIM_OT_keyframe_delete_vse(wmOperatorType *ot)
void ANIM_OT_keying_set_add(wmOperatorType *ot)
void ANIM_OT_driver_button_remove(wmOperatorType *ot)
Definition drivers.cc:1095
void ANIM_OT_driver_button_add(wmOperatorType *ot)
Definition drivers.cc:1046
void ANIM_OT_keyframe_insert(wmOperatorType *ot)
void ANIM_OT_driver_button_edit(wmOperatorType *ot)
Definition drivers.cc:1131
void ANIM_OT_keying_set_path_remove(wmOperatorType *ot)
void ANIM_OT_keyframe_clear_button(wmOperatorType *ot)
void ANIM_OT_keyframe_insert_by_name(wmOperatorType *ot)
void ANIM_OT_keyframe_delete(wmOperatorType *ot)
void ANIM_OT_keyingset_button_add(wmOperatorType *ot)
void ANIM_OT_keyframe_clear_v3d(wmOperatorType *ot)
void ANIM_OT_keying_set_remove(wmOperatorType *ot)
void ANIM_OT_paste_driver_button(wmOperatorType *ot)
Definition drivers.cc:1216
void ANIM_OT_keyframe_insert_button(wmOperatorType *ot)
void ANIM_OT_keying_set_active_set(wmOperatorType *ot)
void ANIM_OT_copy_driver_button(wmOperatorType *ot)
Definition drivers.cc:1171
void ANIM_OT_keyingset_button_remove(wmOperatorType *ot)
void ANIM_OT_keying_set_path_add(wmOperatorType *ot)
void ANIM_OT_keyframe_delete_v3d(wmOperatorType *ot)
void ANIM_OT_keyframe_delete_button(wmOperatorType *ot)
void ANIM_OT_keyframe_delete_by_name(wmOperatorType *ot)
void ANIM_OT_keyframe_clear_vse(wmOperatorType *ot)
int ED_markers_find_nearest_marker_time(ListBase *markers, float x)
static wmOperatorStatus debug_channel_list_exec(bContext *C, wmOperator *)
Definition anim_ops.cc:1125
void ED_operatortypes_anim()
Definition anim_ops.cc:1397
static void change_frame_apply(bContext *C, wmOperator *op, const bool always_update)
Definition anim_ops.cc:548
static void ANIM_OT_previewrange_set(wmOperatorType *ot)
Definition anim_ops.cc:1046
static bool anim_set_end_frames_poll(bContext *C)
Definition anim_ops.cc:870
static void ANIM_OT_previewrange_clear(wmOperatorType *ot)
Definition anim_ops.cc:1102
static void append_frame_snap_target(const Scene *scene, const float timeline_frame, const int step, blender::Vector< SnapTarget > &r_targets)
Definition anim_ops.cc:266
static void ANIM_OT_convert_legacy_action(wmOperatorType *ot)
Definition anim_ops.cc:1271
static wmOperatorStatus merge_actions_selection_exec(bContext *C, wmOperator *op)
Definition anim_ops.cc:1304
static float get_snap_threshold(const ToolSettings *tool_settings, const ARegion *region)
Definition anim_ops.cc:139
static wmOperatorStatus change_frame_exec(bContext *C, wmOperator *op)
Definition anim_ops.cc:590
static void ANIM_OT_start_frame_set(wmOperatorType *ot)
Definition anim_ops.cc:933
static void ANIM_OT_scene_range_frame(wmOperatorType *ot)
Definition anim_ops.cc:1196
static bool merge_actions_selection_poll(bContext *C)
Definition anim_ops.cc:1286
static void append_nla_strip_snap_target(bContext *C, const float timeline_frame, blender::Vector< SnapTarget > &r_targets)
Definition anim_ops.cc:313
static wmOperatorStatus previewrange_define_exec(bContext *C, wmOperator *op)
Definition anim_ops.cc:1010
static wmOperatorStatus change_frame_modal(bContext *C, wmOperator *op, const wmEvent *event)
Definition anim_ops.cc:750
static void seq_frame_snap_update_best(const float position, const float timeline_frame, float *r_best_frame, float *r_best_distance)
Definition anim_ops.cc:277
static bool use_playhead_snapping(bContext *C)
Definition anim_ops.cc:636
static void ANIM_OT_end_frame_set(wmOperatorType *ot)
Definition anim_ops.cc:989
static void change_frame_seq_preview_begin(bContext *C, const wmEvent *event, SpaceSeq *sseq)
Definition anim_ops.cc:618
static wmOperatorStatus anim_set_sfra_exec(bContext *C, wmOperator *op)
Definition anim_ops.cc:892
static wmOperatorStatus change_frame_invoke(bContext *C, wmOperator *op, const wmEvent *event)
Definition anim_ops.cc:677
static void ensure_change_frame_keylist(bContext *C, FrameChangeModalData &op_data)
Definition anim_ops.cc:146
static wmOperatorStatus previewrange_clear_exec(bContext *C, wmOperator *)
Definition anim_ops.cc:1078
static bool sequencer_skip_for_handle_tweak(const bContext *C, const wmEvent *event)
Definition anim_ops.cc:658
static blender::Vector< SnapTarget > action_get_snap_targets(bContext *C, FrameChangeModalData &op_data, const float timeline_frame)
Definition anim_ops.cc:426
static wmOperatorStatus convert_action_exec(bContext *C, wmOperator *)
Definition anim_ops.cc:1216
static wmOperatorStatus scene_range_frame_exec(bContext *C, wmOperator *)
Definition anim_ops.cc:1174
static std::string change_frame_get_name(wmOperatorType *, PointerRNA *ptr)
Definition anim_ops.cc:826
static float frame_from_event(bContext *C, const wmEvent *event)
Definition anim_ops.cc:600
static wmOperatorStatus anim_set_efra_exec(bContext *C, wmOperator *op)
Definition anim_ops.cc:948
static void append_second_snap_target(Scene *scene, const float timeline_frame, const int step, blender::Vector< SnapTarget > &r_targets)
Definition anim_ops.cc:254
void ED_keymap_anim(wmKeyConfig *keyconf)
Definition anim_ops.cc:1452
static blender::Vector< SnapTarget > seq_get_snap_targets(bContext *C, FrameChangeModalData &op_data, const float timeline_frame)
Definition anim_ops.cc:357
static void append_marker_snap_target(Scene *scene, const float timeline_frame, blender::Vector< SnapTarget > &r_targets)
Definition anim_ops.cc:240
static void ANIM_OT_merge_animation(wmOperatorType *ot)
Definition anim_ops.cc:1377
static bool convert_action_poll(bContext *C)
Definition anim_ops.cc:1250
static bool need_extra_redraw_after_scrubbing_ends(bContext *C)
Definition anim_ops.cc:717
static void append_sequencer_strip_snap_target(blender::Span< Strip * > strips, const Scene *scene, const float timeline_frame, blender::Vector< SnapTarget > &r_targets)
Definition anim_ops.cc:288
static bool change_frame_poll(bContext *C)
Definition anim_ops.cc:97
static void ANIM_OT_change_frame(wmOperatorType *ot)
Definition anim_ops.cc:835
static void ANIM_OT_debug_channel_list(wmOperatorType *ot)
Definition anim_ops.cc:1153
static blender::Vector< SnapTarget > graph_get_snap_targets(bContext *C, FrameChangeModalData &op_data, const float timeline_frame)
Definition anim_ops.cc:454
static float apply_frame_snap(bContext *C, FrameChangeModalData &op_data, const float frame)
Definition anim_ops.cc:486
static void change_frame_seq_preview_end(SpaceSeq *sseq)
Definition anim_ops.cc:627
static void change_frame_cancel(bContext *C, wmOperator *op)
Definition anim_ops.cc:731
static blender::Vector< SnapTarget > nla_get_snap_targets(bContext *C, const float timeline_frame)
Definition anim_ops.cc:400
static void append_keyframe_snap_target(bContext *C, FrameChangeModalData &op_data, const float timeline_frame, blender::Vector< SnapTarget > &r_targets)
Definition anim_ops.cc:227
AnimKeylist * keylist
Definition anim_ops.cc:71
void append(const T &value)
void slot_identifier_set(Main &bmain, Slot &slot, StringRefNull new_identifier)
const Slot * slot(int64_t index) const
blender::Span< const Slot * > slots() const
Slot * slot_for_handle(slot_handle_t handle)
#define filter
#define printf(...)
#define round
#define abs
VecBase< float, D > step(VecOp< float, D >, VecOp< float, D >) RET
void fcurve_to_keylist(AnimData *adt, FCurve *fcu, AnimKeylist *keylist, const int saction_flag, blender::float2 range, const bool use_nla_remapping)
const ActKeyColumn * ED_keylist_find_closest(const AnimKeylist *keylist, const float cfra)
void ED_keylist_prepare_for_direct_access(AnimKeylist *keylist)
AnimKeylist * ED_keylist_create()
void ED_keylist_free(AnimKeylist *keylist)
void sequencer_strip_to_keylist(const Strip &strip, AnimKeylist &keylist, Scene &scene)
void grease_pencil_cels_to_keylist(AnimData *, const GreasePencilLayer *gpl, AnimKeylist *keylist, int)
void gpl_to_keylist(bDopeSheet *, bGPDlayer *gpl, AnimKeylist *keylist)
DEG_id_tag_update_ex(cb_data->bmain, cb_data->owner_id, ID_RECALC_TAG_FOR_UNDO|ID_RECALC_SYNC_TO_EVAL)
#define G(x, y, z)
Vector< ID * > find_related_ids(Main &bmain, ID &id)
Definition animdata.cc:62
Action * get_action(ID &animated_id)
Action * convert_to_layered_action(Main &bmain, const Action &legacy_action)
bool assign_action(bAction *action, ID &animated_id)
ActionSlotAssignmentResult assign_action_slot(Slot *slot_to_assign, ID &animated_id)
void move_slot(Main &bmain, Slot &slot, Action &from_action, Action &to_action)
void POSELIB_OT_asset_delete(wmOperatorType *ot)
void POSELIB_OT_create_pose_asset(wmOperatorType *ot)
void POSELIB_OT_asset_modify(wmOperatorType *ot)
ListBase get_editable_fcurves(bAnimContext &ac)
bool check_show_strip(const SpaceSeq &sseq)
StripSelection pick_strip_and_handle(const struct Scene *scene, const View2D *v2d, float mouse_co[2])
void sync_active_scene_and_time_with_scene_strip(bContext &C)
void special_preview_set(bContext *C, const int mval[2])
int time_right_handle_frame_get(const Scene *scene, const Strip *strip)
VectorSet< Strip * > query_all_strips(ListBase *seqbase)
Definition iterator.cc:143
Editing * editing_get(const Scene *scene)
Definition sequencer.cc:286
int time_left_handle_frame_get(const Scene *, const Strip *strip)
ListBase * active_seqbase_get(const Editing *ed)
Definition sequencer.cc:433
const int status
return ret
void RNA_boolean_set(PointerRNA *ptr, const char *name, bool value)
float RNA_float_get(PointerRNA *ptr, const char *name)
void RNA_float_set(PointerRNA *ptr, const char *name, float value)
bool RNA_boolean_get(PointerRNA *ptr, const char *name)
PropertyRNA * RNA_def_float(StructOrFunctionRNA *cont_, const char *identifier, const float default_value, const float hardmin, const float hardmax, const char *ui_name, const char *ui_description, const float softmin, const float softmax)
PropertyRNA * RNA_def_boolean(StructOrFunctionRNA *cont_, const char *identifier, const bool default_value, const char *ui_name, const char *ui_description)
void RNA_def_property_flag(PropertyRNA *prop, PropertyFlag flag)
#define FLT_MAX
Definition stdcycles.h:14
bAction * action
int32_t slot_handle
Definition DNA_ID.h:414
char name[258]
Definition DNA_ID.h:432
void * first
ListBase strips
struct AnimData * adt
struct ToolSettings * toolsettings
struct RenderData r
ListBase markers
struct SceneEEVEE eevee
ListBase spacedata
float pos
Definition anim_ops.cc:88
bool use_snap_treshold
Definition anim_ops.cc:93
int16_t snap_step_seconds
int16_t snap_step_frames
eAnimCont_Types datatype
float xmax
float xmin
int xmin
int xmax
wmEventType type
Definition WM_types.hh:757
short val
Definition WM_types.hh:759
int mval[2]
Definition WM_types.hh:763
struct ReportList * reports
struct PointerRNA * ptr
bool ED_time_scrub_event_in_region(const ARegion *region, const wmEvent *event)
void WM_main_add_notifier(uint type, void *reference)
wmEventHandler_Op * WM_event_add_modal_handler(bContext *C, wmOperator *op)
void WM_event_add_notifier(const bContext *C, uint type, void *reference)
@ RIGHTMOUSE
@ EVT_RIGHTCTRLKEY
@ EVT_LEFTCTRLKEY
@ MOUSEMOVE
@ LEFTMOUSE
@ MIDDLEMOUSE
@ EVT_ESCKEY
PointerRNA * ptr
Definition wm_files.cc:4238
wmOperatorType * ot
Definition wm_files.cc:4237
void WM_gesture_box_cancel(bContext *C, wmOperator *op)
wmOperatorStatus WM_gesture_box_modal(bContext *C, wmOperator *op, const wmEvent *event)
wmOperatorStatus WM_gesture_box_invoke(bContext *C, wmOperator *op, const wmEvent *event)
wmKeyMap * WM_keymap_ensure(wmKeyConfig *keyconf, const char *idname, int spaceid, int regionid)
Definition wm_keymap.cc:895
void WM_operator_properties_border_to_rcti(wmOperator *op, rcti *r_rect)
void WM_operator_properties_border(wmOperatorType *ot)
void WM_operatortype_append(void(*opfunc)(wmOperatorType *))