Blender V4.3
sequencer_edit.cc
Go to the documentation of this file.
1/* SPDX-FileCopyrightText: 2001-2002 NaN Holding BV. All rights reserved.
2 *
3 * SPDX-License-Identifier: GPL-2.0-or-later */
4
9#include "MEM_guardedalloc.h"
10
11#include "BLI_fileops.h"
12#include "BLI_math_vector.h"
13#include "BLI_path_utils.hh"
14#include "BLI_string.h"
15#include "BLI_timecode.h"
16#include "BLI_utildefines.h"
17
18#include "BLT_translation.hh"
19
20#include "DNA_anim_types.h"
21#include "DNA_scene_types.h"
22#include "DNA_sound_types.h"
23
24#include "BKE_context.hh"
25#include "BKE_global.hh"
26#include "BKE_main.hh"
27#include "BKE_report.hh"
28#include "BKE_sound.h"
29
30#include "SEQ_add.hh"
31#include "SEQ_animation.hh"
32#include "SEQ_channels.hh"
33#include "SEQ_connect.hh"
34#include "SEQ_edit.hh"
35#include "SEQ_effects.hh"
36#include "SEQ_iterator.hh"
37#include "SEQ_prefetch.hh"
38#include "SEQ_relations.hh"
39#include "SEQ_render.hh"
40#include "SEQ_select.hh"
41#include "SEQ_sequencer.hh"
43#include "SEQ_time.hh"
44#include "SEQ_transform.hh"
45#include "SEQ_utils.hh"
46
47#include "ANIM_action_legacy.hh"
48
49#include "WM_api.hh"
50#include "WM_types.hh"
51
52#include "RNA_define.hh"
53#include "RNA_enum_types.hh"
54#include "RNA_prototypes.hh"
55
56/* For menu, popup, icons, etc. */
57#include "ED_fileselect.hh"
58#include "ED_numinput.hh"
59#include "ED_scene.hh"
60#include "ED_screen.hh"
61#include "ED_sequencer.hh"
62
63#include "UI_interface.hh"
64#include "UI_resources.hh"
65#include "UI_view2d.hh"
66
67#include "DEG_depsgraph.hh"
69
70/* Own include. */
71#include "sequencer_intern.hh"
72
73/* -------------------------------------------------------------------- */
81
83{
84 if (sseq && sseq->mainb == SEQ_DRAW_IMG_IMBUF) {
85 return (SEQ_active_mask_get(scene) != nullptr);
86 }
87
88 return false;
89}
90
92{
93 SpaceSeq *sseq = CTX_wm_space_seq(C);
94
95 if (sseq) {
96 Scene *scene = CTX_data_scene(C);
98 }
99
100 return false;
101}
102
108
113
115{
116 if (!BLI_str_startswith(fcurve->rna_path, "sequence_editor.sequences_all[\"")) {
117 return false;
118 }
119
120 if (!BLI_str_endswith(fcurve->rna_path, "\"].color")) {
121 return false;
122 }
123
124 return true;
125}
126
128{
129 if (sseq->draw_flag & SEQ_DRAW_BACKDROP) {
130 return true;
131 }
132
133 if (!scene->adt) {
134 return false;
135 }
136 if (!scene->adt->action) {
137 return false;
138 }
139
142 return true;
143 }
144 }
145
146 return false;
147}
148
151/* -------------------------------------------------------------------- */
156{
157 return (SEQ_editing_get(CTX_data_scene(C)) != nullptr);
158}
159
161{
162 if (!sequencer_edit_poll(C)) {
163 return false;
164 }
165 ARegion *region = CTX_wm_region(C);
166 if (!(region && (region->regiontype == RGN_TYPE_CHANNELS))) {
167 return false;
168 }
169 return true;
170}
171
176
177#if 0 /* UNUSED */
178bool sequencer_strip_poll(bContext *C)
179{
180 Editing *ed;
181 return (((ed = SEQ_editing_get(CTX_data_scene(C))) != nullptr) && (ed->act_seq != nullptr));
182}
183#endif
184
186{
187 Scene *scene = CTX_data_scene(C);
188 if (!ID_IS_EDITABLE(&scene->id)) {
189 return false;
190 }
191 Editing *ed = SEQ_editing_get(scene);
192 return (ed && (ed->act_seq != nullptr));
193}
194
196{
197 Editing *ed;
198 Sequence *seq;
199 return (((ed = SEQ_editing_get(CTX_data_scene(C))) != nullptr) &&
200 ((seq = ed->act_seq) != nullptr) && SEQ_HAS_PATH(seq));
201}
202
204{
205 SpaceSeq *sseq = CTX_wm_space_seq(C);
206 if (sseq == nullptr) {
207 return false;
208 }
209 if (SEQ_editing_get(CTX_data_scene(C)) == nullptr) {
210 return false;
211 }
213 (sseq->mainb == SEQ_DRAW_IMG_IMBUF)))
214 {
215 return false;
216 }
217 ARegion *region = CTX_wm_region(C);
218 if (!(region && region->regiontype == RGN_TYPE_PREVIEW)) {
219 return false;
220 }
221
222 return true;
223}
224
226{
227 SpaceSeq *sseq = CTX_wm_space_seq(C);
228 if (sseq == nullptr) {
229 return false;
230 }
231 if (SEQ_editing_get(CTX_data_scene(C)) == nullptr) {
232 return false;
233 }
234 if (!(ELEM(sseq->view, SEQ_VIEW_PREVIEW) && (sseq->mainb == SEQ_DRAW_IMG_IMBUF))) {
235 return false;
236 }
237 ARegion *region = CTX_wm_region(C);
238 if (!(region && region->regiontype == RGN_TYPE_PREVIEW)) {
239 return false;
240 }
241
242 return true;
243}
244
246{
247 SpaceSeq *sseq = CTX_wm_space_seq(C);
248 if (sseq == nullptr) {
249 return false;
250 }
252 return false;
253 }
254 ARegion *region = CTX_wm_region(C);
255 if (!(region && region->regiontype == RGN_TYPE_WINDOW)) {
256 return false;
257 }
258 return true;
259}
260
263/* -------------------------------------------------------------------- */
268{
269 Scene *scene = CTX_data_scene(C);
270 const bool do_all = RNA_boolean_get(op->ptr, "all");
271 const Editing *ed = SEQ_editing_get(scene);
272
273 SEQ_edit_remove_gaps(scene, ed->seqbasep, scene->r.cfra, do_all);
274
277
278 return OPERATOR_FINISHED;
279}
280
282{
283 /* Identifiers. */
284 ot->name = "Remove Gaps";
285 ot->idname = "SEQUENCER_OT_gap_remove";
286 ot->description =
287 "Remove gap at current frame to first strip at the right, independent of selection or "
288 "locked state of strips";
289
290 /* Api callbacks. */
291 // ot->invoke = sequencer_snap_invoke;
294
295 /* Flags. */
297
298 RNA_def_boolean(ot->srna, "all", false, "All Gaps", "Do all gaps to right of current frame");
299}
300
303/* -------------------------------------------------------------------- */
308{
309 Scene *scene = CTX_data_scene(C);
310 const int frames = RNA_int_get(op->ptr, "frames");
311 const Editing *ed = SEQ_editing_get(scene);
312 SEQ_transform_offset_after_frame(scene, ed->seqbasep, frames, scene->r.cfra);
313
315
316 return OPERATOR_FINISHED;
317}
318
320{
321 /* Identifiers. */
322 ot->name = "Insert Gaps";
323 ot->idname = "SEQUENCER_OT_gap_insert";
324 ot->description =
325 "Insert gap at current frame to first strips at the right, independent of selection or "
326 "locked state of strips";
327
328 /* Api callbacks. */
329 // ot->invoke = sequencer_snap_invoke;
332
333 /* Flags. */
335
337 "frames",
338 10,
339 0,
340 INT_MAX,
341 "Frames",
342 "Frames to insert after current strip",
343 0,
344 1000);
345}
346
349/* -------------------------------------------------------------------- */
354{
355 Scene *scene = CTX_data_scene(C);
356
357 Editing *ed = SEQ_editing_get(scene);
358 ListBase *channels = SEQ_channels_displayed_get(ed);
359 int snap_frame;
360
361 snap_frame = RNA_int_get(op->ptr, "frame");
362
363 /* Check meta-strips. */
364 LISTBASE_FOREACH (Sequence *, seq, ed->seqbasep) {
365 if (seq->flag & SELECT && !SEQ_transform_is_locked(channels, seq) &&
367 {
368 if ((seq->flag & (SEQ_LEFTSEL + SEQ_RIGHTSEL)) == 0) {
369 SEQ_transform_translate_sequence(scene, seq, (snap_frame - seq->startofs) - seq->start);
370 }
371 else {
372 if (seq->flag & SEQ_LEFTSEL) {
373 SEQ_time_left_handle_frame_set(scene, seq, snap_frame);
374 }
375 else { /* SEQ_RIGHTSEL */
376 SEQ_time_right_handle_frame_set(scene, seq, snap_frame);
377 }
378 }
379
381 }
382 }
383
384 /* Test for effects and overlap. */
385 LISTBASE_FOREACH (Sequence *, seq, ed->seqbasep) {
386 if (seq->flag & SELECT && !SEQ_transform_is_locked(channels, seq)) {
387 seq->flag &= ~SEQ_OVERLAP;
388 if (SEQ_transform_test_overlap(scene, ed->seqbasep, seq)) {
390 }
391 }
392 }
393
394 /* Recalculate bounds of effect strips, offsetting the keyframes if not snapping any handle. */
395 LISTBASE_FOREACH (Sequence *, seq, ed->seqbasep) {
396 if (seq->type & SEQ_TYPE_EFFECT) {
397 const bool either_handle_selected = (seq->flag & (SEQ_LEFTSEL | SEQ_RIGHTSEL)) != 0;
398
399 if (seq->seq1 && (seq->seq1->flag & SELECT)) {
400 if (!either_handle_selected) {
402 scene, seq, (snap_frame - SEQ_time_left_handle_frame_get(scene, seq)));
403 }
404 }
405 else if (seq->seq2 && (seq->seq2->flag & SELECT)) {
406 if (!either_handle_selected) {
408 scene, seq, (snap_frame - SEQ_time_left_handle_frame_get(scene, seq)));
409 }
410 }
411 }
412 }
413
416
417 return OPERATOR_FINISHED;
418}
419
420static int sequencer_snap_invoke(bContext *C, wmOperator *op, const wmEvent * /*event*/)
421{
422 Scene *scene = CTX_data_scene(C);
423
424 int snap_frame;
425
426 snap_frame = scene->r.cfra;
427
428 RNA_int_set(op->ptr, "frame", snap_frame);
429 return sequencer_snap_exec(C, op);
430}
431
433{
434 /* Identifiers. */
435 ot->name = "Snap Strips to the Current Frame";
436 ot->idname = "SEQUENCER_OT_snap";
437 ot->description = "Frame where selected strips will be snapped";
438
439 /* Api callbacks. */
443
444 /* Flags. */
446
448 "frame",
449 0,
450 INT_MIN,
451 INT_MAX,
452 "Frame",
453 "Frame where selected strips will be snapped",
454 INT_MIN,
455 INT_MAX);
456}
457
460/* -------------------------------------------------------------------- */
464struct SlipData {
471 bool slow;
472 int slow_offset; /* Offset at the point where offset was turned on. */
474};
475
476static void slip_add_sequences(ListBase *seqbasep, Sequence **seq_array)
477{
478 int i = 0;
479
480 LISTBASE_FOREACH (Sequence *, seq, seqbasep) {
481 if (!(seq->type & SEQ_TYPE_EFFECT) && (seq->flag & SELECT)) {
482 seq_array[i] = seq;
483 i++;
484 }
485 }
486}
487
488static int slip_count_sequences(ListBase *seqbasep)
489{
490 int trimmed_sequences = 0;
491
492 LISTBASE_FOREACH (Sequence *, seq, seqbasep) {
493 if (!(seq->type & SEQ_TYPE_EFFECT) && (seq->flag & SELECT)) {
494 trimmed_sequences++;
495 }
496 }
497
498 return trimmed_sequences;
499}
500
501static int sequencer_slip_invoke(bContext *C, wmOperator *op, const wmEvent *event)
502{
503 SlipData *data;
504 Scene *scene = CTX_data_scene(C);
505 Editing *ed = SEQ_editing_get(scene);
506 float mouseloc[2];
507 int num_seq;
509
510 /* Count the amount of elements to trim. */
511 num_seq = slip_count_sequences(ed->seqbasep);
512
513 if (num_seq == 0) {
514 return OPERATOR_CANCELLED;
515 }
516
517 data = MEM_cnew<SlipData>("trimdata");
518 op->customdata = static_cast<void *>(data);
519 data->seq_array = MEM_cnew_array<Sequence *>(num_seq, "trimdata_sequences");
520 data->num_seq = num_seq;
521 data->previous_offset = 0;
522
523 initNumInput(&data->num_input);
524 data->num_input.idx_max = 0;
525 data->num_input.unit_sys = USER_UNIT_NONE;
526 data->num_input.unit_type[0] = 0;
527
528 slip_add_sequences(ed->seqbasep, data->seq_array);
529
530 UI_view2d_region_to_view(v2d, event->mval[0], event->mval[1], &mouseloc[0], &mouseloc[1]);
531
532 copy_v2_v2(data->init_mouseloc, mouseloc);
533
534 data->slow = false;
535
537
538 /* Notify so we draw extensions immediately. */
540
542}
543
544static void sequencer_slip_strips(Scene *scene, SlipData *data, int delta, float subframe_delta)
545{
546 for (int i = data->num_seq - 1; i >= 0; i--) {
547 Sequence *seq = data->seq_array[i];
548
550 if (SEQ_transform_is_locked(channels, seq)) {
551 continue;
552 }
553
554 SEQ_time_slip_strip(scene, seq, delta, subframe_delta);
555 }
556
557 for (int i = data->num_seq - 1; i >= 0; i--) {
558 Sequence *seq = data->seq_array[i];
560 }
561}
562
563/* Make sure, that each strip contains at least 1 frame of content.
564 * Returns clamped offset relative to current strip positions. */
565static int sequencer_slip_apply_limits(const Scene *scene, SlipData *data, int *offset)
566{
567 int delta_offset = *offset - data->previous_offset;
568
569 for (int i = 0; i < data->num_seq; i++) {
570 Sequence *seq = data->seq_array[i];
571 int seq_content_start = SEQ_time_start_frame_get(seq) + delta_offset;
572 int seq_content_end = seq_content_start + seq->len + seq->anim_startofs + seq->anim_endofs;
573 int diff = 0;
574
575 if (seq_content_start >= SEQ_time_right_handle_frame_get(scene, seq)) {
576 diff = SEQ_time_right_handle_frame_get(scene, seq) - seq_content_start - 1;
577 }
578
579 if (seq_content_end <= SEQ_time_left_handle_frame_get(scene, seq)) {
580 diff = SEQ_time_left_handle_frame_get(scene, seq) - seq_content_end + 1;
581 }
582 *offset += diff;
583 delta_offset += diff;
584 }
585 data->previous_offset = *offset;
586
587 return delta_offset;
588}
589
591{
592 Scene *scene = CTX_data_scene(C);
593 Editing *ed = SEQ_editing_get(scene);
594
595 /* Count the amount of elements to trim. */
596 int num_seq = slip_count_sequences(ed->seqbasep);
597
598 if (num_seq == 0) {
599 return OPERATOR_CANCELLED;
600 }
601
602 SlipData *data = MEM_cnew<SlipData>("trimdata");
603 op->customdata = static_cast<void *>(data);
604 data->seq_array = MEM_cnew_array<Sequence *>(num_seq, "trimdata_sequences");
605 data->num_seq = num_seq;
606
607 slip_add_sequences(ed->seqbasep, data->seq_array);
608
609 float offset_fl = RNA_float_get(op->ptr, "offset");
610 int offset = round_fl_to_int(offset_fl);
611
612 float subframe_delta = 0.0f;
613 if (std::trunc(offset_fl) != offset_fl) {
614 /* Only apply subframe offsets if the input is not an integer. */
615 subframe_delta = offset_fl - offset;
616 }
617
618 sequencer_slip_apply_limits(scene, data, &offset);
619 sequencer_slip_strips(scene, data, offset, subframe_delta);
620
621 MEM_freeN(data->seq_array);
622 MEM_freeN(data);
623
626 return OPERATOR_FINISHED;
627}
628
629static void sequencer_slip_update_header(Scene *scene, ScrArea *area, SlipData *data, int offset)
630{
631 if (area == nullptr) {
632 return;
633 }
634
635 char msg[UI_MAX_DRAW_STR];
636 if (hasNumInput(&data->num_input)) {
637 char num_str[NUM_STR_REP_LEN];
638 outputNumInput(&data->num_input, num_str, &scene->unit);
639 SNPRINTF(msg, IFACE_("Slip offset: %s"), num_str);
640 }
641 else {
642 SNPRINTF(msg, IFACE_("Slip offset: %d"), offset);
643 }
644
645 ED_area_status_text(area, msg);
646}
647
649 bContext *C, wmOperator *op, ScrArea *area, SlipData *data, Scene *scene)
650{
651 float offset_fl;
652 applyNumInput(&data->num_input, &offset_fl);
653 int offset = round_fl_to_int(offset_fl);
654
655 const int delta_offset = sequencer_slip_apply_limits(scene, data, &offset);
656 sequencer_slip_update_header(scene, area, data, offset);
657
658 RNA_float_set(op->ptr, "offset", offset_fl);
659
660 float subframe_delta = 0.0f;
661 if (data->subframe_restore != 0.0f) {
662 /* Always remove the previous sub-frame adjustments we have potentially made with the mouse
663 * input when the user starts entering values by hand.
664 */
665 subframe_delta = -data->subframe_restore;
666 data->subframe_restore = 0.0f;
667 }
668 if (std::trunc(offset_fl) != offset_fl) {
669 /* Only apply sub-frame offsets if the input is not an integer. */
670 subframe_delta = offset_fl - data->previous_subframe_offset - delta_offset;
671 data->subframe_restore += subframe_delta;
672 }
673 data->previous_subframe_offset = offset_fl;
674 sequencer_slip_strips(scene, data, delta_offset, subframe_delta);
675
677}
678
679static int sequencer_slip_modal(bContext *C, wmOperator *op, const wmEvent *event)
680{
681 Scene *scene = CTX_data_scene(C);
682 SlipData *data = (SlipData *)op->customdata;
683 ScrArea *area = CTX_wm_area(C);
684 const bool has_numInput = hasNumInput(&data->num_input);
685 bool handled = true;
686
687 /* Modal numinput active, try to handle numeric inputs. */
688 if (event->val == KM_PRESS && has_numInput && handleNumInput(C, &data->num_input, event)) {
689 handle_number_input(C, op, area, data, scene);
691 }
692
693 switch (event->type) {
694 case MOUSEMOVE: {
695 if (!has_numInput) {
696 float mouseloc[2];
697 int offset;
698 float mouse_x;
700
701 if (data->slow) {
702 mouse_x = event->mval[0] - data->slow_offset;
703 mouse_x *= 0.1f;
704 mouse_x += data->slow_offset;
705 }
706 else {
707 mouse_x = event->mval[0];
708 }
709
710 /* Choose the side based on which side of the current frame the mouse is. */
711 UI_view2d_region_to_view(v2d, mouse_x, 0, &mouseloc[0], &mouseloc[1]);
712 float offset_fl = mouseloc[0] - data->init_mouseloc[0];
713 offset = offset_fl;
714
715 const int delta_offset = sequencer_slip_apply_limits(scene, data, &offset);
716 sequencer_slip_update_header(scene, area, data, offset);
717
718 if (!data->slow) {
719 RNA_float_set(op->ptr, "offset", offset);
720 }
721 float subframe_delta = 0.0f;
722 if (data->slow) {
723 RNA_float_set(op->ptr, "offset", offset_fl);
724 subframe_delta = offset_fl - data->previous_subframe_offset - delta_offset;
725 data->subframe_restore += subframe_delta;
726 }
727 else if (data->subframe_restore != 0.0f) {
728 /* If we exit slow mode, make sure we undo the fractional adjustments we have done. */
729 subframe_delta = -data->subframe_restore;
730 data->subframe_restore = 0.0f;
731 }
732 data->previous_subframe_offset = offset_fl;
733 sequencer_slip_strips(scene, data, delta_offset, subframe_delta);
734
736 }
737 break;
738 }
739
740 case LEFTMOUSE:
741 case EVT_RETKEY:
742 case EVT_SPACEKEY: {
743 MEM_freeN(data->seq_array);
744 MEM_freeN(data);
745 op->customdata = nullptr;
746 if (area) {
747 ED_area_status_text(area, nullptr);
748 }
751 return OPERATOR_FINISHED;
752 }
753
754 case EVT_ESCKEY:
755 case RIGHTMOUSE: {
756 int offset = data->previous_offset;
757 float subframe_delta = data->subframe_restore;
758 sequencer_slip_strips(scene, data, -offset, -subframe_delta);
759
760 MEM_freeN(data->seq_array);
761 MEM_freeN(data);
762 op->customdata = nullptr;
763
765
766 if (area) {
767 ED_area_status_text(area, nullptr);
768 }
769
770 return OPERATOR_CANCELLED;
771 }
772
774 case EVT_LEFTSHIFTKEY:
775 if (!has_numInput) {
776 if (event->val == KM_PRESS) {
777 data->slow = true;
778 data->slow_offset = event->mval[0];
779 }
780 else if (event->val == KM_RELEASE) {
781 data->slow = false;
782 }
783 }
784 break;
785
786 default:
787 handled = false;
788 break;
789 }
790
791 /* Modal numinput inactive, try to handle numeric inputs. */
792 if (!handled && event->val == KM_PRESS && handleNumInput(C, &data->num_input, event)) {
793 handle_number_input(C, op, area, data, scene);
794 }
795
797}
798
800{
801 /* Identifiers. */
802 ot->name = "Slip Strips";
803 ot->idname = "SEQUENCER_OT_slip";
804 ot->description = "Slip the contents of selected strips";
805
806 /* Api callbacks. */
811
812 /* Flags. */
814
815 /* Properties. */
816 PropertyRNA *prop;
817
818 prop = RNA_def_float(ot->srna,
819 "offset",
820 0,
821 -FLT_MAX,
822 FLT_MAX,
823 "Offset",
824 "Offset to the data of the strip",
825 -FLT_MAX,
826 FLT_MAX);
828}
829
832/* -------------------------------------------------------------------- */
837{
838 Scene *scene = CTX_data_scene(C);
839 Editing *ed = SEQ_editing_get(scene);
840 ListBase *channels = SEQ_channels_displayed_get(ed);
841
842 bool selected;
843
844 selected = !RNA_boolean_get(op->ptr, "unselected");
845
846 LISTBASE_FOREACH (Sequence *, seq, ed->seqbasep) {
847 if (!SEQ_transform_is_locked(channels, seq)) {
848 if (selected) {
849 if (seq->flag & SELECT) {
850 seq->flag |= SEQ_MUTE;
852 }
853 }
854 else {
855 if ((seq->flag & SELECT) == 0) {
856 seq->flag |= SEQ_MUTE;
858 }
859 }
860 }
861 }
862
865
866 return OPERATOR_FINISHED;
867}
868
870{
871 /* Identifiers. */
872 ot->name = "Mute Strips";
873 ot->idname = "SEQUENCER_OT_mute";
874 ot->description = "Mute (un)selected strips";
875
876 /* Api callbacks. */
879
880 /* Flags. */
882
884 ot->srna, "unselected", false, "Unselected", "Mute unselected rather than selected strips");
885}
886
889/* -------------------------------------------------------------------- */
894{
895 Scene *scene = CTX_data_scene(C);
896 Editing *ed = SEQ_editing_get(scene);
897 ListBase *channels = SEQ_channels_displayed_get(ed);
898 bool selected;
899
900 selected = !RNA_boolean_get(op->ptr, "unselected");
901
902 LISTBASE_FOREACH (Sequence *, seq, ed->seqbasep) {
903 if (!SEQ_transform_is_locked(channels, seq)) {
904 if (selected) {
905 if (seq->flag & SELECT) {
906 seq->flag &= ~SEQ_MUTE;
908 }
909 }
910 else {
911 if ((seq->flag & SELECT) == 0) {
912 seq->flag &= ~SEQ_MUTE;
914 }
915 }
916 }
917 }
918
921
922 return OPERATOR_FINISHED;
923}
924
926{
927 /* Identifiers. */
928 ot->name = "Unmute Strips";
929 ot->idname = "SEQUENCER_OT_unmute";
930 ot->description = "Unmute (un)selected strips";
931
932 /* Api callbacks. */
935
936 /* Flags. */
938
940 "unselected",
941 false,
942 "Unselected",
943 "Unmute unselected rather than selected strips");
944}
945
948/* -------------------------------------------------------------------- */
953{
954 Scene *scene = CTX_data_scene(C);
955 Editing *ed = SEQ_editing_get(scene);
956
957 LISTBASE_FOREACH (Sequence *, seq, ed->seqbasep) {
958 if (seq->flag & SELECT) {
959 seq->flag |= SEQ_LOCK;
960 }
961 }
962
964
965 return OPERATOR_FINISHED;
966}
967
969{
970 /* Identifiers. */
971 ot->name = "Lock Strips";
972 ot->idname = "SEQUENCER_OT_lock";
973 ot->description = "Lock strips so they can't be transformed";
974
975 /* Api callbacks. */
978
979 /* Flags. */
981}
982
985/* -------------------------------------------------------------------- */
990{
991 Scene *scene = CTX_data_scene(C);
992 Editing *ed = SEQ_editing_get(scene);
993
994 LISTBASE_FOREACH (Sequence *, seq, ed->seqbasep) {
995 if (seq->flag & SELECT) {
996 seq->flag &= ~SEQ_LOCK;
997 }
998 }
999
1001
1002 return OPERATOR_FINISHED;
1003}
1004
1006{
1007 /* Identifiers. */
1008 ot->name = "Unlock Strips";
1009 ot->idname = "SEQUENCER_OT_unlock";
1010 ot->description = "Unlock strips so they can be transformed";
1011
1012 /* Api callbacks. */
1015
1016 /* Flags. */
1018}
1019
1022/* -------------------------------------------------------------------- */
1027{
1028 Scene *scene = CTX_data_scene(C);
1029 Editing *ed = SEQ_editing_get(scene);
1030 ListBase *active_seqbase = SEQ_active_seqbase_get(ed);
1031
1033
1034 if (selected.is_empty()) {
1035 return OPERATOR_CANCELLED;
1036 }
1037
1038 const bool toggle = RNA_boolean_get(op->ptr, "toggle");
1039 if (toggle && SEQ_are_strips_connected_together(selected)) {
1040 SEQ_disconnect(selected);
1041 }
1042 else {
1043 SEQ_connect(selected);
1044 }
1045
1047 return OPERATOR_FINISHED;
1048}
1049
1051{
1052 ot->name = "Connect Strips";
1053 ot->idname = "SEQUENCER_OT_connect";
1054 ot->description = "Link selected strips together for simplified group selection";
1055
1058
1060
1061 RNA_def_boolean(ot->srna, "toggle", true, "Toggle", "Toggle strip connections");
1062}
1063
1066/* -------------------------------------------------------------------- */
1071{
1072 Scene *scene = CTX_data_scene(C);
1073 Editing *ed = SEQ_editing_get(scene);
1074 ListBase *active_seqbase = SEQ_active_seqbase_get(ed);
1075
1077
1078 if (SEQ_disconnect(selected)) {
1080 return OPERATOR_FINISHED;
1081 }
1082 else {
1083 return OPERATOR_CANCELLED;
1084 }
1085}
1086
1088{
1089 ot->name = "Disconnect Strips";
1090 ot->idname = "SEQUENCER_OT_disconnect";
1091 ot->description = "Unlink selected strips so that they can be selected individually";
1092
1095
1097}
1098
1101/* -------------------------------------------------------------------- */
1106{
1107 Main *bmain = CTX_data_main(C);
1108 Scene *scene = CTX_data_scene(C);
1109 Editing *ed = SEQ_editing_get(scene);
1110 const bool adjust_length = RNA_boolean_get(op->ptr, "adjust_length");
1111
1112 LISTBASE_FOREACH (Sequence *, seq, ed->seqbasep) {
1113 if (seq->flag & SELECT) {
1114 SEQ_add_reload_new_file(bmain, scene, seq, !adjust_length);
1116
1117 if (adjust_length) {
1118 if (SEQ_transform_test_overlap(scene, ed->seqbasep, seq)) {
1119 SEQ_transform_seqbase_shuffle(ed->seqbasep, seq, scene);
1120 }
1121 }
1122 }
1123 }
1124
1126
1127 return OPERATOR_FINISHED;
1128}
1129
1131{
1132 PropertyRNA *prop;
1133
1134 /* Identifiers. */
1135 ot->name = "Reload Strips";
1136 ot->idname = "SEQUENCER_OT_reload";
1137 ot->description = "Reload strips in the sequencer";
1138
1139 /* Api callbacks. */
1142
1143 /* Flags. */
1144 ot->flag = OPTYPE_REGISTER; /* No undo, the data changed is stored outside 'main'. */
1145
1146 prop = RNA_def_boolean(ot->srna,
1147 "adjust_length",
1148 false,
1149 "Adjust Length",
1150 "Adjust length of strips to their data length");
1152}
1153
1156/* -------------------------------------------------------------------- */
1161{
1162 if (G.is_rendering) {
1163 return false;
1164 }
1165 return sequencer_edit_poll(C);
1166}
1167
1169{
1170 Scene *scene = CTX_data_scene(C);
1171 Editing *ed = SEQ_editing_get(scene);
1172
1173 SEQ_relations_free_imbuf(scene, &ed->seqbase, false);
1176
1178
1179 return OPERATOR_FINISHED;
1180}
1181
1183{
1184 /* Identifiers. */
1185 ot->name = "Refresh Sequencer";
1186 ot->idname = "SEQUENCER_OT_refresh_all";
1187 ot->description = "Refresh the sequencer editor";
1188
1189 /* Api callbacks. */
1192}
1193
1196/* -------------------------------------------------------------------- */
1201 Sequence *activeseq,
1202 int type,
1203 Sequence **r_selseq1,
1204 Sequence **r_selseq2,
1205 const char **r_error_str)
1206{
1207 Editing *ed = SEQ_editing_get(scene);
1208 Sequence *seq1 = nullptr, *seq2 = nullptr;
1209
1210 *r_error_str = nullptr;
1211
1212 if (!activeseq) {
1213 seq2 = SEQ_select_active_get(scene);
1214 }
1215
1216 if (SEQ_effect_get_num_inputs(type) == 0) {
1217 *r_selseq1 = *r_selseq2 = nullptr;
1218 return 1;
1219 }
1220
1221 LISTBASE_FOREACH (Sequence *, seq, ed->seqbasep) {
1222 if (seq->flag & SELECT) {
1223 if (seq->type == SEQ_TYPE_SOUND_RAM) {
1224 *r_error_str = N_("Cannot apply effects to audio sequence strips");
1225 return 0;
1226 }
1227 if (!ELEM(seq, activeseq, seq2)) {
1228 if (seq2 == nullptr) {
1229 seq2 = seq;
1230 }
1231 else if (seq1 == nullptr) {
1232 seq1 = seq;
1233 }
1234 else {
1235 *r_error_str = N_("Cannot apply effect to more than 2 sequence strips");
1236 return 0;
1237 }
1238 }
1239 }
1240 }
1241
1242 switch (SEQ_effect_get_num_inputs(type)) {
1243 case 1:
1244 if (seq2 == nullptr) {
1245 *r_error_str = N_("At least one selected sequence strip is needed");
1246 return 0;
1247 }
1248 if (seq1 == nullptr) {
1249 seq1 = seq2;
1250 }
1252 case 2:
1253 if (seq1 == nullptr || seq2 == nullptr) {
1254 *r_error_str = N_("2 selected sequence strips are needed");
1255 return 0;
1256 }
1257 break;
1258 }
1259
1260 if (seq1 == nullptr && seq2 == nullptr) {
1261 *r_error_str = N_("TODO: in what cases does this happen?");
1262 return 0;
1263 }
1264
1265 *r_selseq1 = seq1;
1266 *r_selseq2 = seq2;
1267
1268 /* TODO(Richard): This function needs some refactoring, this is just quick hack for #73828. */
1269 if (SEQ_effect_get_num_inputs(type) < 2) {
1270 *r_selseq2 = nullptr;
1271 }
1272
1273 return 1;
1274}
1275
1277{
1278 Scene *scene = CTX_data_scene(C);
1279 Sequence *seq1, *seq2, *last_seq = SEQ_select_active_get(scene);
1280 const char *error_msg;
1281
1282 if (SEQ_effect_get_num_inputs(last_seq->type) == 0) {
1283 BKE_report(op->reports, RPT_ERROR, "Cannot reassign inputs: strip has no inputs");
1284 return OPERATOR_CANCELLED;
1285 }
1286
1287 if (!seq_effect_find_selected(scene, last_seq, last_seq->type, &seq1, &seq2, &error_msg) ||
1288 SEQ_effect_get_num_inputs(last_seq->type) == 0)
1289 {
1290 BKE_report(op->reports, RPT_ERROR, error_msg);
1291 return OPERATOR_CANCELLED;
1292 }
1293 /* Check if reassigning would create recursivity. */
1294 if (SEQ_relations_render_loop_check(seq1, last_seq) ||
1295 SEQ_relations_render_loop_check(seq2, last_seq))
1296 {
1297 BKE_report(op->reports, RPT_ERROR, "Cannot reassign inputs: recursion detected");
1298 return OPERATOR_CANCELLED;
1299 }
1300
1301 last_seq->seq1 = seq1;
1302 last_seq->seq2 = seq2;
1303
1304 int old_start = last_seq->start;
1305
1306 /* Force time position update for reassigned effects.
1307 * TODO(Richard): This is because internally startdisp is still used, due to poor performance of
1308 * mapping effect range to inputs. This mapping could be cached though. */
1311
1313 SEQ_offset_animdata(scene, last_seq, (last_seq->start - old_start));
1314
1316
1317 return OPERATOR_FINISHED;
1318}
1319
1321{
1322 Scene *scene = CTX_data_scene(C);
1323 Editing *ed = SEQ_editing_get(scene);
1324
1325 if (ed) {
1326 Sequence *last_seq = SEQ_select_active_get(scene);
1327 if (last_seq && (last_seq->type & SEQ_TYPE_EFFECT)) {
1328 return true;
1329 }
1330 }
1331
1332 return false;
1333}
1334
1336{
1337 /* Identifiers. */
1338 ot->name = "Reassign Inputs";
1339 ot->idname = "SEQUENCER_OT_reassign_inputs";
1340 ot->description = "Reassign the inputs for the effect strip";
1341
1342 /* Api callbacks. */
1345
1346 /* Flags. */
1348}
1349
1352/* -------------------------------------------------------------------- */
1357{
1358 Scene *scene = CTX_data_scene(C);
1359 Sequence *seq, *last_seq = SEQ_select_active_get(scene);
1360
1361 if (last_seq->seq1 == nullptr || last_seq->seq2 == nullptr) {
1362 BKE_report(op->reports, RPT_ERROR, "No valid inputs to swap");
1363 return OPERATOR_CANCELLED;
1364 }
1365
1366 seq = last_seq->seq1;
1367 last_seq->seq1 = last_seq->seq2;
1368 last_seq->seq2 = seq;
1369
1371
1373
1374 return OPERATOR_FINISHED;
1375}
1377{
1378 /* Identifiers. */
1379 ot->name = "Swap Inputs";
1380 ot->idname = "SEQUENCER_OT_swap_inputs";
1381 ot->description = "Swap the two inputs of the effect strip";
1382
1383 /* Api callbacks. */
1386
1387 /* Flags. */
1389}
1390
1393/* -------------------------------------------------------------------- */
1397static int mouse_frame_side(View2D *v2d, short mouse_x, int frame)
1398{
1399 int mval[2];
1400 float mouseloc[2];
1401
1402 mval[0] = mouse_x;
1403 mval[1] = 0;
1404
1405 /* Choose the side based on which side of the current frame the mouse is on. */
1406 UI_view2d_region_to_view(v2d, mval[0], mval[1], &mouseloc[0], &mouseloc[1]);
1407
1408 return mouseloc[0] > frame ? SEQ_SIDE_RIGHT : SEQ_SIDE_LEFT;
1409}
1410
1412 {SEQ_SPLIT_SOFT, "SOFT", 0, "Soft", ""},
1413 {SEQ_SPLIT_HARD, "HARD", 0, "Hard", ""},
1414 {0, nullptr, 0, nullptr, nullptr},
1415};
1416
1418 {SEQ_SIDE_MOUSE, "MOUSE", 0, "Mouse Position", ""},
1419 {SEQ_SIDE_LEFT, "LEFT", 0, "Left", ""},
1420 {SEQ_SIDE_RIGHT, "RIGHT", 0, "Right", ""},
1421 {SEQ_SIDE_BOTH, "BOTH", 0, "Both", ""},
1422 {SEQ_SIDE_NO_CHANGE, "NO_CHANGE", 0, "No Change", ""},
1423 {0, nullptr, 0, nullptr, nullptr},
1424};
1425
1426/* Get the splitting side for the Split Strips's operator exec() callback. */
1428{
1429 const int split_side = RNA_enum_get(op->ptr, "side");
1430
1431 /* The mouse position can not be resolved from the exec() as the mouse coordinate is not
1432 * accessible. So fall-back to the RIGHT side instead.
1433 *
1434 * The SEQ_SIDE_MOUSE is used by the Strip menu, together with the EXEC_DEFAULT operator
1435 * context in order to have properly resolved shortcut in the menu. */
1436 if (split_side == SEQ_SIDE_MOUSE) {
1437 return SEQ_SIDE_RIGHT;
1438 }
1439
1440 return split_side;
1441}
1442
1444{
1445 Main *bmain = CTX_data_main(C);
1446 Scene *scene = CTX_data_scene(C);
1447 Editing *ed = SEQ_editing_get(scene);
1448 bool changed = false;
1449 bool seq_selected = false;
1450
1451 const bool use_cursor_position = RNA_boolean_get(op->ptr, "use_cursor_position");
1452
1453 const int split_frame = RNA_struct_property_is_set(op->ptr, "frame") ?
1454 RNA_int_get(op->ptr, "frame") :
1455 scene->r.cfra;
1456 const int split_channel = RNA_int_get(op->ptr, "channel");
1457
1458 const eSeqSplitMethod method = eSeqSplitMethod(RNA_enum_get(op->ptr, "type"));
1459 const int split_side = sequence_split_side_for_exec_get(op);
1460 const bool ignore_selection = RNA_boolean_get(op->ptr, "ignore_selection");
1461
1462 SEQ_prefetch_stop(scene);
1463
1464 LISTBASE_FOREACH (Sequence *, seq, ed->seqbasep) {
1465 seq->tmp = nullptr;
1466 }
1467
1469 if (use_cursor_position && seq->machine != split_channel) {
1470 continue;
1471 }
1472
1473 if (ignore_selection || seq->flag & SELECT) {
1474 const char *error_msg = nullptr;
1475 if (SEQ_edit_strip_split(bmain, scene, ed->seqbasep, seq, split_frame, method, &error_msg) !=
1476 nullptr)
1477 {
1478 changed = true;
1479 }
1480 if (error_msg != nullptr) {
1481 BKE_report(op->reports, RPT_ERROR, error_msg);
1482 }
1483 }
1484 }
1485
1486 if (changed) { /* Got new strips? */
1487 if (ignore_selection) {
1488 if (use_cursor_position) {
1490 if (SEQ_time_right_handle_frame_get(scene, seq) == split_frame &&
1491 seq->machine == split_channel)
1492 {
1493 seq_selected = seq->flag & SEQ_ALLSEL;
1494 }
1495 }
1496 if (!seq_selected) {
1498 if (SEQ_time_left_handle_frame_get(scene, seq) == split_frame &&
1499 seq->machine == split_channel)
1500 {
1501 seq->flag &= ~SEQ_ALLSEL;
1502 }
1503 }
1504 }
1505 }
1506 }
1507 else {
1508 if (split_side != SEQ_SIDE_BOTH) {
1510 if (split_side == SEQ_SIDE_LEFT) {
1511 if (SEQ_time_left_handle_frame_get(scene, seq) >= split_frame) {
1512 seq->flag &= ~SEQ_ALLSEL;
1513 }
1514 }
1515 else {
1516 if (SEQ_time_right_handle_frame_get(scene, seq) <= split_frame) {
1517 seq->flag &= ~SEQ_ALLSEL;
1518 }
1519 }
1520 }
1521 }
1522 }
1523 }
1524 if (changed) {
1526 return OPERATOR_FINISHED;
1527 }
1528
1529 /* Passthrough to selection if used as tool. */
1531}
1532
1533static int sequencer_split_invoke(bContext *C, wmOperator *op, const wmEvent *event)
1534{
1535 Scene *scene = CTX_data_scene(C);
1536 View2D *v2d = UI_view2d_fromcontext(C);
1537
1538 int split_side = RNA_enum_get(op->ptr, "side");
1539 int split_frame = scene->r.cfra;
1540
1541 if (split_side == SEQ_SIDE_MOUSE) {
1542 if (ED_operator_sequencer_active(C) && v2d) {
1543 split_side = mouse_frame_side(v2d, event->mval[0], split_frame);
1544 }
1545 else {
1546 split_side = SEQ_SIDE_BOTH;
1547 }
1548 }
1549 float mouseloc[2];
1550 if (v2d) {
1551 UI_view2d_region_to_view(v2d, event->mval[0], event->mval[1], &mouseloc[0], &mouseloc[1]);
1552 if (RNA_boolean_get(op->ptr, "use_cursor_position")) {
1553 split_frame = mouseloc[0];
1554 }
1555 RNA_int_set(op->ptr, "channel", mouseloc[1]);
1556 }
1557 RNA_int_set(op->ptr, "frame", split_frame);
1558 RNA_enum_set(op->ptr, "side", split_side);
1559 // RNA_enum_set(op->ptr, "type", split_hard);
1560
1561 return sequencer_split_exec(C, op);
1562}
1563
1564static void sequencer_split_ui(bContext * /*C*/, wmOperator *op)
1565{
1566 uiLayout *layout = op->layout;
1567 uiLayoutSetPropSep(layout, true);
1568 uiLayoutSetPropDecorate(layout, false);
1569
1570 uiLayout *row = uiLayoutRow(layout, false);
1571 uiItemR(row, op->ptr, "type", UI_ITEM_R_EXPAND, nullptr, ICON_NONE);
1572 uiItemR(layout, op->ptr, "frame", UI_ITEM_NONE, nullptr, ICON_NONE);
1573 uiItemR(layout, op->ptr, "side", UI_ITEM_NONE, nullptr, ICON_NONE);
1574
1575 uiItemS(layout);
1576
1577 uiItemR(layout, op->ptr, "use_cursor_position", UI_ITEM_NONE, nullptr, ICON_NONE);
1578 if (RNA_boolean_get(op->ptr, "use_cursor_position")) {
1579 uiItemR(layout, op->ptr, "channel", UI_ITEM_NONE, nullptr, ICON_NONE);
1580 }
1581}
1582
1584{
1585 /* Identifiers. */
1586 ot->name = "Split Strips";
1587 ot->idname = "SEQUENCER_OT_split";
1588 ot->description = "Split the selected strips in two";
1589
1590 /* Api callbacks. */
1595
1596 /* Flags. */
1598
1599 PropertyRNA *prop;
1601 "frame",
1602 0,
1603 INT_MIN,
1604 INT_MAX,
1605 "Frame",
1606 "Frame where selected strips will be split",
1607 INT_MIN,
1608 INT_MAX);
1610 "channel",
1611 0,
1612 INT_MIN,
1613 INT_MAX,
1614 "Channel",
1615 "Channel in which strip will be cut",
1616 INT_MIN,
1617 INT_MAX);
1619 "type",
1622 "Type",
1623 "The type of split operation to perform on strips");
1624
1626 "use_cursor_position",
1627 false,
1628 "Use Cursor Position",
1629 "Split at position of the cursor instead of current frame");
1630
1631 prop = RNA_def_enum(ot->srna,
1632 "side",
1635 "Side",
1636 "The side that remains selected after splitting");
1637
1639
1640 prop = RNA_def_boolean(
1641 ot->srna,
1642 "ignore_selection",
1643 false,
1644 "Ignore Selection",
1645 "Make cut even if strip is not selected preserving selection state after cut");
1646
1648}
1649
1652/* -------------------------------------------------------------------- */
1657{
1658 Scene *scene = CTX_data_scene(C);
1659 Editing *ed = SEQ_editing_get(scene);
1660
1661 if (ed == nullptr) {
1662 return OPERATOR_CANCELLED;
1663 }
1664
1665 Sequence *active_seq = SEQ_select_active_get(scene);
1666 ListBase duplicated_strips = {nullptr, nullptr};
1667
1668 SEQ_sequence_base_dupli_recursive(scene, scene, &duplicated_strips, ed->seqbasep, 0, 0);
1670
1671 if (duplicated_strips.first == nullptr) {
1672 return OPERATOR_CANCELLED;
1673 }
1674
1675 /* Duplicate animation.
1676 * First backup original curves from scene and duplicate strip curves from backup into scene.
1677 * This way, when pasted strips are renamed, curves are renamed with them. Finally, restore
1678 * original curves from backup.
1679 */
1680 SeqAnimationBackup animation_backup = {{nullptr}};
1681 SEQ_animation_backup_original(scene, &animation_backup);
1682
1683 Sequence *seq = static_cast<Sequence *>(duplicated_strips.first);
1684
1685 /* Rely on the `duplicated_strips` list being added at the end.
1686 * Their UIDs has been re-generated by the #SEQ_sequence_base_dupli_recursive(). */
1687 BLI_movelisttolist(ed->seqbasep, &duplicated_strips);
1688
1689 /* Handle duplicated strips: set active, select, ensure unique name and duplicate animation
1690 * data. */
1691 for (; seq; seq = seq->next) {
1692 if (active_seq != nullptr && STREQ(seq->name, active_seq->name)) {
1693 SEQ_select_active_set(scene, seq);
1694 }
1695 seq->flag &= ~(SEQ_LEFTSEL + SEQ_RIGHTSEL + SEQ_LOCK);
1697
1698 SEQ_animation_duplicate_backup_to_scene(scene, seq, &animation_backup);
1699 SEQ_ensure_unique_name(seq, scene);
1700 }
1701
1702 SEQ_animation_restore_original(scene, &animation_backup);
1703
1707 return OPERATOR_FINISHED;
1708}
1709
1711{
1712 /* Identifiers. */
1713 ot->name = "Duplicate Strips";
1714 ot->idname = "SEQUENCER_OT_duplicate";
1715 ot->description = "Duplicate the selected strips";
1716
1717 /* Api callbacks. */
1720
1721 /* Flags. */
1723}
1724
1727/* -------------------------------------------------------------------- */
1732{
1733 if (seq->type != SEQ_TYPE_SCENE) {
1734 return;
1735 }
1736
1737 Main *bmain = CTX_data_main(C);
1738 if (seq->scene) {
1739 if (ED_scene_delete(C, bmain, seq->scene)) {
1741 }
1742 }
1743}
1744
1746{
1747 Main *bmain = CTX_data_main(C);
1748 Scene *scene = CTX_data_scene(C);
1750 const bool delete_data = RNA_boolean_get(op->ptr, "delete_data");
1751
1753 return OPERATOR_CANCELLED;
1754 }
1755
1756 SEQ_prefetch_stop(scene);
1757
1759 SEQ_edit_flag_for_removal(scene, seqbasep, seq);
1760 if (delete_data) {
1762 }
1763 }
1764 SEQ_edit_remove_flagged_sequences(scene, seqbasep);
1765
1769 return OPERATOR_FINISHED;
1770}
1771
1772static int sequencer_delete_invoke(bContext *C, wmOperator *op, const wmEvent *event)
1773{
1774 Scene *scene = CTX_data_scene(C);
1775 ListBase *markers = &scene->markers;
1776
1778 ARegion *region = CTX_wm_region(C);
1779 if (region && (region->regiontype == RGN_TYPE_WINDOW)) {
1780 /* Bounding box of 30 pixels is used for markers shortcuts,
1781 * prevent conflict with markers shortcuts here. */
1782 if (event->mval[1] <= 30) {
1783 return OPERATOR_PASS_THROUGH;
1784 }
1785 }
1786 }
1787
1788 return sequencer_delete_exec(C, op);
1789}
1790
1792{
1793
1794 /* Identifiers. */
1795 ot->name = "Delete Strips";
1796 ot->idname = "SEQUENCER_OT_delete";
1797 ot->description = "Delete selected strips from the sequencer";
1798
1799 /* Api callbacks. */
1803
1804 /* Flags. */
1806
1807 /* Properties. */
1809 "delete_data",
1810 false,
1811 "Delete Data",
1812 "After removing the Strip, delete the associated data also");
1814}
1815
1818/* -------------------------------------------------------------------- */
1823{
1824 Scene *scene = CTX_data_scene(C);
1825 Editing *ed = SEQ_editing_get(scene);
1826 Sequence *seq;
1828
1829 /* For effects, try to find a replacement input. */
1830 for (seq = static_cast<Sequence *>(ed->seqbasep->first); seq;
1831 seq = static_cast<Sequence *>(seq->next))
1832 {
1833 if (SEQ_transform_is_locked(channels, seq)) {
1834 continue;
1835 }
1836
1837 if ((seq->type & SEQ_TYPE_EFFECT) == 0 && (seq->flag & SELECT)) {
1838 seq->startofs = seq->endofs = 0;
1839 }
1840 }
1841
1842 /* Update lengths, etc. */
1843 seq = static_cast<Sequence *>(ed->seqbasep->first);
1844 while (seq) {
1846 seq = seq->next;
1847 }
1848
1849 for (seq = static_cast<Sequence *>(ed->seqbasep->first); seq;
1850 seq = static_cast<Sequence *>(seq->next))
1851 {
1852 if ((seq->type & SEQ_TYPE_EFFECT) == 0 && (seq->flag & SELECT)) {
1853 if (SEQ_transform_test_overlap(scene, ed->seqbasep, seq)) {
1854 SEQ_transform_seqbase_shuffle(ed->seqbasep, seq, scene);
1855 }
1856 }
1857 }
1858
1860
1861 return OPERATOR_FINISHED;
1862}
1863
1865{
1866
1867 /* Identifiers. */
1868 ot->name = "Clear Strip Offset";
1869 ot->idname = "SEQUENCER_OT_offset_clear";
1870 ot->description = "Clear strip offsets from the start and end frames";
1871
1872 /* Api callbacks. */
1875
1876 /* Flags. */
1878}
1879
1882/* -------------------------------------------------------------------- */
1887{
1888 Scene *scene = CTX_data_scene(C);
1889 Editing *ed = SEQ_editing_get(scene);
1890 ListBase *seqbase = SEQ_active_seqbase_get(ed);
1891
1892 Sequence *seq, *seq_new;
1893 Strip *strip_new;
1894 StripElem *se, *se_new;
1895 int start_ofs, timeline_frame, frame_end;
1896 int step = RNA_int_get(op->ptr, "length");
1897
1898 seq = static_cast<Sequence *>(seqbase->first); /* Poll checks this is valid. */
1899
1900 SEQ_prefetch_stop(scene);
1901
1902 while (seq) {
1903 if ((seq->flag & SELECT) && (seq->type == SEQ_TYPE_IMAGE) && (seq->len > 1)) {
1904 Sequence *seq_next;
1905
1906 /* TODO: remove f-curve and assign to split image strips.
1907 * The old animation system would remove the user of `seq->ipo`. */
1908
1909 start_ofs = timeline_frame = SEQ_time_left_handle_frame_get(scene, seq);
1910 frame_end = SEQ_time_right_handle_frame_get(scene, seq);
1911
1912 while (timeline_frame < frame_end) {
1913 /* New seq. */
1914 se = SEQ_render_give_stripelem(scene, seq, timeline_frame);
1915
1916 seq_new = SEQ_sequence_dupli_recursive(scene, scene, seqbase, seq, SEQ_DUPE_UNIQUE_NAME);
1917
1918 seq_new->start = start_ofs;
1919 seq_new->type = SEQ_TYPE_IMAGE;
1920 seq_new->len = 1;
1921 seq_new->flag |= SEQ_SINGLE_FRAME_CONTENT;
1922 seq_new->endofs = 1 - step;
1923
1924 /* New strip. */
1925 strip_new = seq_new->strip;
1926 strip_new->us = 1;
1927
1928 /* New stripdata, only one element now. */
1929 /* Note this assume all elements (images) have the same dimension,
1930 * since we only copy the name here. */
1931 se_new = static_cast<StripElem *>(MEM_reallocN(strip_new->stripdata, sizeof(*se_new)));
1932 STRNCPY(se_new->filename, se->filename);
1933 strip_new->stripdata = se_new;
1934
1935 if (step > 1) {
1936 seq_new->flag &= ~SEQ_OVERLAP;
1937 if (SEQ_transform_test_overlap(scene, seqbase, seq_new)) {
1938 SEQ_transform_seqbase_shuffle(seqbase, seq_new, scene);
1939 }
1940 }
1941
1942 /* XXX, COPY FCURVES */
1943
1944 timeline_frame++;
1945 start_ofs += step;
1946 }
1947
1948 seq_next = static_cast<Sequence *>(seq->next);
1949 SEQ_edit_flag_for_removal(scene, seqbase, seq);
1950 seq = seq_next;
1951 }
1952 else {
1953 seq = seq->next;
1954 }
1955 }
1956
1957 SEQ_edit_remove_flagged_sequences(scene, seqbase);
1959
1960 return OPERATOR_FINISHED;
1961}
1962
1964{
1966 C, op, event, IFACE_("Separate Sequence Images"), IFACE_("Separate"));
1967}
1968
1970{
1971 /* Identifiers. */
1972 ot->name = "Separate Images";
1973 ot->idname = "SEQUENCER_OT_images_separate";
1974 ot->description = "On image sequence strips, it returns a strip for each image";
1975
1976 /* Api callbacks. */
1980
1981 /* Flags. */
1983
1984 RNA_def_int(ot->srna, "length", 1, 1, INT_MAX, "Length", "Length of each frame", 1, 1000);
1985}
1986
1989/* -------------------------------------------------------------------- */
1994{
1995 Scene *scene = CTX_data_scene(C);
1996 Editing *ed = SEQ_editing_get(scene);
1997 Sequence *active_seq = SEQ_select_active_get(scene);
1998
1999 SEQ_prefetch_stop(scene);
2000
2001 if (active_seq && active_seq->type == SEQ_TYPE_META && active_seq->flag & SELECT) {
2002 /* Deselect active meta seq. */
2003 SEQ_select_active_set(scene, nullptr);
2004 SEQ_meta_stack_set(scene, active_seq);
2005 }
2006 else {
2007 /* Exit meta-strip if possible. */
2008 if (BLI_listbase_is_empty(&ed->metastack)) {
2009 return OPERATOR_CANCELLED;
2010 }
2011
2012 /* Display parent meta. */
2013 Sequence *meta_parent = SEQ_meta_stack_pop(ed);
2014 SEQ_select_active_set(scene, meta_parent);
2015 }
2016
2019
2020 return OPERATOR_FINISHED;
2021}
2022
2024{
2025 /* Identifiers. */
2026 ot->name = "Toggle Meta Strip";
2027 ot->idname = "SEQUENCER_OT_meta_toggle";
2028 ot->description = "Toggle a meta-strip (to edit enclosed strips)";
2029
2030 /* Api callbacks. */
2033
2034 /* Flags. */
2036}
2037
2040/* -------------------------------------------------------------------- */
2045{
2046 Scene *scene = CTX_data_scene(C);
2047 Editing *ed = SEQ_editing_get(scene);
2048 Sequence *active_seq = SEQ_select_active_get(scene);
2049 ListBase *active_seqbase = SEQ_active_seqbase_get(ed);
2050
2051 if (SEQ_transform_seqbase_isolated_sel_check(active_seqbase) == false) {
2052 BKE_report(op->reports, RPT_ERROR, "Please select all related strips");
2053 return OPERATOR_CANCELLED;
2054 }
2055
2056 SEQ_prefetch_stop(scene);
2057
2058 int channel_max = 1, channel_min = INT_MAX, meta_start_frame = MAXFRAME,
2059 meta_end_frame = MINFRAME;
2060 Sequence *seqm = SEQ_sequence_alloc(active_seqbase, 1, 1, SEQ_TYPE_META);
2061
2062 /* Remove all selected from main list, and put in meta.
2063 * Sequence is moved within the same edit, no need to re-generate the UID. */
2064 blender::VectorSet<Sequence *> strips_to_move;
2065 LISTBASE_FOREACH (Sequence *, seq, active_seqbase) {
2066 if (seq != seqm && seq->flag & SELECT) {
2067 strips_to_move.add(seq);
2068 strips_to_move.add_multiple(SEQ_get_connected_strips(seq));
2069 }
2070 }
2071
2072 for (Sequence *seq : strips_to_move) {
2074 BLI_remlink(active_seqbase, seq);
2075 BLI_addtail(&seqm->seqbase, seq);
2076 channel_max = max_ii(seq->machine, channel_max);
2077 channel_min = min_ii(seq->machine, channel_min);
2078 meta_start_frame = min_ii(SEQ_time_left_handle_frame_get(scene, seq), meta_start_frame);
2079 meta_end_frame = max_ii(SEQ_time_right_handle_frame_get(scene, seq), meta_end_frame);
2080 }
2081
2082 ListBase *channels_cur = SEQ_channels_displayed_get(ed);
2083 ListBase *channels_meta = &seqm->channels;
2084 for (int i = channel_min; i <= channel_max; i++) {
2085 SeqTimelineChannel *channel_cur = SEQ_channel_get_by_index(channels_cur, i);
2086 SeqTimelineChannel *channel_meta = SEQ_channel_get_by_index(channels_meta, i);
2087 STRNCPY(channel_meta->name, channel_cur->name);
2088 channel_meta->flag = channel_cur->flag;
2089 }
2090
2091 seqm->machine = active_seq ? active_seq->machine : channel_max;
2092 BLI_strncpy(seqm->name + 2, DATA_("MetaStrip"), sizeof(seqm->name) - 2);
2094 seqm->start = meta_start_frame;
2095 seqm->len = meta_end_frame - meta_start_frame;
2096 SEQ_select_active_set(scene, seqm);
2097 if (SEQ_transform_test_overlap(scene, active_seqbase, seqm)) {
2098 SEQ_transform_seqbase_shuffle(active_seqbase, seqm, scene);
2099 }
2100
2104
2105 return OPERATOR_FINISHED;
2106}
2107
2109{
2110 /* Identifiers. */
2111 ot->name = "Make Meta Strip";
2112 ot->idname = "SEQUENCER_OT_meta_make";
2113 ot->description = "Group selected strips into a meta-strip";
2114
2115 /* Api callbacks. */
2118
2119 /* Flags. */
2121}
2122
2125/* -------------------------------------------------------------------- */
2130{
2131 Scene *scene = CTX_data_scene(C);
2132 Editing *ed = SEQ_editing_get(scene);
2133 Sequence *active_seq = SEQ_select_active_get(scene);
2134
2135 if (active_seq == nullptr || active_seq->type != SEQ_TYPE_META) {
2136 return OPERATOR_CANCELLED;
2137 }
2138
2139 SEQ_prefetch_stop(scene);
2140
2141 LISTBASE_FOREACH (Sequence *, seq, &active_seq->seqbase) {
2143 }
2144
2145 /* Remove all selected from meta, and put in main list.
2146 * Sequence is moved within the same edit, no need to re-generate the UID. */
2147 BLI_movelisttolist(ed->seqbasep, &active_seq->seqbase);
2148 BLI_listbase_clear(&active_seq->seqbase);
2149
2150 ListBase *active_seqbase = SEQ_active_seqbase_get(ed);
2151 SEQ_edit_flag_for_removal(scene, active_seqbase, active_seq);
2152 SEQ_edit_remove_flagged_sequences(scene, active_seqbase);
2153
2154 /* Test for effects and overlap. */
2155 LISTBASE_FOREACH (Sequence *, seq, active_seqbase) {
2156 if (seq->flag & SELECT) {
2157 seq->flag &= ~SEQ_OVERLAP;
2158 if (SEQ_transform_test_overlap(scene, active_seqbase, seq)) {
2159 SEQ_transform_seqbase_shuffle(active_seqbase, seq, scene);
2160 }
2161 }
2162 }
2163
2166
2167 return OPERATOR_FINISHED;
2168}
2169
2171{
2172 /* Identifiers. */
2173 ot->name = "UnMeta Strip";
2174 ot->idname = "SEQUENCER_OT_meta_separate";
2175 ot->description = "Put the contents of a meta-strip back in the sequencer";
2176
2177 /* Api callbacks. */
2180
2181 /* Flags. */
2183}
2184
2187/* -------------------------------------------------------------------- */
2191static bool strip_jump_internal(Scene *scene,
2192 const short side,
2193 const bool do_skip_mute,
2194 const bool do_center)
2195{
2196 bool changed = false;
2197 int timeline_frame = scene->r.cfra;
2198 int next_frame = SEQ_time_find_next_prev_edit(
2199 scene, timeline_frame, side, do_skip_mute, do_center, false);
2200
2201 if (next_frame != timeline_frame) {
2202 scene->r.cfra = next_frame;
2203 changed = true;
2204 }
2205
2206 return changed;
2207}
2208
2210{
2211 /* Prevent changes during render. */
2212 if (G.is_rendering) {
2213 return false;
2214 }
2215
2216 return sequencer_edit_poll(C);
2217}
2218
2220{
2221 Scene *scene = CTX_data_scene(C);
2222 const bool next = RNA_boolean_get(op->ptr, "next");
2223 const bool center = RNA_boolean_get(op->ptr, "center");
2224
2225 /* Currently do_skip_mute is always true. */
2226 if (!strip_jump_internal(scene, next ? SEQ_SIDE_RIGHT : SEQ_SIDE_LEFT, true, center)) {
2227 return OPERATOR_CANCELLED;
2228 }
2229
2232
2233 return OPERATOR_FINISHED;
2234}
2235
2237{
2238 /* Identifiers. */
2239 ot->name = "Jump to Strip";
2240 ot->idname = "SEQUENCER_OT_strip_jump";
2241 ot->description = "Move frame to previous edit point";
2242
2243 /* Api callbacks. */
2246
2247 /* Flags. */
2248 ot->flag = OPTYPE_UNDO;
2249
2250 /* Properties. */
2251 RNA_def_boolean(ot->srna, "next", true, "Next Strip", "");
2252 RNA_def_boolean(ot->srna, "center", true, "Use Strip Center", "");
2253}
2254
2257/* -------------------------------------------------------------------- */
2262 {SEQ_SIDE_LEFT, "LEFT", 0, "Left", ""},
2263 {SEQ_SIDE_RIGHT, "RIGHT", 0, "Right", ""},
2264 {0, nullptr, 0, nullptr, nullptr},
2265};
2266
2267static void swap_sequence(Scene *scene, Sequence *seqa, Sequence *seqb)
2268{
2269 int gap = SEQ_time_left_handle_frame_get(scene, seqb) -
2271 int seq_a_start;
2272 int seq_b_start;
2273
2274 seq_b_start = (seqb->start - SEQ_time_left_handle_frame_get(scene, seqb)) +
2275 SEQ_time_left_handle_frame_get(scene, seqa);
2276 SEQ_transform_translate_sequence(scene, seqb, seq_b_start - seqb->start);
2278
2279 seq_a_start = (seqa->start - SEQ_time_left_handle_frame_get(scene, seqa)) +
2280 SEQ_time_right_handle_frame_get(scene, seqb) + gap;
2281 SEQ_transform_translate_sequence(scene, seqa, seq_a_start - seqa->start);
2283}
2284
2285static Sequence *find_next_prev_sequence(Scene *scene, Sequence *test, int lr, int sel)
2286{
2287 /* sel: 0==unselected, 1==selected, -1==don't care. */
2288 Sequence *seq, *best_seq = nullptr;
2289 Editing *ed = SEQ_editing_get(scene);
2290
2291 int dist, best_dist;
2292 best_dist = MAXFRAME * 2;
2293
2294 if (ed == nullptr) {
2295 return nullptr;
2296 }
2297
2298 seq = static_cast<Sequence *>(ed->seqbasep->first);
2299 while (seq) {
2300 if ((seq != test) && (test->machine == seq->machine) &&
2301 ((sel == -1) || (sel == (seq->flag & SELECT))))
2302 {
2303 dist = MAXFRAME * 2;
2304
2305 switch (lr) {
2306 case SEQ_SIDE_LEFT:
2307 if (SEQ_time_right_handle_frame_get(scene, seq) <=
2308 SEQ_time_left_handle_frame_get(scene, test))
2309 {
2310 dist = SEQ_time_right_handle_frame_get(scene, test) -
2312 }
2313 break;
2314 case SEQ_SIDE_RIGHT:
2315 if (SEQ_time_left_handle_frame_get(scene, seq) >=
2317 {
2318 dist = SEQ_time_left_handle_frame_get(scene, seq) -
2320 }
2321 break;
2322 }
2323
2324 if (dist == 0) {
2325 best_seq = seq;
2326 break;
2327 }
2328 if (dist < best_dist) {
2329 best_dist = dist;
2330 best_seq = seq;
2331 }
2332 }
2333 seq = static_cast<Sequence *>(seq->next);
2334 }
2335 return best_seq; /* Can be nullptr. */
2336}
2337
2338static bool seq_is_parent(const Sequence *par, const Sequence *seq)
2339{
2340 return ((par->seq1 == seq) || (par->seq2 == seq));
2341}
2342
2344{
2345 Scene *scene = CTX_data_scene(C);
2346 Editing *ed = SEQ_editing_get(scene);
2347 Sequence *active_seq = SEQ_select_active_get(scene);
2348 ListBase *seqbase = SEQ_active_seqbase_get(ed);
2349 Sequence *seq;
2350 int side = RNA_enum_get(op->ptr, "side");
2351
2352 if (active_seq == nullptr) {
2353 return OPERATOR_CANCELLED;
2354 }
2355
2356 seq = find_next_prev_sequence(scene, active_seq, side, -1);
2357
2358 if (seq) {
2359
2360 /* Disallow effect strips. */
2361 if (SEQ_effect_get_num_inputs(seq->type) >= 1 && (seq->effectdata || seq->seq1 || seq->seq2)) {
2362 return OPERATOR_CANCELLED;
2363 }
2364 if ((SEQ_effect_get_num_inputs(active_seq->type) >= 1) &&
2365 (active_seq->effectdata || active_seq->seq1 || active_seq->seq2))
2366 {
2367 return OPERATOR_CANCELLED;
2368 }
2369
2371 if (SEQ_transform_is_locked(channels, seq) || SEQ_transform_is_locked(channels, active_seq)) {
2372 return OPERATOR_CANCELLED;
2373 }
2374
2375 switch (side) {
2376 case SEQ_SIDE_LEFT:
2377 swap_sequence(scene, seq, active_seq);
2378 break;
2379 case SEQ_SIDE_RIGHT:
2380 swap_sequence(scene, active_seq, seq);
2381 break;
2382 }
2383
2384 /* Do this in a new loop since both effects need to be calculated first. */
2385 LISTBASE_FOREACH (Sequence *, iseq, seqbase) {
2386 if ((iseq->type & SEQ_TYPE_EFFECT) &&
2387 (seq_is_parent(iseq, active_seq) || seq_is_parent(iseq, seq)))
2388 {
2389 /* This may now overlap. */
2390 if (SEQ_transform_test_overlap(scene, seqbase, iseq)) {
2391 SEQ_transform_seqbase_shuffle(seqbase, iseq, scene);
2392 }
2393 }
2394 }
2395
2397 return OPERATOR_FINISHED;
2398 }
2399
2400 return OPERATOR_CANCELLED;
2401}
2402
2404{
2405 /* Identifiers. */
2406 ot->name = "Swap Strip";
2407 ot->idname = "SEQUENCER_OT_swap";
2408 ot->description = "Swap active strip with strip to the right or left";
2409
2410 /* Api callbacks. */
2413
2414 /* Flags. */
2416
2417 /* Properties. */
2419 ot->srna, "side", prop_side_lr_types, SEQ_SIDE_RIGHT, "Side", "Side of the strip to swap");
2420}
2421
2424/* -------------------------------------------------------------------- */
2429{
2430 Scene *scene = CTX_data_scene(C);
2431 Sequence *active_seq = SEQ_select_active_get(scene);
2432 StripElem *se = nullptr;
2433
2434 if (active_seq == nullptr || active_seq->strip == nullptr) {
2435 return OPERATOR_CANCELLED;
2436 }
2437
2438 switch (active_seq->type) {
2439 case SEQ_TYPE_IMAGE:
2440 se = SEQ_render_give_stripelem(scene, active_seq, scene->r.cfra);
2441 break;
2442 case SEQ_TYPE_MOVIE:
2443 se = active_seq->strip->stripdata;
2444 break;
2445 default:
2446 return OPERATOR_CANCELLED;
2447 }
2448
2449 if (se == nullptr) {
2450 return OPERATOR_CANCELLED;
2451 }
2452
2453 /* Prevent setting the render size if sequence values aren't initialized. */
2454 if (se->orig_width <= 0 || se->orig_height <= 0) {
2455 return OPERATOR_CANCELLED;
2456 }
2457
2458 scene->r.xsch = se->orig_width;
2459 scene->r.ysch = se->orig_height;
2460
2461 active_seq->strip->transform->scale_x = active_seq->strip->transform->scale_y = 1.0f;
2462 active_seq->strip->transform->xofs = active_seq->strip->transform->yofs = 0.0f;
2463
2467
2468 return OPERATOR_FINISHED;
2469}
2470
2472{
2473 /* Identifiers. */
2474 ot->name = "Set Render Size";
2475 ot->idname = "SEQUENCER_OT_rendersize";
2476 ot->description = "Set render size and aspect from active sequence";
2477
2478 /* Api callbacks. */
2481
2482 /* Flags. */
2484}
2485
2488/* -------------------------------------------------------------------- */
2493{
2494 /* Identifiers. */
2495 ot->name = "Copy";
2496 ot->idname = "SEQUENCER_OT_copy";
2497 ot->description = "Copy the selected strips to the internal clipboard";
2498
2499 /* Api callbacks. */
2502
2503 /* Flags. */
2505}
2506
2509/* -------------------------------------------------------------------- */
2514{
2515 Editing *ed = SEQ_editing_get(scene);
2516 bool changed = false;
2517
2518 if (ed == nullptr) {
2519 return changed;
2520 }
2521
2523 if (seq->flag & SEQ_ALLSEL) {
2524 seq->flag &= ~SEQ_ALLSEL;
2525 changed = true;
2526 }
2527 }
2528 return changed;
2529}
2530
2532{
2533 /* Identifiers. */
2534 ot->name = "Paste";
2535 ot->idname = "SEQUENCER_OT_paste";
2536 ot->description = "Paste strips from the internal clipboard";
2537
2538 /* Api callbacks. */
2541
2542 /* Flags. */
2544
2545 /* Properties. */
2547 ot->srna,
2548 "keep_offset",
2549 false,
2550 "Keep Offset",
2551 "Keep strip offset relative to the current frame when pasting");
2553}
2554
2557/* -------------------------------------------------------------------- */
2562{
2563 Scene *scene = CTX_data_scene(C);
2564 Sequence *seq_act;
2565 Sequence *seq_other;
2566 const char *error_msg;
2567
2568 if (SEQ_select_active_get_pair(scene, &seq_act, &seq_other) == false) {
2569 BKE_report(op->reports, RPT_ERROR, "Please select two strips");
2570 return OPERATOR_CANCELLED;
2571 }
2572
2573 if (SEQ_edit_sequence_swap(scene, seq_act, seq_other, &error_msg) == false) {
2574 BKE_report(op->reports, RPT_ERROR, error_msg);
2575 return OPERATOR_CANCELLED;
2576 }
2577
2578 if (seq_act->scene_sound) {
2580 }
2581
2582 if (seq_other->scene_sound) {
2583 BKE_sound_remove_scene_sound(scene, seq_other->scene_sound);
2584 }
2585
2586 seq_act->scene_sound = nullptr;
2587 seq_other->scene_sound = nullptr;
2588
2589 if (seq_act->sound) {
2590 BKE_sound_add_scene_sound_defaults(scene, seq_act);
2591 }
2592 if (seq_other->sound) {
2593 BKE_sound_add_scene_sound_defaults(scene, seq_other);
2594 }
2595
2596 SEQ_relations_invalidate_cache_raw(scene, seq_act);
2597 SEQ_relations_invalidate_cache_raw(scene, seq_other);
2598
2600
2601 return OPERATOR_FINISHED;
2602}
2603
2605{
2606 /* Identifiers. */
2607 ot->name = "Sequencer Swap Data";
2608 ot->idname = "SEQUENCER_OT_swap_data";
2609 ot->description = "Swap 2 sequencer strips";
2610
2611 /* Api callbacks. */
2614
2615 /* Flags. */
2617}
2618
2621/* -------------------------------------------------------------------- */
2626{
2627 Scene *scene = CTX_data_scene(C);
2628 Sequence *seq = SEQ_select_active_get(scene);
2629
2630 Sequence **seq_1 = &seq->seq1, **seq_2 = &seq->seq2;
2631
2632 if (*seq_1 == nullptr || *seq_2 == nullptr) {
2633 BKE_report(op->reports, RPT_ERROR, "One of the effect inputs is unset, cannot swap");
2634 return OPERATOR_CANCELLED;
2635 }
2636
2637 std::swap(*seq_1, *seq_2);
2638
2641
2642 return OPERATOR_FINISHED;
2643}
2644
2646{
2647 /* Identifiers. */
2648 ot->name = "Change Effect Input";
2649 ot->idname = "SEQUENCER_OT_change_effect_input";
2650
2651 /* Api callbacks. */
2654
2655 /* Flags. */
2657}
2658
2661/* -------------------------------------------------------------------- */
2666 {SEQ_TYPE_CROSS, "CROSS", 0, "Crossfade", "Crossfade effect strip type"},
2667 {SEQ_TYPE_ADD, "ADD", 0, "Add", "Add effect strip type"},
2668 {SEQ_TYPE_SUB, "SUBTRACT", 0, "Subtract", "Subtract effect strip type"},
2669 {SEQ_TYPE_ALPHAOVER, "ALPHA_OVER", 0, "Alpha Over", "Alpha Over effect strip type"},
2670 {SEQ_TYPE_ALPHAUNDER, "ALPHA_UNDER", 0, "Alpha Under", "Alpha Under effect strip type"},
2671 {SEQ_TYPE_GAMCROSS, "GAMMA_CROSS", 0, "Gamma Cross", "Gamma Cross effect strip type"},
2672 {SEQ_TYPE_MUL, "MULTIPLY", 0, "Multiply", "Multiply effect strip type"},
2673 {SEQ_TYPE_OVERDROP, "OVER_DROP", 0, "Alpha Over Drop", "Alpha Over Drop effect strip type"},
2674 {SEQ_TYPE_WIPE, "WIPE", 0, "Wipe", "Wipe effect strip type"},
2675 {SEQ_TYPE_GLOW, "GLOW", 0, "Glow", "Glow effect strip type"},
2676 {SEQ_TYPE_TRANSFORM, "TRANSFORM", 0, "Transform", "Transform effect strip type"},
2677 {SEQ_TYPE_COLOR, "COLOR", 0, "Color", "Color effect strip type"},
2678 {SEQ_TYPE_SPEED, "SPEED", 0, "Speed", "Color effect strip type"},
2679 {SEQ_TYPE_MULTICAM, "MULTICAM", 0, "Multicam Selector", ""},
2680 {SEQ_TYPE_ADJUSTMENT, "ADJUSTMENT", 0, "Adjustment Layer", ""},
2681 {SEQ_TYPE_GAUSSIAN_BLUR, "GAUSSIAN_BLUR", 0, "Gaussian Blur", ""},
2682 {SEQ_TYPE_TEXT, "TEXT", 0, "Text", ""},
2683 {SEQ_TYPE_COLORMIX, "COLORMIX", 0, "Color Mix", ""},
2684 {0, nullptr, 0, nullptr, nullptr},
2685};
2686
2688{
2689 Scene *scene = CTX_data_scene(C);
2690 Sequence *seq = SEQ_select_active_get(scene);
2691 const int new_type = RNA_enum_get(op->ptr, "type");
2692
2693 /* Free previous effect and init new effect. */
2694 SeqEffectHandle sh;
2695
2696 if ((seq->type & SEQ_TYPE_EFFECT) == 0) {
2697 return OPERATOR_CANCELLED;
2698 }
2699
2700 /* Can someone explain the logic behind only allowing to increase this,
2701 * copied from 2.4x - campbell */
2703 BKE_report(op->reports, RPT_ERROR, "New effect needs more input strips");
2704 return OPERATOR_CANCELLED;
2705 }
2706
2707 sh = SEQ_effect_handle_get(seq);
2708 sh.free(seq, true);
2709
2710 seq->type = new_type;
2711
2712 sh = SEQ_effect_handle_get(seq);
2713 sh.init(seq);
2714
2717
2718 return OPERATOR_FINISHED;
2719}
2720
2722{
2723 /* Identifiers. */
2724 ot->name = "Change Effect Type";
2725 ot->idname = "SEQUENCER_OT_change_effect_type";
2726
2727 /* Api callbacks. */
2730
2731 /* Flags. */
2733
2735 "type",
2738 "Type",
2739 "Sequencer effect type");
2741}
2742
2745/* -------------------------------------------------------------------- */
2750{
2751 Main *bmain = CTX_data_main(C);
2752 Scene *scene = CTX_data_scene(C);
2753 Sequence *seq = SEQ_select_active_get(scene);
2754 const bool is_relative_path = RNA_boolean_get(op->ptr, "relative_path");
2755 const bool use_placeholders = RNA_boolean_get(op->ptr, "use_placeholders");
2756 int minext_frameme, numdigits;
2757
2758 if (seq->type == SEQ_TYPE_IMAGE) {
2759 char directory[FILE_MAX];
2760 int len;
2761 StripElem *se;
2762
2763 /* Need to find min/max frame for placeholders. */
2764 if (use_placeholders) {
2765 len = sequencer_image_seq_get_minmax_frame(op, seq->sfra, &minext_frameme, &numdigits);
2766 }
2767 else {
2769 }
2770 if (len == 0) {
2771 return OPERATOR_CANCELLED;
2772 }
2773
2774 RNA_string_get(op->ptr, "directory", directory);
2775 if (is_relative_path) {
2776 /* TODO(@ideasman42): shouldn't this already be relative from the filesel?
2777 * (as the 'filepath' is) for now just make relative here,
2778 * but look into changing after 2.60. */
2779 BLI_path_rel(directory, BKE_main_blendfile_path(bmain));
2780 }
2781 STRNCPY(seq->strip->dirpath, directory);
2782
2783 if (seq->strip->stripdata) {
2784 MEM_freeN(seq->strip->stripdata);
2785 }
2786 seq->strip->stripdata = se = MEM_cnew_array<StripElem>(len, "stripelem");
2787
2788 if (use_placeholders) {
2789 sequencer_image_seq_reserve_frames(op, se, len, minext_frameme, numdigits);
2790 }
2791 else {
2792 RNA_BEGIN (op->ptr, itemptr, "files") {
2793 char *filename = RNA_string_get_alloc(&itemptr, "name", nullptr, 0, nullptr);
2794 STRNCPY(se->filename, filename);
2795 MEM_freeN(filename);
2796 se++;
2797 }
2798 RNA_END;
2799 }
2800
2801 if (len == 1) {
2803 }
2804 else {
2805 seq->flag &= ~SEQ_SINGLE_FRAME_CONTENT;
2806 }
2807
2808 /* Reset these else we won't see all the images. */
2809 seq->anim_startofs = seq->anim_endofs = 0;
2810
2811 /* Correct start/end frames so we don't move.
2812 * Important not to set seq->len = len; allow the function to handle it. */
2813 SEQ_add_reload_new_file(bmain, scene, seq, true);
2814 }
2815 else if (seq->type == SEQ_TYPE_SOUND_RAM) {
2816 bSound *sound = seq->sound;
2817 if (sound == nullptr) {
2818 return OPERATOR_CANCELLED;
2819 }
2820 char filepath[FILE_MAX];
2821 RNA_string_get(op->ptr, "filepath", filepath);
2822 STRNCPY(sound->filepath, filepath);
2823 BKE_sound_load(bmain, sound);
2824 }
2825 else {
2826 /* Lame, set rna filepath. */
2827 PropertyRNA *prop;
2828 char filepath[FILE_MAX];
2829
2830 PointerRNA seq_ptr = RNA_pointer_create(&scene->id, &RNA_Sequence, seq);
2831
2832 RNA_string_get(op->ptr, "filepath", filepath);
2833 prop = RNA_struct_find_property(&seq_ptr, "filepath");
2834 RNA_property_string_set(&seq_ptr, prop, filepath);
2835 RNA_property_update(C, &seq_ptr, prop);
2837 }
2838
2841
2842 return OPERATOR_FINISHED;
2843}
2844
2845static int sequencer_change_path_invoke(bContext *C, wmOperator *op, const wmEvent * /*event*/)
2846{
2847 Scene *scene = CTX_data_scene(C);
2848 Sequence *seq = SEQ_select_active_get(scene);
2849 char filepath[FILE_MAX];
2850
2851 BLI_path_join(filepath, sizeof(filepath), seq->strip->dirpath, seq->strip->stripdata->filename);
2852
2853 RNA_string_set(op->ptr, "directory", seq->strip->dirpath);
2854 RNA_string_set(op->ptr, "filepath", filepath);
2855
2856 /* Set default display depending on seq type. */
2857 if (seq->type == SEQ_TYPE_IMAGE) {
2858 RNA_boolean_set(op->ptr, "filter_movie", false);
2859 }
2860 else {
2861 RNA_boolean_set(op->ptr, "filter_image", false);
2862 }
2863
2865
2867}
2868
2870{
2871 /* Identifiers. */
2872 ot->name = "Change Data/Files";
2873 ot->idname = "SEQUENCER_OT_change_path";
2874
2875 /* Api callbacks. */
2879
2880 /* Flags. */
2882
2892 "use_placeholders",
2893 false,
2894 "Use Placeholders",
2895 "Use placeholders for missing frames of the strip");
2896}
2897
2900/* -------------------------------------------------------------------- */
2905{
2907 if (ed == nullptr) {
2908 return false;
2909 }
2910 Sequence *seq = ed->act_seq;
2911 return ((seq != nullptr) && (seq->type == SEQ_TYPE_SCENE));
2912}
2914{
2915 Main *bmain = CTX_data_main(C);
2916 Scene *scene = CTX_data_scene(C);
2917 Scene *scene_seq = static_cast<Scene *>(
2918 BLI_findlink(&bmain->scenes, RNA_enum_get(op->ptr, "scene")));
2919
2920 if (scene_seq == nullptr) {
2921 BKE_report(op->reports, RPT_ERROR, "Scene not found");
2922 return OPERATOR_CANCELLED;
2923 }
2924
2925 /* Assign new scene. */
2926 Sequence *seq = SEQ_select_active_get(scene);
2927 if (seq) {
2928 seq->scene = scene_seq;
2929 /* Do a refresh of the sequencer data. */
2933 }
2934
2937
2938 return OPERATOR_FINISHED;
2939}
2940
2942{
2943 if (!RNA_struct_property_is_set(op->ptr, "scene")) {
2944 return WM_enum_search_invoke(C, op, event);
2945 }
2946
2947 return sequencer_change_scene_exec(C, op);
2948}
2949
2951{
2952 PropertyRNA *prop;
2953
2954 /* Identifiers. */
2955 ot->name = "Change Scene";
2956 ot->idname = "SEQUENCER_OT_change_scene";
2957 ot->description = "Change Scene assigned to Strip";
2958
2959 /* Api callbacks. */
2963
2964 /* Flags. */
2966
2967 /* Properties. */
2968 prop = RNA_def_enum(ot->srna, "scene", rna_enum_dummy_NULL_items, 0, "Scene", "");
2971 ot->prop = prop;
2972}
2973
2976/* -------------------------------------------------------------------- */
2981static int seq_cmp_time_startdisp_channel(void *thunk, const void *a, const void *b)
2982{
2983 const Scene *scene = static_cast<Scene *>(thunk);
2984 const Sequence *seq_a = static_cast<const Sequence *>(a);
2985 const Sequence *seq_b = static_cast<const Sequence *>(b);
2986
2987 int seq_a_start = SEQ_time_left_handle_frame_get(scene, seq_a);
2988 int seq_b_start = SEQ_time_left_handle_frame_get(scene, seq_b);
2989
2990 /* If strips have the same start frame favor the one with a higher channel. */
2991 if (seq_a_start == seq_b_start) {
2992 return seq_a->machine > seq_b->machine;
2993 }
2994
2995 return (seq_a_start > seq_b_start);
2996}
2997
2999 wmOperator *op,
3000 const wmEvent * /*event*/)
3001{
3003
3005
3007}
3008
3013
3014static bool seq_get_text_strip_cb(Sequence *seq, void *user_data)
3015{
3016 Seq_get_text_cb_data *cd = (Seq_get_text_cb_data *)user_data;
3017 Editing *ed = SEQ_editing_get(cd->scene);
3018 ListBase *channels = SEQ_channels_displayed_get(ed);
3019 /* Only text strips that are not muted and don't end with negative frame. */
3020 if ((seq->type == SEQ_TYPE_TEXT) && !SEQ_render_is_muted(channels, seq) &&
3022 {
3024 }
3025 return true;
3026}
3027
3029{
3030 Scene *scene = CTX_data_scene(C);
3031 Sequence *seq, *seq_next;
3032 Editing *ed = SEQ_editing_get(scene);
3033 ListBase text_seq = {nullptr};
3034 int iter = 1; /* Sequence numbers in `.srt` files are 1-indexed. */
3035 FILE *file;
3036 char filepath[FILE_MAX];
3037
3038 if (!RNA_struct_property_is_set_ex(op->ptr, "filepath", false)) {
3039 BKE_report(op->reports, RPT_ERROR, "No filepath given");
3040 return OPERATOR_CANCELLED;
3041 }
3042
3043 RNA_string_get(op->ptr, "filepath", filepath);
3044 BLI_path_extension_ensure(filepath, sizeof(filepath), ".srt");
3045
3046 /* Avoid File write exceptions. */
3047 if (!BLI_exists(filepath)) {
3049 if (!BLI_file_touch(filepath)) {
3050 BKE_report(op->reports, RPT_ERROR, "Can't create subtitle file");
3051 return OPERATOR_CANCELLED;
3052 }
3053 }
3054 else if (!BLI_file_is_writable(filepath)) {
3055 BKE_report(op->reports, RPT_ERROR, "Can't overwrite export file");
3056 return OPERATOR_CANCELLED;
3057 }
3058
3059 if (ed != nullptr) {
3060 Seq_get_text_cb_data cb_data = {&text_seq, scene};
3062 }
3063
3064 if (BLI_listbase_is_empty(&text_seq)) {
3065 BKE_report(op->reports, RPT_ERROR, "No subtitles (text strips) to export");
3066 return OPERATOR_CANCELLED;
3067 }
3068
3070
3071 /* Open and write file. */
3072 file = BLI_fopen(filepath, "w");
3073
3074 for (seq = static_cast<Sequence *>(text_seq.first); seq; seq = seq_next) {
3075 TextVars *data = static_cast<TextVars *>(seq->effectdata);
3076 char timecode_str_start[32];
3077 char timecode_str_end[32];
3078
3079 /* Write time-code relative to start frame of scene. Don't allow negative time-codes. */
3081 timecode_str_start,
3082 sizeof(timecode_str_start),
3083 -2,
3084 FRA2TIME(max_ii(SEQ_time_left_handle_frame_get(scene, seq) - scene->r.sfra, 0)),
3085 FPS,
3088 timecode_str_end,
3089 sizeof(timecode_str_end),
3090 -2,
3091 FRA2TIME(SEQ_time_right_handle_frame_get(scene, seq) - scene->r.sfra),
3092 FPS,
3094
3095 fprintf(
3096 file, "%d\n%s --> %s\n%s\n\n", iter++, timecode_str_start, timecode_str_end, data->text);
3097
3098 seq_next = static_cast<Sequence *>(seq->next);
3099 MEM_freeN(seq);
3100 }
3101
3102 fclose(file);
3103
3104 return OPERATOR_FINISHED;
3105}
3106
3108{
3109 Editing *ed;
3110 Sequence *seq;
3111 return (((ed = SEQ_editing_get(CTX_data_scene(C))) != nullptr) &&
3112 ((seq = ed->act_seq) != nullptr) && (seq->type == SEQ_TYPE_TEXT));
3113}
3114
3116{
3117 /* Identifiers. */
3118 ot->name = "Export Subtitles";
3119 ot->idname = "SEQUENCER_OT_export_subtitles";
3120 ot->description = "Export .srt file containing text strips";
3121
3122 /* Api callbacks. */
3126
3127 /* Flags. */
3129
3133 FILE_SAVE,
3137}
3138
3141/* -------------------------------------------------------------------- */
3146{
3147 Scene *scene = CTX_data_scene(C);
3148 Editing *ed = SEQ_editing_get(scene);
3149
3150 int sfra = MAXFRAME;
3151 int efra = -MAXFRAME;
3152 bool selected = false;
3153 const bool preview = RNA_boolean_get(op->ptr, "preview");
3154
3155 LISTBASE_FOREACH (Sequence *, seq, ed->seqbasep) {
3156 if (seq->flag & SELECT) {
3157 selected = true;
3158 sfra = min_ii(sfra, SEQ_time_left_handle_frame_get(scene, seq));
3159 /* Offset of -1 is needed because in the sequencer every frame has width.
3160 * Range from 1 to 1 is drawn as range 1 to 2, because 1 frame long strip starts at frame 1
3161 * and ends at frame 2. See #106480. */
3162 efra = max_ii(efra, SEQ_time_right_handle_frame_get(scene, seq) - 1);
3163 }
3164 }
3165
3166 if (!selected) {
3167 BKE_report(op->reports, RPT_WARNING, "Select one or more strips");
3168 return OPERATOR_CANCELLED;
3169 }
3170 if (efra < 0) {
3171 BKE_report(op->reports, RPT_ERROR, "Can't set a negative range");
3172 return OPERATOR_CANCELLED;
3173 }
3174
3175 if (preview) {
3176 scene->r.flag |= SCER_PRV_RANGE;
3177 scene->r.psfra = max_ii(0, sfra);
3178 scene->r.pefra = efra;
3179 }
3180 else {
3181 scene->r.flag &= ~SCER_PRV_RANGE;
3182 scene->r.sfra = max_ii(0, sfra);
3183 scene->r.efra = efra;
3184 }
3185
3187
3188 return OPERATOR_FINISHED;
3189}
3190
3192{
3193 PropertyRNA *prop;
3194
3195 /* Identifiers. */
3196 ot->name = "Set Range to Strips";
3197 ot->idname = "SEQUENCER_OT_set_range_to_strips";
3198 ot->description = "Set the frame range to the selected strips start and end";
3199
3200 /* Api callbacks. */
3203
3204 /* Flags. */
3206
3207 prop = RNA_def_boolean(ot->srna, "preview", false, "Preview", "Set the preview range instead");
3209}
3210
3213/* -------------------------------------------------------------------- */
3217enum {
3222};
3223
3225 {STRIP_TRANSFORM_POSITION, "POSITION", 0, "Position", "Reset strip transform location"},
3226 {STRIP_TRANSFORM_SCALE, "SCALE", 0, "Scale", "Reset strip transform scale"},
3227 {STRIP_TRANSFORM_ROTATION, "ROTATION", 0, "Rotation", "Reset strip transform rotation"},
3228 {STRIP_TRANSFORM_ALL, "ALL", 0, "All", "Reset strip transform location, scale and rotation"},
3229 {0, nullptr, 0, nullptr, nullptr},
3230};
3231
3233{
3234 Scene *scene = CTX_data_scene(C);
3235 const Editing *ed = SEQ_editing_get(scene);
3236 const int property = RNA_enum_get(op->ptr, "property");
3237
3238 LISTBASE_FOREACH (Sequence *, seq, ed->seqbasep) {
3239 if (seq->flag & SELECT && seq->type != SEQ_TYPE_SOUND_RAM) {
3240 StripTransform *transform = seq->strip->transform;
3241 switch (property) {
3243 transform->xofs = 0;
3244 transform->yofs = 0;
3245 break;
3247 transform->scale_x = 1.0f;
3248 transform->scale_y = 1.0f;
3249 break;
3251 transform->rotation = 0.0f;
3252 break;
3254 transform->xofs = 0;
3255 transform->yofs = 0;
3256 transform->scale_x = 1.0f;
3257 transform->scale_y = 1.0f;
3258 transform->rotation = 0.0f;
3259 break;
3260 }
3262 }
3263 }
3264
3266 return OPERATOR_FINISHED;
3267}
3268
3270{
3271 /* Identifiers. */
3272 ot->name = "Clear Strip Transform";
3273 ot->idname = "SEQUENCER_OT_strip_transform_clear";
3274 ot->description = "Reset image transformation to default value";
3275
3276 /* Api callbacks. */
3279
3280 /* Flags. */
3282
3284 "property",
3287 "Property",
3288 "Strip transform property to be reset");
3289}
3290
3293/* -------------------------------------------------------------------- */
3298 {SEQ_SCALE_TO_FIT, "FIT", 0, "Scale to Fit", "Scale image so fits in preview"},
3299 {SEQ_SCALE_TO_FILL, "FILL", 0, "Scale to Fill", "Scale image so it fills preview completely"},
3300 {SEQ_STRETCH_TO_FILL, "STRETCH", 0, "Stretch to Fill", "Stretch image so it fills preview"},
3301 {0, nullptr, 0, nullptr, nullptr},
3302};
3303
3305{
3306 Scene *scene = CTX_data_scene(C);
3307 const Editing *ed = SEQ_editing_get(scene);
3308 const eSeqImageFitMethod fit_method = eSeqImageFitMethod(RNA_enum_get(op->ptr, "fit_method"));
3309
3310 LISTBASE_FOREACH (Sequence *, seq, ed->seqbasep) {
3311 if (seq->flag & SELECT && seq->type != SEQ_TYPE_SOUND_RAM) {
3312 const int timeline_frame = scene->r.cfra;
3313 StripElem *strip_elem = SEQ_render_give_stripelem(scene, seq, timeline_frame);
3314
3315 if (strip_elem == nullptr) {
3316 continue;
3317 }
3318
3320 strip_elem->orig_width,
3321 strip_elem->orig_height,
3322 scene->r.xsch,
3323 scene->r.ysch,
3324 fit_method);
3326 }
3327 }
3328
3330 return OPERATOR_FINISHED;
3331}
3332
3334{
3335 /* Identifiers. */
3336 ot->name = "Strip Transform Set Fit";
3337 ot->idname = "SEQUENCER_OT_strip_transform_fit";
3338
3339 /* Api callbacks. */
3342
3343 /* Flags. */
3345
3347 "fit_method",
3350 "Fit Method",
3351 "Scale fit fit_method");
3352}
3353
3355{
3356 Scene *scene = CTX_data_scene(C);
3357 const Editing *ed = SEQ_editing_get(scene);
3358 const short color_tag = RNA_enum_get(op->ptr, "color");
3359
3360 LISTBASE_FOREACH (Sequence *, seq, ed->seqbasep) {
3361 if (seq->flag & SELECT) {
3362 seq->color_tag = color_tag;
3363 }
3364 }
3365
3367 return OPERATOR_FINISHED;
3368}
3369
3371{
3372 Scene *scene = CTX_data_scene(C);
3373 if (scene == nullptr) {
3374 return false;
3375 }
3376
3377 Editing *ed = SEQ_editing_get(scene);
3378 if (ed == nullptr) {
3379 return false;
3380 }
3381
3382 Sequence *act_seq = ed->act_seq;
3383 return act_seq != nullptr;
3384}
3385
3387{
3388 /* Identifiers. */
3389 ot->name = "Set Color Tag";
3390 ot->idname = "SEQUENCER_OT_strip_color_tag_set";
3391 ot->description = "Set a color tag for the selected strips";
3392
3393 /* Api callbacks. */
3396
3397 /* Flags. */
3399
3401 ot->srna, "color", rna_enum_strip_color_items, SEQUENCE_COLOR_NONE, "Color Tag", "");
3402}
3403
3406/* -------------------------------------------------------------------- */
3411{
3412 Scene *scene = CTX_data_scene(C);
3413 SpaceSeq *sseq = CTX_wm_space_seq(C);
3414
3415 float cursor_pixel[2];
3416 RNA_float_get_array(op->ptr, "location", cursor_pixel);
3417
3418 SEQ_image_preview_unit_from_px(scene, cursor_pixel, sseq->cursor);
3419
3421
3422 /* Use pass-through to allow click-drag to transform the cursor. */
3424}
3425
3427{
3428 ARegion *region = CTX_wm_region(C);
3429 float cursor_pixel[2];
3431 &region->v2d, event->mval[0], event->mval[1], &cursor_pixel[0], &cursor_pixel[1]);
3432
3433 RNA_float_set_array(op->ptr, "location", cursor_pixel);
3434
3435 return sequencer_set_2d_cursor_exec(C, op);
3436}
3437
3439{
3440 /* identifiers */
3441 ot->name = "Set 2D Cursor";
3442 ot->description = "Set 2D cursor location";
3443 ot->idname = "SEQUENCER_OT_cursor_set";
3444
3445 /* api callbacks */
3449
3450 /* flags */
3452
3453 /* properties */
3455 "location",
3456 2,
3457 nullptr,
3458 -FLT_MAX,
3459 FLT_MAX,
3460 "Location",
3461 "Cursor location in normalized preview coordinates",
3462 -10.0f,
3463 10.0f);
3464}
3465
3468/* -------------------------------------------------------------------- */
3473{
3474 Scene *scene = CTX_data_scene(C);
3475 Editing *ed = SEQ_editing_get(scene);
3476 Sequence *seq = ed->act_seq;
3477
3478 const int old_start = SEQ_time_left_handle_frame_get(scene, seq);
3479 const int old_end = SEQ_time_right_handle_frame_get(scene, seq);
3480
3481 Scene *target_scene = seq->scene;
3482
3483 seq->len = target_scene->r.efra - target_scene->r.sfra + 1;
3484 SEQ_time_left_handle_frame_set(scene, seq, old_start);
3485 SEQ_time_right_handle_frame_set(scene, seq, old_end);
3486
3490 return OPERATOR_FINISHED;
3491}
3492
3494{
3496 return (ed != nullptr && ed->act_seq != nullptr && (ed->act_seq->type & SEQ_TYPE_SCENE) != 0);
3497}
3498
3500{
3501 /* identifiers */
3502 ot->name = "Update Scene Frame Range";
3503 ot->description = "Update frame range of scene strip";
3504 ot->idname = "SEQUENCER_OT_scene_frame_range_update";
3505
3506 /* api callbacks */
3509
3510 /* flags */
3512}
3513
Functions for backward compatibility with the legacy Action API.
ScrArea * CTX_wm_area(const bContext *C)
Scene * CTX_data_scene(const bContext *C)
SpaceSeq * CTX_wm_space_seq(const bContext *C)
Main * CTX_data_main(const bContext *C)
ARegion * CTX_wm_region(const bContext *C)
const char * BKE_main_blendfile_path(const Main *bmain) ATTR_NONNULL()
Definition main.cc:832
void BKE_report(ReportList *reports, eReportType type, const char *message)
Definition report.cc:125
void BKE_sound_load(struct Main *bmain, struct bSound *sound)
void * BKE_sound_add_scene_sound_defaults(struct Scene *scene, struct Sequence *sequence)
void BKE_sound_remove_scene_sound(struct Scene *scene, void *handle)
#define ATTR_FALLTHROUGH
File and directory operations.
bool BLI_file_touch(const char *filepath) ATTR_NONNULL(1)
Definition fileops_c.cc:316
int BLI_exists(const char *path) ATTR_WARN_UNUSED_RESULT ATTR_NONNULL()
Definition storage.cc:350
bool BLI_file_is_writable(const char *filepath) ATTR_WARN_UNUSED_RESULT ATTR_NONNULL()
Definition fileops_c.cc:291
FILE * BLI_fopen(const char *filepath, const char *mode) ATTR_WARN_UNUSED_RESULT ATTR_NONNULL()
bool BLI_file_ensure_parent_dir_exists(const char *filepath) ATTR_NONNULL(1)
Definition fileops_c.cc:429
BLI_INLINE bool BLI_listbase_is_empty(const struct ListBase *lb)
#define LISTBASE_FOREACH(type, var, list)
#define LISTBASE_FOREACH_BACKWARD(type, var, list)
BLI_INLINE void BLI_listbase_clear(struct ListBase *lb)
void * BLI_findlink(const struct ListBase *listbase, int number) ATTR_WARN_UNUSED_RESULT ATTR_NONNULL(1)
void void void BLI_movelisttolist(struct ListBase *dst, struct ListBase *src) ATTR_NONNULL(1
void BLI_addtail(struct ListBase *listbase, void *vlink) ATTR_NONNULL(1)
Definition listbase.cc:110
void BLI_remlink(struct ListBase *listbase, void *vlink) ATTR_NONNULL(1)
Definition listbase.cc:130
void void void BLI_listbase_sort_r(ListBase *listbase, int(*cmp)(void *, const void *, const void *), void *thunk) ATTR_NONNULL(1
MINLINE int round_fl_to_int(float a)
MINLINE int min_ii(int a, int b)
MINLINE int max_ii(int a, int b)
MINLINE void copy_v2_v2(float r[2], const float a[2])
#define FILE_MAX
#define BLI_path_join(...)
bool BLI_path_extension_ensure(char *path, size_t path_maxncpy, const char *ext) ATTR_NONNULL(1
bool void BLI_path_rel(char path[FILE_MAX], const char *basepath) ATTR_NONNULL(1)
int bool BLI_str_startswith(const char *__restrict str, const char *__restrict start) ATTR_WARN_UNUSED_RESULT ATTR_NONNULL(1
#define STRNCPY(dst, src)
Definition BLI_string.h:593
#define SNPRINTF(dst, format,...)
Definition BLI_string.h:597
int bool bool BLI_str_endswith(const char *__restrict str, const char *__restrict end) ATTR_NONNULL(1
char * BLI_strncpy(char *__restrict dst, const char *__restrict src, size_t dst_maxncpy) ATTR_NONNULL(1
size_t BLI_timecode_string_from_time(char *str, size_t maxncpy, int brevity_level, float time_seconds, double fps, short timecode_style) ATTR_NONNULL()
Definition timecode.c:23
#define ELEM(...)
#define STREQ(a, b)
#define BLT_I18NCONTEXT_ID_SEQUENCE
#define IFACE_(msgid)
#define DATA_(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:1092
@ ID_RECALC_AUDIO
Definition DNA_ID.h:1099
@ ID_RECALC_SEQUENCER_STRIPS
Definition DNA_ID.h:1089
#define ID_IS_EDITABLE(_id)
Definition DNA_ID.h:658
eSeqImageFitMethod
@ SEQ_SCALE_TO_FILL
@ SEQ_STRETCH_TO_FILL
@ SEQ_SCALE_TO_FIT
@ USER_UNIT_NONE
#define MINFRAME
@ SCER_PRV_RANGE
#define FPS
#define FRA2TIME(a)
#define MAXFRAME
@ RGN_TYPE_CHANNELS
@ RGN_TYPE_WINDOW
@ RGN_TYPE_PREVIEW
@ SEQ_TYPE_TRANSFORM
@ SEQ_TYPE_SOUND_RAM
@ SEQ_TYPE_CROSS
@ SEQ_TYPE_GLOW
@ SEQ_TYPE_COLORMIX
@ SEQ_TYPE_WIPE
@ SEQ_TYPE_META
@ SEQ_TYPE_OVERDROP
@ SEQ_TYPE_ALPHAUNDER
@ SEQ_TYPE_SCENE
@ SEQ_TYPE_GAMCROSS
@ SEQ_TYPE_MULTICAM
@ SEQ_TYPE_MUL
@ SEQ_TYPE_GAUSSIAN_BLUR
@ SEQ_TYPE_ADD
@ SEQ_TYPE_ALPHAOVER
@ SEQ_TYPE_TEXT
@ SEQ_TYPE_IMAGE
@ SEQ_TYPE_SUB
@ SEQ_TYPE_SPEED
@ SEQ_TYPE_COLOR
@ SEQ_TYPE_EFFECT
@ SEQ_TYPE_MOVIE
@ SEQ_TYPE_ADJUSTMENT
#define SEQ_HAS_PATH(_seq)
@ SEQUENCE_COLOR_NONE
#define SEQ_ALLSEL
@ SEQ_SINGLE_FRAME_CONTENT
@ SEQ_RIGHTSEL
@ SEQ_IGNORE_CHANNEL_LOCK
@ SEQ_LEFTSEL
@ FILE_SORT_DEFAULT
@ FILE_SPECIAL
@ FILE_BLENDER
@ FILE_TYPE_FOLDER
@ SEQ_VIEW_SEQUENCE_PREVIEW
@ SEQ_VIEW_SEQUENCE
@ SEQ_VIEW_PREVIEW
@ SEQ_DRAW_BACKDROP
@ FILE_DEFAULTDISPLAY
@ SEQ_DRAW_IMG_IMBUF
@ USER_TIMECODE_SUBRIP
@ OPERATOR_RUNNING_MODAL
@ OPERATOR_PASS_THROUGH
void ED_fileselect_ensure_default_filepath(bContext *C, wmOperator *op, const char *extension)
Definition filesel.cc:1466
void initNumInput(NumInput *n)
Definition numinput.cc:70
#define NUM_STR_REP_LEN
void outputNumInput(NumInput *n, char *str, const UnitSettings *unit_settings)
Definition numinput.cc:88
bool handleNumInput(bContext *C, NumInput *n, const wmEvent *event)
Definition numinput.cc:312
bool applyNumInput(NumInput *n, float *vec)
Definition numinput.cc:190
bool hasNumInput(const NumInput *n)
Definition numinput.cc:171
bool ED_scene_delete(bContext *C, Main *bmain, Scene *scene) ATTR_NONNULL()
void ED_area_status_text(ScrArea *area, const char *str)
Definition area.cc:803
bool ED_operator_sequencer_active(bContext *C)
blender::VectorSet< Sequence * > ED_sequencer_selected_strips_from_context(bContext *C)
Read Guarded memory(de)allocation.
#define MEM_reallocN(vmemh, len)
#define RNA_BEGIN(sptr, itemptr, propname)
#define RNA_END
const EnumPropertyItem * RNA_scene_without_active_itemf(bContext *C, PointerRNA *ptr, PropertyRNA *prop, bool *r_free)
@ PROP_ENUM_NO_TRANSLATE
Definition RNA_types.hh:321
@ PROP_SKIP_SAVE
Definition RNA_types.hh:245
@ PROP_HIDDEN
Definition RNA_types.hh:239
eSeqSplitMethod
Definition SEQ_edit.hh:54
@ SEQ_SPLIT_SOFT
Definition SEQ_edit.hh:55
@ SEQ_SPLIT_HARD
Definition SEQ_edit.hh:56
#define SEQ_DUPE_UNIQUE_NAME
@ SEQ_SIDE_RIGHT
@ SEQ_SIDE_MOUSE
@ SEQ_SIDE_BOTH
@ SEQ_SIDE_NO_CHANGE
@ SEQ_SIDE_LEFT
uiLayout * uiLayoutRow(uiLayout *layout, bool align)
void uiLayoutSetPropSep(uiLayout *layout, bool is_sep)
void uiItemS(uiLayout *layout)
#define UI_ITEM_NONE
#define UI_MAX_DRAW_STR
void uiLayoutSetPropDecorate(uiLayout *layout, bool is_sep)
void uiItemR(uiLayout *layout, PointerRNA *ptr, const char *propname, eUI_Item_Flag flag, const char *name, int icon)
@ UI_ITEM_R_EXPAND
View2D * UI_view2d_fromcontext(const bContext *C)
Definition view2d.cc:1850
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:1663
@ WM_FILESEL_FILES
Definition WM_api.hh:937
@ WM_FILESEL_DIRECTORY
Definition WM_api.hh:934
@ WM_FILESEL_RELPATH
Definition WM_api.hh:933
@ WM_FILESEL_FILEPATH
Definition WM_api.hh:936
@ FILE_OPENFILE
Definition WM_api.hh:945
@ FILE_SAVE
Definition WM_api.hh:946
#define ND_SEQUENCER
Definition WM_types.hh:404
#define ND_SPACE_SEQUENCER
Definition WM_types.hh:501
@ OPTYPE_UNDO
Definition WM_types.hh:162
@ OPTYPE_REGISTER
Definition WM_types.hh:160
#define ND_RENDER_OPTIONS
Definition WM_types.hh:402
@ KM_PRESS
Definition WM_types.hh:284
@ KM_RELEASE
Definition WM_types.hh:285
#define NC_SCENE
Definition WM_types.hh:345
#define ND_FRAME_RANGE
Definition WM_types.hh:418
#define ND_FRAME
Definition WM_types.hh:401
#define NA_REMOVED
Definition WM_types.hh:553
#define ND_SCENEBROWSE
Definition WM_types.hh:399
#define NC_SPACE
Definition WM_types.hh:359
void SEQ_animation_backup_original(Scene *scene, SeqAnimationBackup *backup)
Definition animation.cc:120
void SEQ_offset_animdata(Scene *scene, Sequence *seq, int ofs)
Definition animation.cc:69
void SEQ_animation_duplicate_backup_to_scene(Scene *scene, Sequence *seq, SeqAnimationBackup *backup)
Definition animation.cc:161
void SEQ_animation_restore_original(Scene *scene, SeqAnimationBackup *backup)
Definition animation.cc:130
SeqTimelineChannel * SEQ_channel_get_by_index(const ListBase *channels, const int channel_index)
Definition channels.cc:61
ListBase * SEQ_channels_displayed_get(Editing *ed)
Definition channels.cc:23
bool add(const Key &key)
void add_multiple(Span< Key > keys)
local_group_size(16, 16) .push_constant(Type b
#define SELECT
FILE * file
int len
SeqEffectHandle SEQ_effect_handle_get(Sequence *seq)
Definition effects.cc:3430
int SEQ_effect_get_num_inputs(int seq_type)
Definition effects.cc:3467
IMETHOD Vector diff(const Vector &a, const Vector &b, double dt)
Definition frames.inl:1166
const vector< Marker > & markers
VectorSet< Sequence * > SEQ_query_selected_strips(ListBase *seqbase)
Definition iterator.cc:106
void SEQ_for_each_callback(ListBase *seqbase, SeqForEachFunc callback, void *user_data)
Definition iterator.cc:43
void MEM_freeN(void *vmemh)
Definition mallocn.cc:105
void *(* MEM_dupallocN)(const void *vmemh)
Definition mallocn.cc:39
static ulong * next
#define G(x, y, z)
Vector< FCurve * > fcurves_for_assigned_action(AnimData *adt)
void thumbnail_cache_invalidate_strip(Scene *scene, const Sequence *seq)
void media_presence_free(Scene *scene)
void thumbnail_cache_clear(Scene *scene)
void SEQ_prefetch_stop(Scene *scene)
Definition prefetch.cc:247
bool SEQ_render_is_muted(const ListBase *channels, const Sequence *seq)
Definition render.cc:2154
StripElem * SEQ_render_give_stripelem(const Scene *scene, const Sequence *seq, int timeline_frame)
Definition render.cc:248
void RNA_string_set(PointerRNA *ptr, const char *name, const char *value)
PropertyRNA * RNA_struct_find_property(PointerRNA *ptr, const char *identifier)
void RNA_boolean_set(PointerRNA *ptr, const char *name, bool value)
bool RNA_struct_property_is_set_ex(PointerRNA *ptr, const char *identifier, bool use_ghost)
void RNA_int_set(PointerRNA *ptr, const char *name, int value)
void RNA_float_get_array(PointerRNA *ptr, const char *name, float *values)
void RNA_property_update(bContext *C, PointerRNA *ptr, PropertyRNA *prop)
void RNA_string_get(PointerRNA *ptr, const char *name, char *value)
int RNA_int_get(PointerRNA *ptr, const char *name)
char * RNA_string_get_alloc(PointerRNA *ptr, const char *name, char *fixedbuf, int fixedlen, int *r_len)
float RNA_float_get(PointerRNA *ptr, const char *name)
void RNA_float_set(PointerRNA *ptr, const char *name, float value)
bool RNA_struct_property_is_set(PointerRNA *ptr, const char *identifier)
bool RNA_boolean_get(PointerRNA *ptr, const char *name)
void RNA_enum_set(PointerRNA *ptr, const char *name, int value)
void RNA_float_set_array(PointerRNA *ptr, const char *name, const float *values)
PointerRNA RNA_pointer_create(ID *id, StructRNA *type, void *data)
int RNA_enum_get(PointerRNA *ptr, const char *name)
int RNA_property_collection_length(PointerRNA *ptr, PropertyRNA *prop)
void RNA_property_string_set(PointerRNA *ptr, PropertyRNA *prop, const char *value)
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_float_vector(StructOrFunctionRNA *cont_, const char *identifier, const int len, 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_enum(StructOrFunctionRNA *cont_, const char *identifier, const EnumPropertyItem *items, const int default_value, const char *ui_name, const char *ui_description)
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_translation_context(PropertyRNA *prop, const char *context)
void RNA_def_property_flag(PropertyRNA *prop, PropertyFlag flag)
void RNA_def_enum_funcs(PropertyRNA *prop, EnumPropertyItemFunc itemfunc)
void RNA_def_property_ui_range(PropertyRNA *prop, double min, double max, double step, int precision)
PropertyRNA * RNA_def_int(StructOrFunctionRNA *cont_, const char *identifier, const int default_value, const int hardmin, const int hardmax, const char *ui_name, const char *ui_description, const int softmin, const int softmax)
const EnumPropertyItem rna_enum_dummy_NULL_items[]
Definition rna_rna.cc:29
const EnumPropertyItem rna_enum_strip_color_items[]
void SEQ_sequence_lookup_invalidate(const Scene *scene)
void SEQ_sequence_base_unique_name_recursive(Scene *scene, ListBase *seqbasep, Sequence *seq)
void SEQ_set_scale_to_fit(const Sequence *seq, const int image_width, const int image_height, const int preview_width, const int preview_height, const eSeqImageFitMethod fit_method)
void SEQ_ensure_unique_name(Sequence *seq, Scene *scene)
Mask * SEQ_active_mask_get(Scene *scene)
void SEQ_sequence_base_dupli_recursive(const Scene *scene_src, Scene *scene_dst, ListBase *nseqbase, const ListBase *seqbase, int dupe_flag, const int flag)
Definition sequencer.cc:653
ListBase * SEQ_active_seqbase_get(const Editing *ed)
Definition sequencer.cc:416
Sequence * SEQ_meta_stack_pop(Editing *ed)
Definition sequencer.cc:481
Sequence * SEQ_sequence_dupli_recursive(const Scene *scene_src, Scene *scene_dst, ListBase *new_seq_list, Sequence *seq, int dupe_flag)
Definition sequencer.cc:639
void SEQ_meta_stack_set(const Scene *scene, Sequence *dst_seq)
Definition sequencer.cc:457
Sequence * SEQ_sequence_alloc(ListBase *lb, int timeline_frame, int machine, int type)
Definition sequencer.cc:123
Editing * SEQ_editing_get(const Scene *scene)
Definition sequencer.cc:262
void sequencer_image_seq_reserve_frames(wmOperator *op, StripElem *se, int len, int minframe, int numdigits)
int sequencer_image_seq_get_minmax_frame(wmOperator *op, int sfra, int *r_minframe, int *r_numdigits)
int sequencer_clipboard_paste_exec(bContext *C, wmOperator *op)
int sequencer_clipboard_copy_exec(bContext *C, wmOperator *op)
bool sequencer_view_preview_only_poll(const bContext *C)
bool ED_space_sequencer_check_show_strip(SpaceSeq *sseq)
static bool sequencer_strip_color_tag_set_poll(bContext *C)
void SEQUENCER_OT_change_effect_input(wmOperatorType *ot)
static void sequencer_slip_strips(Scene *scene, SlipData *data, int delta, float subframe_delta)
void SEQUENCER_OT_strip_transform_fit(wmOperatorType *ot)
static int sequencer_snap_exec(bContext *C, wmOperator *op)
static int sequencer_reassign_inputs_exec(bContext *C, wmOperator *op)
bool sequencer_strip_has_path_poll(bContext *C)
static int sequencer_change_scene_exec(bContext *C, wmOperator *op)
static int sequencer_mute_exec(bContext *C, wmOperator *op)
void SEQUENCER_OT_mute(wmOperatorType *ot)
static int sequencer_separate_images_invoke(bContext *C, wmOperator *op, const wmEvent *event)
void SEQUENCER_OT_copy(wmOperatorType *ot)
static int sequencer_lock_exec(bContext *C, wmOperator *)
void SEQUENCER_OT_delete(wmOperatorType *ot)
bool ED_space_sequencer_check_show_imbuf(SpaceSeq *sseq)
void SEQUENCER_OT_rendersize(wmOperatorType *ot)
static int sequencer_separate_images_exec(bContext *C, wmOperator *op)
static int sequencer_meta_make_exec(bContext *C, wmOperator *op)
static int sequencer_delete_invoke(bContext *C, wmOperator *op, const wmEvent *event)
void SEQUENCER_OT_set_range_to_strips(wmOperatorType *ot)
int seq_effect_find_selected(Scene *scene, Sequence *activeseq, int type, Sequence **r_selseq1, Sequence **r_selseq2, const char **r_error_str)
static int sequencer_connect_exec(bContext *C, wmOperator *op)
static int sequencer_reload_exec(bContext *C, wmOperator *op)
static void sequencer_split_ui(bContext *, wmOperator *op)
static bool sequencer_scene_frame_range_update_poll(bContext *C)
bool ED_space_sequencer_maskedit_poll(bContext *C)
bool sequencer_view_has_preview_poll(bContext *C)
void SEQUENCER_OT_change_effect_type(wmOperatorType *ot)
static int sequencer_slip_exec(bContext *C, wmOperator *op)
static void handle_number_input(bContext *C, wmOperator *op, ScrArea *area, SlipData *data, Scene *scene)
void SEQUENCER_OT_scene_frame_range_update(wmOperatorType *ot)
bool ED_space_sequencer_maskedit_mask_poll(bContext *C)
@ STRIP_TRANSFORM_ALL
@ STRIP_TRANSFORM_SCALE
@ STRIP_TRANSFORM_POSITION
@ STRIP_TRANSFORM_ROTATION
static int sequencer_slip_modal(bContext *C, wmOperator *op, const wmEvent *event)
static int sequencer_meta_separate_exec(bContext *C, wmOperator *)
void SEQUENCER_OT_reload(wmOperatorType *ot)
static void sequencer_delete_strip_data(bContext *C, Sequence *seq)
static int sequencer_strip_transform_clear_exec(bContext *C, wmOperator *op)
void SEQUENCER_OT_swap_data(wmOperatorType *ot)
static bool seq_is_parent(const Sequence *par, const Sequence *seq)
static int slip_count_sequences(ListBase *seqbasep)
void SEQUENCER_OT_strip_transform_clear(wmOperatorType *ot)
static const EnumPropertyItem scale_fit_methods[]
static bool sequencer_refresh_all_poll(bContext *C)
void SEQUENCER_OT_lock(wmOperatorType *ot)
static bool sequencer_strip_change_scene_poll(bContext *C)
static int sequencer_swap_data_exec(bContext *C, wmOperator *op)
static int sequencer_slip_invoke(bContext *C, wmOperator *op, const wmEvent *event)
void SEQUENCER_OT_disconnect(wmOperatorType *ot)
void SEQUENCER_OT_connect(wmOperatorType *ot)
void SEQUENCER_OT_strip_color_tag_set(wmOperatorType *ot)
void SEQUENCER_OT_images_separate(wmOperatorType *ot)
static int sequencer_unmute_exec(bContext *C, wmOperator *op)
static bool sequencer_fcurves_targets_color_strip(const FCurve *fcurve)
static int sequencer_offset_clear_exec(bContext *C, wmOperator *)
static int seq_cmp_time_startdisp_channel(void *thunk, const void *a, const void *b)
void SEQUENCER_OT_reassign_inputs(wmOperatorType *ot)
static bool sequencer_strip_is_text_poll(bContext *C)
static int sequence_split_side_for_exec_get(wmOperator *op)
static int sequencer_set_2d_cursor_exec(bContext *C, wmOperator *op)
void SEQUENCER_OT_change_path(wmOperatorType *ot)
static bool seq_get_text_strip_cb(Sequence *seq, void *user_data)
static int sequencer_snap_invoke(bContext *C, wmOperator *op, const wmEvent *)
void SEQUENCER_OT_refresh_all(wmOperatorType *ot)
void SEQUENCER_OT_offset_clear(wmOperatorType *ot)
static int sequencer_gap_insert_exec(bContext *C, wmOperator *op)
static int sequencer_strip_jump_exec(bContext *C, wmOperator *op)
static bool strip_jump_internal(Scene *scene, const short side, const bool do_skip_mute, const bool do_center)
void SEQUENCER_OT_meta_make(wmOperatorType *ot)
bool sequencer_edit_with_channel_region_poll(bContext *C)
void SEQUENCER_OT_unmute(wmOperatorType *ot)
static int sequencer_change_effect_type_exec(bContext *C, wmOperator *op)
void SEQUENCER_OT_gap_insert(wmOperatorType *ot)
const EnumPropertyItem sequencer_prop_effect_types[]
static int sequencer_set_2d_cursor_invoke(bContext *C, wmOperator *op, const wmEvent *event)
bool ED_space_sequencer_has_playback_animation(const SpaceSeq *sseq, const Scene *scene)
static int sequencer_export_subtitles_exec(bContext *C, wmOperator *op)
const EnumPropertyItem prop_side_types[]
static int sequencer_change_scene_invoke(bContext *C, wmOperator *op, const wmEvent *event)
static int sequencer_refresh_all_exec(bContext *C, wmOperator *)
void SEQUENCER_OT_duplicate(wmOperatorType *ot)
static bool sequencer_effect_poll(bContext *C)
static void slip_add_sequences(ListBase *seqbasep, Sequence **seq_array)
static int mouse_frame_side(View2D *v2d, short mouse_x, int frame)
static int sequencer_slip_apply_limits(const Scene *scene, SlipData *data, int *offset)
static int sequencer_add_duplicate_exec(bContext *C, wmOperator *)
bool sequencer_edit_poll(bContext *C)
static int sequencer_disconnect_exec(bContext *C, wmOperator *)
static bool sequencer_strip_jump_poll(bContext *C)
static int sequencer_strip_color_tag_set_exec(bContext *C, wmOperator *op)
bool sequencer_view_strips_poll(bContext *C)
static int sequencer_scene_frame_range_update_exec(bContext *C, wmOperator *)
static void sequencer_slip_update_header(Scene *scene, ScrArea *area, SlipData *data, int offset)
void SEQUENCER_OT_slip(wmOperatorType *ot)
bool sequencer_editing_initialized_and_active(bContext *C)
void SEQUENCER_OT_swap(wmOperatorType *ot)
static int sequencer_split_exec(bContext *C, wmOperator *op)
static int sequencer_rendersize_exec(bContext *C, wmOperator *)
void SEQUENCER_OT_gap_remove(wmOperatorType *ot)
void SEQUENCER_OT_snap(wmOperatorType *ot)
static int sequencer_change_path_exec(bContext *C, wmOperator *op)
static int sequencer_gap_remove_exec(bContext *C, wmOperator *op)
bool sequencer_strip_editable_poll(bContext *C)
static int sequencer_unlock_exec(bContext *C, wmOperator *)
bool ED_sequencer_deselect_all(Scene *scene)
void SEQUENCER_OT_paste(wmOperatorType *ot)
void SEQUENCER_OT_swap_inputs(wmOperatorType *ot)
static int sequencer_set_range_to_strips_exec(bContext *C, wmOperator *op)
static int sequencer_meta_toggle_exec(bContext *C, wmOperator *)
void SEQUENCER_OT_meta_toggle(wmOperatorType *ot)
static const EnumPropertyItem prop_split_types[]
void SEQUENCER_OT_export_subtitles(wmOperatorType *ot)
void SEQUENCER_OT_change_scene(wmOperatorType *ot)
static int sequencer_change_effect_input_exec(bContext *C, wmOperator *op)
static const EnumPropertyItem prop_side_lr_types[]
void SEQUENCER_OT_split(wmOperatorType *ot)
bool ED_space_sequencer_check_show_maskedit(SpaceSeq *sseq, Scene *scene)
void SEQUENCER_OT_unlock(wmOperatorType *ot)
static int sequencer_swap_inputs_exec(bContext *C, wmOperator *op)
void SEQUENCER_OT_cursor_set(wmOperatorType *ot)
static int sequencer_change_path_invoke(bContext *C, wmOperator *op, const wmEvent *)
static int sequencer_swap_exec(bContext *C, wmOperator *op)
static int sequencer_delete_exec(bContext *C, wmOperator *op)
static int sequencer_strip_transform_fit_exec(bContext *C, wmOperator *op)
void SEQUENCER_OT_strip_jump(wmOperatorType *ot)
static int sequencer_export_subtitles_invoke(bContext *C, wmOperator *op, const wmEvent *)
void SEQUENCER_OT_meta_separate(wmOperatorType *ot)
static void swap_sequence(Scene *scene, Sequence *seqa, Sequence *seqb)
static const EnumPropertyItem transform_reset_properties[]
static Sequence * find_next_prev_sequence(Scene *scene, Sequence *test, int lr, int sel)
static int sequencer_split_invoke(bContext *C, wmOperator *op, const wmEvent *event)
#define FLT_MAX
Definition stdcycles.h:14
void SEQ_add_reload_new_file(Main *bmain, Scene *scene, Sequence *seq, const bool lock_range)
Definition strip_add.cc:525
bool SEQ_disconnect(Sequence *seq)
void SEQ_connect(Sequence *seq1, Sequence *seq2)
blender::VectorSet< Sequence * > SEQ_get_connected_strips(const Sequence *seq)
bool SEQ_are_strips_connected_together(blender::VectorSet< Sequence * > &seq_list)
bool SEQ_edit_remove_gaps(Scene *scene, ListBase *seqbase, const int initial_frame, const bool remove_all_gaps)
void SEQ_edit_flag_for_removal(Scene *scene, ListBase *seqbase, Sequence *seq)
Sequence * SEQ_edit_strip_split(Main *bmain, Scene *scene, ListBase *seqbase, Sequence *seq, const int timeline_frame, const eSeqSplitMethod method, const char **r_error)
bool SEQ_edit_sequence_swap(Scene *scene, Sequence *seq_a, Sequence *seq_b, const char **r_error_str)
Definition strip_edit.cc:42
void SEQ_edit_remove_flagged_sequences(Scene *scene, ListBase *seqbase)
bool SEQ_relations_render_loop_check(Sequence *seq_main, Sequence *seq)
void SEQ_relations_invalidate_cache_raw(Scene *scene, Sequence *seq)
void SEQ_relations_sequence_free_anim(Sequence *seq)
void SEQ_relations_invalidate_dependent(Scene *scene, Sequence *seq)
void SEQ_relations_free_imbuf(Scene *scene, ListBase *seqbase, bool for_render)
void SEQ_relations_invalidate_cache_preprocessed(Scene *scene, Sequence *seq)
void SEQ_relations_invalidate_cache_composite(Scene *scene, Sequence *seq)
bool SEQ_select_active_get_pair(Scene *scene, Sequence **r_seq_act, Sequence **r_seq_other)
void SEQ_select_active_set(Scene *scene, Sequence *seq)
Sequence * SEQ_select_active_get(const Scene *scene)
void SEQ_time_right_handle_frame_set(const Scene *scene, Sequence *seq, int timeline_frame)
void SEQ_time_left_handle_frame_set(const Scene *scene, Sequence *seq, int timeline_frame)
int SEQ_time_left_handle_frame_get(const Scene *, const Sequence *seq)
void SEQ_time_slip_strip(const Scene *scene, Sequence *seq, int delta, float subframe_delta)
int SEQ_time_find_next_prev_edit(Scene *scene, int timeline_frame, const short side, const bool do_skip_mute, const bool do_center, const bool do_unselected)
float SEQ_time_start_frame_get(const Sequence *seq)
int SEQ_time_right_handle_frame_get(const Scene *scene, const Sequence *seq)
bool SEQ_transform_seqbase_isolated_sel_check(ListBase *seqbase)
bool SEQ_transform_seqbase_shuffle(ListBase *seqbasep, Sequence *test, Scene *evil_scene)
bool SEQ_transform_test_overlap(const Scene *scene, ListBase *seqbasep, Sequence *test)
void SEQ_transform_translate_sequence(Scene *evil_scene, Sequence *seq, int delta)
bool SEQ_transform_is_locked(ListBase *channels, const Sequence *seq)
void SEQ_image_preview_unit_from_px(const Scene *scene, const float co_src[2], float co_dst[2])
bool SEQ_transform_sequence_can_be_translated(const Sequence *seq)
void SEQ_transform_offset_after_frame(Scene *scene, ListBase *seqbase, const int delta, const int timeline_frame)
ListBase seqbase
ListBase * seqbasep
Sequence * act_seq
ListBase metastack
char * rna_path
void * first
ListBase scenes
Definition BKE_main.hh:210
struct RenderData r
void(* free)(Sequence *seq, bool do_id_user)
void(* init)(Sequence *seq)
struct Scene * scene
ListBase channels
struct bSound * sound
struct Sequence * seq1
struct Sequence * seq2
struct Sequence * next
float init_mouseloc[2]
NumInput num_input
float previous_subframe_offset
Sequence ** seq_array
float subframe_restore
float cursor[2]
char filename[256]
char dirpath[768]
StripTransform * transform
StripElem * stripdata
char filepath[1024]
short val
Definition WM_types.hh:724
int mval[2]
Definition WM_types.hh:728
short type
Definition WM_types.hh:722
const char * name
Definition WM_types.hh:990
bool(* poll)(bContext *C) ATTR_WARN_UNUSED_RESULT
Definition WM_types.hh:1042
const char * idname
Definition WM_types.hh:992
int(* modal)(bContext *C, wmOperator *op, const wmEvent *event) ATTR_WARN_UNUSED_RESULT
Definition WM_types.hh:1036
int(* invoke)(bContext *C, wmOperator *op, const wmEvent *event) ATTR_WARN_UNUSED_RESULT
Definition WM_types.hh:1022
int(* exec)(bContext *C, wmOperator *op) ATTR_WARN_UNUSED_RESULT
Definition WM_types.hh:1006
const char * description
Definition WM_types.hh:996
void(* ui)(bContext *C, wmOperator *op)
Definition WM_types.hh:1053
PropertyRNA * prop
Definition WM_types.hh:1092
StructRNA * srna
Definition WM_types.hh:1080
struct ReportList * reports
struct uiLayout * layout
struct PointerRNA * ptr
#define N_(msgid)
void WM_event_add_fileselect(bContext *C, wmOperator *op)
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_SPACEKEY
@ MOUSEMOVE
@ LEFTMOUSE
@ EVT_ESCKEY
@ EVT_RIGHTSHIFTKEY
@ EVT_LEFTSHIFTKEY
@ EVT_RETKEY
wmOperatorType * ot
Definition wm_files.cc:4125
void WM_operator_properties_filesel(wmOperatorType *ot, const int filter, const short type, const eFileSel_Action action, const eFileSel_Flag flag, const short display, const short sort)
int WM_operator_props_popup_confirm_ex(bContext *C, wmOperator *op, const wmEvent *, std::optional< std::string > title, std::optional< std::string > confirm_text, const bool cancel_default)
int WM_enum_search_invoke(bContext *C, wmOperator *op, const wmEvent *)