Blender V4.5
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) {
114 /* Check the region type so tools (which are shared between preview/strip view)
115 * don't conflict with actions which can have the same key bound (2D cursor for example). */
116 const ARegion *region = CTX_wm_region(C);
117 if (region && region->regiontype == RGN_TYPE_WINDOW) {
118 return true;
119 }
120 }
121 if (area->spacetype == SPACE_GRAPH) {
122 const SpaceGraph *sipo = static_cast<const SpaceGraph *>(area->spacedata.first);
123 /* Driver Editor's X axis is not time. */
124 if (sipo->mode != SIPO_MODE_DRIVERS) {
125 return true;
126 }
127 }
128 }
129
130 CTX_wm_operator_poll_msg_set(C, "Expected an animation area to be active");
131 return false;
132}
133
134/* Returns the playhead snap threshold in frames. Of course that depends on the zoom level of the
135 * editor. */
136static float get_snap_threshold(const ToolSettings *tool_settings, const ARegion *region)
137{
138 const int snap_threshold = tool_settings->playhead_snap_distance;
139 return UI_view2d_region_to_view_x(&region->v2d, snap_threshold) -
140 UI_view2d_region_to_view_x(&region->v2d, 0);
141}
142
144{
145 /* Only populate data once. */
146 if (op_data.keylist != nullptr) {
147 return;
148 }
149
150 ScrArea *area = CTX_wm_area(C);
151
152 if (area->spacetype == SPACE_SEQ) {
153 /* Special case for the sequencer since it has retiming keys, but those have no bAnimListElem
154 * representation. Need to manually add entries to keylist. */
155 op_data.keylist = ED_keylist_create();
156 Scene *scene = CTX_data_scene(C);
157 if (!scene) {
158 return;
159 }
160
162 LISTBASE_FOREACH (Strip *, strip, seqbase) {
163 sequencer_strip_to_keylist(*strip, *op_data.keylist, *scene);
164 }
166 return;
167 }
168
169 op_data.keylist = ED_keylist_create();
170
171 bAnimContext ac;
172 if (!ANIM_animdata_get_context(C, &ac)) {
173 /* If there is no action, getting the anim context fails in the action editor. */
175 return;
176 }
177
178 ListBase anim_data = {nullptr, nullptr};
179
180 switch (area->spacetype) {
181 case SPACE_ACTION: {
183 ANIM_animdata_filter(&ac, &anim_data, filter, ac.data, ac.datatype);
184 break;
185 }
186
187 case SPACE_GRAPH:
189 break;
190
191 default:
193 break;
194 }
195
196 LISTBASE_FOREACH (bAnimListElem *, ale, &anim_data) {
197 switch (ale->datatype) {
198 case ALE_FCURVE: {
199 FCurve *fcurve = static_cast<FCurve *>(ale->data);
200 fcurve_to_keylist(ale->adt, fcurve, op_data.keylist, 0, {-FLT_MAX, FLT_MAX}, true);
201 break;
202 }
203
204 case ALE_GPFRAME: {
205 gpl_to_keylist(nullptr, static_cast<bGPDlayer *>(ale->data), op_data.keylist);
206 break;
207 }
208
211 ale->adt, static_cast<const GreasePencilLayer *>(ale->data), op_data.keylist, 0);
212 break;
213 }
214
215 default:
216 break;
217 }
218 }
219 ANIM_animdata_freelist(&anim_data);
220
222}
223
225 FrameChangeModalData &op_data,
226 const float timeline_frame,
228{
230 const ActKeyColumn *closest_column = ED_keylist_find_closest(op_data.keylist, timeline_frame);
231 if (!closest_column) {
232 return;
233 }
234 r_targets.append({closest_column->cfra, true});
235}
236
238 const float timeline_frame,
240{
241 if (BLI_listbase_is_empty(&scene->markers)) {
242 /* This check needs to be here because `ED_markers_find_nearest_marker_time` returns the
243 * current frame if there are no markers. */
244 return;
245 }
246 const float nearest_marker = ED_markers_find_nearest_marker_time(&scene->markers,
247 timeline_frame);
248 r_targets.append({nearest_marker, true});
249}
250
252 const float timeline_frame,
253 const int step,
255{
256 const int start_frame = scene->r.sfra;
257 const float snap_frame = BKE_scene_frame_snap_by_seconds(
258 scene, step, timeline_frame - start_frame) +
259 start_frame;
260 r_targets.append({snap_frame, false});
261}
262
263static void append_frame_snap_target(const Scene *scene,
264 const float timeline_frame,
265 const int step,
267{
268 const int start_frame = scene->r.sfra;
269 const float snap_frame = (round((timeline_frame - start_frame) / float(step)) * step) +
270 start_frame;
271 r_targets.append({snap_frame, false});
272}
273
274static void seq_frame_snap_update_best(const float position,
275 const float timeline_frame,
276 float *r_best_frame,
277 float *r_best_distance)
278{
279 if (abs(position - timeline_frame) < *r_best_distance) {
280 *r_best_distance = abs(position - timeline_frame);
281 *r_best_frame = position;
282 }
283}
284
286 const Scene *scene,
287 const float timeline_frame,
289{
290 float best_frame = FLT_MAX;
291 float best_distance = FLT_MAX;
292
293 for (Strip *strip : strips) {
295 timeline_frame,
296 &best_frame,
297 &best_distance);
299 timeline_frame,
300 &best_frame,
301 &best_distance);
302 }
303
304 /* best_frame will be FLT_MAX if no target was found. */
305 if (best_distance != FLT_MAX) {
306 r_targets.append({best_frame, true});
307 }
308}
309
311 const float timeline_frame,
313{
314
315 bAnimContext ac;
316 if (!ANIM_animdata_get_context(C, &ac)) {
318 }
319
320 ListBase anim_data = {nullptr, nullptr};
323 ANIM_animdata_filter(&ac, &anim_data, filter, ac.data, eAnimCont_Types(ac.datatype));
324
325 float best_frame = FLT_MAX;
326 float best_distance = FLT_MAX;
327
328 LISTBASE_FOREACH (bAnimListElem *, ale, &anim_data) {
329 if (ale->type != ANIMTYPE_NLATRACK) {
330 continue;
331 }
332 NlaTrack *track = static_cast<NlaTrack *>(ale->data);
333 LISTBASE_FOREACH (NlaStrip *, strip, &track->strips) {
334 if (abs(strip->start - timeline_frame) < best_distance) {
335 best_distance = abs(strip->start - timeline_frame);
336 best_frame = strip->start;
337 }
338 if (abs(strip->end - timeline_frame) < best_distance) {
339 best_distance = abs(strip->end - timeline_frame);
340 best_frame = strip->end;
341 }
342 }
343 }
344 ANIM_animdata_freelist(&anim_data);
345
346 /* If no strip was found, best_frame will be FLT_MAX. */
347 if (best_frame != FLT_MAX) {
348 r_targets.append({best_frame, true});
349 }
350}
351
352/* ---- */
353
355 FrameChangeModalData &op_data,
356 const float timeline_frame)
357{
358 Scene *scene = CTX_data_scene(C);
359 if (!scene) {
360 return {};
361 }
362
363 ToolSettings *tool_settings = scene->toolsettings;
365
366 if (ed == nullptr) {
367 return {};
368 }
369
371
372 if (tool_settings->snap_playhead_mode & SCE_SNAP_TO_STRIPS) {
375 blender::seq::query_all_strips(seqbase), scene, timeline_frame, targets);
376 }
377
378 if (tool_settings->snap_playhead_mode & SCE_SNAP_TO_MARKERS) {
379 append_marker_snap_target(scene, timeline_frame, targets);
380 }
381
382 if (tool_settings->snap_playhead_mode & SCE_SNAP_TO_KEYS) {
383 append_keyframe_snap_target(C, op_data, timeline_frame, targets);
384 }
385
386 if (tool_settings->snap_playhead_mode & SCE_SNAP_TO_SECOND) {
387 append_second_snap_target(scene, timeline_frame, tool_settings->snap_step_seconds, targets);
388 }
389
390 if (tool_settings->snap_playhead_mode & SCE_SNAP_TO_FRAME) {
391 append_frame_snap_target(scene, timeline_frame, tool_settings->snap_step_frames, targets);
392 }
393
394 return targets;
395}
396
397static blender::Vector<SnapTarget> nla_get_snap_targets(bContext *C, const float timeline_frame)
398{
399 Scene *scene = CTX_data_scene(C);
400 ToolSettings *tool_settings = scene->toolsettings;
401
403
404 if (tool_settings->snap_playhead_mode & SCE_SNAP_TO_STRIPS) {
405 append_nla_strip_snap_target(C, timeline_frame, targets);
406 }
407
408 if (tool_settings->snap_playhead_mode & SCE_SNAP_TO_MARKERS) {
409 append_marker_snap_target(scene, timeline_frame, targets);
410 }
411
412 if (tool_settings->snap_playhead_mode & SCE_SNAP_TO_SECOND) {
413 append_second_snap_target(scene, timeline_frame, tool_settings->snap_step_seconds, targets);
414 }
415
416 if (tool_settings->snap_playhead_mode & SCE_SNAP_TO_FRAME) {
417 append_frame_snap_target(scene, timeline_frame, tool_settings->snap_step_frames, targets);
418 }
419
420 return targets;
421}
422
424 FrameChangeModalData &op_data,
425 const float timeline_frame)
426{
427 Scene *scene = CTX_data_scene(C);
428 ToolSettings *tool_settings = scene->toolsettings;
429
431
432 if (tool_settings->snap_playhead_mode & SCE_SNAP_TO_MARKERS) {
433 append_marker_snap_target(scene, timeline_frame, targets);
434 }
435
436 if (tool_settings->snap_playhead_mode & SCE_SNAP_TO_KEYS) {
437 append_keyframe_snap_target(C, op_data, timeline_frame, targets);
438 }
439
440 if (tool_settings->snap_playhead_mode & SCE_SNAP_TO_SECOND) {
441 append_second_snap_target(scene, timeline_frame, tool_settings->snap_step_seconds, targets);
442 }
443
444 if (tool_settings->snap_playhead_mode & SCE_SNAP_TO_FRAME) {
445 append_frame_snap_target(scene, timeline_frame, tool_settings->snap_step_frames, targets);
446 }
447
448 return targets;
449}
450
452 FrameChangeModalData &op_data,
453 const float timeline_frame)
454{
455 Scene *scene = CTX_data_scene(C);
456 ToolSettings *tool_settings = scene->toolsettings;
457
459
460 if (tool_settings->snap_playhead_mode & SCE_SNAP_TO_MARKERS) {
461 append_marker_snap_target(scene, timeline_frame, targets);
462 }
463
464 if (tool_settings->snap_playhead_mode & SCE_SNAP_TO_KEYS) {
465 append_keyframe_snap_target(C, op_data, timeline_frame, targets);
466 }
467
468 if (tool_settings->snap_playhead_mode & SCE_SNAP_TO_SECOND) {
469 append_second_snap_target(scene, timeline_frame, tool_settings->snap_step_seconds, targets);
470 }
471
472 if (tool_settings->snap_playhead_mode & SCE_SNAP_TO_FRAME) {
473 append_frame_snap_target(scene, timeline_frame, tool_settings->snap_step_frames, targets);
474 }
475
476 return targets;
477}
478
479/* ---- */
480
481/* Returns a frame that is snapped to the closest point of interest defined by the area. If no
482 * point of interest is nearby, the frame is returned unmodified. */
483static float apply_frame_snap(bContext *C, FrameChangeModalData &op_data, const float frame)
484{
485 ScrArea *area = CTX_wm_area(C);
486
488 Scene *scene = CTX_data_scene(C);
489 if (!scene) {
490 return frame;
491 }
492
493 switch (area->spacetype) {
494 case SPACE_SEQ:
495 targets = seq_get_snap_targets(C, op_data, frame);
496 break;
497 case SPACE_ACTION:
498 targets = action_get_snap_targets(C, op_data, frame);
499 break;
500 case SPACE_GRAPH:
501 targets = graph_get_snap_targets(C, op_data, frame);
502 break;
503 case SPACE_NLA:
504 targets = nla_get_snap_targets(C, frame);
505 break;
506
507 default:
508 break;
509 }
510
511 float snap_frame = FLT_MAX;
512
513 /* Find closest frame of all targets. */
514 for (const SnapTarget &target : targets) {
515 if (abs(target.pos - frame) < abs(snap_frame - frame)) {
516 snap_frame = target.pos;
517 }
518 }
519
520 const ARegion *region = CTX_wm_region(C);
521 if (abs(snap_frame - frame) < get_snap_threshold(scene->toolsettings, region)) {
522 return snap_frame;
523 }
524
525 snap_frame = FLT_MAX;
526 /* No frame is close enough to the snap threshold. Hard snap to targets without a threshold. */
527 for (const SnapTarget &target : targets) {
528 if (target.use_snap_treshold) {
529 continue;
530 }
531 if (abs(target.pos - frame) < abs(snap_frame - frame)) {
532 snap_frame = target.pos;
533 }
534 }
535
536 if (snap_frame != FLT_MAX) {
537 return snap_frame;
538 }
539
540 return frame;
541}
542
543/* Set the new frame number */
544static void change_frame_apply(bContext *C, wmOperator *op, const bool always_update)
545{
546 Scene *scene = CTX_data_scene(C);
547 float frame = RNA_float_get(op->ptr, "frame");
548 bool do_snap = RNA_boolean_get(op->ptr, "snap");
549
550 const int old_frame = scene->r.cfra;
551 const float old_subframe = scene->r.subframe;
552
553 if (do_snap) {
554 FrameChangeModalData *op_data = static_cast<FrameChangeModalData *>(op->customdata);
555 frame = apply_frame_snap(C, *op_data, frame);
556 }
557
558 /* set the new frame number */
559 if (scene->r.flag & SCER_SHOW_SUBFRAME) {
560 scene->r.cfra = int(frame);
561 scene->r.subframe = frame - int(frame);
562 }
563 else {
564 scene->r.cfra = round_fl_to_int(frame);
565 scene->r.subframe = 0.0f;
566 }
568
569 /* do updates */
570 const bool frame_changed = (old_frame != scene->r.cfra) || (old_subframe != scene->r.subframe);
571 if (frame_changed || always_update) {
574 }
575}
576
577/* ---- */
578
579/* Non-modal callback for running operator without user input */
581{
582 change_frame_apply(C, op, true);
583
584 return OPERATOR_FINISHED;
585}
586
587/* ---- */
588
589/* Get frame from mouse coordinates */
590static float frame_from_event(bContext *C, const wmEvent *event)
591{
592 ARegion *region = CTX_wm_region(C);
593 Scene *scene = CTX_data_scene(C);
594 float frame;
595
596 /* convert from region coordinates to View2D 'tot' space */
597 frame = UI_view2d_region_to_view_x(&region->v2d, event->mval[0]);
598
599 /* respect preview range restrictions (if only allowed to move around within that range) */
600 if (scene->r.flag & SCER_LOCK_FRAME_SELECTION) {
601 CLAMP(frame, PSFRA, PEFRA);
602 }
603
604 return frame;
605}
606
607static void change_frame_seq_preview_begin(bContext *C, const wmEvent *event, SpaceSeq *sseq)
608{
609 BLI_assert(sseq != nullptr);
610 ARegion *region = CTX_wm_region(C);
613 }
614}
615
617{
618 BLI_assert(sseq != nullptr);
619 UNUSED_VARS_NDEBUG(sseq);
620 if (blender::ed::vse::special_preview_get() != nullptr) {
622 }
623}
624
626{
627 Scene *scene = CTX_data_scene(C);
628 if (!scene) {
629 return false;
630 }
631
632 ScrArea *area = CTX_wm_area(C);
633
634 if (area->spacetype == SPACE_GRAPH) {
635 SpaceGraph *graph_editor = static_cast<SpaceGraph *>(area->spacedata.first);
636 /* Snapping is disabled for driver mode. Need to evaluate if it makes sense there and what form
637 * it should take. */
638 if (graph_editor->mode == SIPO_MODE_DRIVERS) {
639 return false;
640 }
641 }
642
644}
645
646static bool sequencer_skip_for_handle_tweak(const bContext *C, const wmEvent *event)
647{
648 if ((U.sequencer_editor_flag & USER_SEQ_ED_SIMPLE_TWEAKING) == 0) {
649 return false;
650 }
651
652 const Scene *scene = CTX_data_scene(C);
653 if (!blender::seq::editing_get(scene)) {
654 return false;
655 }
656
657 const View2D *v2d = UI_view2d_fromcontext(C);
658
659 float mouse_co[2];
660 UI_view2d_region_to_view(v2d, event->mval[0], event->mval[1], &mouse_co[0], &mouse_co[1]);
661
663 scene, v2d, mouse_co);
664
666}
667
668/* Modal Operator init */
670{
671 bScreen *screen = CTX_wm_screen(C);
672 FrameChangeModalData *op_data = MEM_new<FrameChangeModalData>(__func__);
673 op->customdata = op_data;
674
675 /* This check is done in case scrubbing and strip tweaking in the sequencer are bound to the same
676 * event (e.g. RCS keymap where both are activated on left mouse press). Tweaking should take
677 * precedence. */
680 }
681
682 /* Change to frame that mouse is over before adding modal handler,
683 * as user could click on a single frame (jump to frame) as well as
684 * click-dragging over a range (modal scrubbing).
685 */
686 RNA_float_set(op->ptr, "frame", frame_from_event(C, event));
687
689 RNA_boolean_set(op->ptr, "snap", true);
690 }
691
692 screen->scrubbing = true;
693
694 if (RNA_boolean_get(op->ptr, "seq_solo_preview")) {
695 SpaceSeq *sseq = CTX_wm_space_seq(C);
696 if (sseq) {
697 change_frame_seq_preview_begin(C, event, sseq);
698 }
699 }
700
701 change_frame_apply(C, op, true);
702
703 /* add temp handler */
705
707}
708
710{
711 if (CTX_wm_space_seq(C)) {
712 /* During scrubbing in the sequencer, a preview of the final video might be drawn. After
713 * scrubbing, the actual result should be shown again. */
714 return true;
715 }
716 Scene *scene = CTX_data_scene(C);
717 if (scene->eevee.taa_samples != 1) {
718 return true;
719 }
720 return false;
721}
722
724{
725 bScreen *screen = CTX_wm_screen(C);
726 screen->scrubbing = false;
727
728 if (RNA_boolean_get(op->ptr, "seq_solo_preview")) {
729 SpaceSeq *sseq = CTX_wm_space_seq(C);
730 if (sseq != nullptr) {
732 }
733 }
734
736 Scene *scene = CTX_data_scene(C);
738 }
739}
740
741/* Modal event handling of frame changing */
743{
745 /* execute the events */
746 switch (event->type) {
747 case EVT_ESCKEY:
749 break;
750
751 case MOUSEMOVE:
752 RNA_float_set(op->ptr, "frame", frame_from_event(C, event));
753 change_frame_apply(C, op, false);
754 break;
755
756 case LEFTMOUSE:
757 case RIGHTMOUSE:
758 case MIDDLEMOUSE:
759 /* We check for either mouse-button to end, to work with all user keymaps. */
760 if (event->val == KM_RELEASE) {
762 }
763 break;
764
765 case EVT_LEFTCTRLKEY:
766 case EVT_RIGHTCTRLKEY:
767 /* Use Ctrl key to invert snapping in sequencer. */
769 if (event->val == KM_RELEASE) {
770 RNA_boolean_set(op->ptr, "snap", true);
771 }
772 else if (event->val == KM_PRESS) {
773 RNA_boolean_set(op->ptr, "snap", false);
774 }
775 }
776 else {
777 if (event->val == KM_RELEASE) {
778 RNA_boolean_set(op->ptr, "snap", false);
779 }
780 else if (event->val == KM_PRESS) {
781 RNA_boolean_set(op->ptr, "snap", true);
782 }
783 }
784 break;
785 default: {
786 break;
787 }
788 }
789
790 WorkspaceStatus status(C);
791 status.item(IFACE_("Toggle Snapping"), ICON_EVENT_CTRL);
792
794 ED_workspace_status_text(C, nullptr);
795 bScreen *screen = CTX_wm_screen(C);
796 screen->scrubbing = false;
797
798 FrameChangeModalData *op_data = static_cast<FrameChangeModalData *>(op->customdata);
799 MEM_delete(op_data);
800 op->customdata = nullptr;
801
802 if (RNA_boolean_get(op->ptr, "seq_solo_preview")) {
803 SpaceSeq *sseq = CTX_wm_space_seq(C);
804 if (sseq != nullptr) {
806 }
807 }
808
810 Scene *scene = CTX_data_scene(C);
812 }
813 }
814
815 return ret;
816}
817
819{
820 if (RNA_boolean_get(ptr, "seq_solo_preview")) {
821 return CTX_IFACE_(BLT_I18NCONTEXT_OPERATOR_DEFAULT, "Set Frame (Strip Preview)");
822 }
823
824 return {};
825}
826
828{
829 PropertyRNA *prop;
830
831 /* identifiers */
832 ot->name = "Change Frame";
833 ot->idname = "ANIM_OT_change_frame";
834 ot->description = "Interactively change the current frame number";
835
836 /* API callbacks. */
837 ot->exec = change_frame_exec;
838 ot->invoke = change_frame_invoke;
839 ot->cancel = change_frame_cancel;
840 ot->modal = change_frame_modal;
841 ot->poll = change_frame_poll;
842 ot->get_name = change_frame_get_name;
843
844 /* flags */
846 ot->undo_group = "Frame Change";
847
848 /* rna */
849 ot->prop = RNA_def_float(
850 ot->srna, "frame", 0, MINAFRAME, MAXFRAME, "Frame", "", MINAFRAME, MAXFRAME);
851 prop = RNA_def_boolean(ot->srna, "snap", false, "Snap", "");
853 prop = RNA_def_boolean(ot->srna, "seq_solo_preview", false, "Strip Preview", "");
854}
855
857
858/* -------------------------------------------------------------------- */
861
863{
864 ScrArea *area = CTX_wm_area(C);
865
866 /* XXX temp? prevent changes during render */
867 if (G.is_rendering) {
868 return false;
869 }
870
871 /* although it's only included in keymaps for regions using ED_KEYMAP_ANIMATION,
872 * this shouldn't show up in 3D editor (or others without 2D timeline view) via search
873 */
874 if (area) {
876 return true;
877 }
878 }
879
880 CTX_wm_operator_poll_msg_set(C, "Expected an animation area to be active");
881 return false;
882}
883
885{
886 Scene *scene = CTX_data_scene(C);
887 int frame;
888
889 if (scene == nullptr) {
890 return OPERATOR_CANCELLED;
891 }
892
893 frame = scene->r.cfra;
894
895 /* if Preview Range is defined, set the 'start' frame for that */
896 if (PRVRANGEON) {
897 scene->r.psfra = frame;
898 }
899 else {
900 /* Clamping should be in sync with 'rna_Scene_start_frame_set()'. */
901 int frame_clamped = frame;
902 CLAMP(frame_clamped, MINFRAME, MAXFRAME);
903 if (frame_clamped != frame) {
904 BKE_report(op->reports, RPT_WARNING, "Start frame clamped to valid rendering range");
905 }
906 frame = frame_clamped;
907 scene->r.sfra = frame;
908 }
909
910 if (PEFRA < frame) {
911 if (PRVRANGEON) {
912 scene->r.pefra = frame;
913 }
914 else {
915 scene->r.efra = frame;
916 }
917 }
918
920
921 return OPERATOR_FINISHED;
922}
923
925{
926 /* identifiers */
927 ot->name = "Set Start Frame";
928 ot->idname = "ANIM_OT_start_frame_set";
929 ot->description = "Set the current frame as the preview or scene start frame";
930
931 /* API callbacks. */
932 ot->exec = anim_set_sfra_exec;
934
935 /* flags */
937}
938
940{
941 Scene *scene = CTX_data_scene(C);
942 int frame;
943
944 if (scene == nullptr) {
945 return OPERATOR_CANCELLED;
946 }
947
948 frame = scene->r.cfra;
949
950 /* if Preview Range is defined, set the 'end' frame for that */
951 if (PRVRANGEON) {
952 scene->r.pefra = frame;
953 }
954 else {
955 /* Clamping should be in sync with 'rna_Scene_end_frame_set()'. */
956 int frame_clamped = frame;
957 CLAMP(frame_clamped, MINFRAME, MAXFRAME);
958 if (frame_clamped != frame) {
959 BKE_report(op->reports, RPT_WARNING, "End frame clamped to valid rendering range");
960 }
961 frame = frame_clamped;
962 scene->r.efra = frame;
963 }
964
965 if (PSFRA > frame) {
966 if (PRVRANGEON) {
967 scene->r.psfra = frame;
968 }
969 else {
970 scene->r.sfra = frame;
971 }
972 }
973
975
976 return OPERATOR_FINISHED;
977}
978
980{
981 /* identifiers */
982 ot->name = "Set End Frame";
983 ot->idname = "ANIM_OT_end_frame_set";
984 ot->description = "Set the current frame as the preview or scene end frame";
985
986 /* API callbacks. */
987 ot->exec = anim_set_efra_exec;
989
990 /* flags */
992}
993
995
996/* -------------------------------------------------------------------- */
999
1001{
1002 Scene *scene = CTX_data_scene(C);
1003 ARegion *region = CTX_wm_region(C);
1004 float sfra, efra;
1005 rcti rect;
1006
1007 /* get min/max values from box select rect (already in region coordinates, not screen) */
1009
1010 /* convert min/max values to frames (i.e. region to 'tot' rect) */
1011 sfra = UI_view2d_region_to_view_x(&region->v2d, rect.xmin);
1012 efra = UI_view2d_region_to_view_x(&region->v2d, rect.xmax);
1013
1014 /* set start/end frames for preview-range
1015 * - must clamp within allowable limits
1016 * - end must not be before start (though this won't occur most of the time)
1017 */
1020 efra = std::max(efra, sfra);
1021
1022 scene->r.flag |= SCER_PRV_RANGE;
1023 scene->r.psfra = round_fl_to_int(sfra);
1024 scene->r.pefra = round_fl_to_int(efra);
1025
1026 /* send notifiers */
1028
1029 return OPERATOR_FINISHED;
1030}
1031
1033{
1034 /* identifiers */
1035 ot->name = "Set Preview Range";
1036 ot->idname = "ANIM_OT_previewrange_set";
1037 ot->description = "Interactively define frame range used for playback";
1038
1039 /* API callbacks. */
1040 ot->invoke = WM_gesture_box_invoke;
1042 ot->modal = WM_gesture_box_modal;
1043 ot->cancel = WM_gesture_box_cancel;
1044
1046
1047 /* flags */
1048 ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
1049
1050 /* rna */
1051 /* used to define frame range.
1052 *
1053 * NOTE: border Y values are not used,
1054 * but are needed by box_select gesture operator stuff */
1056}
1057
1059
1060/* -------------------------------------------------------------------- */
1063
1065{
1066 Scene *scene = CTX_data_scene(C);
1067 ScrArea *curarea = CTX_wm_area(C);
1068
1069 /* sanity checks */
1070 if (ELEM(nullptr, scene, curarea)) {
1071 return OPERATOR_CANCELLED;
1072 }
1073
1074 /* simply clear values */
1075 scene->r.flag &= ~SCER_PRV_RANGE;
1076 scene->r.psfra = 0;
1077 scene->r.pefra = 0;
1078
1079 ED_area_tag_redraw(curarea);
1080
1081 /* send notifiers */
1083
1084 return OPERATOR_FINISHED;
1085}
1086
1088{
1089 /* identifiers */
1090 ot->name = "Clear Preview Range";
1091 ot->idname = "ANIM_OT_previewrange_clear";
1092 ot->description = "Clear preview range";
1093
1094 /* API callbacks. */
1096
1098
1099 /* flags */
1100 ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
1101}
1102
1104
1105/* -------------------------------------------------------------------- */
1108
1109#ifndef NDEBUG
1111{
1112 bAnimContext ac;
1113 if (ANIM_animdata_get_context(C, &ac) == 0) {
1114 return OPERATOR_CANCELLED;
1115 }
1116
1117 ListBase anim_data = {nullptr, nullptr};
1118 /* Same filter flags as in action_channel_region_draw() in
1119 * `source/blender/editors/space_action/space_action.cc`. */
1122 ANIM_animdata_filter(&ac, &anim_data, filter, ac.data, eAnimCont_Types(ac.datatype));
1123
1124 printf("==============================================\n");
1125 printf("Animation Channel List:\n");
1126 printf("----------------------------------------------\n");
1127
1128 LISTBASE_FOREACH (bAnimListElem *, ale, &anim_data) {
1130 }
1131
1132 printf("==============================================\n");
1133
1134 ANIM_animdata_freelist(&anim_data);
1135 return OPERATOR_FINISHED;
1136}
1137
1139{
1140 ot->name = "Debug Channel List";
1141 ot->idname = "ANIM_OT_debug_channel_list";
1142 ot->description =
1143 "Log the channel list info in the terminal. This operator is only available in debug builds "
1144 "of Blender";
1145
1148
1149 ot->flag = OPTYPE_REGISTER;
1150}
1151#endif /* !NDEBUG */
1152
1154
1155/* -------------------------------------------------------------------- */
1158
1160{
1161 ARegion *region = CTX_wm_region(C);
1162 const Scene *scene = CTX_data_scene(C);
1163 BLI_assert(region);
1164 BLI_assert(scene);
1165
1166 View2D &v2d = region->v2d;
1167 v2d.cur.xmin = PSFRA;
1168 v2d.cur.xmax = PEFRA;
1169
1171
1174
1175 return OPERATOR_FINISHED;
1176}
1177
1179{
1180 ot->name = "Frame Scene/Preview Range";
1181 ot->idname = "ANIM_OT_scene_range_frame";
1182 ot->description =
1183 "Reset the horizontal view to the current scene frame range, taking the preview range into "
1184 "account if it is active";
1185
1186 ot->exec = scene_range_frame_exec;
1188
1189 ot->flag = OPTYPE_REGISTER;
1190}
1191
1193
1194/* -------------------------------------------------------------------- */
1197
1199{
1200 using namespace blender;
1201
1202 Object *object = CTX_data_active_object(C);
1203 AnimData *adt = BKE_animdata_from_id(&object->id);
1204 BLI_assert(adt != nullptr);
1205 BLI_assert(adt->action != nullptr);
1206
1207 animrig::Action &legacy_action = adt->action->wrap();
1208 Main *bmain = CTX_data_main(C);
1209
1210 animrig::Action *layered_action = animrig::convert_to_layered_action(*bmain, legacy_action);
1211 /* We did already check if the action can be converted. */
1212 BLI_assert(layered_action != nullptr);
1213 const bool assign_ok = animrig::assign_action(layered_action, object->id);
1214 BLI_assert_msg(assign_ok, "Expecting assigning a layered Action to always work");
1215 UNUSED_VARS_NDEBUG(assign_ok);
1216
1217 BLI_assert(layered_action->slots().size() == 1);
1218 animrig::Slot *slot = layered_action->slot(0);
1219 layered_action->slot_identifier_set(*bmain, *slot, object->id.name);
1220
1224
1225 ANIM_id_update(bmain, &object->id);
1228
1229 return OPERATOR_FINISHED;
1230}
1231
1233{
1234 Object *object = CTX_data_active_object(C);
1235 if (!object) {
1236 return false;
1237 }
1238
1239 AnimData *adt = BKE_animdata_from_id(&object->id);
1240 if (!adt || !adt->action) {
1241 return false;
1242 }
1243
1244 /* This will also convert empty actions to layered by just adding an empty slot. */
1245 if (!adt->action->wrap().is_action_legacy()) {
1246 CTX_wm_operator_poll_msg_set(C, "Action is already layered");
1247 return false;
1248 }
1249
1250 return true;
1251}
1252
1254{
1255 /* identifiers */
1256 ot->name = "Convert Legacy Action";
1257 ot->idname = "ANIM_OT_convert_legacy_action";
1258 ot->description = "Convert a legacy Action to a layered Action on the active object";
1259
1260 /* API callbacks. */
1261 ot->exec = convert_action_exec;
1262 ot->poll = convert_action_poll;
1263
1264 /* flags */
1265 ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
1266}
1267
1269{
1270 Object *object = CTX_data_active_object(C);
1271 if (!object) {
1272 CTX_wm_operator_poll_msg_set(C, "No active object");
1273 return false;
1274 }
1276 if (!action) {
1277 CTX_wm_operator_poll_msg_set(C, "Active object has no action");
1278 return false;
1279 }
1280 if (!BKE_id_is_editable(CTX_data_main(C), &action->id)) {
1281 return false;
1282 }
1283 return true;
1284}
1285
1287{
1288 using namespace blender::animrig;
1289 Object *active_object = CTX_data_active_object(C);
1290 /* Those cases are caught by the poll. */
1291 BLI_assert(active_object != nullptr);
1292 BLI_assert(active_object->adt->action != nullptr);
1293
1294 Action &active_action = active_object->adt->action->wrap();
1295
1297 if (!CTX_data_selected_objects(C, &selection)) {
1298 return OPERATOR_CANCELLED;
1299 }
1300
1301 Main *bmain = CTX_data_main(C);
1302 int moved_slots_count = 0;
1303 for (const PointerRNA &ptr : selection) {
1304 blender::Vector<ID *> related_ids = find_related_ids(*bmain, *ptr.owner_id);
1305 for (ID *related_id : related_ids) {
1306 Action *action = get_action(*related_id);
1307 if (!action) {
1308 continue;
1309 }
1310 if (action == &active_action) {
1311 /* Object is already animated by the same action, no point in moving. */
1312 continue;
1313 }
1314 if (action->is_action_legacy()) {
1315 continue;
1316 }
1317 if (!BKE_id_is_editable(bmain, &action->id)) {
1318 BKE_reportf(op->reports, RPT_WARNING, "The action %s is not editable", action->id.name);
1319 continue;
1320 }
1321 AnimData *id_anim_data = BKE_animdata_ensure_id(related_id);
1322 /* Since we already get an action from the ID the animdata has to exist. */
1323 BLI_assert(id_anim_data);
1324 Slot *slot = action->slot_for_handle(id_anim_data->slot_handle);
1325 if (!slot) {
1326 continue;
1327 }
1328 blender::animrig::move_slot(*bmain, *slot, *action, active_action);
1329 moved_slots_count++;
1330 ANIM_id_update(bmain, related_id);
1332 }
1333 }
1334
1335 if (moved_slots_count > 0) {
1336 BKE_reportf(op->reports,
1337 RPT_INFO,
1338 "Moved %i slot(s) into the action of the active object",
1339 moved_slots_count);
1340 }
1341 else {
1342 BKE_reportf(op->reports,
1343 RPT_ERROR,
1344 "Failed to merge any animation. Note that NLA strips cannot be merged");
1345 }
1346
1347 /* `ID_RECALC_ANIMATION_NO_FLUSH` is used here (and above), as the actual animation values do not
1348 * change, so there is no need to flush to the animated IDs. The Action itself does need to be
1349 * re-evaluated to get an up-to-date evaluated copy with the new slots & channelbags. Without
1350 * this, future animation evaluation will break. */
1352
1355
1356 return OPERATOR_FINISHED;
1357}
1358
1360{
1361 ot->name = "Merge Animation";
1362 ot->idname = "ANIM_OT_merge_animation";
1363 ot->description =
1364 "Merge the animation of the selected objects into the action of the active object. Actions "
1365 "are not deleted by this, but might end up with zero users";
1366
1369
1370 ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
1371}
1372
1374
1375/* -------------------------------------------------------------------- */
1378
1380{
1381 /* Animation Editors only -------------------------- */
1383
1386
1389
1391
1392#ifndef NDEBUG
1394#endif
1395
1396 /* Entire UI --------------------------------------- */
1407
1413
1416
1421
1423
1426
1430}
1431
1433{
1434 WM_keymap_ensure(keyconf, "Animation", SPACE_EMPTY, RGN_TYPE_WINDOW);
1435}
1436
Functions and classes to work with Actions.
Functions to work with AnimData.
AnimData * BKE_animdata_ensure_id(ID *id)
Definition anim_data.cc:96
AnimData * BKE_animdata_from_id(const ID *id)
Definition anim_data.cc:82
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)
bool BKE_id_is_editable(const Main *bmain, const ID *id)
Definition lib_id.cc:2503
void BKE_reportf(ReportList *reports, eReportType type, const char *format,...) ATTR_PRINTF_FORMAT(3
void BKE_report(ReportList *reports, eReportType type, const char *message)
Definition report.cc:126
int BKE_scene_frame_snap_by_seconds(Scene *scene, double interval_in_seconds, int frame)
Definition scene.cc:2323
#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:1033
@ ID_RECALC_ANIMATION_NO_FLUSH
Definition DNA_ID.h:1084
#define MINFRAME
#define MINAFRAME
#define PSFRA
@ SCER_SHOW_SUBFRAME
@ SCER_PRV_RANGE
@ SCER_LOCK_FRAME_SELECTION
@ SCE_SNAP
#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)
@ USER_SEQ_ED_SIMPLE_TWEAKING
@ 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:714
bool ED_operator_animview_active(bContext *C)
void ED_workspace_status_text(bContext *C, const char *str)
Definition area.cc:1040
@ PROP_SKIP_SAVE
Definition RNA_types.hh:330
#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:1854
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:1667
float UI_view2d_region_to_view_x(const View2D *v2d, float x)
Definition view2d.cc:1656
#define ND_NLA_ACTCHANGE
Definition WM_types.hh:495
@ 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 NC_ANIMATION
Definition WM_types.hh:385
#define NC_SCENE
Definition WM_types.hh:375
#define ND_FRAME
Definition WM_types.hh:431
@ KM_PRESS
Definition WM_types.hh:308
@ KM_RELEASE
Definition WM_types.hh:309
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:739
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_keying_set_add(wmOperatorType *ot)
void ANIM_OT_driver_button_remove(wmOperatorType *ot)
Definition drivers.cc:1112
void ANIM_OT_driver_button_add(wmOperatorType *ot)
Definition drivers.cc:1063
void ANIM_OT_keyframe_insert(wmOperatorType *ot)
void ANIM_OT_driver_button_edit(wmOperatorType *ot)
Definition drivers.cc:1148
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:1233
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:1188
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)
int ED_markers_find_nearest_marker_time(ListBase *markers, float x)
static wmOperatorStatus debug_channel_list_exec(bContext *C, wmOperator *)
Definition anim_ops.cc:1110
void ED_operatortypes_anim()
Definition anim_ops.cc:1379
static void change_frame_apply(bContext *C, wmOperator *op, const bool always_update)
Definition anim_ops.cc:544
static void ANIM_OT_previewrange_set(wmOperatorType *ot)
Definition anim_ops.cc:1032
static bool anim_set_end_frames_poll(bContext *C)
Definition anim_ops.cc:862
static void ANIM_OT_previewrange_clear(wmOperatorType *ot)
Definition anim_ops.cc:1087
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:263
static void ANIM_OT_convert_legacy_action(wmOperatorType *ot)
Definition anim_ops.cc:1253
static wmOperatorStatus merge_actions_selection_exec(bContext *C, wmOperator *op)
Definition anim_ops.cc:1286
static float get_snap_threshold(const ToolSettings *tool_settings, const ARegion *region)
Definition anim_ops.cc:136
static wmOperatorStatus change_frame_exec(bContext *C, wmOperator *op)
Definition anim_ops.cc:580
static void ANIM_OT_start_frame_set(wmOperatorType *ot)
Definition anim_ops.cc:924
static void ANIM_OT_scene_range_frame(wmOperatorType *ot)
Definition anim_ops.cc:1178
static bool merge_actions_selection_poll(bContext *C)
Definition anim_ops.cc:1268
static void append_nla_strip_snap_target(bContext *C, const float timeline_frame, blender::Vector< SnapTarget > &r_targets)
Definition anim_ops.cc:310
static wmOperatorStatus previewrange_define_exec(bContext *C, wmOperator *op)
Definition anim_ops.cc:1000
static wmOperatorStatus change_frame_modal(bContext *C, wmOperator *op, const wmEvent *event)
Definition anim_ops.cc:742
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:274
static bool use_playhead_snapping(bContext *C)
Definition anim_ops.cc:625
static void ANIM_OT_end_frame_set(wmOperatorType *ot)
Definition anim_ops.cc:979
static void change_frame_seq_preview_begin(bContext *C, const wmEvent *event, SpaceSeq *sseq)
Definition anim_ops.cc:607
static wmOperatorStatus anim_set_sfra_exec(bContext *C, wmOperator *op)
Definition anim_ops.cc:884
static wmOperatorStatus change_frame_invoke(bContext *C, wmOperator *op, const wmEvent *event)
Definition anim_ops.cc:669
static void ensure_change_frame_keylist(bContext *C, FrameChangeModalData &op_data)
Definition anim_ops.cc:143
static wmOperatorStatus previewrange_clear_exec(bContext *C, wmOperator *)
Definition anim_ops.cc:1064
static bool sequencer_skip_for_handle_tweak(const bContext *C, const wmEvent *event)
Definition anim_ops.cc:646
static blender::Vector< SnapTarget > action_get_snap_targets(bContext *C, FrameChangeModalData &op_data, const float timeline_frame)
Definition anim_ops.cc:423
static wmOperatorStatus convert_action_exec(bContext *C, wmOperator *)
Definition anim_ops.cc:1198
static wmOperatorStatus scene_range_frame_exec(bContext *C, wmOperator *)
Definition anim_ops.cc:1159
static std::string change_frame_get_name(wmOperatorType *, PointerRNA *ptr)
Definition anim_ops.cc:818
static float frame_from_event(bContext *C, const wmEvent *event)
Definition anim_ops.cc:590
static wmOperatorStatus anim_set_efra_exec(bContext *C, wmOperator *op)
Definition anim_ops.cc:939
static void append_second_snap_target(Scene *scene, const float timeline_frame, const int step, blender::Vector< SnapTarget > &r_targets)
Definition anim_ops.cc:251
void ED_keymap_anim(wmKeyConfig *keyconf)
Definition anim_ops.cc:1432
static blender::Vector< SnapTarget > seq_get_snap_targets(bContext *C, FrameChangeModalData &op_data, const float timeline_frame)
Definition anim_ops.cc:354
static void append_marker_snap_target(Scene *scene, const float timeline_frame, blender::Vector< SnapTarget > &r_targets)
Definition anim_ops.cc:237
static void ANIM_OT_merge_animation(wmOperatorType *ot)
Definition anim_ops.cc:1359
static bool convert_action_poll(bContext *C)
Definition anim_ops.cc:1232
static bool need_extra_redraw_after_scrubbing_ends(bContext *C)
Definition anim_ops.cc:709
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:285
static bool change_frame_poll(bContext *C)
Definition anim_ops.cc:97
static void ANIM_OT_change_frame(wmOperatorType *ot)
Definition anim_ops.cc:827
static void ANIM_OT_debug_channel_list(wmOperatorType *ot)
Definition anim_ops.cc:1138
static blender::Vector< SnapTarget > graph_get_snap_targets(bContext *C, FrameChangeModalData &op_data, const float timeline_frame)
Definition anim_ops.cc:451
static float apply_frame_snap(bContext *C, FrameChangeModalData &op_data, const float frame)
Definition anim_ops.cc:483
static void change_frame_seq_preview_end(SpaceSeq *sseq)
Definition anim_ops.cc:616
static void change_frame_cancel(bContext *C, wmOperator *op)
Definition anim_ops.cc:723
static blender::Vector< SnapTarget > nla_get_snap_targets(bContext *C, const float timeline_frame)
Definition anim_ops.cc:397
static void append_keyframe_snap_target(bContext *C, FrameChangeModalData &op_data, const float timeline_frame, blender::Vector< SnapTarget > &r_targets)
Definition anim_ops.cc:224
#define U
AnimKeylist * keylist
Definition anim_ops.cc:71
void item(std::string text, int icon1, int icon2=0)
Definition area.cc:979
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 round
#define abs
#define filter
VecBase< float, D > step(VecOp< float, D >, VecOp< float, D >) RET
#define printf(...)
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 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:118
Editing * editing_get(const Scene *scene)
Definition sequencer.cc:272
int time_left_handle_frame_get(const Scene *, const Strip *strip)
ListBase * active_seqbase_get(const Editing *ed)
Definition sequencer.cc:420
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:404
char name[66]
Definition DNA_ID.h:415
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:754
short val
Definition WM_types.hh:756
int mval[2]
Definition WM_types.hh:760
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:4226
wmOperatorType * ot
Definition wm_files.cc:4225
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:893
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 *))