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
8
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/* -------------------------------------------------------------------- */
76
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{
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
150
151/* -------------------------------------------------------------------- */
154
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
262
263/* -------------------------------------------------------------------- */
266
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;
293 ot->poll = sequencer_edit_poll;
294
295 /* Flags. */
297
298 RNA_def_boolean(ot->srna, "all", false, "All Gaps", "Do all gaps to right of current frame");
299}
300
302
303/* -------------------------------------------------------------------- */
306
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;
331 ot->poll = sequencer_edit_poll;
332
333 /* Flags. */
335
336 RNA_def_int(ot->srna,
337 "frames",
338 10,
339 0,
340 INT_MAX,
341 "Frames",
342 "Frames to insert after current strip",
343 0,
344 1000);
345}
346
348
349/* -------------------------------------------------------------------- */
352
354{
355 Scene *scene = CTX_data_scene(C);
356
357 Editing *ed = SEQ_editing_get(scene);
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. */
440 ot->invoke = sequencer_snap_invoke;
441 ot->exec = sequencer_snap_exec;
442 ot->poll = sequencer_edit_poll;
443
444 /* Flags. */
446
447 RNA_def_int(ot->srna,
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
459
460/* -------------------------------------------------------------------- */
463
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
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);
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);
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);
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);
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. */
807 ot->invoke = sequencer_slip_invoke;
808 ot->modal = sequencer_slip_modal;
809 ot->exec = sequencer_slip_exec;
810 ot->poll = sequencer_edit_poll;
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
831
832/* -------------------------------------------------------------------- */
835
837{
838 Scene *scene = CTX_data_scene(C);
839 Editing *ed = SEQ_editing_get(scene);
841
842 bool selected;
843
844 selected = !RNA_boolean_get(op->ptr, "unselected");
845
846 LISTBASE_FOREACH (Sequence *, seq, ed->seqbasep) {
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. */
877 ot->exec = sequencer_mute_exec;
878 ot->poll = sequencer_edit_poll;
879
880 /* Flags. */
882
884 ot->srna, "unselected", false, "Unselected", "Mute unselected rather than selected strips");
885}
886
888
889/* -------------------------------------------------------------------- */
892
894{
895 Scene *scene = CTX_data_scene(C);
896 Editing *ed = SEQ_editing_get(scene);
898 bool selected;
899
900 selected = !RNA_boolean_get(op->ptr, "unselected");
901
902 LISTBASE_FOREACH (Sequence *, seq, ed->seqbasep) {
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. */
934 ot->poll = sequencer_edit_poll;
935
936 /* Flags. */
938
939 RNA_def_boolean(ot->srna,
940 "unselected",
941 false,
942 "Unselected",
943 "Unmute unselected rather than selected strips");
944}
945
947
948/* -------------------------------------------------------------------- */
951
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. */
976 ot->exec = sequencer_lock_exec;
977 ot->poll = sequencer_edit_poll;
978
979 /* Flags. */
981}
982
984
985/* -------------------------------------------------------------------- */
988
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. */
1013 ot->exec = sequencer_unlock_exec;
1014 ot->poll = sequencer_edit_poll;
1015
1016 /* Flags. */
1017 ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
1018}
1019
1021
1022/* -------------------------------------------------------------------- */
1025
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
1056 ot->exec = sequencer_connect_exec;
1057 ot->poll = sequencer_edit_poll;
1058
1059 ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
1060
1061 RNA_def_boolean(ot->srna, "toggle", true, "Toggle", "Toggle strip connections");
1062}
1063
1065
1066/* -------------------------------------------------------------------- */
1069
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
1094 ot->poll = sequencer_edit_poll;
1095
1096 ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
1097}
1098
1100
1101/* -------------------------------------------------------------------- */
1104
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. */
1140 ot->exec = sequencer_reload_exec;
1141 ot->poll = sequencer_edit_poll;
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
1155
1156/* -------------------------------------------------------------------- */
1159
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
1195
1196/* -------------------------------------------------------------------- */
1199
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. */
1344 ot->poll = sequencer_effect_poll;
1345
1346 /* Flags. */
1347 ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
1348}
1349
1351
1352/* -------------------------------------------------------------------- */
1355
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. */
1385 ot->poll = sequencer_effect_poll;
1386
1387 /* Flags. */
1388 ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
1389}
1390
1392
1393/* -------------------------------------------------------------------- */
1396
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);
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. */
1591 ot->invoke = sequencer_split_invoke;
1592 ot->exec = sequencer_split_exec;
1593 ot->poll = sequencer_edit_poll;
1594 ot->ui = sequencer_split_ui;
1595
1596 /* Flags. */
1597 ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
1598
1599 PropertyRNA *prop;
1600 RNA_def_int(ot->srna,
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);
1609 RNA_def_int(ot->srna,
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);
1618 RNA_def_enum(ot->srna,
1619 "type",
1622 "Type",
1623 "The type of split operation to perform on strips");
1624
1625 RNA_def_boolean(ot->srna,
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
1651
1652/* -------------------------------------------------------------------- */
1655
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. */
1722 ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
1723}
1724
1726
1727/* -------------------------------------------------------------------- */
1730
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
1777 if (!BLI_listbase_is_empty(markers)) {
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. */
1800 ot->invoke = sequencer_delete_invoke;
1801 ot->exec = sequencer_delete_exec;
1802 ot->poll = sequencer_edit_poll;
1803
1804 /* Flags. */
1805 ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
1806
1807 /* Properties. */
1808 ot->prop = RNA_def_boolean(ot->srna,
1809 "delete_data",
1810 false,
1811 "Delete Data",
1812 "After removing the Strip, delete the associated data also");
1814}
1815
1817
1818/* -------------------------------------------------------------------- */
1821
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 {
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. */
1874 ot->poll = sequencer_edit_poll;
1875
1876 /* Flags. */
1877 ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
1878}
1879
1881
1882/* -------------------------------------------------------------------- */
1885
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. */
1979 ot->poll = sequencer_edit_poll;
1980
1981 /* Flags. */
1982 ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
1983
1984 RNA_def_int(ot->srna, "length", 1, 1, INT_MAX, "Length", "Length of each frame", 1, 1000);
1985}
1986
1988
1989/* -------------------------------------------------------------------- */
1992
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. */
2032 ot->poll = sequencer_edit_poll;
2033
2034 /* Flags. */
2035 ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
2036}
2037
2039
2040/* -------------------------------------------------------------------- */
2043
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. */
2117 ot->poll = sequencer_edit_poll;
2118
2119 /* Flags. */
2120 ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
2121}
2122
2124
2125/* -------------------------------------------------------------------- */
2128
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. */
2179 ot->poll = sequencer_edit_poll;
2180
2181 /* Flags. */
2182 ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
2183}
2184
2186
2187/* -------------------------------------------------------------------- */
2190
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
2256
2257/* -------------------------------------------------------------------- */
2260
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
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. */
2411 ot->exec = sequencer_swap_exec;
2412 ot->poll = sequencer_edit_poll;
2413
2414 /* Flags. */
2415 ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
2416
2417 /* Properties. */
2419 ot->srna, "side", prop_side_lr_types, SEQ_SIDE_RIGHT, "Side", "Side of the strip to swap");
2420}
2421
2423
2424/* -------------------------------------------------------------------- */
2427
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. */
2480 ot->poll = sequencer_edit_poll;
2481
2482 /* Flags. */
2483 ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
2484}
2485
2487
2488/* -------------------------------------------------------------------- */
2491
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. */
2501 ot->poll = sequencer_edit_poll;
2502
2503 /* Flags. */
2504 ot->flag = OPTYPE_REGISTER;
2505}
2506
2508
2509/* -------------------------------------------------------------------- */
2512
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. */
2543 ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
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
2556
2557/* -------------------------------------------------------------------- */
2560
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. */
2616 ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
2617}
2618
2620
2621/* -------------------------------------------------------------------- */
2624
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. */
2653 ot->poll = sequencer_effect_poll;
2654
2655 /* Flags. */
2656 ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
2657}
2658
2660
2661/* -------------------------------------------------------------------- */
2664
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. */
2729 ot->poll = sequencer_effect_poll;
2730
2731 /* Flags. */
2732 ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
2733
2734 ot->prop = RNA_def_enum(ot->srna,
2735 "type",
2738 "Type",
2739 "Sequencer effect type");
2741}
2742
2744
2745/* -------------------------------------------------------------------- */
2748
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 {
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. */
2881 ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
2882
2891 RNA_def_boolean(ot->srna,
2892 "use_placeholders",
2893 false,
2894 "Use Placeholders",
2895 "Use placeholders for missing frames of the strip");
2896}
2897
2899
2900/* -------------------------------------------------------------------- */
2903
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. */
2965 ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
2966
2967 /* Properties. */
2968 prop = RNA_def_enum(ot->srna, "scene", rna_enum_dummy_NULL_items, 0, "Scene", "");
2971 ot->prop = prop;
2972}
2973
2975
2976/* -------------------------------------------------------------------- */
2979
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);
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. */
3128 ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
3129
3133 FILE_SAVE,
3137}
3138
3140
3141/* -------------------------------------------------------------------- */
3144
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. */
3202 ot->poll = sequencer_edit_poll;
3203
3204 /* Flags. */
3205 ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
3206
3207 prop = RNA_def_boolean(ot->srna, "preview", false, "Preview", "Set the preview range instead");
3209}
3210
3212
3213/* -------------------------------------------------------------------- */
3216
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. */
3278 ot->poll = sequencer_edit_poll;
3279
3280 /* Flags. */
3281 ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
3282
3283 ot->prop = RNA_def_enum(ot->srna,
3284 "property",
3287 "Property",
3288 "Strip transform property to be reset");
3289}
3290
3292
3293/* -------------------------------------------------------------------- */
3296
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. */
3341 ot->poll = sequencer_edit_poll;
3342
3343 /* Flags. */
3344 ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
3345
3346 ot->prop = RNA_def_enum(ot->srna,
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. */
3398 ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
3399
3401 ot->srna, "color", rna_enum_strip_color_items, SEQUENCE_COLOR_NONE, "Color Tag", "");
3402}
3403
3405
3406/* -------------------------------------------------------------------- */
3409
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 */
3451 ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
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
3467
3468/* -------------------------------------------------------------------- */
3471
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 */
3511 ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
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
#define MINFRAME
@ USER_UNIT_NONE
@ 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_OVERLAP
@ 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)
Group Output data from inside of a node group A color picker Mix two input colors RGB to Convert a color s luminance to a grayscale value Generate a normal vector and a dot product Brightness Control the brightness and contrast of the input color Vector Map input vector components with curves Camera Retrieve information about the camera and how it relates to the current shading point s position Clamp a value between a minimum and a maximum Vector Perform vector math operation Invert Invert a producing a negative Combine Generate a color from its and blue channels(Deprecated)") DefNode(ShaderNode
#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
#define C
Definition RandGen.cpp:29
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
#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
@ KM_PRESS
Definition WM_types.hh:284
@ KM_RELEASE
Definition WM_types.hh:285
#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
SIMD_FORCE_INLINE btVector3 transform(const btVector3 &point) const
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
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
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
static const EnumPropertyItem scale_fit_methods[]
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)
@ STRIP_TRANSFORM_ALL
@ STRIP_TRANSFORM_SCALE
@ STRIP_TRANSFORM_POSITION
@ STRIP_TRANSFORM_ROTATION
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)
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 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)
bAction * action
ListBase seqbase
ListBase * seqbasep
Sequence * act_seq
ListBase metastack
char * rna_path
void * first
ListBase scenes
Definition BKE_main.hh:210
struct RenderData r
struct AnimData * adt
struct UnitSettings unit
ListBase markers
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
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 *)