2 * ***** begin GPL LICENSE BLOCK *****
4 * This program is free software; you can redistribute it and/or
5 * modify it under the terms of the GNU General Public License
6 * as published by the Free Software Foundation; either version 2
7 * of the License, or (at your option) any later version.
9 * This program is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 * GNU General Public License for more details.
14 * You should have received a copy of the GNU General Public License
15 * along with this program; if not, write to the Free Software Foundation,
16 * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
18 * The Original Code is Copyright (C) 2001-2002 by NaN Holding BV.
19 * All rights reserved.
21 * Contributor(s): Blender Foundation, 2003-2009
23 * ***** END GPL LICENSE BLOCK *****
26 /** \file blender/editors/space_sequencer/sequencer_edit.c
35 #include "MEM_guardedalloc.h"
37 #include "BLI_blenlib.h"
38 #include "BLI_ghash.h"
40 #include "BLI_timecode.h"
41 #include "BLI_utildefines.h"
43 #include "BLT_translation.h"
45 #include "DNA_scene_types.h"
46 #include "DNA_sound_types.h"
48 #include "BKE_context.h"
49 #include "BKE_global.h"
51 #include "BKE_sequencer.h"
52 #include "BKE_report.h"
53 #include "BKE_sound.h"
59 #include "RNA_define.h"
60 #include "RNA_enum_types.h"
62 /* for menu/popup icons etc etc*/
64 #include "ED_anim_api.h"
65 #include "ED_numinput.h"
66 #include "ED_screen.h"
67 #include "ED_transform.h"
68 #include "ED_sequencer.h"
69 #include "ED_space_api.h"
71 #include "UI_view2d.h"
72 #include "UI_interface.h"
76 #include "sequencer_intern.h"
79 /* RNA Enums, used in multiple files */
80 EnumPropertyItem sequencer_prop_effect_types[] = {
81 {SEQ_TYPE_CROSS, "CROSS", 0, "Crossfade", "Crossfade effect strip type"},
82 {SEQ_TYPE_ADD, "ADD", 0, "Add", "Add effect strip type"},
83 {SEQ_TYPE_SUB, "SUBTRACT", 0, "Subtract", "Subtract effect strip type"},
84 {SEQ_TYPE_ALPHAOVER, "ALPHA_OVER", 0, "Alpha Over", "Alpha Over effect strip type"},
85 {SEQ_TYPE_ALPHAUNDER, "ALPHA_UNDER", 0, "Alpha Under", "Alpha Under effect strip type"},
86 {SEQ_TYPE_GAMCROSS, "GAMMA_CROSS", 0, "Gamma Cross", "Gamma Cross effect strip type"},
87 {SEQ_TYPE_MUL, "MULTIPLY", 0, "Multiply", "Multiply effect strip type"},
88 {SEQ_TYPE_OVERDROP, "OVER_DROP", 0, "Alpha Over Drop", "Alpha Over Drop effect strip type"},
89 {SEQ_TYPE_WIPE, "WIPE", 0, "Wipe", "Wipe effect strip type"},
90 {SEQ_TYPE_GLOW, "GLOW", 0, "Glow", "Glow effect strip type"},
91 {SEQ_TYPE_TRANSFORM, "TRANSFORM", 0, "Transform", "Transform effect strip type"},
92 {SEQ_TYPE_COLOR, "COLOR", 0, "Color", "Color effect strip type"},
93 {SEQ_TYPE_SPEED, "SPEED", 0, "Speed", "Color effect strip type"},
94 {SEQ_TYPE_MULTICAM, "MULTICAM", 0, "Multicam Selector", ""},
95 {SEQ_TYPE_ADJUSTMENT, "ADJUSTMENT", 0, "Adjustment Layer", ""},
96 {SEQ_TYPE_GAUSSIAN_BLUR, "GAUSSIAN_BLUR", 0, "Gaussian Blur", ""},
97 {SEQ_TYPE_TEXT, "TEXT", 0, "Text", ""},
98 {SEQ_TYPE_COLORMIX, "COLORMIX", 0, "Color Mix", ""},
99 {0, NULL, 0, NULL, NULL}
104 #define SEQ_SIDE_MOUSE -1
106 EnumPropertyItem prop_side_types[] = {
107 {SEQ_SIDE_MOUSE, "MOUSE", 0, "Mouse position", "" },
108 {SEQ_SIDE_LEFT, "LEFT", 0, "Left", "" },
109 {SEQ_SIDE_RIGHT, "RIGHT", 0, "Right", ""},
110 {SEQ_SIDE_BOTH, "BOTH", 0, "Both", ""},
111 {0, NULL, 0, NULL, NULL}
114 static const EnumPropertyItem prop_side_lr_types[] = {
115 {SEQ_SIDE_LEFT, "LEFT", 0, "Left", ""},
116 {SEQ_SIDE_RIGHT, "RIGHT", 0, "Right", ""},
117 {0, NULL, 0, NULL, NULL}
120 typedef struct TransSeq {
122 int startstill, endstill;
123 int startdisp, enddisp;
124 int startofs, endofs;
125 int anim_startofs, anim_endofs;
126 /* int final_left, final_right; */ /* UNUSED */
130 /* ********************************************************************** */
132 /* ***************** proxy job manager ********************** */
134 typedef struct ProxyBuildJob {
141 static void proxy_freejob(void *pjv)
145 BLI_freelistN(&pj->queue);
150 /* only this runs inside thread */
151 static void proxy_startjob(void *pjv, short *stop, short *do_update, float *progress)
156 for (link = pj->queue.first; link; link = link->next) {
157 struct SeqIndexBuildContext *context = link->data;
159 BKE_sequencer_proxy_rebuild(context, stop, do_update, progress);
163 fprintf(stderr, "Canceling proxy rebuild on users request...\n");
169 static void proxy_endjob(void *pjv)
172 Editing *ed = BKE_sequencer_editing_get(pj->scene, false);
175 for (link = pj->queue.first; link; link = link->next) {
176 BKE_sequencer_proxy_rebuild_finish(link->data, pj->stop);
179 BKE_sequencer_free_imbuf(pj->scene, &ed->seqbase, false);
181 WM_main_add_notifier(NC_SCENE | ND_SEQUENCER, pj->scene);
184 static void seq_proxy_build_job(const bContext *C)
188 Scene *scene = CTX_data_scene(C);
189 Editing *ed = BKE_sequencer_editing_get(scene, false);
190 ScrArea *sa = CTX_wm_area(C);
198 wm_job = WM_jobs_get(CTX_wm_manager(C), CTX_wm_window(C), sa, "Building Proxies",
199 WM_JOB_PROGRESS, WM_JOB_TYPE_SEQ_BUILD_PROXY);
201 pj = WM_jobs_customdata_get(wm_job);
204 pj = MEM_callocN(sizeof(ProxyJob), "proxy rebuild job");
207 pj->main = CTX_data_main(C);
209 WM_jobs_customdata_set(wm_job, pj, proxy_freejob);
210 WM_jobs_timer(wm_job, 0.1, NC_SCENE | ND_SEQUENCER, NC_SCENE | ND_SEQUENCER);
211 WM_jobs_callbacks(wm_job, proxy_startjob, NULL, NULL, proxy_endjob);
214 file_list = BLI_gset_new(BLI_ghashutil_strhash_p, BLI_ghashutil_strcmp, "file list");
217 if ((seq->flag & SELECT)) {
218 BKE_sequencer_proxy_rebuild_context(pj->main, pj->scene, seq, file_list, &pj->queue);
223 BLI_gset_free(file_list, MEM_freeN);
225 if (!WM_jobs_is_running(wm_job)) {
227 WM_jobs_start(CTX_wm_manager(C), wm_job);
230 ED_area_tag_redraw(sa);
233 /* ********************************************************************** */
235 void seq_rectf(Sequence *seq, rctf *rectf)
237 if (seq->startstill) rectf->xmin = seq->start;
238 else rectf->xmin = seq->startdisp;
239 rectf->ymin = seq->machine + SEQ_STRIP_OFSBOTTOM;
240 if (seq->endstill) rectf->xmax = seq->start + seq->len;
241 else rectf->xmax = seq->enddisp;
242 rectf->ymax = seq->machine + SEQ_STRIP_OFSTOP;
245 void boundbox_seq(Scene *scene, rctf *rect)
248 Editing *ed = BKE_sequencer_editing_get(scene, false);
249 float min[2], max[2];
252 if (ed == NULL) return;
259 seq = ed->seqbasep->first;
262 if (min[0] > seq->startdisp - 1) min[0] = seq->startdisp - 1;
263 if (max[0] < seq->enddisp + 1) max[0] = seq->enddisp + 1;
264 if (max[1] < seq->machine + 2) max[1] = seq->machine + 2;
276 static int mouse_frame_side(View2D *v2d, short mouse_x, int frame)
284 /* choose the side based on which side of the playhead the mouse is on */
285 UI_view2d_region_to_view(v2d, mval[0], mval[1], &mouseloc[0], &mouseloc[1]);
287 return mouseloc[0] > frame ? SEQ_SIDE_RIGHT : SEQ_SIDE_LEFT;
291 Sequence *find_neighboring_sequence(Scene *scene, Sequence *test, int lr, int sel)
293 /* sel - 0==unselected, 1==selected, -1==done care*/
295 Editing *ed = BKE_sequencer_editing_get(scene, false);
297 if (ed == NULL) return NULL;
299 if (sel > 0) sel = SELECT;
301 for (seq = ed->seqbasep->first; seq; seq = seq->next) {
303 (test->machine == seq->machine) &&
304 ((sel == -1) || (sel && (seq->flag & SELECT)) || (sel == 0 && (seq->flag & SELECT) == 0)))
308 if (test->startdisp == (seq->enddisp)) {
313 if (test->enddisp == (seq->startdisp)) {
323 static Sequence *find_next_prev_sequence(Scene *scene, Sequence *test, int lr, int sel)
325 /* sel - 0==unselected, 1==selected, -1==done care*/
326 Sequence *seq, *best_seq = NULL;
327 Editing *ed = BKE_sequencer_editing_get(scene, false);
330 best_dist = MAXFRAME * 2;
333 if (ed == NULL) return NULL;
335 seq = ed->seqbasep->first;
338 (test->machine == seq->machine) &&
339 (test->depth == seq->depth) &&
340 ((sel == -1) || (sel == (seq->flag & SELECT))))
346 if (seq->enddisp <= test->startdisp) {
347 dist = test->enddisp - seq->startdisp;
351 if (seq->startdisp >= test->enddisp) {
352 dist = seq->startdisp - test->enddisp;
361 else if (dist < best_dist) {
368 return best_seq; /* can be null */
372 Sequence *find_nearest_seq(Scene *scene, View2D *v2d, int *hand, const int mval[2])
375 Editing *ed = BKE_sequencer_editing_get(scene, false);
380 *hand = SEQ_SIDE_NONE;
383 if (ed == NULL) return NULL;
385 pixelx = BLI_rctf_size_x(&v2d->cur) / BLI_rcti_size_x(&v2d->mask);
387 UI_view2d_region_to_view(v2d, mval[0], mval[1], &x, &y);
389 seq = ed->seqbasep->first;
392 if (seq->machine == (int)y) {
393 /* check for both normal strips, and strips that have been flipped horizontally */
394 if (((seq->startdisp < seq->enddisp) && (seq->startdisp <= x && seq->enddisp >= x)) ||
395 ((seq->startdisp > seq->enddisp) && (seq->startdisp >= x && seq->enddisp <= x)) )
397 if (BKE_sequence_tx_test(seq)) {
399 /* clamp handles to defined size in pixel space */
401 handsize = seq->handsize;
402 displen = (float)abs(seq->startdisp - seq->enddisp);
404 if (displen / pixelx > 16) { /* don't even try to grab the handles of small strips */
405 /* Set the max value to handle to 1/3 of the total len when its less than 28.
406 * This is important because otherwise selecting handles happens even when you click in the middle */
408 if ((displen / 3) < 30 * pixelx) {
409 handsize = displen / 3;
412 CLAMP(handsize, 7 * pixelx, 30 * pixelx);
415 if (handsize + seq->startdisp >= x)
416 *hand = SEQ_SIDE_LEFT;
417 else if (-handsize + seq->enddisp <= x)
418 *hand = SEQ_SIDE_RIGHT;
430 static bool seq_is_parent(Sequence *par, Sequence *seq)
432 return ((par->seq1 == seq) || (par->seq2 == seq) || (par->seq3 == seq));
435 static bool seq_is_predecessor(Sequence *pred, Sequence *seq)
438 if (pred == seq) return 0;
439 else if (seq_is_parent(pred, seq)) return 1;
440 else if (pred->seq1 && seq_is_predecessor(pred->seq1, seq)) return 1;
441 else if (pred->seq2 && seq_is_predecessor(pred->seq2, seq)) return 1;
442 else if (pred->seq3 && seq_is_predecessor(pred->seq3, seq)) return 1;
447 void ED_sequencer_deselect_all(Scene *scene)
450 Editing *ed = BKE_sequencer_editing_get(scene, false);
453 if (ed == NULL) return;
457 seq->flag &= ~SEQ_ALLSEL;
463 void recurs_sel_seq(Sequence *seqm)
467 seq = seqm->seqbase.first;
470 if (seqm->flag & (SEQ_LEFTSEL + SEQ_RIGHTSEL)) seq->flag &= ~SEQ_ALLSEL;
471 else if (seqm->flag & SELECT) seq->flag |= SELECT;
472 else seq->flag &= ~SEQ_ALLSEL;
474 if (seq->seqbase.first) recurs_sel_seq(seq);
480 bool ED_space_sequencer_maskedit_mask_poll(bContext *C)
482 /* in this case both funcs are the same, for clip editor not */
483 return ED_space_sequencer_maskedit_poll(C);
486 bool ED_space_sequencer_check_show_maskedit(SpaceSeq *sseq, Scene *scene)
488 if (sseq && sseq->mainb == SEQ_DRAW_IMG_IMBUF) {
489 return (BKE_sequencer_mask_get(scene) != NULL);
495 bool ED_space_sequencer_maskedit_poll(bContext *C)
497 SpaceSeq *sseq = CTX_wm_space_seq(C);
500 Scene *scene = CTX_data_scene(C);
501 return ED_space_sequencer_check_show_maskedit(sseq, scene);
507 /* are we displaying the seq output (not channels or histogram)*/
508 bool ED_space_sequencer_check_show_imbuf(SpaceSeq *sseq)
510 return (ELEM(sseq->view, SEQ_VIEW_PREVIEW, SEQ_VIEW_SEQUENCE_PREVIEW) &&
511 ELEM(sseq->mainb, SEQ_DRAW_SEQUENCE, SEQ_DRAW_IMG_IMBUF));
514 bool ED_space_sequencer_check_show_strip(SpaceSeq *sseq)
516 return (ELEM(sseq->view, SEQ_VIEW_SEQUENCE, SEQ_VIEW_SEQUENCE_PREVIEW) &&
517 ELEM(sseq->mainb, SEQ_DRAW_SEQUENCE, SEQ_DRAW_IMG_IMBUF));
521 int seq_effect_find_selected(Scene *scene, Sequence *activeseq, int type, Sequence **selseq1, Sequence **selseq2, Sequence **selseq3, const char **error_str)
523 Editing *ed = BKE_sequencer_editing_get(scene, false);
524 Sequence *seq1 = NULL, *seq2 = NULL, *seq3 = NULL, *seq;
529 seq2 = BKE_sequencer_active_get(scene);
531 for (seq = ed->seqbasep->first; seq; seq = seq->next) {
532 if (seq->flag & SELECT) {
533 if (seq->type == SEQ_TYPE_SOUND_RAM && BKE_sequence_effect_get_num_inputs(type) != 0) {
534 *error_str = N_("Cannot apply effects to audio sequence strips");
537 if ((seq != activeseq) && (seq != seq2)) {
538 if (seq2 == NULL) seq2 = seq;
539 else if (seq1 == NULL) seq1 = seq;
540 else if (seq3 == NULL) seq3 = seq;
542 *error_str = N_("Cannot apply effect to more than 3 sequence strips");
549 /* make sequence selection a little bit more intuitive
550 * for 3 strips: the last-strip should be sequence3 */
551 if (seq3 != NULL && seq2 != NULL) {
552 Sequence *tmp = seq2;
558 switch (BKE_sequence_effect_get_num_inputs(type)) {
560 *selseq1 = *selseq2 = *selseq3 = NULL;
561 return 1; /* succsess */
564 *error_str = N_("At least one selected sequence strip is needed");
567 if (seq1 == NULL) seq1 = seq2;
568 if (seq3 == NULL) seq3 = seq2;
571 if (seq1 == NULL || seq2 == NULL) {
572 *error_str = N_("2 selected sequence strips are needed");
575 if (seq3 == NULL) seq3 = seq2;
579 if (seq1 == NULL && seq2 == NULL && seq3 == NULL) {
580 *error_str = N_("TODO: in what cases does this happen?");
591 static Sequence *del_seq_find_replace_recurs(Scene *scene, Sequence *seq)
593 Sequence *seq1, *seq2, *seq3;
595 /* try to find a replacement input sequence, and flag for later deletion if
596 * no replacement can be found */
600 else if (!(seq->type & SEQ_TYPE_EFFECT))
601 return ((seq->flag & SELECT) ? NULL : seq);
602 else if (!(seq->flag & SELECT)) {
603 /* try to find replacement for effect inputs */
604 seq1 = del_seq_find_replace_recurs(scene, seq->seq1);
605 seq2 = del_seq_find_replace_recurs(scene, seq->seq2);
606 seq3 = del_seq_find_replace_recurs(scene, seq->seq3);
608 if (seq1 == seq->seq1 && seq2 == seq->seq2 && seq3 == seq->seq3) {
611 else if (seq1 || seq2 || seq3) {
612 seq->seq1 = (seq1) ? seq1 : (seq2) ? seq2 : seq3;
613 seq->seq2 = (seq2) ? seq2 : (seq1) ? seq1 : seq3;
614 seq->seq3 = (seq3) ? seq3 : (seq1) ? seq1 : seq2;
616 BKE_sequencer_update_changed_seq_and_deps(scene, seq, 1, 1);
619 seq->flag |= SELECT; /* mark for delete */
622 if (seq->flag & SELECT) {
623 if ((seq1 = del_seq_find_replace_recurs(scene, seq->seq1))) return seq1;
624 if ((seq2 = del_seq_find_replace_recurs(scene, seq->seq2))) return seq2;
625 if ((seq3 = del_seq_find_replace_recurs(scene, seq->seq3))) return seq3;
632 static void del_seq_clear_modifiers_recurs(Scene *scene, Sequence *deleting_sequence)
634 Editing *ed = BKE_sequencer_editing_get(scene, false);
635 Sequence *current_sequence;
637 SEQP_BEGIN(ed, current_sequence)
639 if (!(current_sequence->flag & SELECT) && current_sequence != deleting_sequence) {
640 SequenceModifierData *smd;
642 for (smd = current_sequence->modifiers.first; smd; smd = smd->next) {
643 if (smd->mask_sequence == deleting_sequence) {
644 smd->mask_sequence = NULL;
652 static void recurs_del_seq_flag(Scene *scene, ListBase *lb, short flag, short deleteall)
654 Sequence *seq, *seqn;
655 Sequence *last_seq = BKE_sequencer_active_get(scene);
660 if ((seq->flag & flag) || deleteall) {
661 BLI_remlink(lb, seq);
662 if (seq == last_seq) BKE_sequencer_active_set(scene, NULL);
663 if (seq->type == SEQ_TYPE_META) recurs_del_seq_flag(scene, &seq->seqbase, flag, 1);
664 BKE_sequence_free(scene, seq);
671 static Sequence *cut_seq_hard(Scene *scene, Sequence *seq, int cutframe)
674 Sequence *seqn = NULL;
675 bool skip_dup = false;
677 /* Unlike soft-cut, it's important to use the same value for both strips. */
678 const bool is_end_exact = ((seq->start + seq->len) == cutframe);
681 ts.start = seq->start;
682 ts.machine = seq->machine;
683 ts.startstill = seq->startstill;
684 ts.endstill = seq->endstill;
685 ts.startdisp = seq->startdisp;
686 ts.enddisp = seq->enddisp;
687 ts.startofs = seq->startofs;
688 ts.endofs = seq->endofs;
689 ts.anim_startofs = seq->anim_startofs;
690 ts.anim_endofs = seq->anim_endofs;
694 /* strips with extended stillfames before */
696 /* Precaution, needed because the length saved on-disk may not match the length saved in the blend file,
697 * or our code may have minor differences reading file length between versions.
698 * This causes hard-cut to fail, see: T47862 */
699 if (seq->type != SEQ_TYPE_META) {
700 BKE_sequence_reload_new_file(scene, seq, true);
701 BKE_sequence_calc(scene, seq);
704 /* Important to offset the start when 'cutframe == seq->start'
705 * because we need at least one frame of content after start/end still have clipped it. */
706 if ((seq->startstill) && (cutframe <= seq->start)) {
707 /* don't do funny things with METAs ... */
708 if (seq->type == SEQ_TYPE_META) {
710 seq->startstill = seq->start - cutframe;
713 seq->start = cutframe - 1;
714 seq->startstill = cutframe - seq->startdisp - 1;
715 seq->anim_endofs += seq->len - 1;
720 else if ((is_end_exact == false) &&
721 ((cutframe >= seq->start) && (cutframe <= (seq->start + seq->len))))
725 seq->anim_endofs += (seq->start + seq->len) - cutframe;
727 /* strips with extended stillframes after */
728 else if ((is_end_exact == true) ||
729 (((seq->start + seq->len) < cutframe) && (seq->endstill)))
731 seq->endstill -= seq->enddisp - cutframe;
732 /* don't do funny things with METAs ... */
733 if (seq->type == SEQ_TYPE_META) {
738 BKE_sequence_reload_new_file(scene, seq, false);
739 BKE_sequence_calc(scene, seq);
742 /* Duplicate AFTER the first change */
743 seqn = BKE_sequence_dupli_recursive(scene, scene, seq, SEQ_DUPE_ANIM);
747 seqn->flag |= SELECT;
749 /* Important not to re-assign this (unlike soft-cut) */
751 is_end_exact = ((seqn->start + seqn->len) == cutframe);
754 /* strips with extended stillframes before */
755 if ((seqn->startstill) && (cutframe == seqn->start + 1)) {
756 seqn->start = ts.start;
757 seqn->startstill = ts.start - cutframe;
758 seqn->anim_endofs = ts.anim_endofs;
759 seqn->endstill = ts.endstill;
763 else if ((is_end_exact == false) &&
764 ((cutframe >= seqn->start) && (cutframe <= (seqn->start + seqn->len))))
766 seqn->start = cutframe;
767 seqn->startstill = 0;
769 seqn->endofs = ts.endofs;
770 seqn->anim_startofs += cutframe - ts.start;
771 seqn->anim_endofs = ts.anim_endofs;
772 seqn->endstill = ts.endstill;
775 /* strips with extended stillframes after */
776 else if ((is_end_exact == true) ||
777 (((seqn->start + seqn->len) < cutframe) && (seqn->endstill)))
779 seqn->start = cutframe;
781 seqn->anim_startofs += ts.len - 1;
782 seqn->endstill = ts.enddisp - cutframe - 1;
783 seqn->startstill = 0;
786 BKE_sequence_reload_new_file(scene, seqn, false);
787 BKE_sequence_calc(scene, seqn);
792 static Sequence *cut_seq_soft(Scene *scene, Sequence *seq, int cutframe)
795 Sequence *seqn = NULL;
796 bool skip_dup = false;
798 bool is_end_exact = ((seq->start + seq->len) == cutframe);
801 ts.start = seq->start;
802 ts.machine = seq->machine;
803 ts.startstill = seq->startstill;
804 ts.endstill = seq->endstill;
805 ts.startdisp = seq->startdisp;
806 ts.enddisp = seq->enddisp;
807 ts.startofs = seq->startofs;
808 ts.endofs = seq->endofs;
809 ts.anim_startofs = seq->anim_startofs;
810 ts.anim_endofs = seq->anim_endofs;
814 /* strips with extended stillfames before */
816 /* Important to offset the start when 'cutframe == seq->start'
817 * because we need at least one frame of content after start/end still have clipped it. */
818 if ((seq->startstill) && (cutframe <= seq->start)) {
819 /* don't do funny things with METAs ... */
820 if (seq->type == SEQ_TYPE_META) {
822 seq->startstill = seq->start - cutframe;
825 seq->start = cutframe - 1;
826 seq->startstill = cutframe - seq->startdisp - 1;
827 seq->endofs = seq->len - 1;
832 else if ((is_end_exact == false) &&
833 (cutframe >= seq->start) && (cutframe <= (seq->start + seq->len)))
835 seq->endofs = (seq->start + seq->len) - cutframe;
837 /* strips with extended stillframes after */
838 else if ((is_end_exact == true) ||
839 (((seq->start + seq->len) < cutframe) && (seq->endstill)))
841 seq->endstill -= seq->enddisp - cutframe;
842 /* don't do funny things with METAs ... */
843 if (seq->type == SEQ_TYPE_META) {
848 BKE_sequence_calc(scene, seq);
851 /* Duplicate AFTER the first change */
852 seqn = BKE_sequence_dupli_recursive(scene, scene, seq, SEQ_DUPE_ANIM);
856 seqn->flag |= SELECT;
858 is_end_exact = ((seqn->start + seqn->len) == cutframe);
861 /* strips with extended stillframes before */
862 if ((seqn->startstill) && (cutframe == seqn->start + 1)) {
863 seqn->start = ts.start;
864 seqn->startstill = ts.start - cutframe;
865 seqn->endofs = ts.endofs;
866 seqn->endstill = ts.endstill;
870 else if ((is_end_exact == false) &&
871 (cutframe >= seqn->start) && (cutframe <= (seqn->start + seqn->len)))
873 seqn->startstill = 0;
874 seqn->startofs = cutframe - ts.start;
875 seqn->endofs = ts.endofs;
876 seqn->endstill = ts.endstill;
879 /* strips with extended stillframes after */
880 else if ((is_end_exact == true) ||
881 (((seqn->start + seqn->len) < cutframe) && (seqn->endstill)))
883 seqn->start = cutframe - ts.len + 1;
884 seqn->startofs = ts.len - 1;
885 seqn->endstill = ts.enddisp - cutframe - 1;
886 seqn->startstill = 0;
889 BKE_sequence_calc(scene, seqn);
895 /* like duplicate, but only duplicate and cut overlapping strips,
896 * strips to the left of the cutframe are ignored and strips to the right
897 * are moved to the end of slist
898 * we have to work on the same slist (not using a separate list), since
899 * otherwise dupli_seq can't check for duplicate names properly and
900 * may generate strips with the same name (which will mess up animdata)
903 static bool cut_seq_list(Scene *scene, ListBase *slist, int cutframe,
904 Sequence * (*cut_seq)(Scene *, Sequence *, int))
906 Sequence *seq, *seq_next_iter;
907 Sequence *seq_first_new = NULL;
911 while (seq && seq != seq_first_new) {
912 seq_next_iter = seq->next; /* we need this because we may remove seq */
914 if (seq->flag & SELECT) {
915 if (cutframe > seq->startdisp &&
916 cutframe < seq->enddisp)
918 Sequence *seqn = cut_seq(scene, seq, cutframe);
920 BLI_addtail(slist, seqn);
921 if (seq_first_new == NULL) {
922 seq_first_new = seqn;
926 else if (seq->enddisp <= cutframe) {
929 else if (seq->startdisp >= cutframe) {
931 BLI_remlink(slist, seq);
932 BLI_addtail(slist, seq);
934 if (seq_first_new == NULL) {
942 return (seq_first_new != NULL);
945 static bool sequence_offset_after_frame(Scene *scene, const int delta, const int cfra)
948 Editing *ed = BKE_sequencer_editing_get(scene, false);
952 /* all strips >= cfra are shifted */
954 if (ed == NULL) return 0;
956 for (seq = ed->seqbasep->first; seq; seq = seq->next) {
957 if (seq->startdisp >= cfra) {
958 BKE_sequence_translate(scene, seq, delta);
959 BKE_sequence_calc(scene, seq);
964 if (!scene->toolsettings->lock_markers) {
965 for (marker = scene->markers.first; marker; marker = marker->next) {
966 if (marker->frame >= cfra) {
967 marker->frame += delta;
976 static void set_filter_seq(Scene *scene)
979 Editing *ed = BKE_sequencer_editing_get(scene, false);
982 if (ed == NULL) return;
984 if (okee("Set Deinterlace") == 0) return;
988 if (seq->flag & SELECT) {
989 if (seq->type == SEQ_TYPE_MOVIE) {
990 seq->flag |= SEQ_FILTERY;
991 BKE_sequence_reload_new_file(scene, seq, false);
992 BKE_sequence_calc(scene, seq);
1001 static void UNUSED_FUNCTION(seq_remap_paths) (Scene *scene)
1003 Sequence *seq, *last_seq = BKE_sequencer_active_get(scene);
1004 Editing *ed = BKE_sequencer_editing_get(scene, false);
1005 char from[FILE_MAX], to[FILE_MAX], stripped[FILE_MAX];
1008 if (last_seq == NULL)
1011 BLI_strncpy(from, last_seq->strip->dir, sizeof(from));
1012 // XXX if (0 == sbutton(from, 0, sizeof(from) - 1, "From: "))
1015 BLI_strncpy(to, from, sizeof(to));
1016 // XXX if (0 == sbutton(to, 0, sizeof(to) - 1, "To: "))
1019 if (STREQ(to, from))
1022 SEQP_BEGIN (ed, seq)
1024 if (seq->flag & SELECT) {
1025 if (STREQLEN(seq->strip->dir, from, strlen(from))) {
1026 printf("found %s\n", seq->strip->dir);
1028 /* strip off the beginning */
1030 BLI_strncpy(stripped, seq->strip->dir + strlen(from), FILE_MAX);
1033 BLI_snprintf(seq->strip->dir, sizeof(seq->strip->dir), "%s%s", to, stripped);
1034 printf("new %s\n", seq->strip->dir);
1043 static int sequencer_gap_remove_exec(bContext *C, wmOperator *op)
1045 Scene *scene = CTX_data_scene(C);
1047 int cfra, efra, sfra;
1048 bool first = false, done;
1049 bool do_all = RNA_boolean_get(op->ptr, "all");
1051 /* get first and last frame */
1052 boundbox_seq(scene, &rectf);
1053 sfra = (int)rectf.xmin;
1054 efra = (int)rectf.xmax;
1056 /* first check if the current frame has a gap already */
1057 for (cfra = CFRA; cfra >= sfra; cfra--) {
1058 if (BKE_sequencer_evaluate_frame(scene, cfra)) {
1064 for ( ; cfra < efra; cfra++) {
1065 /* first == 0 means there's still no strip to remove a gap for */
1066 if (first == false) {
1067 if (BKE_sequencer_evaluate_frame(scene, cfra) ) first = true;
1069 else if (BKE_sequencer_evaluate_frame(scene, cfra) == 0) {
1071 while (BKE_sequencer_evaluate_frame(scene, cfra) == 0) {
1072 done = sequence_offset_after_frame(scene, -1, cfra);
1073 if (done == false) break;
1075 if (done == false || do_all == false) break;
1079 WM_event_add_notifier(C, NC_SCENE | ND_SEQUENCER, scene);
1081 return OPERATOR_FINISHED;
1086 void SEQUENCER_OT_gap_remove(struct wmOperatorType *ot)
1089 ot->name = "Remove Gaps";
1090 ot->idname = "SEQUENCER_OT_gap_remove";
1091 ot->description = "Remove gap at current frame to first strip at the right, independent of selection or locked state of strips";
1094 // ot->invoke = sequencer_snap_invoke;
1095 ot->exec = sequencer_gap_remove_exec;
1096 ot->poll = sequencer_edit_poll;
1099 ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
1101 RNA_def_boolean(ot->srna, "all", 0, "All Gaps", "Do all gaps to right of current frame");
1104 static int sequencer_gap_insert_exec(bContext *C, wmOperator *op)
1106 Scene *scene = CTX_data_scene(C);
1107 int frames = RNA_int_get(op->ptr, "frames");
1109 sequence_offset_after_frame(scene, frames, CFRA);
1111 WM_event_add_notifier(C, NC_SCENE | ND_SEQUENCER, scene);
1113 return OPERATOR_FINISHED;
1117 void SEQUENCER_OT_gap_insert(struct wmOperatorType *ot)
1120 ot->name = "Insert Gaps";
1121 ot->idname = "SEQUENCER_OT_gap_insert";
1122 ot->description = "Insert gap at current frame to first strips at the right, independent of selection or locked state of strips";
1125 // ot->invoke = sequencer_snap_invoke;
1126 ot->exec = sequencer_gap_insert_exec;
1127 ot->poll = sequencer_edit_poll;
1130 ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
1132 RNA_def_int(ot->srna, "frames", 10, 0, INT_MAX, "Frames", "Frames to insert after current strip", 0, 1000);
1137 static int seq_get_snaplimit(View2D *v2d)
1139 /* fake mouse coords to get the snap value
1140 * a bit lazy but its only done once pre transform */
1141 float xmouse, ymouse, x;
1142 int mval[2] = {24, 0}; /* 24 screen px snap */
1144 UI_view2d_region_to_view(v2d, mval[0], mval[1], &xmouse, &ymouse);
1147 UI_view2d_region_to_view(v2d, mval[0], mval[1], &xmouse, &ymouse);
1148 return (int)(x - xmouse);
1152 /* Operator functions */
1153 bool sequencer_edit_poll(bContext *C)
1155 return (BKE_sequencer_editing_get(CTX_data_scene(C), false) != NULL);
1159 bool sequencer_strip_poll(bContext *C)
1162 return (((ed = BKE_sequencer_editing_get(CTX_data_scene(C), false)) != NULL) && (ed->act_seq != NULL));
1166 bool sequencer_strip_has_path_poll(bContext *C)
1170 return (((ed = BKE_sequencer_editing_get(CTX_data_scene(C), false)) != NULL) && ((seq = ed->act_seq) != NULL) && (SEQ_HAS_PATH(seq)));
1173 bool sequencer_view_preview_poll(bContext *C)
1175 SpaceSeq *sseq = CTX_wm_space_seq(C);
1176 Editing *ed = BKE_sequencer_editing_get(CTX_data_scene(C), false);
1177 if (ed && sseq && (sseq->mainb == SEQ_DRAW_IMG_IMBUF))
1183 bool sequencer_view_strips_poll(bContext *C)
1185 SpaceSeq *sseq = CTX_wm_space_seq(C);
1186 if (sseq && ED_space_sequencer_check_show_strip(sseq))
1193 static int sequencer_snap_exec(bContext *C, wmOperator *op)
1195 Scene *scene = CTX_data_scene(C);
1197 Editing *ed = BKE_sequencer_editing_get(scene, false);
1201 snap_frame = RNA_int_get(op->ptr, "frame");
1203 /* also check metas */
1204 for (seq = ed->seqbasep->first; seq; seq = seq->next) {
1205 if (seq->flag & SELECT && !(seq->depth == 0 && seq->flag & SEQ_LOCK) &&
1206 BKE_sequence_tx_test(seq))
1208 if ((seq->flag & (SEQ_LEFTSEL + SEQ_RIGHTSEL)) == 0) {
1209 /* simple but no anim update */
1210 /* seq->start = snap_frame-seq->startofs+seq->startstill; */
1212 BKE_sequence_translate(scene, seq, (snap_frame - seq->startofs + seq->startstill) - seq->start);
1215 if (seq->flag & SEQ_LEFTSEL) {
1216 BKE_sequence_tx_set_final_left(seq, snap_frame);
1218 else { /* SEQ_RIGHTSEL */
1219 BKE_sequence_tx_set_final_right(seq, snap_frame);
1221 BKE_sequence_tx_handle_xlimits(seq, seq->flag & SEQ_LEFTSEL, seq->flag & SEQ_RIGHTSEL);
1222 BKE_sequence_single_fix(seq);
1224 BKE_sequence_calc(scene, seq);
1228 /* test for effects and overlap
1229 * don't use SEQP_BEGIN since that would be recursive */
1230 for (seq = ed->seqbasep->first; seq; seq = seq->next) {
1231 if (seq->flag & SELECT && !(seq->depth == 0 && seq->flag & SEQ_LOCK)) {
1232 seq->flag &= ~SEQ_OVERLAP;
1233 if (BKE_sequence_test_overlap(ed->seqbasep, seq) ) {
1234 BKE_sequence_base_shuffle(ed->seqbasep, seq, scene);
1237 else if (seq->type & SEQ_TYPE_EFFECT) {
1238 if (seq->seq1 && (seq->seq1->flag & SELECT))
1239 BKE_sequence_calc(scene, seq);
1240 else if (seq->seq2 && (seq->seq2->flag & SELECT))
1241 BKE_sequence_calc(scene, seq);
1242 else if (seq->seq3 && (seq->seq3->flag & SELECT))
1243 BKE_sequence_calc(scene, seq);
1248 BKE_sequencer_sort(scene);
1250 WM_event_add_notifier(C, NC_SCENE | ND_SEQUENCER, scene);
1252 return OPERATOR_FINISHED;
1255 static int sequencer_snap_invoke(bContext *C, wmOperator *op, const wmEvent *UNUSED(event))
1257 Scene *scene = CTX_data_scene(C);
1263 RNA_int_set(op->ptr, "frame", snap_frame);
1264 return sequencer_snap_exec(C, op);
1267 void SEQUENCER_OT_snap(struct wmOperatorType *ot)
1270 ot->name = "Snap Strips to Frame";
1271 ot->idname = "SEQUENCER_OT_snap";
1272 ot->description = "Frame where selected strips will be snapped";
1275 ot->invoke = sequencer_snap_invoke;
1276 ot->exec = sequencer_snap_exec;
1277 ot->poll = sequencer_edit_poll;
1280 ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
1282 RNA_def_int(ot->srna, "frame", 0, INT_MIN, INT_MAX, "Frame", "Frame where selected strips will be snapped", INT_MIN, INT_MAX);
1285 typedef struct SlipData {
1287 float init_mouseloc[2];
1289 Sequence **seq_array;
1293 int slow_offset; /* offset at the point where offset was turned on */
1298 static void transseq_backup(TransSeq *ts, Sequence *seq)
1300 ts->start = seq->start;
1301 ts->machine = seq->machine;
1302 ts->startstill = seq->startstill;
1303 ts->endstill = seq->endstill;
1304 ts->startdisp = seq->startdisp;
1305 ts->enddisp = seq->enddisp;
1306 ts->startofs = seq->startofs;
1307 ts->endofs = seq->endofs;
1308 ts->anim_startofs = seq->anim_startofs;
1309 ts->anim_endofs = seq->anim_endofs;
1314 static void transseq_restore(TransSeq *ts, Sequence *seq)
1316 seq->start = ts->start;
1317 seq->machine = ts->machine;
1318 seq->startstill = ts->startstill;
1319 seq->endstill = ts->endstill;
1320 seq->startdisp = ts->startdisp;
1321 seq->enddisp = ts->enddisp;
1322 seq->startofs = ts->startofs;
1323 seq->endofs = ts->endofs;
1324 seq->anim_startofs = ts->anim_startofs;
1325 seq->anim_endofs = ts->anim_endofs;
1329 static void draw_slip_extensions(const bContext *C, ARegion *ar, void *data)
1331 Scene *scene = CTX_data_scene(C);
1332 SlipData *td = data;
1335 for (i = 0; i < td->num_seq; i++) {
1336 Sequence *seq = td->seq_array[i];
1338 if ((seq->type != SEQ_TYPE_META) && td->trim[i]) {
1339 draw_sequence_extensions(scene, ar, seq);
1344 static int slip_add_sequences_rec(ListBase *seqbasep, Sequence **seq_array, bool *trim, int offset, bool do_trim)
1349 for (seq = seqbasep->first; seq; seq = seq->next) {
1350 if (!do_trim || (!(seq->type & SEQ_TYPE_EFFECT) && (seq->flag & SELECT))) {
1351 seq_array[offset + num_items] = seq;
1352 trim[offset + num_items] = do_trim;
1355 if (seq->type == SEQ_TYPE_META) {
1356 /* trim the sub-sequences */
1357 num_items += slip_add_sequences_rec(&seq->seqbase, seq_array, trim, num_items + offset, false);
1359 else if (seq->type & SEQ_TYPE_EFFECT) {
1360 trim[offset + num_items] = false;
1368 static int slip_count_sequences_rec(ListBase *seqbasep, bool first_level)
1371 int trimmed_sequences = 0;
1373 for (seq = seqbasep->first; seq; seq = seq->next) {
1374 if (!first_level || (!(seq->type & SEQ_TYPE_EFFECT) && (seq->flag & SELECT))) {
1375 trimmed_sequences++;
1377 if (seq->type == SEQ_TYPE_META) {
1378 /* trim the sub-sequences */
1379 trimmed_sequences += slip_count_sequences_rec(&seq->seqbase, false);
1384 return trimmed_sequences;
1387 static int sequencer_slip_invoke(bContext *C, wmOperator *op, const wmEvent *event)
1390 Scene *scene = CTX_data_scene(C);
1391 Editing *ed = BKE_sequencer_editing_get(scene, false);
1392 ARegion *ar = CTX_wm_region(C);
1395 View2D *v2d = UI_view2d_fromcontext(C);
1397 /* first recursively cound the trimmed elements */
1398 num_seq = slip_count_sequences_rec(ed->seqbasep, true);
1401 return OPERATOR_CANCELLED;
1403 data = op->customdata = MEM_mallocN(sizeof(SlipData), "trimdata");
1404 data->ts = MEM_mallocN(num_seq * sizeof(TransSeq), "trimdata_transform");
1405 data->seq_array = MEM_mallocN(num_seq * sizeof(Sequence *), "trimdata_sequences");
1406 data->trim = MEM_mallocN(num_seq * sizeof(bool), "trimdata_trim");
1407 data->num_seq = num_seq;
1409 initNumInput(&data->num_input);
1410 data->num_input.idx_max = 0;
1411 data->num_input.val_flag[0] |= NUM_NO_FRACTION;
1412 data->num_input.unit_sys = USER_UNIT_NONE;
1413 data->num_input.unit_type[0] = 0;
1416 slip_add_sequences_rec(ed->seqbasep, data->seq_array, data->trim, 0, true);
1418 for (i = 0; i < num_seq; i++) {
1419 transseq_backup(data->ts + i, data->seq_array[i]);
1422 data->draw_handle = ED_region_draw_cb_activate(ar->type, draw_slip_extensions, data, REGION_DRAW_POST_VIEW);
1424 UI_view2d_region_to_view(v2d, event->mval[0], event->mval[1], &mouseloc[0], &mouseloc[1]);
1426 copy_v2_v2_int(data->init_mouse, event->mval);
1427 copy_v2_v2(data->init_mouseloc, mouseloc);
1431 WM_event_add_modal_handler(C, op);
1433 /* notify so we draw extensions immediately */
1434 WM_event_add_notifier(C, NC_SCENE | ND_SEQUENCER, scene);
1436 return OPERATOR_RUNNING_MODAL;
1439 static bool sequencer_slip_recursively(Scene *scene, SlipData *data, int offset)
1442 /* only data types supported for now */
1444 Editing *ed = BKE_sequencer_editing_get(scene, false);
1447 /* we iterate in reverse so metastrips are iterated after their children */
1448 for (i = data->num_seq - 1; i >= 0; i--) {
1449 Sequence *seq = data->seq_array[i];
1451 /* we have the offset, do the terrible math */
1453 /* first, do the offset */
1454 seq->start = data->ts[i].start + offset;
1456 if (data->trim[i]) {
1457 /* find the endframe */
1458 endframe = seq->start + seq->len;
1460 /* now compute the terrible offsets */
1461 if (endframe > seq->enddisp) {
1463 seq->endofs = endframe - seq->enddisp;
1465 else if (endframe <= seq->enddisp) {
1466 seq->endstill = seq->enddisp - endframe;
1470 if (seq->start > seq->startdisp) {
1471 seq->startstill = seq->start - seq->startdisp;
1474 else if (seq->start <= seq->startdisp) {
1475 seq->startstill = 0;
1476 seq->startofs = seq->startdisp - seq->start;
1480 /* if no real trim, don't change the data, rather transform the strips themselves */
1481 seq->startdisp = data->ts[i].startdisp + offset;
1482 seq->enddisp = data->ts[i].enddisp + offset;
1485 /* effects are only added if we they are in a metastrip. In this case, dependent strips will just be transformed and we can skip calculating for effects
1486 * This way we can avoid an extra loop just for effects*/
1487 if (!(seq->type & SEQ_TYPE_EFFECT))
1488 BKE_sequence_calc(scene, seq);
1490 BKE_sequencer_free_imbuf(scene, &ed->seqbase, false);
1498 static int sequencer_slip_exec(bContext *C, wmOperator *op)
1501 Scene *scene = CTX_data_scene(C);
1502 Editing *ed = BKE_sequencer_editing_get(scene, false);
1504 int offset = RNA_int_get(op->ptr, "offset");
1505 bool success = false;
1507 /* first recursively cound the trimmed elements */
1508 num_seq = slip_count_sequences_rec(ed->seqbasep, true);
1511 return OPERATOR_CANCELLED;
1513 data = op->customdata = MEM_mallocN(sizeof(SlipData), "trimdata");
1514 data->ts = MEM_mallocN(num_seq * sizeof(TransSeq), "trimdata_transform");
1515 data->seq_array = MEM_mallocN(num_seq * sizeof(Sequence *), "trimdata_sequences");
1516 data->trim = MEM_mallocN(num_seq * sizeof(bool), "trimdata_trim");
1517 data->num_seq = num_seq;
1519 slip_add_sequences_rec(ed->seqbasep, data->seq_array, data->trim, 0, true);
1521 for (i = 0; i < num_seq; i++) {
1522 transseq_backup(data->ts + i, data->seq_array[i]);
1525 success = sequencer_slip_recursively(scene, data, offset);
1527 MEM_freeN(data->seq_array);
1528 MEM_freeN(data->trim);
1529 MEM_freeN(data->ts);
1533 WM_event_add_notifier(C, NC_SCENE | ND_SEQUENCER, scene);
1534 return OPERATOR_FINISHED;
1537 return OPERATOR_CANCELLED;
1542 static void sequencer_slip_update_header(Scene *scene, ScrArea *sa, SlipData *data, int offset)
1544 char msg[UI_MAX_DRAW_STR];
1547 if (hasNumInput(&data->num_input)) {
1548 char num_str[NUM_STR_REP_LEN];
1549 outputNumInput(&data->num_input, num_str, &scene->unit);
1550 BLI_snprintf(msg, sizeof(msg), IFACE_("Trim offset: %s"), num_str);
1553 BLI_snprintf(msg, sizeof(msg), IFACE_("Trim offset: %d"), offset);
1557 ED_area_headerprint(sa, msg);
1560 static int sequencer_slip_modal(bContext *C, wmOperator *op, const wmEvent *event)
1562 Scene *scene = CTX_data_scene(C);
1563 SlipData *data = (SlipData *)op->customdata;
1564 ScrArea *sa = CTX_wm_area(C);
1565 ARegion *ar = CTX_wm_region(C);
1566 const bool has_numInput = hasNumInput(&data->num_input);
1567 bool handled = true;
1569 /* Modal numinput active, try to handle numeric inputs first... */
1570 if (event->val == KM_PRESS && has_numInput && handleNumInput(C, &data->num_input, event)) {
1572 applyNumInput(&data->num_input, &offset);
1574 sequencer_slip_update_header(scene, sa, data, (int)offset);
1576 RNA_int_set(op->ptr, "offset", offset);
1578 if (sequencer_slip_recursively(scene, data, offset)) {
1579 WM_event_add_notifier(C, NC_SCENE | ND_SEQUENCER, scene);
1582 return OPERATOR_RUNNING_MODAL;
1585 switch (event->type) {
1588 if (!has_numInput) {
1592 View2D *v2d = UI_view2d_fromcontext(C);
1595 mouse_x = event->mval[0] - data->slow_offset;
1597 mouse_x += data->slow_offset;
1600 mouse_x = event->mval[0];
1604 /* choose the side based on which side of the playhead the mouse is on */
1605 UI_view2d_region_to_view(v2d, mouse_x, 0, &mouseloc[0], &mouseloc[1]);
1606 offset = mouseloc[0] - data->init_mouseloc[0];
1608 sequencer_slip_update_header(scene, sa, data, offset);
1610 RNA_int_set(op->ptr, "offset", offset);
1612 if (sequencer_slip_recursively(scene, data, offset)) {
1613 WM_event_add_notifier(C, NC_SCENE | ND_SEQUENCER, scene);
1623 ED_region_draw_cb_exit(ar->type, data->draw_handle);
1624 MEM_freeN(data->seq_array);
1625 MEM_freeN(data->trim);
1626 MEM_freeN(data->ts);
1628 op->customdata = NULL;
1630 ED_area_headerprint(sa, NULL);
1632 WM_event_add_notifier(C, NC_SCENE | ND_SEQUENCER, scene);
1633 return OPERATOR_FINISHED;
1640 Editing *ed = BKE_sequencer_editing_get(scene, false);
1642 for (i = 0; i < data->num_seq; i++) {
1643 transseq_restore(data->ts + i, data->seq_array[i]);
1646 for (i = 0; i < data->num_seq; i++) {
1647 Sequence *seq = data->seq_array[i];
1648 BKE_sequence_reload_new_file(scene, seq, false);
1649 BKE_sequence_calc(scene, seq);
1652 ED_region_draw_cb_exit(ar->type, data->draw_handle);
1654 MEM_freeN(data->seq_array);
1655 MEM_freeN(data->ts);
1656 MEM_freeN(data->trim);
1658 op->customdata = NULL;
1660 WM_event_add_notifier(C, NC_SCENE | ND_SEQUENCER, scene);
1662 BKE_sequencer_free_imbuf(scene, &ed->seqbase, false);
1665 ED_area_headerprint(sa, NULL);
1668 return OPERATOR_CANCELLED;
1673 if (!has_numInput) {
1674 if (event->val == KM_PRESS) {
1676 data->slow_offset = event->mval[0];
1678 else if (event->val == KM_RELEASE) {
1689 /* Modal numinput inactive, try to handle numeric inputs last... */
1690 if (!handled && event->val == KM_PRESS && handleNumInput(C, &data->num_input, event)) {
1692 applyNumInput(&data->num_input, &offset);
1694 sequencer_slip_update_header(scene, sa, data, (int)offset);
1696 RNA_int_set(op->ptr, "offset", offset);
1698 if (sequencer_slip_recursively(scene, data, offset)) {
1699 WM_event_add_notifier(C, NC_SCENE | ND_SEQUENCER, scene);
1703 return OPERATOR_RUNNING_MODAL;
1706 void SEQUENCER_OT_slip(struct wmOperatorType *ot)
1709 ot->name = "Trim Strips";
1710 ot->idname = "SEQUENCER_OT_slip";
1711 ot->description = "Trim the contents of the active strip";
1714 ot->invoke = sequencer_slip_invoke;
1715 ot->modal = sequencer_slip_modal;
1716 ot->exec = sequencer_slip_exec;
1717 ot->poll = sequencer_edit_poll;
1720 ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
1722 RNA_def_int(ot->srna, "offset", 0, INT32_MIN, INT32_MAX, "Offset", "Offset to the data of the strip",
1723 INT32_MIN, INT32_MAX);
1727 static int sequencer_mute_exec(bContext *C, wmOperator *op)
1729 Scene *scene = CTX_data_scene(C);
1730 Editing *ed = BKE_sequencer_editing_get(scene, false);
1734 selected = !RNA_boolean_get(op->ptr, "unselected");
1736 for (seq = ed->seqbasep->first; seq; seq = seq->next) {
1737 if ((seq->flag & SEQ_LOCK) == 0) {
1738 if (selected) { /* mute unselected */
1739 if (seq->flag & SELECT) {
1740 seq->flag |= SEQ_MUTE;
1741 BKE_sequence_invalidate_dependent(scene, seq);
1745 if ((seq->flag & SELECT) == 0) {
1746 seq->flag |= SEQ_MUTE;
1747 BKE_sequence_invalidate_dependent(scene, seq);
1753 BKE_sequencer_update_muting(ed);
1754 WM_event_add_notifier(C, NC_SCENE | ND_SEQUENCER, scene);
1756 return OPERATOR_FINISHED;
1759 void SEQUENCER_OT_mute(struct wmOperatorType *ot)
1762 ot->name = "Mute Strips";
1763 ot->idname = "SEQUENCER_OT_mute";
1764 ot->description = "Mute (un)selected strips";
1767 ot->exec = sequencer_mute_exec;
1768 ot->poll = sequencer_edit_poll;
1771 ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
1773 RNA_def_boolean(ot->srna, "unselected", 0, "Unselected", "Mute unselected rather than selected strips");
1777 /* unmute operator */
1778 static int sequencer_unmute_exec(bContext *C, wmOperator *op)
1780 Scene *scene = CTX_data_scene(C);
1781 Editing *ed = BKE_sequencer_editing_get(scene, false);
1785 selected = !RNA_boolean_get(op->ptr, "unselected");
1787 for (seq = ed->seqbasep->first; seq; seq = seq->next) {
1788 if ((seq->flag & SEQ_LOCK) == 0) {
1789 if (selected) { /* unmute unselected */
1790 if (seq->flag & SELECT) {
1791 seq->flag &= ~SEQ_MUTE;
1792 BKE_sequence_invalidate_dependent(scene, seq);
1796 if ((seq->flag & SELECT) == 0) {
1797 seq->flag &= ~SEQ_MUTE;
1798 BKE_sequence_invalidate_dependent(scene, seq);
1804 BKE_sequencer_update_muting(ed);
1805 WM_event_add_notifier(C, NC_SCENE | ND_SEQUENCER, scene);
1807 return OPERATOR_FINISHED;
1810 void SEQUENCER_OT_unmute(struct wmOperatorType *ot)
1813 ot->name = "Un-Mute Strips";
1814 ot->idname = "SEQUENCER_OT_unmute";
1815 ot->description = "Unmute (un)selected strips";
1818 ot->exec = sequencer_unmute_exec;
1819 ot->poll = sequencer_edit_poll;
1822 ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
1824 RNA_def_boolean(ot->srna, "unselected", 0, "Unselected", "Unmute unselected rather than selected strips");
1829 static int sequencer_lock_exec(bContext *C, wmOperator *UNUSED(op))
1831 Scene *scene = CTX_data_scene(C);
1832 Editing *ed = BKE_sequencer_editing_get(scene, false);
1835 for (seq = ed->seqbasep->first; seq; seq = seq->next) {
1836 if (seq->flag & SELECT) {
1837 seq->flag |= SEQ_LOCK;
1841 WM_event_add_notifier(C, NC_SCENE | ND_SEQUENCER, scene);
1843 return OPERATOR_FINISHED;
1846 void SEQUENCER_OT_lock(struct wmOperatorType *ot)
1849 ot->name = "Lock Strips";
1850 ot->idname = "SEQUENCER_OT_lock";
1851 ot->description = "Lock the active strip so that it can't be transformed";
1854 ot->exec = sequencer_lock_exec;
1855 ot->poll = sequencer_edit_poll;
1858 ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
1861 /* unlock operator */
1862 static int sequencer_unlock_exec(bContext *C, wmOperator *UNUSED(op))
1864 Scene *scene = CTX_data_scene(C);
1865 Editing *ed = BKE_sequencer_editing_get(scene, false);
1868 for (seq = ed->seqbasep->first; seq; seq = seq->next) {
1869 if (seq->flag & SELECT) {
1870 seq->flag &= ~SEQ_LOCK;
1874 WM_event_add_notifier(C, NC_SCENE | ND_SEQUENCER, scene);
1876 return OPERATOR_FINISHED;
1879 void SEQUENCER_OT_unlock(struct wmOperatorType *ot)
1882 ot->name = "UnLock Strips";
1883 ot->idname = "SEQUENCER_OT_unlock";
1884 ot->description = "Unlock the active strip so that it can't be transformed";
1887 ot->exec = sequencer_unlock_exec;
1888 ot->poll = sequencer_edit_poll;
1891 ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
1894 /* reload operator */
1895 static int sequencer_reload_exec(bContext *C, wmOperator *op)
1897 Scene *scene = CTX_data_scene(C);
1898 Editing *ed = BKE_sequencer_editing_get(scene, false);
1900 const bool adjust_length = RNA_boolean_get(op->ptr, "adjust_length");
1902 for (seq = ed->seqbasep->first; seq; seq = seq->next) {
1903 if (seq->flag & SELECT) {
1904 BKE_sequencer_update_changed_seq_and_deps(scene, seq, 0, 1);
1905 BKE_sequence_reload_new_file(scene, seq, !adjust_length);
1907 if (adjust_length) {
1908 if (BKE_sequence_test_overlap(ed->seqbasep, seq))
1909 BKE_sequence_base_shuffle(ed->seqbasep, seq, scene);
1914 WM_event_add_notifier(C, NC_SCENE | ND_SEQUENCER, scene);
1916 return OPERATOR_FINISHED;
1919 void SEQUENCER_OT_reload(struct wmOperatorType *ot)
1924 ot->name = "Reload Strips";
1925 ot->idname = "SEQUENCER_OT_reload";
1926 ot->description = "Reload strips in the sequencer";
1929 ot->exec = sequencer_reload_exec;
1930 ot->poll = sequencer_edit_poll;
1933 ot->flag = OPTYPE_REGISTER; /* no undo, the data changed is stored outside 'main' */
1935 prop = RNA_def_boolean(ot->srna, "adjust_length", 0, "Adjust Length",
1936 "Adjust length of strips to their data length");
1937 RNA_def_property_flag(prop, PROP_SKIP_SAVE);
1940 /* reload operator */
1941 static bool sequencer_refresh_all_poll(bContext *C)
1943 if (G.is_rendering) {
1946 return sequencer_edit_poll(C);
1949 static int sequencer_refresh_all_exec(bContext *C, wmOperator *UNUSED(op))
1951 Scene *scene = CTX_data_scene(C);
1952 Editing *ed = BKE_sequencer_editing_get(scene, false);
1954 BKE_sequencer_free_imbuf(scene, &ed->seqbase, false);
1956 WM_event_add_notifier(C, NC_SCENE | ND_SEQUENCER, scene);
1958 return OPERATOR_FINISHED;
1961 void SEQUENCER_OT_refresh_all(struct wmOperatorType *ot)
1964 ot->name = "Refresh Sequencer";
1965 ot->idname = "SEQUENCER_OT_refresh_all";
1966 ot->description = "Refresh the sequencer editor";
1969 ot->exec = sequencer_refresh_all_exec;
1970 ot->poll = sequencer_refresh_all_poll;
1973 static int sequencer_reassign_inputs_exec(bContext *C, wmOperator *op)
1975 Scene *scene = CTX_data_scene(C);
1976 Sequence *seq1, *seq2, *seq3, *last_seq = BKE_sequencer_active_get(scene);
1977 const char *error_msg;
1979 if (!seq_effect_find_selected(scene, last_seq, last_seq->type, &seq1, &seq2, &seq3, &error_msg)) {
1980 BKE_report(op->reports, RPT_ERROR, error_msg);
1981 return OPERATOR_CANCELLED;
1983 /* see reassigning would create a cycle */
1984 if (seq_is_predecessor(seq1, last_seq) ||
1985 seq_is_predecessor(seq2, last_seq) ||
1986 seq_is_predecessor(seq3, last_seq))
1988 BKE_report(op->reports, RPT_ERROR, "Cannot reassign inputs: no cycles allowed");
1989 return OPERATOR_CANCELLED;
1992 last_seq->seq1 = seq1;
1993 last_seq->seq2 = seq2;
1994 last_seq->seq3 = seq3;
1996 BKE_sequencer_update_changed_seq_and_deps(scene, last_seq, 1, 1);
1998 WM_event_add_notifier(C, NC_SCENE | ND_SEQUENCER, scene);
2000 return OPERATOR_FINISHED;
2003 static bool sequencer_effect_poll(bContext *C)
2005 Scene *scene = CTX_data_scene(C);
2006 Editing *ed = BKE_sequencer_editing_get(scene, false);
2009 Sequence *last_seq = BKE_sequencer_active_get(scene);
2010 if (last_seq && (last_seq->type & SEQ_TYPE_EFFECT)) {
2018 void SEQUENCER_OT_reassign_inputs(struct wmOperatorType *ot)
2021 ot->name = "Reassign Inputs";
2022 ot->idname = "SEQUENCER_OT_reassign_inputs";
2023 ot->description = "Reassign the inputs for the effect strip";
2026 ot->exec = sequencer_reassign_inputs_exec;
2027 ot->poll = sequencer_effect_poll;
2030 ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
2034 static int sequencer_swap_inputs_exec(bContext *C, wmOperator *op)
2036 Scene *scene = CTX_data_scene(C);
2037 Sequence *seq, *last_seq = BKE_sequencer_active_get(scene);
2039 if (last_seq->seq1 == NULL || last_seq->seq2 == NULL) {
2040 BKE_report(op->reports, RPT_ERROR, "No valid inputs to swap");
2041 return OPERATOR_CANCELLED;
2044 seq = last_seq->seq1;
2045 last_seq->seq1 = last_seq->seq2;
2046 last_seq->seq2 = seq;
2048 BKE_sequencer_update_changed_seq_and_deps(scene, last_seq, 1, 1);
2050 WM_event_add_notifier(C, NC_SCENE | ND_SEQUENCER, scene);
2052 return OPERATOR_FINISHED;
2054 void SEQUENCER_OT_swap_inputs(struct wmOperatorType *ot)
2057 ot->name = "Swap Inputs";
2058 ot->idname = "SEQUENCER_OT_swap_inputs";
2059 ot->description = "Swap the first two inputs for the effect strip";
2062 ot->exec = sequencer_swap_inputs_exec;
2063 ot->poll = sequencer_effect_poll;
2066 ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
2071 static const EnumPropertyItem prop_cut_types[] = {
2072 {SEQ_CUT_SOFT, "SOFT", 0, "Soft", ""},
2073 {SEQ_CUT_HARD, "HARD", 0, "Hard", ""},
2074 {0, NULL, 0, NULL, NULL}
2077 static int sequencer_cut_exec(bContext *C, wmOperator *op)
2079 Scene *scene = CTX_data_scene(C);
2080 Editing *ed = BKE_sequencer_editing_get(scene, false);
2081 int cut_side, cut_hard, cut_frame;
2085 cut_frame = RNA_int_get(op->ptr, "frame");
2086 cut_hard = RNA_enum_get(op->ptr, "type");
2087 cut_side = RNA_enum_get(op->ptr, "side");
2089 if (cut_hard == SEQ_CUT_HARD) {
2090 changed = cut_seq_list(scene, ed->seqbasep, cut_frame, cut_seq_hard);
2093 changed = cut_seq_list(scene, ed->seqbasep, cut_frame, cut_seq_soft);
2096 if (changed) { /* got new strips ? */
2099 if (cut_side != SEQ_SIDE_BOTH) {
2100 SEQP_BEGIN (ed, seq)
2102 if (cut_side == SEQ_SIDE_LEFT) {
2103 if (seq->startdisp >= cut_frame) {
2104 seq->flag &= ~SEQ_ALLSEL;
2108 if (seq->enddisp <= cut_frame) {
2109 seq->flag &= ~SEQ_ALLSEL;
2116 SEQP_BEGIN (ed, seq)
2118 BKE_sequence_base_unique_name_recursive(&ed->seqbase, seq);
2119 if (seq->seq1 || seq->seq2 || seq->seq3) {
2120 BKE_sequence_calc(scene, seq);
2126 BKE_sequencer_sort(scene);
2130 WM_event_add_notifier(C, NC_SCENE | ND_SEQUENCER, scene);
2131 return OPERATOR_FINISHED;
2134 return OPERATOR_CANCELLED;
2139 static int sequencer_cut_invoke(bContext *C, wmOperator *op, const wmEvent *event)
2141 Scene *scene = CTX_data_scene(C);
2142 View2D *v2d = UI_view2d_fromcontext(C);
2144 int cut_side = RNA_enum_get(op->ptr, "side");
2145 int cut_frame = CFRA;
2147 if (cut_side == SEQ_SIDE_MOUSE) {
2148 if (ED_operator_sequencer_active(C) && v2d) {
2149 cut_side = mouse_frame_side(v2d, event->mval[0], cut_frame);
2152 cut_side = SEQ_SIDE_BOTH;
2155 RNA_int_set(op->ptr, "frame", cut_frame);
2156 RNA_enum_set(op->ptr, "side", cut_side);
2157 /*RNA_enum_set(op->ptr, "type", cut_hard); */ /*This type is set from the key shortcut */
2158 return sequencer_cut_exec(C, op);
2162 void SEQUENCER_OT_cut(struct wmOperatorType *ot)
2165 ot->name = "Cut Strips";
2166 ot->idname = "SEQUENCER_OT_cut";
2167 ot->description = "Cut the selected strips";
2170 ot->invoke = sequencer_cut_invoke;
2171 ot->exec = sequencer_cut_exec;
2172 ot->poll = sequencer_edit_poll;
2175 ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
2178 RNA_def_int(ot->srna, "frame", 0, INT_MIN, INT_MAX, "Frame", "Frame where selected strips will be cut", INT_MIN, INT_MAX);
2179 RNA_def_enum(ot->srna, "type", prop_cut_types, SEQ_CUT_SOFT, "Type", "The type of cut operation to perform on strips");
2180 prop = RNA_def_enum(ot->srna, "side", prop_side_types, SEQ_SIDE_MOUSE, "Side", "The side that remains selected after cutting");
2181 RNA_def_property_flag(prop, PROP_SKIP_SAVE);
2184 #undef SEQ_SIDE_MOUSE
2186 /* duplicate operator */
2187 static int apply_unique_name_cb(Sequence *seq, void *arg_pt)
2189 Scene *scene = (Scene *)arg_pt;
2190 char name[sizeof(seq->name) - 2];
2192 BLI_strncpy_utf8(name, seq->name + 2, sizeof(name));
2193 BKE_sequence_base_unique_name_recursive(&scene->ed->seqbase, seq);
2194 BKE_sequencer_dupe_animdata(scene, name, seq->name + 2);
2199 static int sequencer_add_duplicate_exec(bContext *C, wmOperator *UNUSED(op))
2201 Scene *scene = CTX_data_scene(C);
2202 Editing *ed = BKE_sequencer_editing_get(scene, false);
2204 ListBase nseqbase = {NULL, NULL};
2207 return OPERATOR_CANCELLED;
2209 BKE_sequence_base_dupli_recursive(scene, scene, &nseqbase, ed->seqbasep, SEQ_DUPE_CONTEXT, 0);
2211 if (nseqbase.first) {
2212 Sequence *seq = nseqbase.first;
2213 /* rely on the nseqbase list being added at the end */
2214 BLI_movelisttolist(ed->seqbasep, &nseqbase);
2216 for (; seq; seq = seq->next)
2217 BKE_sequencer_recursive_apply(seq, apply_unique_name_cb, scene);
2219 WM_event_add_notifier(C, NC_SCENE | ND_SEQUENCER, scene);
2220 return OPERATOR_FINISHED;
2223 return OPERATOR_CANCELLED;
2226 void SEQUENCER_OT_duplicate(wmOperatorType *ot)
2229 ot->name = "Duplicate Strips";
2230 ot->idname = "SEQUENCER_OT_duplicate";
2231 ot->description = "Duplicate the selected strips";
2234 ot->exec = sequencer_add_duplicate_exec;
2235 ot->poll = ED_operator_sequencer_active;
2238 ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
2240 /* to give to transform */
2241 RNA_def_enum(ot->srna, "mode", rna_enum_transform_mode_types, TFM_TRANSLATION, "Mode", "");
2244 /* delete operator */
2245 static int sequencer_delete_exec(bContext *C, wmOperator *UNUSED(op))
2247 Scene *scene = CTX_data_scene(C);
2248 Editing *ed = BKE_sequencer_editing_get(scene, false);
2251 bool nothing_selected = true;
2253 seq = BKE_sequencer_active_get(scene);
2254 if (seq && seq->flag & SELECT) { /* avoid a loop since this is likely to be selected */
2255 nothing_selected = false;
2258 for (seq = ed->seqbasep->first; seq; seq = seq->next) {
2259 if (seq->flag & SELECT) {
2260 nothing_selected = false;
2266 if (nothing_selected) {
2267 return OPERATOR_FINISHED;
2270 /* for effects and modifiers, try to find a replacement input */
2271 for (seq = ed->seqbasep->first; seq; seq = seq->next) {
2272 if (!(seq->flag & SELECT)) {
2273 if ((seq->type & SEQ_TYPE_EFFECT)) {
2274 del_seq_find_replace_recurs(scene, seq);
2278 del_seq_clear_modifiers_recurs(scene, seq);
2282 /* delete all selected strips */
2283 recurs_del_seq_flag(scene, ed->seqbasep, SELECT, 0);
2285 /* updates lengths etc */
2286 seq = ed->seqbasep->first;
2288 BKE_sequence_calc(scene, seq);
2292 /* free parent metas */
2293 ms = ed->metastack.last;
2295 BKE_sequence_calc(scene, ms->parseq);
2299 WM_event_add_notifier(C, NC_SCENE | ND_SEQUENCER, scene);
2301 return OPERATOR_FINISHED;
2304 static int sequencer_delete_invoke(bContext *C, wmOperator *op, const wmEvent *event)
2306 ARegion *ar = CTX_wm_region(C);
2308 if (ar->regiontype == RGN_TYPE_WINDOW) {
2309 /* bounding box of 30 pixels is used for markers shortcuts,
2310 * prevent conflict with markers shortcuts here
2312 if (event->mval[1] <= 30)
2313 return OPERATOR_PASS_THROUGH;
2316 return WM_operator_confirm(C, op, event);
2319 void SEQUENCER_OT_delete(wmOperatorType *ot)
2323 ot->name = "Erase Strips";
2324 ot->idname = "SEQUENCER_OT_delete";
2325 ot->description = "Erase selected strips from the sequencer";
2328 ot->invoke = sequencer_delete_invoke;
2329 ot->exec = sequencer_delete_exec;
2330 ot->poll = sequencer_edit_poll;
2333 ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
2337 /* offset clear operator */
2338 static int sequencer_offset_clear_exec(bContext *C, wmOperator *UNUSED(op))
2340 Scene *scene = CTX_data_scene(C);
2341 Editing *ed = BKE_sequencer_editing_get(scene, false);
2344 /* for effects, try to find a replacement input */
2345 for (seq = ed->seqbasep->first; seq; seq = seq->next) {
2346 if ((seq->type & SEQ_TYPE_EFFECT) == 0 && (seq->flag & SELECT)) {
2347 seq->startofs = seq->endofs = seq->startstill = seq->endstill = 0;
2351 /* updates lengths etc */
2352 seq = ed->seqbasep->first;
2354 BKE_sequence_calc(scene, seq);
2358 for (seq = ed->seqbasep->first; seq; seq = seq->next) {
2359 if ((seq->type & SEQ_TYPE_EFFECT) == 0 && (seq->flag & SELECT)) {
2360 if (BKE_sequence_test_overlap(ed->seqbasep, seq)) {
2361 BKE_sequence_base_shuffle(ed->seqbasep, seq, scene);
2366 WM_event_add_notifier(C, NC_SCENE | ND_SEQUENCER, scene);
2368 return OPERATOR_FINISHED;
2372 void SEQUENCER_OT_offset_clear(wmOperatorType *ot)
2376 ot->name = "Clear Strip Offset";
2377 ot->idname = "SEQUENCER_OT_offset_clear";
2378 ot->description = "Clear strip offsets from the start and end frames";
2381 ot->exec = sequencer_offset_clear_exec;
2382 ot->poll = sequencer_edit_poll;
2385 ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
2389 /* separate_images operator */
2390 static int sequencer_separate_images_exec(bContext *C, wmOperator *op)
2392 Scene *scene = CTX_data_scene(C);
2393 Editing *ed = BKE_sequencer_editing_get(scene, false);
2395 Sequence *seq, *seq_new;
2397 StripElem *se, *se_new;
2398 int start_ofs, cfra, frame_end;
2399 int step = RNA_int_get(op->ptr, "length");
2401 seq = ed->seqbasep->first; /* poll checks this is valid */
2404 if ((seq->flag & SELECT) && (seq->type == SEQ_TYPE_IMAGE) && (seq->len > 1)) {
2407 /* remove seq so overlap tests don't conflict,
2408 * see seq_free_sequence below for the real free'ing */
2409 BLI_remlink(ed->seqbasep, seq);
2410 /* if (seq->ipo) id_us_min(&seq->ipo->id); */
2411 /* XXX, remove fcurve and assign to split image strips */
2413 start_ofs = cfra = BKE_sequence_tx_get_final_left(seq, false);
2414 frame_end = BKE_sequence_tx_get_final_right(seq, false);
2416 while (cfra < frame_end) {
2418 se = BKE_sequencer_give_stripelem(seq, cfra);
2420 seq_new = BKE_sequence_dupli_recursive(scene, scene, seq, SEQ_DUPE_UNIQUE_NAME);
2421 BLI_addtail(ed->seqbasep, seq_new);
2423 seq_new->start = start_ofs;
2424 seq_new->type = SEQ_TYPE_IMAGE;
2426 seq_new->endstill = step - 1;
2429 strip_new = seq_new->strip;
2432 /* new stripdata (only one element now!) */
2433 /* Note this assume all elements (images) have the same dimension, since we only copy the name here. */
2434 se_new = MEM_reallocN(strip_new->stripdata, sizeof(*se_new));
2435 BLI_strncpy(se_new->name, se->name, sizeof(se_new->name));
2436 strip_new->stripdata = se_new;
2438 BKE_sequence_calc(scene, seq_new);
2441 seq_new->flag &= ~SEQ_OVERLAP;
2442 if (BKE_sequence_test_overlap(ed->seqbasep, seq_new)) {
2443 BKE_sequence_base_shuffle(ed->seqbasep, seq_new, scene);
2447 /* XXX, COPY FCURVES */
2453 seq_next = seq->next;
2454 BKE_sequence_free(scene, seq);
2463 BKE_sequencer_sort(scene);
2465 WM_event_add_notifier(C, NC_SCENE | ND_SEQUENCER, scene);
2467 return OPERATOR_FINISHED;
2471 void SEQUENCER_OT_images_separate(wmOperatorType *ot)
2474 ot->name = "Separate Images";
2475 ot->idname = "SEQUENCER_OT_images_separate";
2476 ot->description = "On image sequence strips, it returns a strip for each image";
2479 ot->exec = sequencer_separate_images_exec;
2480 ot->invoke = WM_operator_props_popup_confirm;
2481 ot->poll = sequencer_edit_poll;
2484 ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
2486 RNA_def_int(ot->srna, "length", 1, 1, INT_MAX, "Length", "Length of each frame", 1, 1000);
2490 /* META Operators */
2492 /* separate_meta_toggle operator */
2493 static int sequencer_meta_toggle_exec(bContext *C, wmOperator *UNUSED(op))
2495 Scene *scene = CTX_data_scene(C);
2496 Editing *ed = BKE_sequencer_editing_get(scene, false);
2497 Sequence *last_seq = BKE_sequencer_active_get(scene);
2500 if (last_seq && last_seq->type == SEQ_TYPE_META && last_seq->flag & SELECT) {
2501 /* Enter Metastrip */
2502 ms = MEM_mallocN(sizeof(MetaStack), "metastack");
2503 BLI_addtail(&ed->metastack, ms);
2504 ms->parseq = last_seq;
2505 ms->oldbasep = ed->seqbasep;
2506 copy_v2_v2_int(ms->disp_range, &ms->parseq->startdisp);
2508 ed->seqbasep = &last_seq->seqbase;
2510 BKE_sequencer_active_set(scene, NULL);
2514 /* Exit Metastrip (if possible) */
2518 if (BLI_listbase_is_empty(&ed->metastack))
2519 return OPERATOR_CANCELLED;
2521 ms = ed->metastack.last;
2522 BLI_remlink(&ed->metastack, ms);
2524 ed->seqbasep = ms->oldbasep;
2526 /* for old files, update from meta */
2527 if (ms->disp_range[0] == ms->disp_range[1]) {
2528 copy_v2_v2_int(ms->disp_range, &ms->parseq->startdisp);
2531 /* recalc all: the meta can have effects connected to it */
2532 for (seq = ed->seqbasep->first; seq; seq = seq->next)
2533 BKE_sequence_calc(scene, seq);
2535 /* 2.73+, keeping endpoings is important!
2536 * moving them around means you can't usefully use metas in a complex edit */
2538 BKE_sequence_tx_set_final_left(ms->parseq, ms->disp_range[0]);
2539 BKE_sequence_tx_set_final_right(ms->parseq, ms->disp_range[1]);
2540 BKE_sequence_single_fix(ms->parseq);
2541 BKE_sequence_calc(scene, ms->parseq);
2543 if (BKE_sequence_test_overlap(ed->seqbasep, ms->parseq))
2544 BKE_sequence_base_shuffle(ed->seqbasep, ms->parseq, scene);
2547 BKE_sequencer_active_set(scene, ms->parseq);
2549 ms->parseq->flag |= SELECT;
2550 recurs_sel_seq(ms->parseq);
2556 BKE_sequencer_update_muting(ed);
2557 WM_event_add_notifier(C, NC_SCENE | ND_SEQUENCER, scene);
2559 return OPERATOR_FINISHED;
2562 void SEQUENCER_OT_meta_toggle(wmOperatorType *ot)
2565 ot->name = "Toggle Meta Strip";
2566 ot->idname = "SEQUENCER_OT_meta_toggle";
2567 ot->description = "Toggle a metastrip (to edit enclosed strips)";
2570 ot->exec = sequencer_meta_toggle_exec;
2571 ot->poll = sequencer_edit_poll;
2574 ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
2578 /* separate_meta_make operator */
2579 static int sequencer_meta_make_exec(bContext *C, wmOperator *op)
2581 Scene *scene = CTX_data_scene(C);
2582 Editing *ed = BKE_sequencer_editing_get(scene, false);
2584 Sequence *seq, *seqm, *next, *last_seq = BKE_sequencer_active_get(scene);
2585 int channel_max = 1;
2587 if (BKE_sequence_base_isolated_sel_check(ed->seqbasep) == false) {
2588 BKE_report(op->reports, RPT_ERROR, "Please select all related strips");
2589 return OPERATOR_CANCELLED;
2592 /* remove all selected from main list, and put in meta */
2594 seqm = BKE_sequence_alloc(ed->seqbasep, 1, 1); /* channel number set later */
2595 strcpy(seqm->name + 2, "MetaStrip");
2596 seqm->type = SEQ_TYPE_META;
2597 seqm->flag = SELECT;
2599 seq = ed->seqbasep->first;
2602 if (seq != seqm && (seq->flag & SELECT)) {
2603 BKE_sequence_invalidate_cache(scene, seq);
2604 channel_max = max_ii(seq->machine, channel_max);
2605 BLI_remlink(ed->seqbasep, seq);
2606 BLI_addtail(&seqm->seqbase, seq);
2610 seqm->machine = last_seq ? last_seq->machine : channel_max;
2611 BKE_sequence_calc(scene, seqm);
2613 seqm->strip = MEM_callocN(sizeof(Strip), "metastrip");
2614 seqm->strip->us = 1;
2616 BKE_sequencer_active_set(scene, seqm);
2618 if (BKE_sequence_test_overlap(ed->seqbasep, seqm) ) BKE_sequence_base_shuffle(ed->seqbasep, seqm, scene);
2620 BKE_sequencer_update_muting(ed);
2622 BKE_sequence_base_unique_name_recursive(&scene->ed->seqbase, seqm);
2624 WM_event_add_notifier(C, NC_SCENE | ND_SEQUENCER, scene);
2626 return OPERATOR_FINISHED;
2629 void SEQUENCER_OT_meta_make(wmOperatorType *ot)
2632 ot->name = "Make Meta Strip";
2633 ot->idname = "SEQUENCER_OT_meta_make";
2634 ot->description = "Group selected strips into a metastrip";
2637 ot->exec = sequencer_meta_make_exec;
2638 ot->poll = sequencer_edit_poll;
2641 ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
2645 static int seq_depends_on_meta(Sequence *seq, Sequence *seqm)
2647 if (seq == seqm) return 1;
2648 else if (seq->seq1 && seq_depends_on_meta(seq->seq1, seqm)) return 1;
2649 else if (seq->seq2 && seq_depends_on_meta(seq->seq2, seqm)) return 1;
2650 else if (seq->seq3 && seq_depends_on_meta(seq->seq3, seqm)) return 1;
2654 /* separate_meta_make operator */
2655 static int sequencer_meta_separate_exec(bContext *C, wmOperator *UNUSED(op))
2657 Scene *scene = CTX_data_scene(C);
2658 Editing *ed = BKE_sequencer_editing_get(scene, false);
2660 Sequence *seq, *last_seq = BKE_sequencer_active_get(scene); /* last_seq checks (ed == NULL) */
2662 if (last_seq == NULL || last_seq->type != SEQ_TYPE_META)
2663 return OPERATOR_CANCELLED;
2665 for (seq = last_seq->seqbase.first; seq != NULL; seq = seq->next) {
2666 BKE_sequence_invalidate_cache(scene, seq);
2669 BLI_movelisttolist(ed->seqbasep, &last_seq->seqbase);
2671 BLI_listbase_clear(&last_seq->seqbase);
2673 BLI_remlink(ed->seqbasep, last_seq);
2674 BKE_sequence_free(scene, last_seq);
2676 /* emtpy meta strip, delete all effects depending on it */
2677 for (seq = ed->seqbasep->first; seq; seq = seq->next)
2678 if ((seq->type & SEQ_TYPE_EFFECT) && seq_depends_on_meta(seq, last_seq))
2679 seq->flag |= SEQ_FLAG_DELETE;
2681 recurs_del_seq_flag(scene, ed->seqbasep, SEQ_FLAG_DELETE, 0);
2683 /* test for effects and overlap
2684 * don't use SEQP_BEGIN since that would be recursive */
2685 for (seq = ed->seqbasep->first; seq; seq = seq->next) {
2686 if (seq->flag & SELECT) {
2687 seq->flag &= ~SEQ_OVERLAP;
2688 if (BKE_sequence_test_overlap(ed->seqbasep, seq)) {
2689 BKE_sequence_base_shuffle(ed->seqbasep, seq, scene);
2694 BKE_sequencer_sort(scene);
2695 BKE_sequencer_update_muting(ed);
2697 WM_event_add_notifier(C, NC_SCENE | ND_SEQUENCER, scene);
2699 return OPERATOR_FINISHED;
2702 void SEQUENCER_OT_meta_separate(wmOperatorType *ot)
2705 ot->name = "UnMeta Strip";
2706 ot->idname = "SEQUENCER_OT_meta_separate";
2707 ot->description = "Put the contents of a metastrip back in the sequencer";
2710 ot->exec = sequencer_meta_separate_exec;
2711 ot->poll = sequencer_edit_poll;
2714 ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
2717 /* view_all operator */
2718 static int sequencer_view_all_exec(bContext *C, wmOperator *op)
2720 ARegion *ar = CTX_wm_region(C);
2721 View2D *v2d = UI_view2d_fromcontext(C);
2722 const int smooth_viewtx = WM_operator_smooth_viewtx_get(op);
2724 UI_view2d_smooth_view(C, ar, &v2d->tot, smooth_viewtx);
2725 return OPERATOR_FINISHED;
2728 void SEQUENCER_OT_view_all(wmOperatorType *ot)
2731 ot->name = "View All";
2732 ot->idname = "SEQUENCER_OT_view_all";
2733 ot->description = "View all the strips in the sequencer";
2736 ot->exec = sequencer_view_all_exec;
2737 ot->poll = ED_operator_sequencer_active;
2740 ot->flag = OPTYPE_REGISTER;
2743 static int sequencer_view_frame_exec(bContext *C, wmOperator *op)
2745 const int smooth_viewtx = WM_operator_smooth_viewtx_get(op);
2746 ANIM_center_frame(C, smooth_viewtx);
2748 return OPERATOR_FINISHED;
2751 void SEQUENCER_OT_view_frame(wmOperatorType *ot)
2754 ot->name = "View Frame";
2755 ot->idname = "SEQUENCER_OT_view_frame";
2756 ot->description = "Reset viewable area to show range around current frame";
2759 ot->exec = sequencer_view_frame_exec;
2760 ot->poll = ED_operator_sequencer_active;
2763 ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
2766 /* view_all operator */
2767 static int sequencer_view_all_preview_exec(bContext *C, wmOperator *UNUSED(op))
2769 bScreen *sc = CTX_wm_screen(C);
2770 ScrArea *area = CTX_wm_area(C);
2772 ARegion *ar = CTX_wm_region(C);
2773 SpaceSeq *sseq = area->spacedata.first;
2774 Scene *scene = CTX_data_scene(C);
2776 View2D *v2d = UI_view2d_fromcontext(C);
2778 v2d->cur = v2d->tot;
2779 UI_view2d_curRect_validate(v2d);
2780 UI_view2d_sync(sc, area, v2d, V2D_LOCK_COPY);
2783 /* Like zooming on an image view */
2785 int width, height, imgwidth, imgheight;
2790 seq_reset_imageofs(sseq);
2792 imgwidth = (scene->r.size * scene->r.xsch) / 100;
2793 imgheight = (scene->r.size * scene->r.ysch) / 100;
2795 /* Apply aspect, dosnt need to be that accurate */
2796 imgwidth = (int)(imgwidth * (scene->r.xasp / scene->r.yasp));
2798 if (((imgwidth >= width) || (imgheight >= height)) &&
2799 ((width > 0) && (height > 0)))
2801 /* Find the zoom value that will fit the image in the image space */
2802 zoomX = ((float)width) / ((float)imgwidth);
2803 zoomY = ((float)height) / ((float)imgheight);
2804 sseq->zoom = (zoomX < zoomY) ? zoomX : zoomY;
2806 sseq->zoom = 1.0f / power_of_2(1 / min_ff(zoomX, zoomY));
2813 ED_area_tag_redraw(CTX_wm_area(C));
2814 return OPERATOR_FINISHED;
2817 void SEQUENCER_OT_view_all_preview(wmOperatorType *ot)
2820 ot->name = "View All";
2821 ot->idname = "SEQUENCER_OT_view_all_preview";
2822 ot->description = "Zoom preview to fit in the area";
2825 ot->exec = sequencer_view_all_preview_exec;
2826 ot->poll = ED_operator_sequencer_active;
2829 ot->flag = OPTYPE_REGISTER;
2833 static int sequencer_view_zoom_ratio_exec(bContext *C, wmOperator *op)
2835 RenderData *rd = &CTX_data_scene(C)->r;
2836 View2D *v2d = UI_view2d_fromcontext(C);
2838 float ratio = RNA_float_get(op->ptr, "ratio");
2840 float winx = (int)(rd->size * rd->xsch) / 100;
2841 float winy = (int)(rd->size * rd->ysch) / 100;
2843 float facx = BLI_rcti_size_x(&v2d->mask) / winx;
2844 float facy = BLI_rcti_size_y(&v2d->mask) / winy;
2846 BLI_rctf_resize(&v2d->cur, ceilf(winx * facx / ratio + 0.5f), ceilf(winy * facy / ratio + 0.5f));
2848 ED_region_tag_redraw(CTX_wm_region(C));
2850 return OPERATOR_FINISHED;
2853 void SEQUENCER_OT_view_zoom_ratio(wmOperatorType *ot)
2856 ot->name = "Sequencer View Zoom Ratio";
2857 ot->idname = "SEQUENCER_OT_view_zoom_ratio";
2858 ot->description = "Change zoom ratio of sequencer preview";
2861 ot->exec = sequencer_view_zoom_ratio_exec;
2862 ot->poll = ED_operator_sequencer_active;
2865 RNA_def_float(ot->srna, "ratio", 1.0f, -FLT_MAX, FLT_MAX,
2866 "Ratio", "Zoom ratio, 1.0 is 1:1, higher is zoomed in, lower is zoomed out", -FLT_MAX, FLT_MAX);
2871 static const EnumPropertyItem view_type_items[] = {
2872 {SEQ_VIEW_SEQUENCE, "SEQUENCER", ICON_SEQ_SEQUENCER, "Sequencer", ""},
2873 {SEQ_VIEW_PREVIEW, "PREVIEW", ICON_SEQ_PREVIEW, "Image Preview", ""},
2874 {SEQ_VIEW_SEQUENCE_PREVIEW, "SEQUENCER_PREVIEW", ICON_SEQ_SEQUENCER, "Sequencer and Image Preview", ""},
2875 {0, NULL, 0, NULL, NULL}
2879 /* view_all operator */
2880 static int sequencer_view_toggle_exec(bContext *C, wmOperator *UNUSED(op))
2882 SpaceSeq *sseq = (SpaceSeq *)CTX_wm_space_data(C);
2885 if (sseq->view > SEQ_VIEW_SEQUENCE_PREVIEW) sseq->view = SEQ_VIEW_SEQUENCE;
2887 ED_area_tag_refresh(CTX_wm_area(C));
2889 return OPERATOR_FINISHED;
2892 void SEQUENCER_OT_view_toggle(wmOperatorType *ot)
2895 ot->name = "View Toggle";
2896 ot->idname = "SEQUENCER_OT_view_toggle";
2897 ot->description = "Toggle between sequencer views (sequence, preview, both)";
2900 ot->exec = sequencer_view_toggle_exec;
2901 ot->poll = ED_operator_sequencer_active;
2904 ot->flag = OPTYPE_REGISTER;
2908 /* view_selected operator */
2909 static int sequencer_view_selected_exec(bContext *C, wmOperator *op)
2911 Scene *scene = CTX_data_scene(C);
2912 View2D *v2d = UI_view2d_fromcontext(C);
2913 ARegion *ar = CTX_wm_region(C);
2914 Editing *ed = BKE_sequencer_editing_get(scene, false);
2915 Sequence *last_seq = BKE_sequencer_active_get(scene);
2917 rctf cur_new = v2d->cur;
2919 int xmin = MAXFRAME * 2;
2920 int xmax = -MAXFRAME * 2;
2921 int ymin = MAXSEQ + 1;
2929 return OPERATOR_CANCELLED;
2931 for (seq = ed->seqbasep->first; seq; seq = seq->next) {
2932 if ((seq->flag & SELECT) || (seq == last_seq)) {
2933 xmin = min_ii(xmin, seq->startdisp);
2934 xmax = max_ii(xmax, seq->enddisp);
2936 ymin = min_ii(ymin, seq->machine);
2937 ymax = max_ii(ymax, seq->machine);
2942 const int smooth_viewtx = WM_operator_smooth_viewtx_get(op);
2949 orig_height = BLI_rctf_size_y(&cur_new);
2951 cur_new.xmin = xmin;
2952 cur_new.xmax = xmax;
2954 cur_new.ymin = ymin;
2955 cur_new.ymax = ymax;
2957 /* only zoom out vertically */
2958 if (orig_height > BLI_rctf_size_y(&cur_new)) {
2959 ymid = BLI_rctf_cent_y(&cur_new);
2961 cur_new.ymin = ymid - (orig_height / 2);
2962 cur_new.ymax = ymid + (orig_height / 2);
2965 UI_view2d_smooth_view(C, ar, &cur_new, smooth_viewtx);
2967 return OPERATOR_FINISHED;
2970 return OPERATOR_CANCELLED;
2975 void SEQUENCER_OT_view_selected(wmOperatorType *ot)
2978 ot->name = "View Selected";
2979 ot->idname = "SEQUENCER_OT_view_selected";
2980 ot->description = "Zoom the sequencer on the selected strips";
2983 ot->exec = sequencer_view_selected_exec;
2984 ot->poll = ED_operator_sequencer_active;
2987 ot->flag = OPTYPE_REGISTER;
2990 static bool strip_jump_internal(Scene *scene,
2992 const bool do_skip_mute, const bool do_center)
2994 bool changed = false;
2996 int nfra = BKE_sequencer_find_next_prev_edit(scene, cfra, side, do_skip_mute, do_center, false);
3006 static bool sequencer_strip_jump_poll(bContext *C)
3008 /* prevent changes during render */
3012 return sequencer_edit_poll(C);
3015 /* jump frame to edit point operator */
3016 static int sequencer_strip_jump_exec(bContext *C, wmOperator *op)
3018 Scene *scene = CTX_data_scene(C);
3019 const bool next = RNA_boolean_get(op->ptr, "next");
3020 const bool center = RNA_boolean_get(op->ptr, "center");
3022 /* currently do_skip_mute is always true */
3023 if (!strip_jump_internal(scene, next ? SEQ_SIDE_RIGHT : SEQ_SIDE_LEFT, true, center)) {
3024 return OPERATOR_CANCELLED;
3027 WM_event_add_notifier(C, NC_SCENE | ND_FRAME, scene);
3029 return OPERATOR_FINISHED;
3032 void SEQUENCER_OT_strip_jump(wmOperatorType *ot)
3035 ot->name = "Jump to Strip";
3036 ot->idname = "SEQUENCER_OT_strip_jump";
3037 ot->description = "Move frame to previous edit point";
3040 ot->exec = sequencer_strip_jump_exec;
3041 ot->poll = sequencer_strip_jump_poll;
3044 ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
3047 RNA_def_boolean(ot->srna, "next", true, "Next Strip", "");
3048 RNA_def_boolean(ot->srna, "center", true, "Use strip center", "");
3051 static void swap_sequence(Scene *scene, Sequence *seqa, Sequence *seqb)
3053 int gap = seqb->startdisp - seqa->enddisp;
3057 seq_b_start = (seqb->start - seqb->startdisp) + seqa->startdisp;
3058 BKE_sequence_translate(scene, seqb, seq_b_start - seqb->start);
3059 BKE_sequence_calc(scene, seqb);
3061 seq_a_start = (seqa->start - seqa->startdisp) + seqb->enddisp + gap;
3062 BKE_sequence_translate(scene, seqa, seq_a_start - seqa->start);
3063 BKE_sequence_calc(scene, seqa);
3067 static Sequence *sequence_find_parent(Scene *scene, Sequence *child)
3069 Editing *ed = BKE_sequencer_editing_get(scene, false);
3070 Sequence *parent = NULL;
3073 if (ed == NULL) return NULL;
3075 for (seq = ed->seqbasep->first; seq; seq = seq->next) {
3076 if ((seq != child) && seq_is_parent(seq, child)) {
3086 static int sequencer_swap_exec(bContext *C, wmOperator *op)
3088 Scene *scene = CTX_data_scene(C);
3089 Editing *ed = BKE_sequencer_editing_get(scene, false);
3090 Sequence *active_seq = BKE_sequencer_active_get(scene);
3091 Sequence *seq, *iseq;
3092 int side = RNA_enum_get(op->ptr, "side");
3094 if (active_seq == NULL) return OPERATOR_CANCELLED;
3096 seq = find_next_prev_sequence(scene, active_seq, side, -1);
3100 /* disallow effect strips */
3101 if (BKE_sequence_effect_get_num_inputs(seq->type) >= 1 && (seq->effectdata || seq->seq1 || seq->seq2 || seq->seq3))
3102 return OPERATOR_CANCELLED;
3103 if ((BKE_sequence_effect_get_num_inputs(active_seq->type) >= 1) && (active_seq->effectdata || active_seq->seq1 || active_seq->seq2 || active_seq->seq3))
3104 return OPERATOR_CANCELLED;
3108 swap_sequence(scene, seq, active_seq);
3110 case SEQ_SIDE_RIGHT:
3111 swap_sequence(scene, active_seq, seq);
3115 // XXX - should be a generic function
3116 for (iseq = scene->ed->seqbasep->first; iseq; iseq = iseq->next) {
3117 if ((iseq->type & SEQ_TYPE_EFFECT) && (seq_is_parent(iseq, active_seq) || seq_is_parent(iseq, seq))) {
3118 BKE_sequence_calc(scene, iseq);
3122 /* do this in a new loop since both effects need to be calculated first */
3123 for (iseq = scene->ed->seqbasep->first; iseq; iseq = iseq->next) {
3124 if ((iseq->type & SEQ_TYPE_EFFECT) && (seq_is_parent(iseq, active_seq) || seq_is_parent(iseq, seq))) {
3125 /* this may now overlap */
3126 if (BKE_sequence_test_overlap(ed->seqbasep, iseq) ) {
3127 BKE_sequence_base_shuffle(ed->seqbasep, iseq, scene);
3134 BKE_sequencer_sort(scene);
3136 WM_event_add_notifier(C, NC_SCENE | ND_SEQUENCER, scene);
3138 return OPERATOR_FINISHED;
3141 return OPERATOR_CANCELLED;
3144 void SEQUENCER_OT_swap(wmOperatorType *ot)
3147 ot->name = "Swap Strip";
3148 ot->idname = "SEQUENCER_OT_swap";
3149 ot->description = "Swap active strip with strip to the right or left";
3152 ot->exec = sequencer_swap_exec;
3153 ot->poll = sequencer_edit_poll;
3156 ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
3159 RNA_def_enum(ot->srna, "side", prop_side_lr_types, SEQ_SIDE_RIGHT, "Side", "Side of the strip to swap");
3162 static int sequencer_rendersize_exec(bContext *C, wmOperator *UNUSED(op))
3164 int retval = OPERATOR_CANCELLED;
3165 Scene *scene = CTX_data_scene(C);
3166 Sequence *active_seq = BKE_sequencer_active_get(scene);
3167 StripElem *se = NULL;
3169 if (active_seq == NULL)
3170 return OPERATOR_CANCELLED;
3173 if (active_seq->strip) {
3174 switch (active_seq->type) {
3175 case SEQ_TYPE_IMAGE:
3176 se = BKE_sequencer_give_stripelem(active_seq, scene->r.cfra);
3178 case SEQ_TYPE_MOVIE:
3179 se = active_seq->strip->stripdata;
3181 case SEQ_TYPE_SCENE:
3183 case SEQ_TYPE_SOUND_RAM:
3184 case SEQ_TYPE_SOUND_HD:
3191 // prevent setting the render size if sequence values aren't&nbs