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"
39 #include "BLI_utildefines.h"
40 #include "BLI_ghash.h"
42 #include "BLF_translation.h"
44 #include "DNA_scene_types.h"
46 #include "BKE_context.h"
47 #include "BKE_global.h"
49 #include "BKE_sequencer.h"
50 #include "BKE_report.h"
51 #include "BKE_sound.h"
57 #include "RNA_define.h"
58 #include "RNA_enum_types.h"
60 /* for menu/popup icons etc etc*/
62 #include "ED_numinput.h"
63 #include "ED_screen.h"
64 #include "ED_transform.h"
65 #include "ED_sequencer.h"
66 #include "ED_space_api.h"
68 #include "UI_view2d.h"
69 #include "UI_interface.h"
73 #include "sequencer_intern.h"
76 /* RNA Enums, used in multiple files */
77 EnumPropertyItem sequencer_prop_effect_types[] = {
78 {SEQ_TYPE_CROSS, "CROSS", 0, "Crossfade", "Crossfade effect strip type"},
79 {SEQ_TYPE_ADD, "ADD", 0, "Add", "Add effect strip type"},
80 {SEQ_TYPE_SUB, "SUBTRACT", 0, "Subtract", "Subtract effect strip type"},
81 {SEQ_TYPE_ALPHAOVER, "ALPHA_OVER", 0, "Alpha Over", "Alpha Over effect strip type"},
82 {SEQ_TYPE_ALPHAUNDER, "ALPHA_UNDER", 0, "Alpha Under", "Alpha Under effect strip type"},
83 {SEQ_TYPE_GAMCROSS, "GAMMA_CROSS", 0, "Gamma Cross", "Gamma Cross effect strip type"},
84 {SEQ_TYPE_MUL, "MULTIPLY", 0, "Multiply", "Multiply effect strip type"},
85 {SEQ_TYPE_OVERDROP, "OVER_DROP", 0, "Alpha Over Drop", "Alpha Over Drop effect strip type"},
86 {SEQ_TYPE_WIPE, "WIPE", 0, "Wipe", "Wipe effect strip type"},
87 {SEQ_TYPE_GLOW, "GLOW", 0, "Glow", "Glow effect strip type"},
88 {SEQ_TYPE_TRANSFORM, "TRANSFORM", 0, "Transform", "Transform effect strip type"},
89 {SEQ_TYPE_COLOR, "COLOR", 0, "Color", "Color effect strip type"},
90 {SEQ_TYPE_SPEED, "SPEED", 0, "Speed", "Color effect strip type"},
91 {SEQ_TYPE_MULTICAM, "MULTICAM", 0, "Multicam Selector", ""},
92 {SEQ_TYPE_ADJUSTMENT, "ADJUSTMENT", 0, "Adjustment Layer", ""},
93 {SEQ_TYPE_GAUSSIAN_BLUR, "GAUSSIAN_BLUR", 0, "Gaussian Blur", ""},
94 {SEQ_TYPE_TEXT, "TEXT", 0, "Text", ""},
95 {0, NULL, 0, NULL, NULL}
100 EnumPropertyItem prop_side_types[] = {
101 {SEQ_SIDE_LEFT, "LEFT", 0, "Left", ""},
102 {SEQ_SIDE_RIGHT, "RIGHT", 0, "Right", ""},
103 {SEQ_SIDE_BOTH, "BOTH", 0, "Both", ""},
104 {0, NULL, 0, NULL, NULL}
107 static EnumPropertyItem prop_side_lr_types[] = {
108 {SEQ_SIDE_LEFT, "LEFT", 0, "Left", ""},
109 {SEQ_SIDE_RIGHT, "RIGHT", 0, "Right", ""},
110 {0, NULL, 0, NULL, NULL}
113 typedef struct TransSeq {
115 int startstill, endstill;
116 int startdisp, enddisp;
117 int startofs, endofs;
118 int anim_startofs, anim_endofs;
119 /* int final_left, final_right; */ /* UNUSED */
123 /* ********************************************************************** */
125 /* ***************** proxy job manager ********************** */
127 typedef struct ProxyBuildJob {
134 static void proxy_freejob(void *pjv)
138 BLI_freelistN(&pj->queue);
143 /* only this runs inside thread */
144 static void proxy_startjob(void *pjv, short *stop, short *do_update, float *progress)
149 for (link = pj->queue.first; link; link = link->next) {
150 struct SeqIndexBuildContext *context = link->data;
152 BKE_sequencer_proxy_rebuild(context, stop, do_update, progress);
156 fprintf(stderr, "Canceling proxy rebuild on users request...\n");
162 static void proxy_endjob(void *pjv)
165 Editing *ed = BKE_sequencer_editing_get(pj->scene, false);
168 for (link = pj->queue.first; link; link = link->next) {
169 BKE_sequencer_proxy_rebuild_finish(link->data, pj->stop);
172 BKE_sequencer_free_imbuf(pj->scene, &ed->seqbase, false);
174 WM_main_add_notifier(NC_SCENE | ND_SEQUENCER, pj->scene);
177 static void seq_proxy_build_job(const bContext *C)
181 Scene *scene = CTX_data_scene(C);
182 Editing *ed = BKE_sequencer_editing_get(scene, false);
183 ScrArea *sa = CTX_wm_area(C);
191 wm_job = WM_jobs_get(CTX_wm_manager(C), CTX_wm_window(C), sa, "Building Proxies",
192 WM_JOB_PROGRESS, WM_JOB_TYPE_SEQ_BUILD_PROXY);
194 pj = WM_jobs_customdata_get(wm_job);
197 pj = MEM_callocN(sizeof(ProxyJob), "proxy rebuild job");
200 pj->main = CTX_data_main(C);
202 WM_jobs_customdata_set(wm_job, pj, proxy_freejob);
203 WM_jobs_timer(wm_job, 0.1, NC_SCENE | ND_SEQUENCER, NC_SCENE | ND_SEQUENCER);
204 WM_jobs_callbacks(wm_job, proxy_startjob, NULL, NULL, proxy_endjob);
207 file_list = BLI_gset_new(BLI_ghashutil_strhash_p, BLI_ghashutil_strcmp, "file list");
210 if ((seq->flag & SELECT)) {
211 BKE_sequencer_proxy_rebuild_context(pj->main, pj->scene, seq, file_list, &pj->queue);
216 BLI_gset_free(file_list, MEM_freeN);
218 if (!WM_jobs_is_running(wm_job)) {
220 WM_jobs_start(CTX_wm_manager(C), wm_job);
223 ED_area_tag_redraw(sa);
226 /* ********************************************************************** */
228 void seq_rectf(Sequence *seq, rctf *rectf)
230 if (seq->startstill) rectf->xmin = seq->start;
231 else rectf->xmin = seq->startdisp;
232 rectf->ymin = seq->machine + SEQ_STRIP_OFSBOTTOM;
233 if (seq->endstill) rectf->xmax = seq->start + seq->len;
234 else rectf->xmax = seq->enddisp;
235 rectf->ymax = seq->machine + SEQ_STRIP_OFSTOP;
238 void boundbox_seq(Scene *scene, rctf *rect)
241 Editing *ed = BKE_sequencer_editing_get(scene, false);
242 float min[2], max[2];
245 if (ed == NULL) return;
252 seq = ed->seqbasep->first;
255 if (min[0] > seq->startdisp - 1) min[0] = seq->startdisp - 1;
256 if (max[0] < seq->enddisp + 1) max[0] = seq->enddisp + 1;
257 if (max[1] < seq->machine + 2) max[1] = seq->machine + 2;
269 static int mouse_frame_side(View2D *v2d, short mouse_x, int frame)
277 /* choose the side based on which side of the playhead the mouse is on */
278 UI_view2d_region_to_view(v2d, mval[0], mval[1], &mouseloc[0], &mouseloc[1]);
280 return mouseloc[0] > frame ? SEQ_SIDE_RIGHT : SEQ_SIDE_LEFT;
284 Sequence *find_neighboring_sequence(Scene *scene, Sequence *test, int lr, int sel)
286 /* sel - 0==unselected, 1==selected, -1==done care*/
288 Editing *ed = BKE_sequencer_editing_get(scene, false);
290 if (ed == NULL) return NULL;
292 if (sel > 0) sel = SELECT;
294 for (seq = ed->seqbasep->first; seq; seq = seq->next) {
296 (test->machine == seq->machine) &&
297 ((sel == -1) || (sel && (seq->flag & SELECT)) || (sel == 0 && (seq->flag & SELECT) == 0)))
301 if (test->startdisp == (seq->enddisp)) {
306 if (test->enddisp == (seq->startdisp)) {
316 static Sequence *find_next_prev_sequence(Scene *scene, Sequence *test, int lr, int sel)
318 /* sel - 0==unselected, 1==selected, -1==done care*/
319 Sequence *seq, *best_seq = NULL;
320 Editing *ed = BKE_sequencer_editing_get(scene, false);
323 best_dist = MAXFRAME * 2;
326 if (ed == NULL) return NULL;
328 seq = ed->seqbasep->first;
331 (test->machine == seq->machine) &&
332 (test->depth == seq->depth) &&
333 ((sel == -1) || (sel == (seq->flag & SELECT))))
339 if (seq->enddisp <= test->startdisp) {
340 dist = test->enddisp - seq->startdisp;
344 if (seq->startdisp >= test->enddisp) {
345 dist = seq->startdisp - test->enddisp;
354 else if (dist < best_dist) {
361 return best_seq; /* can be null */
365 Sequence *find_nearest_seq(Scene *scene, View2D *v2d, int *hand, const int mval[2])
368 Editing *ed = BKE_sequencer_editing_get(scene, false);
373 *hand = SEQ_SIDE_NONE;
376 if (ed == NULL) return NULL;
378 pixelx = BLI_rctf_size_x(&v2d->cur) / BLI_rcti_size_x(&v2d->mask);
380 UI_view2d_region_to_view(v2d, mval[0], mval[1], &x, &y);
382 seq = ed->seqbasep->first;
385 if (seq->machine == (int)y) {
386 /* check for both normal strips, and strips that have been flipped horizontally */
387 if (((seq->startdisp < seq->enddisp) && (seq->startdisp <= x && seq->enddisp >= x)) ||
388 ((seq->startdisp > seq->enddisp) && (seq->startdisp >= x && seq->enddisp <= x)) )
390 if (BKE_sequence_tx_test(seq)) {
392 /* clamp handles to defined size in pixel space */
394 handsize = seq->handsize;
395 displen = (float)abs(seq->startdisp - seq->enddisp);
397 if (displen / pixelx > 16) { /* don't even try to grab the handles of small strips */
398 /* Set the max value to handle to 1/3 of the total len when its less than 28.
399 * This is important because otherwise selecting handles happens even when you click in the middle */
401 if ((displen / 3) < 30 * pixelx) {
402 handsize = displen / 3;
405 CLAMP(handsize, 7 * pixelx, 30 * pixelx);
408 if (handsize + seq->startdisp >= x)
409 *hand = SEQ_SIDE_LEFT;
410 else if (-handsize + seq->enddisp <= x)
411 *hand = SEQ_SIDE_RIGHT;
423 static bool seq_is_parent(Sequence *par, Sequence *seq)
425 return ((par->seq1 == seq) || (par->seq2 == seq) || (par->seq3 == seq));
428 static bool seq_is_predecessor(Sequence *pred, Sequence *seq)
431 if (pred == seq) return 0;
432 else if (seq_is_parent(pred, seq)) return 1;
433 else if (pred->seq1 && seq_is_predecessor(pred->seq1, seq)) return 1;
434 else if (pred->seq2 && seq_is_predecessor(pred->seq2, seq)) return 1;
435 else if (pred->seq3 && seq_is_predecessor(pred->seq3, seq)) return 1;
440 void ED_sequencer_deselect_all(Scene *scene)
443 Editing *ed = BKE_sequencer_editing_get(scene, false);
446 if (ed == NULL) return;
450 seq->flag &= ~SEQ_ALLSEL;
456 void recurs_sel_seq(Sequence *seqm)
460 seq = seqm->seqbase.first;
463 if (seqm->flag & (SEQ_LEFTSEL + SEQ_RIGHTSEL)) seq->flag &= ~SEQ_ALLSEL;
464 else if (seqm->flag & SELECT) seq->flag |= SELECT;
465 else seq->flag &= ~SEQ_ALLSEL;
467 if (seq->seqbase.first) recurs_sel_seq(seq);
473 int ED_space_sequencer_maskedit_mask_poll(bContext *C)
475 /* in this case both funcs are the same, for clip editor not */
476 return ED_space_sequencer_maskedit_poll(C);
479 bool ED_space_sequencer_check_show_maskedit(SpaceSeq *sseq, Scene *scene)
481 if (sseq && sseq->mainb == SEQ_DRAW_IMG_IMBUF) {
482 return (BKE_sequencer_mask_get(scene) != NULL);
488 int ED_space_sequencer_maskedit_poll(bContext *C)
490 SpaceSeq *sseq = CTX_wm_space_seq(C);
493 Scene *scene = CTX_data_scene(C);
494 return ED_space_sequencer_check_show_maskedit(sseq, scene);
500 /* are we displaying the seq output (not channels or histogram)*/
501 bool ED_space_sequencer_check_show_imbuf(SpaceSeq *sseq)
503 return (ELEM(sseq->view, SEQ_VIEW_PREVIEW, SEQ_VIEW_SEQUENCE_PREVIEW) &&
504 ELEM(sseq->mainb, SEQ_DRAW_SEQUENCE, SEQ_DRAW_IMG_IMBUF));
507 bool ED_space_sequencer_check_show_strip(SpaceSeq *sseq)
509 return (ELEM(sseq->view, SEQ_VIEW_SEQUENCE, SEQ_VIEW_SEQUENCE_PREVIEW) &&
510 ELEM(sseq->mainb, SEQ_DRAW_SEQUENCE, SEQ_DRAW_IMG_IMBUF));
514 int seq_effect_find_selected(Scene *scene, Sequence *activeseq, int type, Sequence **selseq1, Sequence **selseq2, Sequence **selseq3, const char **error_str)
516 Editing *ed = BKE_sequencer_editing_get(scene, false);
517 Sequence *seq1 = NULL, *seq2 = NULL, *seq3 = NULL, *seq;
522 seq2 = BKE_sequencer_active_get(scene);
524 for (seq = ed->seqbasep->first; seq; seq = seq->next) {
525 if (seq->flag & SELECT) {
526 if (seq->type == SEQ_TYPE_SOUND_RAM && BKE_sequence_effect_get_num_inputs(type) != 0) {
527 *error_str = N_("Cannot apply effects to audio sequence strips");
530 if ((seq != activeseq) && (seq != seq2)) {
531 if (seq2 == NULL) seq2 = seq;
532 else if (seq1 == NULL) seq1 = seq;
533 else if (seq3 == NULL) seq3 = seq;
535 *error_str = N_("Cannot apply effect to more than 3 sequence strips");
542 /* make sequence selection a little bit more intuitive
543 * for 3 strips: the last-strip should be sequence3 */
544 if (seq3 != NULL && seq2 != NULL) {
545 Sequence *tmp = seq2;
551 switch (BKE_sequence_effect_get_num_inputs(type)) {
553 *selseq1 = *selseq2 = *selseq3 = NULL;
554 return 1; /* succsess */
557 *error_str = N_("At least one selected sequence strip is needed");
560 if (seq1 == NULL) seq1 = seq2;
561 if (seq3 == NULL) seq3 = seq2;
564 if (seq1 == NULL || seq2 == NULL) {
565 *error_str = N_("2 selected sequence strips are needed");
568 if (seq3 == NULL) seq3 = seq2;
572 if (seq1 == NULL && seq2 == NULL && seq3 == NULL) {
573 *error_str = N_("TODO: in what cases does this happen?");
584 static Sequence *del_seq_find_replace_recurs(Scene *scene, Sequence *seq)
586 Sequence *seq1, *seq2, *seq3;
588 /* try to find a replacement input sequence, and flag for later deletion if
589 * no replacement can be found */
593 else if (!(seq->type & SEQ_TYPE_EFFECT))
594 return ((seq->flag & SELECT) ? NULL : seq);
595 else if (!(seq->flag & SELECT)) {
596 /* try to find replacement for effect inputs */
597 seq1 = del_seq_find_replace_recurs(scene, seq->seq1);
598 seq2 = del_seq_find_replace_recurs(scene, seq->seq2);
599 seq3 = del_seq_find_replace_recurs(scene, seq->seq3);
601 if (seq1 == seq->seq1 && seq2 == seq->seq2 && seq3 == seq->seq3) {
604 else if (seq1 || seq2 || seq3) {
605 seq->seq1 = (seq1) ? seq1 : (seq2) ? seq2 : seq3;
606 seq->seq2 = (seq2) ? seq2 : (seq1) ? seq1 : seq3;
607 seq->seq3 = (seq3) ? seq3 : (seq1) ? seq1 : seq2;
609 BKE_sequencer_update_changed_seq_and_deps(scene, seq, 1, 1);
612 seq->flag |= SELECT; /* mark for delete */
615 if (seq->flag & SELECT) {
616 if ((seq1 = del_seq_find_replace_recurs(scene, seq->seq1))) return seq1;
617 if ((seq2 = del_seq_find_replace_recurs(scene, seq->seq2))) return seq2;
618 if ((seq3 = del_seq_find_replace_recurs(scene, seq->seq3))) return seq3;
625 static void del_seq_clear_modifiers_recurs(Scene *scene, Sequence *deleting_sequence)
627 Editing *ed = BKE_sequencer_editing_get(scene, false);
628 Sequence *current_sequence;
630 SEQP_BEGIN(ed, current_sequence)
632 if (!(current_sequence->flag & SELECT) && current_sequence != deleting_sequence) {
633 SequenceModifierData *smd;
635 for (smd = current_sequence->modifiers.first; smd; smd = smd->next) {
636 if (smd->mask_sequence == deleting_sequence) {
637 smd->mask_sequence = NULL;
645 static void recurs_del_seq_flag(Scene *scene, ListBase *lb, short flag, short deleteall)
647 Sequence *seq, *seqn;
648 Sequence *last_seq = BKE_sequencer_active_get(scene);
653 if ((seq->flag & flag) || deleteall) {
654 BLI_remlink(lb, seq);
655 if (seq == last_seq) BKE_sequencer_active_set(scene, NULL);
656 if (seq->type == SEQ_TYPE_META) recurs_del_seq_flag(scene, &seq->seqbase, flag, 1);
657 BKE_sequence_free(scene, seq);
664 static Sequence *cut_seq_hard(Scene *scene, Sequence *seq, int cutframe)
667 Sequence *seqn = NULL;
668 bool skip_dup = false;
671 ts.start = seq->start;
672 ts.machine = seq->machine;
673 ts.startstill = seq->startstill;
674 ts.endstill = seq->endstill;
675 ts.startdisp = seq->startdisp;
676 ts.enddisp = seq->enddisp;
677 ts.startofs = seq->startofs;
678 ts.endofs = seq->endofs;
679 ts.anim_startofs = seq->anim_startofs;
680 ts.anim_endofs = seq->anim_endofs;
684 /* strips with extended stillfames before */
686 if ((seq->startstill) && (cutframe < seq->start)) {
687 /* don't do funny things with METAs ... */
688 if (seq->type == SEQ_TYPE_META) {
690 seq->startstill = seq->start - cutframe;
693 seq->start = cutframe - 1;
694 seq->startstill = cutframe - seq->startdisp - 1;
695 seq->anim_endofs += seq->len - 1;
700 else if ((cutframe >= seq->start) && (cutframe <= (seq->start + seq->len))) {
703 seq->anim_endofs += (seq->start + seq->len) - cutframe;
705 /* strips with extended stillframes after */
706 else if (((seq->start + seq->len) < cutframe) && (seq->endstill)) {
707 seq->endstill -= seq->enddisp - cutframe;
708 /* don't do funny things with METAs ... */
709 if (seq->type == SEQ_TYPE_META) {
714 BKE_sequence_reload_new_file(scene, seq, false);
715 BKE_sequence_calc(scene, seq);
718 /* Duplicate AFTER the first change */
719 seqn = BKE_sequence_dupli_recursive(scene, NULL, seq, SEQ_DUPE_UNIQUE_NAME | SEQ_DUPE_ANIM);
723 seqn->flag |= SELECT;
726 /* strips with extended stillframes before */
727 if ((seqn->startstill) && (cutframe == seqn->start + 1)) {
728 seqn->start = ts.start;
729 seqn->startstill = ts.start - cutframe;
730 seqn->anim_endofs = ts.anim_endofs;
731 seqn->endstill = ts.endstill;
735 else if ((cutframe >= seqn->start) && (cutframe <= (seqn->start + seqn->len))) {
736 seqn->start = cutframe;
737 seqn->startstill = 0;
739 seqn->endofs = ts.endofs;
740 seqn->anim_startofs += cutframe - ts.start;
741 seqn->anim_endofs = ts.anim_endofs;
742 seqn->endstill = ts.endstill;
745 /* strips with extended stillframes after */
746 else if (((seqn->start + seqn->len) < cutframe) && (seqn->endstill)) {
747 seqn->start = cutframe;
749 seqn->anim_startofs += ts.len - 1;
750 seqn->endstill = ts.enddisp - cutframe - 1;
751 seqn->startstill = 0;
754 BKE_sequence_reload_new_file(scene, seqn, false);
755 BKE_sequence_calc(scene, seqn);
760 static Sequence *cut_seq_soft(Scene *scene, Sequence *seq, int cutframe)
763 Sequence *seqn = NULL;
764 bool skip_dup = false;
767 ts.start = seq->start;
768 ts.machine = seq->machine;
769 ts.startstill = seq->startstill;
770 ts.endstill = seq->endstill;
771 ts.startdisp = seq->startdisp;
772 ts.enddisp = seq->enddisp;
773 ts.startofs = seq->startofs;
774 ts.endofs = seq->endofs;
775 ts.anim_startofs = seq->anim_startofs;
776 ts.anim_endofs = seq->anim_endofs;
780 /* strips with extended stillfames before */
782 if ((seq->startstill) && (cutframe < seq->start)) {
783 /* don't do funny things with METAs ... */
784 if (seq->type == SEQ_TYPE_META) {
786 seq->startstill = seq->start - cutframe;
789 seq->start = cutframe - 1;
790 seq->startstill = cutframe - seq->startdisp - 1;
791 seq->endofs = seq->len - 1;
796 else if ((cutframe >= seq->start) && (cutframe <= (seq->start + seq->len))) {
797 seq->endofs = (seq->start + seq->len) - cutframe;
799 /* strips with extended stillframes after */
800 else if (((seq->start + seq->len) < cutframe) && (seq->endstill)) {
801 seq->endstill -= seq->enddisp - cutframe;
802 /* don't do funny things with METAs ... */
803 if (seq->type == SEQ_TYPE_META) {
808 BKE_sequence_calc(scene, seq);
811 /* Duplicate AFTER the first change */
812 seqn = BKE_sequence_dupli_recursive(scene, NULL, seq, SEQ_DUPE_UNIQUE_NAME | SEQ_DUPE_ANIM);
816 seqn->flag |= SELECT;
819 /* strips with extended stillframes before */
820 if ((seqn->startstill) && (cutframe == seqn->start + 1)) {
821 seqn->start = ts.start;
822 seqn->startstill = ts.start - cutframe;
823 seqn->endofs = ts.endofs;
824 seqn->endstill = ts.endstill;
828 else if ((cutframe >= seqn->start) && (cutframe <= (seqn->start + seqn->len))) {
829 seqn->startstill = 0;
830 seqn->startofs = cutframe - ts.start;
831 seqn->endofs = ts.endofs;
832 seqn->endstill = ts.endstill;
835 /* strips with extended stillframes after */
836 else if (((seqn->start + seqn->len) < cutframe) && (seqn->endstill)) {
837 seqn->start = cutframe - ts.len + 1;
838 seqn->startofs = ts.len - 1;
839 seqn->endstill = ts.enddisp - cutframe - 1;
840 seqn->startstill = 0;
843 BKE_sequence_calc(scene, seqn);
849 /* like duplicate, but only duplicate and cut overlapping strips,
850 * strips to the left of the cutframe are ignored and strips to the right
851 * are moved to the end of slist
852 * we have to work on the same slist (not using a separate list), since
853 * otherwise dupli_seq can't check for duplicate names properly and
854 * may generate strips with the same name (which will mess up animdata)
857 static bool cut_seq_list(Scene *scene, ListBase *slist, int cutframe,
858 Sequence * (*cut_seq)(Scene *, Sequence *, int))
860 Sequence *seq, *seq_next_iter;
861 Sequence *seq_first_new = NULL;
865 while (seq && seq != seq_first_new) {
866 seq_next_iter = seq->next; /* we need this because we may remove seq */
868 if (seq->flag & SELECT) {
869 if (cutframe > seq->startdisp &&
870 cutframe < seq->enddisp)
872 Sequence *seqn = cut_seq(scene, seq, cutframe);
874 BLI_addtail(slist, seqn);
875 if (seq_first_new == NULL) {
876 seq_first_new = seqn;
880 else if (seq->enddisp <= cutframe) {
883 else if (seq->startdisp >= cutframe) {
885 BLI_remlink(slist, seq);
886 BLI_addtail(slist, seq);
888 if (seq_first_new == NULL) {
896 return (seq_first_new != NULL);
899 static bool sequence_offset_after_frame(Scene *scene, const int delta, const int cfra)
902 Editing *ed = BKE_sequencer_editing_get(scene, false);
906 /* all strips >= cfra are shifted */
908 if (ed == NULL) return 0;
910 for (seq = ed->seqbasep->first; seq; seq = seq->next) {
911 if (seq->startdisp >= cfra) {
912 BKE_sequence_translate(scene, seq, delta);
913 BKE_sequence_calc(scene, seq);
918 if (!scene->toolsettings->lock_markers) {
919 for (marker = scene->markers.first; marker; marker = marker->next) {
920 if (marker->frame >= cfra) {
921 marker->frame += delta;
929 static void UNUSED_FUNCTION(touch_seq_files) (Scene *scene)
932 Editing *ed = BKE_sequencer_editing_get(scene, false);
935 /* touch all strips with movies */
937 if (ed == NULL) return;
939 // XXX25 if (okee("Touch and print selected movies")==0) return;
945 if (seq->flag & SELECT) {
946 if (seq->type == SEQ_TYPE_MOVIE) {
947 if (seq->strip && seq->strip->stripdata) {
948 BLI_make_file_string(G.main->name, str, seq->strip->dir, seq->strip->stripdata->name);
949 BLI_file_touch(seq->name);
961 static void set_filter_seq(Scene *scene)
964 Editing *ed = BKE_sequencer_editing_get(scene, false);
967 if (ed == NULL) return;
969 if (okee("Set Deinterlace") == 0) return;
973 if (seq->flag & SELECT) {
974 if (seq->type == SEQ_TYPE_MOVIE) {
975 seq->flag |= SEQ_FILTERY;
976 BKE_sequence_reload_new_file(scene, seq, false);
977 BKE_sequence_calc(scene, seq);
986 static void UNUSED_FUNCTION(seq_remap_paths) (Scene *scene)
988 Sequence *seq, *last_seq = BKE_sequencer_active_get(scene);
989 Editing *ed = BKE_sequencer_editing_get(scene, false);
990 char from[FILE_MAX], to[FILE_MAX], stripped[FILE_MAX];
993 if (last_seq == NULL)
996 BLI_strncpy(from, last_seq->strip->dir, sizeof(from));
997 // XXX if (0 == sbutton(from, 0, sizeof(from) - 1, "From: "))
1000 BLI_strncpy(to, from, sizeof(to));
1001 // XXX if (0 == sbutton(to, 0, sizeof(to) - 1, "To: "))
1004 if (STREQ(to, from))
1007 SEQP_BEGIN (ed, seq)
1009 if (seq->flag & SELECT) {
1010 if (STREQLEN(seq->strip->dir, from, strlen(from))) {
1011 printf("found %s\n", seq->strip->dir);
1013 /* strip off the beginning */
1015 BLI_strncpy(stripped, seq->strip->dir + strlen(from), FILE_MAX);
1018 BLI_snprintf(seq->strip->dir, sizeof(seq->strip->dir), "%s%s", to, stripped);
1019 printf("new %s\n", seq->strip->dir);
1028 static int sequencer_gap_remove_exec(bContext *C, wmOperator *op)
1030 Scene *scene = CTX_data_scene(C);
1032 int cfra, efra, sfra;
1033 bool first = false, done;
1034 bool do_all = RNA_boolean_get(op->ptr, "all");
1036 /* get first and last frame */
1037 boundbox_seq(scene, &rectf);
1038 sfra = (int)rectf.xmin;
1039 efra = (int)rectf.xmax;
1041 /* first check if the current frame has a gap already */
1042 for (cfra = CFRA; cfra >= sfra; cfra--) {
1043 if (BKE_sequencer_evaluate_frame(scene, cfra)) {
1049 for ( ; cfra < efra; cfra++) {
1050 /* first == 0 means there's still no strip to remove a gap for */
1051 if (first == false) {
1052 if (BKE_sequencer_evaluate_frame(scene, cfra) ) first = true;
1054 else if (BKE_sequencer_evaluate_frame(scene, cfra) == 0) {
1056 while (BKE_sequencer_evaluate_frame(scene, cfra) == 0) {
1057 done = sequence_offset_after_frame(scene, -1, cfra);
1058 if (done == false) break;
1060 if (done == false || do_all == false) break;
1064 WM_event_add_notifier(C, NC_SCENE | ND_SEQUENCER, scene);
1066 return OPERATOR_FINISHED;
1071 void SEQUENCER_OT_gap_remove(struct wmOperatorType *ot)
1074 ot->name = "Remove Gaps";
1075 ot->idname = "SEQUENCER_OT_gap_remove";
1076 ot->description = "Remove gap at current frame to first strip at the right, independent of selection or locked state of strips";
1079 // ot->invoke = sequencer_snap_invoke;
1080 ot->exec = sequencer_gap_remove_exec;
1081 ot->poll = sequencer_edit_poll;
1084 ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
1086 RNA_def_boolean(ot->srna, "all", 0, "All Gaps", "Do all gaps to right of current frame");
1089 static int sequencer_gap_insert_exec(bContext *C, wmOperator *op)
1091 Scene *scene = CTX_data_scene(C);
1092 int frames = RNA_int_get(op->ptr, "frames");
1094 sequence_offset_after_frame(scene, frames, CFRA);
1096 WM_event_add_notifier(C, NC_SCENE | ND_SEQUENCER, scene);
1098 return OPERATOR_FINISHED;
1102 void SEQUENCER_OT_gap_insert(struct wmOperatorType *ot)
1105 ot->name = "Insert Gaps";
1106 ot->idname = "SEQUENCER_OT_gap_insert";
1107 ot->description = "Insert gap at current frame to first strips at the right, independent of selection or locked state of strips";
1110 // ot->invoke = sequencer_snap_invoke;
1111 ot->exec = sequencer_gap_insert_exec;
1112 ot->poll = sequencer_edit_poll;
1115 ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
1117 RNA_def_int(ot->srna, "frames", 10, 0, INT_MAX, "Frames", "Frames to insert after current strip", 0, 1000);
1122 static int seq_get_snaplimit(View2D *v2d)
1124 /* fake mouse coords to get the snap value
1125 * a bit lazy but its only done once pre transform */
1126 float xmouse, ymouse, x;
1127 int mval[2] = {24, 0}; /* 24 screen px snap */
1129 UI_view2d_region_to_view(v2d, mval[0], mval[1], &xmouse, &ymouse);
1132 UI_view2d_region_to_view(v2d, mval[0], mval[1], &xmouse, &ymouse);
1133 return (int)(x - xmouse);
1137 /* Operator functions */
1138 int sequencer_edit_poll(bContext *C)
1140 return (BKE_sequencer_editing_get(CTX_data_scene(C), false) != NULL);
1144 int sequencer_strip_poll(bContext *C)
1147 return (((ed = BKE_sequencer_editing_get(CTX_data_scene(C), false)) != NULL) && (ed->act_seq != NULL));
1151 int sequencer_strip_has_path_poll(bContext *C)
1155 return (((ed = BKE_sequencer_editing_get(CTX_data_scene(C), false)) != NULL) && ((seq = ed->act_seq) != NULL) && (SEQ_HAS_PATH(seq)));
1158 int sequencer_view_preview_poll(bContext *C)
1160 SpaceSeq *sseq = CTX_wm_space_seq(C);
1161 Editing *ed = BKE_sequencer_editing_get(CTX_data_scene(C), false);
1162 if (ed && sseq && (sseq->mainb == SEQ_DRAW_IMG_IMBUF))
1168 int sequencer_view_strips_poll(bContext *C)
1170 SpaceSeq *sseq = CTX_wm_space_seq(C);
1171 if (sseq && ED_space_sequencer_check_show_strip(sseq))
1178 static int sequencer_snap_exec(bContext *C, wmOperator *op)
1180 Scene *scene = CTX_data_scene(C);
1182 Editing *ed = BKE_sequencer_editing_get(scene, false);
1186 snap_frame = RNA_int_get(op->ptr, "frame");
1188 /* also check metas */
1189 for (seq = ed->seqbasep->first; seq; seq = seq->next) {
1190 if (seq->flag & SELECT && !(seq->depth == 0 && seq->flag & SEQ_LOCK) &&
1191 BKE_sequence_tx_test(seq))
1193 if ((seq->flag & (SEQ_LEFTSEL + SEQ_RIGHTSEL)) == 0) {
1194 /* simple but no anim update */
1195 /* seq->start = snap_frame-seq->startofs+seq->startstill; */
1197 BKE_sequence_translate(scene, seq, (snap_frame - seq->startofs + seq->startstill) - seq->start);
1200 if (seq->flag & SEQ_LEFTSEL) {
1201 BKE_sequence_tx_set_final_left(seq, snap_frame);
1203 else { /* SEQ_RIGHTSEL */
1204 BKE_sequence_tx_set_final_right(seq, snap_frame);
1206 BKE_sequence_tx_handle_xlimits(seq, seq->flag & SEQ_LEFTSEL, seq->flag & SEQ_RIGHTSEL);
1208 BKE_sequence_calc(scene, seq);
1212 /* test for effects and overlap
1213 * don't use SEQP_BEGIN since that would be recursive */
1214 for (seq = ed->seqbasep->first; seq; seq = seq->next) {
1215 if (seq->flag & SELECT && !(seq->depth == 0 && seq->flag & SEQ_LOCK)) {
1216 seq->flag &= ~SEQ_OVERLAP;
1217 if (BKE_sequence_test_overlap(ed->seqbasep, seq) ) {
1218 BKE_sequence_base_shuffle(ed->seqbasep, seq, scene);
1221 else if (seq->type & SEQ_TYPE_EFFECT) {
1222 if (seq->seq1 && (seq->seq1->flag & SELECT))
1223 BKE_sequence_calc(scene, seq);
1224 else if (seq->seq2 && (seq->seq2->flag & SELECT))
1225 BKE_sequence_calc(scene, seq);
1226 else if (seq->seq3 && (seq->seq3->flag & SELECT))
1227 BKE_sequence_calc(scene, seq);
1232 BKE_sequencer_sort(scene);
1234 WM_event_add_notifier(C, NC_SCENE | ND_SEQUENCER, scene);
1236 return OPERATOR_FINISHED;
1239 static int sequencer_snap_invoke(bContext *C, wmOperator *op, const wmEvent *UNUSED(event))
1241 Scene *scene = CTX_data_scene(C);
1247 RNA_int_set(op->ptr, "frame", snap_frame);
1248 return sequencer_snap_exec(C, op);
1251 void SEQUENCER_OT_snap(struct wmOperatorType *ot)
1254 ot->name = "Snap Strips";
1255 ot->idname = "SEQUENCER_OT_snap";
1256 ot->description = "Frame where selected strips will be snapped";
1259 ot->invoke = sequencer_snap_invoke;
1260 ot->exec = sequencer_snap_exec;
1261 ot->poll = sequencer_edit_poll;
1264 ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
1266 RNA_def_int(ot->srna, "frame", 0, INT_MIN, INT_MAX, "Frame", "Frame where selected strips will be snapped", INT_MIN, INT_MAX);
1269 typedef struct SlipData {
1271 float init_mouseloc[2];
1273 Sequence **seq_array;
1277 int slow_offset; /* offset at the point where offset was turned on */
1282 static void transseq_backup(TransSeq *ts, Sequence *seq)
1284 ts->start = seq->start;
1285 ts->machine = seq->machine;
1286 ts->startstill = seq->startstill;
1287 ts->endstill = seq->endstill;
1288 ts->startdisp = seq->startdisp;
1289 ts->enddisp = seq->enddisp;
1290 ts->startofs = seq->startofs;
1291 ts->endofs = seq->endofs;
1292 ts->anim_startofs = seq->anim_startofs;
1293 ts->anim_endofs = seq->anim_endofs;
1298 static void transseq_restore(TransSeq *ts, Sequence *seq)
1300 seq->start = ts->start;
1301 seq->machine = ts->machine;
1302 seq->startstill = ts->startstill;
1303 seq->endstill = ts->endstill;
1304 seq->startdisp = ts->startdisp;
1305 seq->enddisp = ts->enddisp;
1306 seq->startofs = ts->startofs;
1307 seq->endofs = ts->endofs;
1308 seq->anim_startofs = ts->anim_startofs;
1309 seq->anim_endofs = ts->anim_endofs;
1313 static void draw_slip_extensions(const bContext *C, ARegion *ar, void *data)
1315 Scene *scene = CTX_data_scene(C);
1316 SlipData *td = data;
1319 for (i = 0; i < td->num_seq; i++) {
1320 Sequence *seq = td->seq_array[i];
1322 if ((seq->type != SEQ_TYPE_META) && td->trim[i]) {
1323 draw_sequence_extensions(scene, ar, seq);
1328 static int slip_add_sequences_rec(ListBase *seqbasep, Sequence **seq_array, bool *trim, int offset, bool do_trim)
1333 for (seq = seqbasep->first; seq; seq = seq->next) {
1334 if (!do_trim || (!(seq->type & SEQ_TYPE_EFFECT) && (seq->flag & SELECT))) {
1335 seq_array[offset + num_items] = seq;
1336 trim[offset + num_items] = do_trim;
1339 if (seq->type == SEQ_TYPE_META) {
1340 /* trim the sub-sequences */
1341 num_items += slip_add_sequences_rec(&seq->seqbase, seq_array, trim, num_items + offset, false);
1343 else if (seq->type & SEQ_TYPE_EFFECT) {
1344 trim[offset + num_items] = false;
1352 static int slip_count_sequences_rec(ListBase *seqbasep, bool first_level)
1355 int trimmed_sequences = 0;
1357 for (seq = seqbasep->first; seq; seq = seq->next) {
1358 if (!first_level || (!(seq->type & SEQ_TYPE_EFFECT) && (seq->flag & SELECT))) {
1359 trimmed_sequences++;
1361 if (seq->type == SEQ_TYPE_META) {
1362 /* trim the sub-sequences */
1363 trimmed_sequences += slip_count_sequences_rec(&seq->seqbase, false);
1368 return trimmed_sequences;
1371 static int sequencer_slip_invoke(bContext *C, wmOperator *op, const wmEvent *event)
1374 Scene *scene = CTX_data_scene(C);
1375 Editing *ed = BKE_sequencer_editing_get(scene, false);
1376 ARegion *ar = CTX_wm_region(C);
1379 View2D *v2d = UI_view2d_fromcontext(C);
1381 /* first recursively cound the trimmed elements */
1382 num_seq = slip_count_sequences_rec(ed->seqbasep, true);
1385 return OPERATOR_CANCELLED;
1387 data = op->customdata = MEM_mallocN(sizeof(SlipData), "trimdata");
1388 data->ts = MEM_mallocN(num_seq * sizeof(TransSeq), "trimdata_transform");
1389 data->seq_array = MEM_mallocN(num_seq * sizeof(Sequence *), "trimdata_sequences");
1390 data->trim = MEM_mallocN(num_seq * sizeof(bool), "trimdata_trim");
1391 data->num_seq = num_seq;
1393 initNumInput(&data->num_input);
1394 data->num_input.idx_max = 0;
1395 data->num_input.val_flag[0] |= NUM_NO_FRACTION;
1396 data->num_input.unit_sys = USER_UNIT_NONE;
1397 data->num_input.unit_type[0] = 0;
1400 slip_add_sequences_rec(ed->seqbasep, data->seq_array, data->trim, 0, true);
1402 for (i = 0; i < num_seq; i++) {
1403 transseq_backup(data->ts + i, data->seq_array[i]);
1406 data->draw_handle = ED_region_draw_cb_activate(ar->type, draw_slip_extensions, data, REGION_DRAW_POST_VIEW);
1408 UI_view2d_region_to_view(v2d, event->mval[0], event->mval[1], &mouseloc[0], &mouseloc[1]);
1410 copy_v2_v2_int(data->init_mouse, event->mval);
1411 copy_v2_v2(data->init_mouseloc, mouseloc);
1415 WM_event_add_modal_handler(C, op);
1417 /* notify so we draw extensions immediately */
1418 WM_event_add_notifier(C, NC_SCENE | ND_SEQUENCER, scene);
1420 return OPERATOR_RUNNING_MODAL;
1423 static bool sequencer_slip_recursively(Scene *scene, SlipData *data, int offset)
1426 /* only data types supported for now */
1428 Editing *ed = BKE_sequencer_editing_get(scene, false);
1431 /* we iterate in reverse so metastrips are iterated after their children */
1432 for (i = data->num_seq - 1; i >= 0; i--) {
1433 Sequence *seq = data->seq_array[i];
1435 /* we have the offset, do the terrible math */
1437 /* first, do the offset */
1438 seq->start = data->ts[i].start + offset;
1440 if (data->trim[i]) {
1441 /* find the endframe */
1442 endframe = seq->start + seq->len;
1444 /* now compute the terrible offsets */
1445 if (endframe > seq->enddisp) {
1447 seq->endofs = endframe - seq->enddisp;
1449 else if (endframe <= seq->enddisp) {
1450 seq->endstill = seq->enddisp - endframe;
1454 if (seq->start > seq->startdisp) {
1455 seq->startstill = seq->start - seq->startdisp;
1458 else if (seq->start <= seq->startdisp) {
1459 seq->startstill = 0;
1460 seq->startofs = seq->startdisp - seq->start;
1464 /* if no real trim, don't change the data, rather transform the strips themselves */
1465 seq->startdisp = data->ts[i].startdisp + offset;
1466 seq->enddisp = data->ts[i].enddisp + offset;
1469 /* 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
1470 * This way we can avoid an extra loop just for effects*/
1471 if (!(seq->type & SEQ_TYPE_EFFECT))
1472 BKE_sequence_calc(scene, seq);
1474 BKE_sequencer_free_imbuf(scene, &ed->seqbase, false);
1482 static int sequencer_slip_exec(bContext *C, wmOperator *op)
1485 Scene *scene = CTX_data_scene(C);
1486 Editing *ed = BKE_sequencer_editing_get(scene, false);
1488 int offset = RNA_int_get(op->ptr, "offset");
1489 bool success = false;
1491 /* first recursively cound the trimmed elements */
1492 num_seq = slip_count_sequences_rec(ed->seqbasep, true);
1495 return OPERATOR_CANCELLED;
1497 data = op->customdata = MEM_mallocN(sizeof(SlipData), "trimdata");
1498 data->ts = MEM_mallocN(num_seq * sizeof(TransSeq), "trimdata_transform");
1499 data->seq_array = MEM_mallocN(num_seq * sizeof(Sequence *), "trimdata_sequences");
1500 data->trim = MEM_mallocN(num_seq * sizeof(bool), "trimdata_trim");
1501 data->num_seq = num_seq;
1503 slip_add_sequences_rec(ed->seqbasep, data->seq_array, data->trim, 0, true);
1505 for (i = 0; i < num_seq; i++) {
1506 transseq_backup(data->ts + i, data->seq_array[i]);
1509 success = sequencer_slip_recursively(scene, data, offset);
1511 MEM_freeN(data->seq_array);
1512 MEM_freeN(data->trim);
1513 MEM_freeN(data->ts);
1517 WM_event_add_notifier(C, NC_SCENE | ND_SEQUENCER, scene);
1518 return OPERATOR_FINISHED;
1521 return OPERATOR_CANCELLED;
1526 static void sequencer_slip_update_header(Scene *scene, ScrArea *sa, SlipData *data, int offset)
1528 #define HEADER_LENGTH 40
1529 char msg[HEADER_LENGTH];
1532 if (hasNumInput(&data->num_input)) {
1533 char num_str[NUM_STR_REP_LEN];
1534 outputNumInput(&data->num_input, num_str, &scene->unit);
1535 BLI_snprintf(msg, HEADER_LENGTH, "Trim offset: %s", num_str);
1538 BLI_snprintf(msg, HEADER_LENGTH, "Trim offset: %d", offset);
1542 ED_area_headerprint(sa, msg);
1544 #undef HEADER_LENGTH
1547 static int sequencer_slip_modal(bContext *C, wmOperator *op, const wmEvent *event)
1549 Scene *scene = CTX_data_scene(C);
1550 SlipData *data = (SlipData *)op->customdata;
1551 ScrArea *sa = CTX_wm_area(C);
1552 ARegion *ar = CTX_wm_region(C);
1553 const bool has_numInput = hasNumInput(&data->num_input);
1554 bool handled = true;
1556 /* Modal numinput active, try to handle numeric inputs first... */
1557 if (event->val == KM_PRESS && has_numInput && handleNumInput(C, &data->num_input, event)) {
1559 applyNumInput(&data->num_input, &offset);
1561 sequencer_slip_update_header(scene, sa, data, (int)offset);
1563 RNA_int_set(op->ptr, "offset", offset);
1565 if (sequencer_slip_recursively(scene, data, offset)) {
1566 WM_event_add_notifier(C, NC_SCENE | ND_SEQUENCER, scene);
1569 return OPERATOR_RUNNING_MODAL;
1572 switch (event->type) {
1575 if (!has_numInput) {
1579 View2D *v2d = UI_view2d_fromcontext(C);
1582 mouse_x = event->mval[0] - data->slow_offset;
1584 mouse_x += data->slow_offset;
1587 mouse_x = event->mval[0];
1591 /* choose the side based on which side of the playhead the mouse is on */
1592 UI_view2d_region_to_view(v2d, mouse_x, 0, &mouseloc[0], &mouseloc[1]);
1593 offset = mouseloc[0] - data->init_mouseloc[0];
1595 sequencer_slip_update_header(scene, sa, data, offset);
1597 RNA_int_set(op->ptr, "offset", offset);
1599 if (sequencer_slip_recursively(scene, data, offset)) {
1600 WM_event_add_notifier(C, NC_SCENE | ND_SEQUENCER, scene);
1610 ED_region_draw_cb_exit(ar->type, data->draw_handle);
1611 MEM_freeN(data->seq_array);
1612 MEM_freeN(data->trim);
1613 MEM_freeN(data->ts);
1615 op->customdata = NULL;
1617 ED_area_headerprint(sa, NULL);
1619 WM_event_add_notifier(C, NC_SCENE | ND_SEQUENCER, scene);
1620 return OPERATOR_FINISHED;
1627 Editing *ed = BKE_sequencer_editing_get(scene, false);
1629 for (i = 0; i < data->num_seq; i++) {
1630 transseq_restore(data->ts + i, data->seq_array[i]);
1633 for (i = 0; i < data->num_seq; i++) {
1634 Sequence *seq = data->seq_array[i];
1635 BKE_sequence_reload_new_file(scene, seq, false);
1636 BKE_sequence_calc(scene, seq);
1639 ED_region_draw_cb_exit(ar->type, data->draw_handle);
1641 MEM_freeN(data->seq_array);
1642 MEM_freeN(data->ts);
1643 MEM_freeN(data->trim);
1645 op->customdata = NULL;
1647 WM_event_add_notifier(C, NC_SCENE | ND_SEQUENCER, scene);
1649 BKE_sequencer_free_imbuf(scene, &ed->seqbase, false);
1652 ED_area_headerprint(sa, NULL);
1655 return OPERATOR_CANCELLED;
1660 if (!has_numInput) {
1661 if (event->val == KM_PRESS) {
1663 data->slow_offset = event->mval[0];
1665 else if (event->val == KM_RELEASE) {
1676 /* Modal numinput inactive, try to handle numeric inputs last... */
1677 if (!handled && event->val == KM_PRESS && handleNumInput(C, &data->num_input, event)) {
1679 applyNumInput(&data->num_input, &offset);
1681 sequencer_slip_update_header(scene, sa, data, (int)offset);
1683 RNA_int_set(op->ptr, "offset", offset);
1685 if (sequencer_slip_recursively(scene, data, offset)) {
1686 WM_event_add_notifier(C, NC_SCENE | ND_SEQUENCER, scene);
1690 return OPERATOR_RUNNING_MODAL;
1693 void SEQUENCER_OT_slip(struct wmOperatorType *ot)
1696 ot->name = "Trim Strips";
1697 ot->idname = "SEQUENCER_OT_slip";
1698 ot->description = "Trim the contents of the active strip";
1701 ot->invoke = sequencer_slip_invoke;
1702 ot->modal = sequencer_slip_modal;
1703 ot->exec = sequencer_slip_exec;
1704 ot->poll = sequencer_edit_poll;
1707 ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
1709 RNA_def_int(ot->srna, "offset", 0, INT32_MIN, INT32_MAX, "Offset", "Offset to the data of the strip",
1710 INT32_MIN, INT32_MAX);
1714 static int sequencer_mute_exec(bContext *C, wmOperator *op)
1716 Scene *scene = CTX_data_scene(C);
1717 Editing *ed = BKE_sequencer_editing_get(scene, false);
1721 selected = !RNA_boolean_get(op->ptr, "unselected");
1723 for (seq = ed->seqbasep->first; seq; seq = seq->next) {
1724 if ((seq->flag & SEQ_LOCK) == 0) {
1725 if (selected) { /* mute unselected */
1726 if (seq->flag & SELECT) {
1727 seq->flag |= SEQ_MUTE;
1728 BKE_sequence_invalidate_dependent(scene, seq);
1732 if ((seq->flag & SELECT) == 0) {
1733 seq->flag |= SEQ_MUTE;
1734 BKE_sequence_invalidate_dependent(scene, seq);
1740 BKE_sequencer_update_muting(ed);
1741 WM_event_add_notifier(C, NC_SCENE | ND_SEQUENCER, scene);
1743 return OPERATOR_FINISHED;
1746 void SEQUENCER_OT_mute(struct wmOperatorType *ot)
1749 ot->name = "Mute Strips";
1750 ot->idname = "SEQUENCER_OT_mute";
1751 ot->description = "Mute (un)selected strips";
1754 ot->exec = sequencer_mute_exec;
1755 ot->poll = sequencer_edit_poll;
1758 ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
1760 RNA_def_boolean(ot->srna, "unselected", 0, "Unselected", "Mute unselected rather than selected strips");
1764 /* unmute operator */
1765 static int sequencer_unmute_exec(bContext *C, wmOperator *op)
1767 Scene *scene = CTX_data_scene(C);
1768 Editing *ed = BKE_sequencer_editing_get(scene, false);
1772 selected = !RNA_boolean_get(op->ptr, "unselected");
1774 for (seq = ed->seqbasep->first; seq; seq = seq->next) {
1775 if ((seq->flag & SEQ_LOCK) == 0) {
1776 if (selected) { /* unmute unselected */
1777 if (seq->flag & SELECT) {
1778 seq->flag &= ~SEQ_MUTE;
1779 BKE_sequence_invalidate_dependent(scene, seq);
1783 if ((seq->flag & SELECT) == 0) {
1784 seq->flag &= ~SEQ_MUTE;
1785 BKE_sequence_invalidate_dependent(scene, seq);
1791 BKE_sequencer_update_muting(ed);
1792 WM_event_add_notifier(C, NC_SCENE | ND_SEQUENCER, scene);
1794 return OPERATOR_FINISHED;
1797 void SEQUENCER_OT_unmute(struct wmOperatorType *ot)
1800 ot->name = "Un-Mute Strips";
1801 ot->idname = "SEQUENCER_OT_unmute";
1802 ot->description = "Unmute (un)selected strips";
1805 ot->exec = sequencer_unmute_exec;
1806 ot->poll = sequencer_edit_poll;
1809 ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
1811 RNA_def_boolean(ot->srna, "unselected", 0, "Unselected", "Unmute unselected rather than selected strips");
1816 static int sequencer_lock_exec(bContext *C, wmOperator *UNUSED(op))
1818 Scene *scene = CTX_data_scene(C);
1819 Editing *ed = BKE_sequencer_editing_get(scene, false);
1822 for (seq = ed->seqbasep->first; seq; seq = seq->next) {
1823 if (seq->flag & SELECT) {
1824 seq->flag |= SEQ_LOCK;
1828 WM_event_add_notifier(C, NC_SCENE | ND_SEQUENCER, scene);
1830 return OPERATOR_FINISHED;
1833 void SEQUENCER_OT_lock(struct wmOperatorType *ot)
1836 ot->name = "Lock Strips";
1837 ot->idname = "SEQUENCER_OT_lock";
1838 ot->description = "Lock the active strip so that it can't be transformed";
1841 ot->exec = sequencer_lock_exec;
1842 ot->poll = sequencer_edit_poll;
1845 ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
1848 /* unlock operator */
1849 static int sequencer_unlock_exec(bContext *C, wmOperator *UNUSED(op))
1851 Scene *scene = CTX_data_scene(C);
1852 Editing *ed = BKE_sequencer_editing_get(scene, false);
1855 for (seq = ed->seqbasep->first; seq; seq = seq->next) {
1856 if (seq->flag & SELECT) {
1857 seq->flag &= ~SEQ_LOCK;
1861 WM_event_add_notifier(C, NC_SCENE | ND_SEQUENCER, scene);
1863 return OPERATOR_FINISHED;
1866 void SEQUENCER_OT_unlock(struct wmOperatorType *ot)
1869 ot->name = "UnLock Strips";
1870 ot->idname = "SEQUENCER_OT_unlock";
1871 ot->description = "Unlock the active strip so that it can't be transformed";
1874 ot->exec = sequencer_unlock_exec;
1875 ot->poll = sequencer_edit_poll;
1878 ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
1881 /* reload operator */
1882 static int sequencer_reload_exec(bContext *C, wmOperator *op)
1884 Scene *scene = CTX_data_scene(C);
1885 Editing *ed = BKE_sequencer_editing_get(scene, false);
1887 const bool adjust_length = RNA_boolean_get(op->ptr, "adjust_length");
1889 for (seq = ed->seqbasep->first; seq; seq = seq->next) {
1890 if (seq->flag & SELECT) {
1891 BKE_sequencer_update_changed_seq_and_deps(scene, seq, 0, 1);
1892 BKE_sequence_reload_new_file(scene, seq, !adjust_length);
1894 if (adjust_length) {
1895 if (BKE_sequence_test_overlap(ed->seqbasep, seq))
1896 BKE_sequence_base_shuffle(ed->seqbasep, seq, scene);
1901 WM_event_add_notifier(C, NC_SCENE | ND_SEQUENCER, scene);
1903 return OPERATOR_FINISHED;
1906 void SEQUENCER_OT_reload(struct wmOperatorType *ot)
1911 ot->name = "Reload Strips";
1912 ot->idname = "SEQUENCER_OT_reload";
1913 ot->description = "Reload strips in the sequencer";
1916 ot->exec = sequencer_reload_exec;
1917 ot->poll = sequencer_edit_poll;
1920 ot->flag = OPTYPE_REGISTER; /* no undo, the data changed is stored outside 'main' */
1922 prop = RNA_def_boolean(ot->srna, "adjust_length", 0, "Adjust Length",
1923 "Adjust length of strips to their data length");
1924 RNA_def_property_flag(prop, PROP_SKIP_SAVE);
1927 /* reload operator */
1928 static int sequencer_refresh_all_exec(bContext *C, wmOperator *UNUSED(op))
1930 Scene *scene = CTX_data_scene(C);
1931 Editing *ed = BKE_sequencer_editing_get(scene, false);
1933 BKE_sequencer_free_imbuf(scene, &ed->seqbase, false);
1935 WM_event_add_notifier(C, NC_SCENE | ND_SEQUENCER, scene);
1937 return OPERATOR_FINISHED;
1940 void SEQUENCER_OT_refresh_all(struct wmOperatorType *ot)
1943 ot->name = "Refresh Sequencer";
1944 ot->idname = "SEQUENCER_OT_refresh_all";
1945 ot->description = "Refresh the sequencer editor";
1948 ot->exec = sequencer_refresh_all_exec;
1949 ot->poll = sequencer_edit_poll;
1952 static int sequencer_reassign_inputs_exec(bContext *C, wmOperator *op)
1954 Scene *scene = CTX_data_scene(C);
1955 Sequence *seq1, *seq2, *seq3, *last_seq = BKE_sequencer_active_get(scene);
1956 const char *error_msg;
1958 if (!seq_effect_find_selected(scene, last_seq, last_seq->type, &seq1, &seq2, &seq3, &error_msg)) {
1959 BKE_report(op->reports, RPT_ERROR, error_msg);
1960 return OPERATOR_CANCELLED;
1962 /* see reassigning would create a cycle */
1963 if (seq_is_predecessor(seq1, last_seq) ||
1964 seq_is_predecessor(seq2, last_seq) ||
1965 seq_is_predecessor(seq3, last_seq))
1967 BKE_report(op->reports, RPT_ERROR, "Cannot reassign inputs: no cycles allowed");
1968 return OPERATOR_CANCELLED;
1971 last_seq->seq1 = seq1;
1972 last_seq->seq2 = seq2;
1973 last_seq->seq3 = seq3;
1975 BKE_sequencer_update_changed_seq_and_deps(scene, last_seq, 1, 1);
1977 WM_event_add_notifier(C, NC_SCENE | ND_SEQUENCER, scene);
1979 return OPERATOR_FINISHED;
1982 static int sequencer_effect_poll(bContext *C)
1984 Scene *scene = CTX_data_scene(C);
1985 Editing *ed = BKE_sequencer_editing_get(scene, false);
1988 Sequence *last_seq = BKE_sequencer_active_get(scene);
1989 if (last_seq && (last_seq->type & SEQ_TYPE_EFFECT)) {
1997 void SEQUENCER_OT_reassign_inputs(struct wmOperatorType *ot)
2000 ot->name = "Reassign Inputs";
2001 ot->idname = "SEQUENCER_OT_reassign_inputs";
2002 ot->description = "Reassign the inputs for the effect strip";
2005 ot->exec = sequencer_reassign_inputs_exec;
2006 ot->poll = sequencer_effect_poll;
2009 ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
2013 static int sequencer_swap_inputs_exec(bContext *C, wmOperator *op)
2015 Scene *scene = CTX_data_scene(C);
2016 Sequence *seq, *last_seq = BKE_sequencer_active_get(scene);
2018 if (last_seq->seq1 == NULL || last_seq->seq2 == NULL) {
2019 BKE_report(op->reports, RPT_ERROR, "No valid inputs to swap");
2020 return OPERATOR_CANCELLED;
2023 seq = last_seq->seq1;
2024 last_seq->seq1 = last_seq->seq2;
2025 last_seq->seq2 = seq;
2027 BKE_sequencer_update_changed_seq_and_deps(scene, last_seq, 1, 1);
2029 WM_event_add_notifier(C, NC_SCENE | ND_SEQUENCER, scene);
2031 return OPERATOR_FINISHED;
2033 void SEQUENCER_OT_swap_inputs(struct wmOperatorType *ot)
2036 ot->name = "Swap Inputs";
2037 ot->idname = "SEQUENCER_OT_swap_inputs";
2038 ot->description = "Swap the first two inputs for the effect strip";
2041 ot->exec = sequencer_swap_inputs_exec;
2042 ot->poll = sequencer_effect_poll;
2045 ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
2050 static EnumPropertyItem prop_cut_types[] = {
2051 {SEQ_CUT_SOFT, "SOFT", 0, "Soft", ""},
2052 {SEQ_CUT_HARD, "HARD", 0, "Hard", ""},
2053 {0, NULL, 0, NULL, NULL}
2056 static int sequencer_cut_exec(bContext *C, wmOperator *op)
2058 Scene *scene = CTX_data_scene(C);
2059 Editing *ed = BKE_sequencer_editing_get(scene, false);
2060 int cut_side, cut_hard, cut_frame;
2064 cut_frame = RNA_int_get(op->ptr, "frame");
2065 cut_hard = RNA_enum_get(op->ptr, "type");
2066 cut_side = RNA_enum_get(op->ptr, "side");
2068 if (cut_hard == SEQ_CUT_HARD) {
2069 changed = cut_seq_list(scene, ed->seqbasep, cut_frame, cut_seq_hard);
2072 changed = cut_seq_list(scene, ed->seqbasep, cut_frame, cut_seq_soft);
2075 if (changed) { /* got new strips ? */
2078 if (cut_side != SEQ_SIDE_BOTH) {
2079 SEQP_BEGIN (ed, seq)
2081 if (cut_side == SEQ_SIDE_LEFT) {
2082 if (seq->startdisp >= cut_frame) {
2083 seq->flag &= ~SEQ_ALLSEL;
2087 if (seq->enddisp <= cut_frame) {
2088 seq->flag &= ~SEQ_ALLSEL;
2095 SEQP_BEGIN (ed, seq)
2097 if (seq->seq1 || seq->seq2 || seq->seq3) {
2098 BKE_sequence_calc(scene, seq);
2104 BKE_sequencer_sort(scene);
2108 WM_event_add_notifier(C, NC_SCENE | ND_SEQUENCER, scene);
2109 return OPERATOR_FINISHED;
2112 return OPERATOR_CANCELLED;
2117 static int sequencer_cut_invoke(bContext *C, wmOperator *op, const wmEvent *event)
2119 Scene *scene = CTX_data_scene(C);
2120 View2D *v2d = UI_view2d_fromcontext(C);
2122 int cut_side = SEQ_SIDE_BOTH;
2123 int cut_frame = CFRA;
2125 if (ED_operator_sequencer_active(C) && v2d)
2126 cut_side = mouse_frame_side(v2d, event->mval[0], cut_frame);
2128 RNA_int_set(op->ptr, "frame", cut_frame);
2129 RNA_enum_set(op->ptr, "side", cut_side);
2130 /*RNA_enum_set(op->ptr, "type", cut_hard); */ /*This type is set from the key shortcut */
2132 return sequencer_cut_exec(C, op);
2136 void SEQUENCER_OT_cut(struct wmOperatorType *ot)
2139 ot->name = "Cut Strips";
2140 ot->idname = "SEQUENCER_OT_cut";
2141 ot->description = "Cut the selected strips";
2144 ot->invoke = sequencer_cut_invoke;
2145 ot->exec = sequencer_cut_exec;
2146 ot->poll = sequencer_edit_poll;
2149 ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
2151 RNA_def_int(ot->srna, "frame", 0, INT_MIN, INT_MAX, "Frame", "Frame where selected strips will be cut", INT_MIN, INT_MAX);
2152 RNA_def_enum(ot->srna, "type", prop_cut_types, SEQ_CUT_SOFT, "Type", "The type of cut operation to perform on strips");
2153 RNA_def_enum(ot->srna, "side", prop_side_types, SEQ_SIDE_BOTH, "Side", "The side that remains selected after cutting");
2156 /* duplicate operator */
2157 static int apply_unique_name_cb(Sequence *seq, void *arg_pt)
2159 Scene *scene = (Scene *)arg_pt;
2160 char name[sizeof(seq->name) - 2];
2162 BLI_strncpy_utf8(name, seq->name + 2, sizeof(name));
2163 BKE_sequence_base_unique_name_recursive(&scene->ed->seqbase, seq);
2164 BKE_sequencer_dupe_animdata(scene, name, seq->name + 2);
2169 static int sequencer_add_duplicate_exec(bContext *C, wmOperator *UNUSED(op))
2171 Scene *scene = CTX_data_scene(C);
2172 Editing *ed = BKE_sequencer_editing_get(scene, false);
2174 ListBase nseqbase = {NULL, NULL};
2177 return OPERATOR_CANCELLED;
2179 BKE_sequence_base_dupli_recursive(scene, NULL, &nseqbase, ed->seqbasep, SEQ_DUPE_CONTEXT);
2181 if (nseqbase.first) {
2182 Sequence *seq = nseqbase.first;
2183 /* rely on the nseqbase list being added at the end */
2184 BLI_movelisttolist(ed->seqbasep, &nseqbase);
2186 for (; seq; seq = seq->next)
2187 BKE_sequencer_recursive_apply(seq, apply_unique_name_cb, scene);
2189 WM_event_add_notifier(C, NC_SCENE | ND_SEQUENCER, scene);
2190 return OPERATOR_FINISHED;
2193 return OPERATOR_CANCELLED;
2196 void SEQUENCER_OT_duplicate(wmOperatorType *ot)
2199 ot->name = "Duplicate Strips";
2200 ot->idname = "SEQUENCER_OT_duplicate";
2201 ot->description = "Duplicate the selected strips";
2204 ot->exec = sequencer_add_duplicate_exec;
2205 ot->poll = ED_operator_sequencer_active;
2208 ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
2210 /* to give to transform */
2211 RNA_def_enum(ot->srna, "mode", transform_mode_types, TFM_TRANSLATION, "Mode", "");
2214 /* delete operator */
2215 static int sequencer_delete_exec(bContext *C, wmOperator *UNUSED(op))
2217 Scene *scene = CTX_data_scene(C);
2218 Editing *ed = BKE_sequencer_editing_get(scene, false);
2221 bool nothingSelected = true;
2223 seq = BKE_sequencer_active_get(scene);
2224 if (seq && seq->flag & SELECT) { /* avoid a loop since this is likely to be selected */
2225 nothingSelected = false;
2228 for (seq = ed->seqbasep->first; seq; seq = seq->next) {
2229 if (seq->flag & SELECT) {
2230 nothingSelected = false;
2236 if (nothingSelected)
2237 return OPERATOR_FINISHED;
2239 /* for effects and modifiers, try to find a replacement input */
2240 for (seq = ed->seqbasep->first; seq; seq = seq->next) {
2241 if (!(seq->flag & SELECT)) {
2242 if ((seq->type & SEQ_TYPE_EFFECT)) {
2243 del_seq_find_replace_recurs(scene, seq);
2247 del_seq_clear_modifiers_recurs(scene, seq);
2251 /* delete all selected strips */
2252 recurs_del_seq_flag(scene, ed->seqbasep, SELECT, 0);
2254 /* updates lengths etc */
2255 seq = ed->seqbasep->first;
2257 BKE_sequence_calc(scene, seq);
2261 /* free parent metas */
2262 ms = ed->metastack.last;
2264 BKE_sequence_calc(scene, ms->parseq);
2268 WM_event_add_notifier(C, NC_SCENE | ND_SEQUENCER, scene);
2270 return OPERATOR_FINISHED;
2273 static int sequencer_delete_invoke(bContext *C, wmOperator *op, const wmEvent *event)
2275 ARegion *ar = CTX_wm_region(C);
2277 if (ar->regiontype == RGN_TYPE_WINDOW) {
2278 /* bounding box of 30 pixels is used for markers shortcuts,
2279 * prevent conflict with markers shortcuts here
2281 if (event->mval[1] <= 30)
2282 return OPERATOR_PASS_THROUGH;
2285 return WM_operator_confirm(C, op, event);
2288 void SEQUENCER_OT_delete(wmOperatorType *ot)
2292 ot->name = "Erase Strips";
2293 ot->idname = "SEQUENCER_OT_delete";
2294 ot->description = "Erase selected strips from the sequencer";
2297 ot->invoke = sequencer_delete_invoke;
2298 ot->exec = sequencer_delete_exec;
2299 ot->poll = sequencer_edit_poll;
2302 ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
2306 /* offset clear operator */
2307 static int sequencer_offset_clear_exec(bContext *C, wmOperator *UNUSED(op))
2309 Scene *scene = CTX_data_scene(C);
2310 Editing *ed = BKE_sequencer_editing_get(scene, false);
2313 /* for effects, try to find a replacement input */
2314 for (seq = ed->seqbasep->first; seq; seq = seq->next) {
2315 if ((seq->type & SEQ_TYPE_EFFECT) == 0 && (seq->flag & SELECT)) {
2316 seq->startofs = seq->endofs = seq->startstill = seq->endstill = 0;
2320 /* updates lengths etc */
2321 seq = ed->seqbasep->first;
2323 BKE_sequence_calc(scene, seq);
2327 for (seq = ed->seqbasep->first; seq; seq = seq->next) {
2328 if ((seq->type & SEQ_TYPE_EFFECT) == 0 && (seq->flag & SELECT)) {
2329 if (BKE_sequence_test_overlap(ed->seqbasep, seq)) {
2330 BKE_sequence_base_shuffle(ed->seqbasep, seq, scene);
2335 WM_event_add_notifier(C, NC_SCENE | ND_SEQUENCER, scene);
2337 return OPERATOR_FINISHED;
2341 void SEQUENCER_OT_offset_clear(wmOperatorType *ot)
2345 ot->name = "Clear Strip Offset";
2346 ot->idname = "SEQUENCER_OT_offset_clear";
2347 ot->description = "Clear strip offsets from the start and end frames";
2350 ot->exec = sequencer_offset_clear_exec;
2351 ot->poll = sequencer_edit_poll;
2354 ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
2358 /* separate_images operator */
2359 static int sequencer_separate_images_exec(bContext *C, wmOperator *op)
2361 Scene *scene = CTX_data_scene(C);
2362 Editing *ed = BKE_sequencer_editing_get(scene, false);
2364 Sequence *seq, *seq_new;
2366 StripElem *se, *se_new;
2367 int start_ofs, cfra, frame_end;
2368 int step = RNA_int_get(op->ptr, "length");
2370 seq = ed->seqbasep->first; /* poll checks this is valid */
2373 if ((seq->flag & SELECT) && (seq->type == SEQ_TYPE_IMAGE) && (seq->len > 1)) {
2376 /* remove seq so overlap tests don't conflict,
2377 * see seq_free_sequence below for the real free'ing */
2378 BLI_remlink(ed->seqbasep, seq);
2379 /* if (seq->ipo) seq->ipo->id.us--; */
2380 /* XXX, remove fcurve and assign to split image strips */
2382 start_ofs = cfra = BKE_sequence_tx_get_final_left(seq, false);
2383 frame_end = BKE_sequence_tx_get_final_right(seq, false);
2385 while (cfra < frame_end) {
2387 se = BKE_sequencer_give_stripelem(seq, cfra);
2389 seq_new = BKE_sequence_dupli_recursive(scene, scene, seq, SEQ_DUPE_UNIQUE_NAME);
2390 BLI_addtail(ed->seqbasep, seq_new);
2392 seq_new->start = start_ofs;
2393 seq_new->type = SEQ_TYPE_IMAGE;
2395 seq_new->endstill = step - 1;
2398 strip_new = seq_new->strip;
2401 /* new stripdata (only one element now!) */
2402 /* Note this assume all elements (images) have the same dimension, since we only copy the name here. */
2403 se_new = MEM_reallocN(strip_new->stripdata, sizeof(*se_new));
2404 BLI_strncpy(se_new->name, se->name, sizeof(se_new->name));
2405 strip_new->stripdata = se_new;
2407 BKE_sequence_calc(scene, seq_new);
2410 seq_new->flag &= ~SEQ_OVERLAP;
2411 if (BKE_sequence_test_overlap(ed->seqbasep, seq_new)) {
2412 BKE_sequence_base_shuffle(ed->seqbasep, seq_new, scene);
2416 /* XXX, COPY FCURVES */
2422 seq_next = seq->next;
2423 BKE_sequence_free(scene, seq);
2432 BKE_sequencer_sort(scene);
2434 WM_event_add_notifier(C, NC_SCENE | ND_SEQUENCER, scene);
2436 return OPERATOR_FINISHED;
2440 void SEQUENCER_OT_images_separate(wmOperatorType *ot)
2443 ot->name = "Separate Images";
2444 ot->idname = "SEQUENCER_OT_images_separate";
2445 ot->description = "On image sequence strips, it returns a strip for each image";
2448 ot->exec = sequencer_separate_images_exec;
2449 ot->invoke = WM_operator_props_popup;
2450 ot->poll = sequencer_edit_poll;
2453 ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
2455 RNA_def_int(ot->srna, "length", 1, 1, INT_MAX, "Length", "Length of each frame", 1, 1000);
2459 /* META Operators */
2461 /* separate_meta_toggle operator */
2462 static int sequencer_meta_toggle_exec(bContext *C, wmOperator *UNUSED(op))
2464 Scene *scene = CTX_data_scene(C);
2465 Editing *ed = BKE_sequencer_editing_get(scene, false);
2466 Sequence *last_seq = BKE_sequencer_active_get(scene);
2469 if (last_seq && last_seq->type == SEQ_TYPE_META && last_seq->flag & SELECT) {
2470 /* Enter Metastrip */
2471 ms = MEM_mallocN(sizeof(MetaStack), "metastack");
2472 BLI_addtail(&ed->metastack, ms);
2473 ms->parseq = last_seq;
2474 ms->oldbasep = ed->seqbasep;
2475 copy_v2_v2_int(ms->disp_range, &ms->parseq->startdisp);
2477 ed->seqbasep = &last_seq->seqbase;
2479 BKE_sequencer_active_set(scene, NULL);
2483 /* Exit Metastrip (if possible) */
2487 if (BLI_listbase_is_empty(&ed->metastack))
2488 return OPERATOR_CANCELLED;
2490 ms = ed->metastack.last;
2491 BLI_remlink(&ed->metastack, ms);
2493 ed->seqbasep = ms->oldbasep;
2495 /* for old files, update from meta */
2496 if (ms->disp_range[0] == ms->disp_range[1]) {
2497 copy_v2_v2_int(ms->disp_range, &ms->parseq->startdisp);
2500 /* recalc all: the meta can have effects connected to it */
2501 for (seq = ed->seqbasep->first; seq; seq = seq->next)
2502 BKE_sequence_calc(scene, seq);
2504 /* 2.73+, keeping endpoings is important!
2505 * moving them around means you can't usefully use metas in a complex edit */
2507 BKE_sequence_tx_set_final_left(ms->parseq, ms->disp_range[0]);
2508 BKE_sequence_tx_set_final_right(ms->parseq, ms->disp_range[1]);
2509 BKE_sequence_calc(scene, ms->parseq);
2511 if (BKE_sequence_test_overlap(ed->seqbasep, ms->parseq))
2512 BKE_sequence_base_shuffle(ed->seqbasep, ms->parseq, scene);
2515 BKE_sequencer_active_set(scene, ms->parseq);
2517 ms->parseq->flag |= SELECT;
2518 recurs_sel_seq(ms->parseq);
2524 BKE_sequencer_update_muting(ed);
2525 WM_event_add_notifier(C, NC_SCENE | ND_SEQUENCER, scene);
2527 return OPERATOR_FINISHED;
2530 void SEQUENCER_OT_meta_toggle(wmOperatorType *ot)
2533 ot->name = "Toggle Meta Strip";
2534 ot->idname = "SEQUENCER_OT_meta_toggle";
2535 ot->description = "Toggle a metastrip (to edit enclosed strips)";
2538 ot->exec = sequencer_meta_toggle_exec;
2539 ot->poll = sequencer_edit_poll;
2542 ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
2546 /* separate_meta_make operator */
2547 static int sequencer_meta_make_exec(bContext *C, wmOperator *op)
2549 Scene *scene = CTX_data_scene(C);
2550 Editing *ed = BKE_sequencer_editing_get(scene, false);
2552 Sequence *seq, *seqm, *next, *last_seq = BKE_sequencer_active_get(scene);
2553 int channel_max = 1;
2555 if (BKE_sequence_base_isolated_sel_check(ed->seqbasep) == false) {
2556 BKE_report(op->reports, RPT_ERROR, "Please select all related strips");
2557 return OPERATOR_CANCELLED;
2560 /* remove all selected from main list, and put in meta */
2562 seqm = BKE_sequence_alloc(ed->seqbasep, 1, 1); /* channel number set later */
2563 strcpy(seqm->name + 2, "MetaStrip");
2564 seqm->type = SEQ_TYPE_META;
2565 seqm->flag = SELECT;
2567 seq = ed->seqbasep->first;
2570 if (seq != seqm && (seq->flag & SELECT)) {
2571 BKE_sequence_invalidate_cache(scene, seq);
2572 channel_max = max_ii(seq->machine, channel_max);
2573 BLI_remlink(ed->seqbasep, seq);
2574 BLI_addtail(&seqm->seqbase, seq);
2578 seqm->machine = last_seq ? last_seq->machine : channel_max;
2579 BKE_sequence_calc(scene, seqm);
2581 seqm->strip = MEM_callocN(sizeof(Strip), "metastrip");
2582 seqm->strip->us = 1;
2584 BKE_sequencer_active_set(scene, seqm);
2586 if (BKE_sequence_test_overlap(ed->seqbasep, seqm) ) BKE_sequence_base_shuffle(ed->seqbasep, seqm, scene);
2588 BKE_sequencer_update_muting(ed);
2590 BKE_sequence_base_unique_name_recursive(&scene->ed->seqbase, seqm);
2592 WM_event_add_notifier(C, NC_SCENE | ND_SEQUENCER, scene);
2594 return OPERATOR_FINISHED;
2597 void SEQUENCER_OT_meta_make(wmOperatorType *ot)
2600 ot->name = "Make Meta Strip";
2601 ot->idname = "SEQUENCER_OT_meta_make";
2602 ot->description = "Group selected strips into a metastrip";
2605 ot->exec = sequencer_meta_make_exec;
2606 ot->poll = sequencer_edit_poll;
2609 ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
2613 static int seq_depends_on_meta(Sequence *seq, Sequence *seqm)
2615 if (seq == seqm) return 1;
2616 else if (seq->seq1 && seq_depends_on_meta(seq->seq1, seqm)) return 1;
2617 else if (seq->seq2 && seq_depends_on_meta(seq->seq2, seqm)) return 1;
2618 else if (seq->seq3 && seq_depends_on_meta(seq->seq3, seqm)) return 1;
2622 /* separate_meta_make operator */
2623 static int sequencer_meta_separate_exec(bContext *C, wmOperator *UNUSED(op))
2625 Scene *scene = CTX_data_scene(C);
2626 Editing *ed = BKE_sequencer_editing_get(scene, false);
2628 Sequence *seq, *last_seq = BKE_sequencer_active_get(scene); /* last_seq checks (ed == NULL) */
2630 if (last_seq == NULL || last_seq->type != SEQ_TYPE_META)
2631 return OPERATOR_CANCELLED;
2633 for (seq = last_seq->seqbase.first; seq != NULL; seq = seq->next) {
2634 BKE_sequence_invalidate_cache(scene, seq);
2637 BLI_movelisttolist(ed->seqbasep, &last_seq->seqbase);
2639 BLI_listbase_clear(&last_seq->seqbase);
2641 BLI_remlink(ed->seqbasep, last_seq);
2642 BKE_sequence_free(scene, last_seq);
2644 /* emtpy meta strip, delete all effects depending on it */
2645 for (seq = ed->seqbasep->first; seq; seq = seq->next)
2646 if ((seq->type & SEQ_TYPE_EFFECT) && seq_depends_on_meta(seq, last_seq))
2647 seq->flag |= SEQ_FLAG_DELETE;
2649 recurs_del_seq_flag(scene, ed->seqbasep, SEQ_FLAG_DELETE, 0);
2651 /* test for effects and overlap
2652 * don't use SEQP_BEGIN since that would be recursive */
2653 for (seq = ed->seqbasep->first; seq; seq = seq->next) {
2654 if (seq->flag & SELECT) {
2655 seq->flag &= ~SEQ_OVERLAP;
2656 if (BKE_sequence_test_overlap(ed->seqbasep, seq)) {
2657 BKE_sequence_base_shuffle(ed->seqbasep, seq, scene);
2662 BKE_sequencer_sort(scene);
2663 BKE_sequencer_update_muting(ed);
2665 WM_event_add_notifier(C, NC_SCENE | ND_SEQUENCER, scene);
2667 return OPERATOR_FINISHED;
2670 void SEQUENCER_OT_meta_separate(wmOperatorType *ot)
2673 ot->name = "UnMeta Strip";
2674 ot->idname = "SEQUENCER_OT_meta_separate";
2675 ot->description = "Put the contents of a metastrip back in the sequencer";
2678 ot->exec = sequencer_meta_separate_exec;
2679 ot->poll = sequencer_edit_poll;
2682 ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
2685 /* view_all operator */
2686 static int sequencer_view_all_exec(bContext *C, wmOperator *op)
2688 ARegion *ar = CTX_wm_region(C);
2689 View2D *v2d = UI_view2d_fromcontext(C);
2690 const int smooth_viewtx = WM_operator_smooth_viewtx_get(op);
2692 UI_view2d_smooth_view(C, ar, &v2d->tot, smooth_viewtx);
2693 return OPERATOR_FINISHED;
2696 void SEQUENCER_OT_view_all(wmOperatorType *ot)
2699 ot->name = "View All";
2700 ot->idname = "SEQUENCER_OT_view_all";
2701 ot->description = "View all the strips in the sequencer";
2704 ot->exec = sequencer_view_all_exec;
2705 ot->poll = ED_operator_sequencer_active;
2708 ot->flag = OPTYPE_REGISTER;
2711 /* view_all operator */
2712 static int sequencer_view_all_preview_exec(bContext *C, wmOperator *UNUSED(op))
2714 bScreen *sc = CTX_wm_screen(C);
2715 ScrArea *area = CTX_wm_area(C);
2717 ARegion *ar = CTX_wm_region(C);
2718 SpaceSeq *sseq = area->spacedata.first;
2719 Scene *scene = CTX_data_scene(C);
2721 View2D *v2d = UI_view2d_fromcontext(C);
2723 v2d->cur = v2d->tot;
2724 UI_view2d_curRect_validate(v2d);
2725 UI_view2d_sync(sc, area, v2d, V2D_LOCK_COPY);
2728 /* Like zooming on an image view */
2730 int width, height, imgwidth, imgheight;
2735 seq_reset_imageofs(sseq);
2737 imgwidth = (scene->r.size * scene->r.xsch) / 100;
2738 imgheight = (scene->r.size * scene->r.ysch) / 100;
2740 /* Apply aspect, dosnt need to be that accurate */
2741 imgwidth = (int)(imgwidth * (scene->r.xasp / scene->r.yasp));
2743 if (((imgwidth >= width) || (imgheight >= height)) &&
2744 ((width > 0) && (height > 0)))
2746 /* Find the zoom value that will fit the image in the image space */
2747 zoomX = ((float)width) / ((float)imgwidth);
2748 zoomY = ((float)height) / ((float)imgheight);
2749 sseq->zoom = (zoomX < zoomY) ? zoomX : zoomY;
2751 sseq->zoom = 1.0f / power_of_2(1 / min_ff(zoomX, zoomY));
2758 ED_area_tag_redraw(CTX_wm_area(C));
2759 return OPERATOR_FINISHED;
2762 void SEQUENCER_OT_view_all_preview(wmOperatorType *ot)
2765 ot->name = "View All";
2766 ot->idname = "SEQUENCER_OT_view_all_preview";
2767 ot->description = "Zoom preview to fit in the area";
2770 ot->exec = sequencer_view_all_preview_exec;
2771 ot->poll = ED_operator_sequencer_active;
2774 ot->flag = OPTYPE_REGISTER;
2778 static int sequencer_view_zoom_ratio_exec(bContext *C, wmOperator *op)
2780 RenderData *rd = &CTX_data_scene(C)->r;
2781 View2D *v2d = UI_view2d_fromcontext(C);
2783 float ratio = RNA_float_get(op->ptr, "ratio");
2785 float winx = (int)(rd->size * rd->xsch) / 100;
2786 float winy = (int)(rd->size * rd->ysch) / 100;
2788 float facx = BLI_rcti_size_x(&v2d->mask) / winx;
2789 float facy = BLI_rcti_size_y(&v2d->mask) / winy;
2791 BLI_rctf_resize(&v2d->cur, floorf(winx * facx / ratio + 0.5f), floorf(winy * facy / ratio + 0.5f));
2793 ED_region_tag_redraw(CTX_wm_region(C));
2795 return OPERATOR_FINISHED;
2798 void SEQUENCER_OT_view_zoom_ratio(wmOperatorType *ot)
2801 ot->name = "Sequencer View Zoom Ratio";
2802 ot->idname = "SEQUENCER_OT_view_zoom_ratio";
2803 ot->description = "Change zoom ratio of sequencer preview";
2806 ot->exec = sequencer_view_zoom_ratio_exec;
2807 ot->poll = ED_operator_sequencer_active;
2810 RNA_def_float(ot->srna, "ratio", 1.0f, -FLT_MAX, FLT_MAX,
2811 "Ratio", "Zoom ratio, 1.0 is 1:1, higher is zoomed in, lower is zoomed out", -FLT_MAX, FLT_MAX);
2816 static EnumPropertyItem view_type_items[] = {
2817 {SEQ_VIEW_SEQUENCE, "SEQUENCER", ICON_SEQ_SEQUENCER, "Sequencer", ""},
2818 {SEQ_VIEW_PREVIEW, "PREVIEW", ICON_SEQ_PREVIEW, "Image Preview", ""},
2819 {SEQ_VIEW_SEQUENCE_PREVIEW, "SEQUENCER_PREVIEW", ICON_SEQ_SEQUENCER, "Sequencer and Image Preview", ""},
2820 {0, NULL, 0, NULL, NULL}
2824 /* view_all operator */
2825 static int sequencer_view_toggle_exec(bContext *C, wmOperator *UNUSED(op))
2827 SpaceSeq *sseq = (SpaceSeq *)CTX_wm_space_data(C);
2830 if (sseq->view > SEQ_VIEW_SEQUENCE_PREVIEW) sseq->view = SEQ_VIEW_SEQUENCE;
2832 ED_area_tag_refresh(CTX_wm_area(C));
2834 return OPERATOR_FINISHED;
2837 void SEQUENCER_OT_view_toggle(wmOperatorType *ot)
2840 ot->name = "View Toggle";
2841 ot->idname = "SEQUENCER_OT_view_toggle";
2842 ot->description = "Toggle between sequencer views (sequence, preview, both)";
2845 ot->exec = sequencer_view_toggle_exec;
2846 ot->poll = ED_operator_sequencer_active;
2849 ot->flag = OPTYPE_REGISTER;
2853 /* view_selected operator */
2854 static int sequencer_view_selected_exec(bContext *C, wmOperator *op)
2856 Scene *scene = CTX_data_scene(C);
2857 View2D *v2d = UI_view2d_fromcontext(C);
2858 ARegion *ar = CTX_wm_region(C);
2859 Editing *ed = BKE_sequencer_editing_get(scene, false);
2860 Sequence *last_seq = BKE_sequencer_active_get(scene);
2862 rctf cur_new = v2d->cur;
2864 int xmin = MAXFRAME * 2;
2865 int xmax = -MAXFRAME * 2;
2866 int ymin = MAXSEQ + 1;
2874 return OPERATOR_CANCELLED;
2876 for (seq = ed->seqbasep->first; seq; seq = seq->next) {
2877 if ((seq->flag & SELECT) || (seq == last_seq)) {
2878 xmin = min_ii(xmin, seq->startdisp);
2879 xmax = max_ii(xmax, seq->enddisp);
2881 ymin = min_ii(ymin, seq->machine);
2882 ymax = max_ii(ymax, seq->machine);
2887 const int smooth_viewtx = WM_operator_smooth_viewtx_get(op);
2894 orig_height = BLI_rctf_size_y(&cur_new);
2896 cur_new.xmin = xmin;
2897 cur_new.xmax = xmax;
2899 cur_new.ymin = ymin;
2900 cur_new.ymax = ymax;
2902 /* only zoom out vertically */
2903 if (orig_height > BLI_rctf_size_y(&cur_new)) {
2904 ymid = BLI_rctf_cent_y(&cur_new);
2906 cur_new.ymin = ymid - (orig_height / 2);
2907 cur_new.ymax = ymid + (orig_height / 2);
2910 UI_view2d_smooth_view(C, ar, &cur_new, smooth_viewtx);
2912 return OPERATOR_FINISHED;
2915 return OPERATOR_CANCELLED;
2920 void SEQUENCER_OT_view_selected(wmOperatorType *ot)
2923 ot->name = "View Selected";
2924 ot->idname = "SEQUENCER_OT_view_selected";
2925 ot->description = "Zoom the sequencer on the selected strips";
2928 ot->exec = sequencer_view_selected_exec;
2929 ot->poll = ED_operator_sequencer_active;
2932 ot->flag = OPTYPE_REGISTER;
2935 static bool strip_jump_internal(Scene *scene,
2937 const bool do_skip_mute, const bool do_center)
2939 bool changed = false;
2941 int nfra = BKE_sequencer_find_next_prev_edit(scene, cfra, side, do_skip_mute, do_center, false);
2951 static int sequencer_strip_jump_poll(bContext *C)
2953 /* prevent changes during render */
2957 return sequencer_edit_poll(C);
2960 /* jump frame to edit point operator */
2961 static int sequencer_strip_jump_exec(bContext *C, wmOperator *op)
2963 Scene *scene = CTX_data_scene(C);
2964 const bool next = RNA_boolean_get(op->ptr, "next");
2965 const bool center = RNA_boolean_get(op->ptr, "center");
2967 /* currently do_skip_mute is always true */
2968 if (!strip_jump_internal(scene, next ? SEQ_SIDE_RIGHT : SEQ_SIDE_LEFT, true, center)) {
2969 return OPERATOR_CANCELLED;
2972 WM_event_add_notifier(C, NC_SCENE | ND_FRAME, scene);
2974 return OPERATOR_FINISHED;
2977 void SEQUENCER_OT_strip_jump(wmOperatorType *ot)
2980 ot->name = "Jump to Strip";
2981 ot->idname = "SEQUENCER_OT_strip_jump";
2982 ot->description = "Move frame to previous edit point";
2985 ot->exec = sequencer_strip_jump_exec;
2986 ot->poll = sequencer_strip_jump_poll;
2989 ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
2992 RNA_def_boolean(ot->srna, "next", true, "Next Strip", "");
2993 RNA_def_boolean(ot->srna, "center", true, "Use strip center", "");
2996 static void swap_sequence(Scene *scene, Sequence *seqa, Sequence *seqb)
2998 int gap = seqb->startdisp - seqa->enddisp;
3002 seq_b_start = (seqb->start - seqb->startdisp) + seqa->startdisp;
3003 BKE_sequence_translate(scene, seqb, seq_b_start - seqb->start);
3004 BKE_sequence_calc(scene, seqb);
3006 seq_a_start = (seqa->start - seqa->startdisp) + seqb->enddisp + gap;
3007 BKE_sequence_translate(scene, seqa, seq_a_start - seqa->start);
3008 BKE_sequence_calc(scene, seqa);
3012 static Sequence *sequence_find_parent(Scene *scene, Sequence *child)
3014 Editing *ed = BKE_sequencer_editing_get(scene, false);
3015 Sequence *parent = NULL;
3018 if (ed == NULL) return NULL;
3020 for (seq = ed->seqbasep->first; seq; seq = seq->next) {
3021 if ((seq != child) && seq_is_parent(seq, child)) {
3031 static int sequencer_swap_exec(bContext *C, wmOperator *op)
3033 Scene *scene = CTX_data_scene(C);
3034 Editing *ed = BKE_sequencer_editing_get(scene, false);
3035 Sequence *active_seq = BKE_sequencer_active_get(scene);
3036 Sequence *seq, *iseq;
3037 int side = RNA_enum_get(op->ptr, "side");
3039 if (active_seq == NULL) return OPERATOR_CANCELLED;
3041 seq = find_next_prev_sequence(scene, active_seq, side, -1);
3045 /* disallow effect strips */
3046 if (BKE_sequence_effect_get_num_inputs(seq->type) >= 1 && (seq->effectdata || seq->seq1 || seq->seq2 || seq->seq3))
3047 return OPERATOR_CANCELLED;
3048 if ((BKE_sequence_effect_get_num_inputs(active_seq->type) >= 1) && (active_seq->effectdata || active_seq->seq1 || active_seq->seq2 || active_seq->seq3))
3049 return OPERATOR_CANCELLED;
3053 swap_sequence(scene, seq, active_seq);
3055 case SEQ_SIDE_RIGHT:
3056 swap_sequence(scene, active_seq, seq);
3060 // XXX - should be a generic function
3061 for (iseq = scene->ed->seqbasep->first; iseq; iseq = iseq->next) {
3062 if ((iseq->type & SEQ_TYPE_EFFECT) && (seq_is_parent(iseq, active_seq) || seq_is_parent(iseq, seq))) {
3063 BKE_sequence_calc(scene, iseq);
3067 /* do this in a new loop since both effects need to be calculated first */
3068 for (iseq = scene->ed->seqbasep->first; iseq; iseq = iseq->next) {
3069 if ((iseq->type & SEQ_TYPE_EFFECT) && (seq_is_parent(iseq, active_seq) || seq_is_parent(iseq, seq))) {
3070 /* this may now overlap */
3071 if (BKE_sequence_test_overlap(ed->seqbasep, iseq) ) {
3072 BKE_sequence_base_shuffle(ed->seqbasep, iseq, scene);
3079 BKE_sequencer_sort(scene);
3081 WM_event_add_notifier(C, NC_SCENE | ND_SEQUENCER, scene);
3083 return OPERATOR_FINISHED;
3086 return OPERATOR_CANCELLED;
3089 void SEQUENCER_OT_swap(wmOperatorType *ot)
3092 ot->name = "Swap Strip";
3093 ot->idname = "SEQUENCER_OT_swap";
3094 ot->description = "Swap active strip with strip to the right or left";
3097 ot->exec = sequencer_swap_exec;
3098 ot->poll = sequencer_edit_poll;
3101 ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
3104 RNA_def_enum(ot->srna, "side", prop_side_lr_types, SEQ_SIDE_RIGHT, "Side", "Side of the strip to swap");
3107 static int sequencer_rendersize_exec(bContext *C, wmOperator *UNUSED(op))
3109 int retval = OPERATOR_CANCELLED;
3110 Scene *scene = CTX_data_scene(C);
3111 Sequence *active_seq = BKE_sequencer_active_get(scene);
3112 StripElem *se = NULL;
3114 if (active_seq == NULL)
3115 return OPERATOR_CANCELLED;
3118 if (active_seq->strip) {
3119 switch (active_seq->type) {
3120 case SEQ_TYPE_IMAGE:
3121 se = BKE_sequencer_give_stripelem(active_seq, scene->r.cfra);
3123 case SEQ_TYPE_MOVIE:
3124 se = active_seq->strip->stripdata;
3126 case SEQ_TYPE_SCENE:
3128 case SEQ_TYPE_SOUND_RAM:
3129 case SEQ_TYPE_SOUND_HD:
3136 // prevent setting the render size if sequence values aren't initialized
3137 if ((se->orig_width > 0) && (se->orig_height > 0)) {
3138 scene->r.xsch = se->orig_width;
3139 scene->r.ysch = se->orig_height;
3140 WM_event_add_notifier(C, NC_SCENE | ND_RENDER_OPTIONS, scene);
3141 retval = OPERATOR_FINISHED;
3148 void SEQUENCER_OT_rendersize(wmOperatorType *ot)
3151 ot->name = "Set Render Size";
3152 ot->idname = "SEQUENCER_OT_rendersize";
3153 ot->description = "Set render size and aspect from active sequence";
3156 ot->exec = sequencer_rendersize_exec;
3157 ot->poll = sequencer_edit_poll;
3160 ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
3165 static void seq_copy_del_sound(Scene *scene, Sequence *seq)