4 * ***** BEGIN GPL LICENSE BLOCK *****
6 * This program is free software; you can redistribute it and/or
7 * modify it under the terms of the GNU General Public License
8 * as published by the Free Software Foundation; either version 2
9 * of the License, or (at your option) any later version.
11 * This program is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 * GNU General Public License for more details.
16 * You should have received a copy of the GNU General Public License
17 * along with this program; if not, write to the Free Software Foundation,
18 * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
20 * The Original Code is Copyright (C) 2001-2002 by NaN Holding BV.
21 * All rights reserved.
23 * Contributor(s): Blender Foundation, 2003-2009
25 * ***** END GPL LICENSE BLOCK *****
37 #include <sys/types.h>
39 #include "MEM_guardedalloc.h"
41 #include "BLI_blenlib.h"
43 #include "BLI_storage_types.h"
45 #include "IMB_imbuf_types.h"
46 #include "IMB_imbuf.h"
48 #include "DNA_ipo_types.h"
49 #include "DNA_curve_types.h"
50 #include "DNA_scene_types.h"
51 #include "DNA_screen_types.h"
52 #include "DNA_space_types.h"
53 #include "DNA_sequence_types.h"
54 #include "DNA_view2d_types.h"
55 #include "DNA_userdef_types.h"
56 #include "DNA_sound_types.h"
58 #include "BKE_context.h"
59 #include "BKE_global.h"
60 #include "BKE_image.h"
61 #include "BKE_library.h"
63 #include "BKE_plugin_types.h"
64 #include "BKE_sequencer.h"
65 #include "BKE_scene.h"
66 #include "BKE_utildefines.h"
67 #include "BKE_report.h"
68 #include "BKE_sound.h"
73 #include "RNA_access.h"
74 #include "RNA_define.h"
76 /* for menu/popup icons etc etc*/
77 #include "UI_interface.h"
78 #include "UI_resources.h"
80 #include "ED_anim_api.h"
81 #include "ED_space_api.h"
83 #include "ED_screen.h"
84 #include "ED_transform.h"
86 #include "ED_sequencer.h"
88 #include "UI_interface.h"
89 #include "UI_resources.h"
90 #include "UI_view2d.h"
93 #include "sequencer_intern.h"
96 //static Sequence *_last_seq=0;
97 //static int _last_seq_init=0;
99 static void error() {}
100 static void waitcursor(int val) {}
101 static void activate_fileselect() {}
102 static int pupmenu() {return 0;}
103 static int okee() {return 0;}
107 /* RNA Enums, used in multiple files */
108 EnumPropertyItem sequencer_prop_effect_types[] = {
109 {SEQ_CROSS, "CROSS", 0, "Crossfade", "Crossfade effect strip type"},
110 {SEQ_ADD, "ADD", 0, "Add", "Add effect strip type"},
111 {SEQ_SUB, "SUBTRACT", 0, "Subtract", "Subtract effect strip type"},
112 {SEQ_ALPHAOVER, "ALPHA_OVER", 0, "Alpha Over", "Alpha Over effect strip type"},
113 {SEQ_ALPHAUNDER, "ALPHA_UNDER", 0, "Alpha Under", "Alpha Under effect strip type"},
114 {SEQ_GAMCROSS, "GAMMA_CROSS", 0, "Gamma Cross", "Gamma Cross effect strip type"},
115 {SEQ_MUL, "MULTIPLY", 0, "Multiply", "Multiply effect strip type"},
116 {SEQ_OVERDROP, "OVER_DROP", 0, "Alpha Over Drop", "Alpha Over Drop effect strip type"},
117 {SEQ_PLUGIN, "PLUGIN", 0, "Plugin", "Plugin effect strip type"},
118 {SEQ_WIPE, "WIPE", 0, "Wipe", "Wipe effect strip type"},
119 {SEQ_GLOW, "GLOW", 0, "Glow", "Glow effect strip type"},
120 {SEQ_TRANSFORM, "TRANSFORM", 0, "Transform", "Transform effect strip type"},
121 {SEQ_COLOR, "COLOR", 0, "Color", "Color effect strip type"},
122 {SEQ_SPEED, "SPEED", 0, "Speed", "Color effect strip type"},
123 {0, NULL, 0, NULL, NULL}
128 EnumPropertyItem prop_side_types[] = {
129 {SEQ_SIDE_LEFT, "LEFT", 0, "Left", ""},
130 {SEQ_SIDE_RIGHT, "RIGHT", 0, "Right", ""},
131 {SEQ_SIDE_BOTH, "BOTH", 0, "Both", ""},
132 {0, NULL, 0, NULL, NULL}
135 EnumPropertyItem prop_side_lr_types[] = {
136 {SEQ_SIDE_LEFT, "LEFT", 0, "Left", ""},
137 {SEQ_SIDE_RIGHT, "RIGHT", 0, "Right", ""},
138 {0, NULL, 0, NULL, NULL}
141 typedef struct TransSeq {
143 int startstill, endstill;
144 int startdisp, enddisp;
145 int startofs, endofs;
146 int final_left, final_right;
150 Sequence *get_foreground_frame_seq(Scene *scene, int frame)
152 Editing *ed= seq_give_editing(scene, FALSE);
153 Sequence *seq, *best_seq=NULL;
154 int best_machine = -1;
158 for (seq=ed->seqbasep->first; seq; seq= seq->next) {
159 if(seq->flag & SEQ_MUTE || seq->startdisp > frame || seq->enddisp <= frame)
161 /* only use elements you can see - not */
162 if (ELEM5(seq->type, SEQ_IMAGE, SEQ_META, SEQ_SCENE, SEQ_MOVIE, SEQ_COLOR)) {
163 if (seq->machine > best_machine) {
165 best_machine = seq->machine;
172 void seq_rectf(Sequence *seq, rctf *rectf)
174 if(seq->startstill) rectf->xmin= seq->start;
175 else rectf->xmin= seq->startdisp;
176 rectf->ymin= seq->machine+SEQ_STRIP_OFSBOTTOM;
177 if(seq->endstill) rectf->xmax= seq->start+seq->len;
178 else rectf->xmax= seq->enddisp;
179 rectf->ymax= seq->machine+SEQ_STRIP_OFSTOP;
182 static void change_plugin_seq(Scene *scene, char *str) /* called from fileselect */
184 Editing *ed= seq_give_editing(scene, FALSE);
185 struct SeqEffectHandle sh;
186 Sequence *last_seq= active_seq_get(scene);
188 if(last_seq && last_seq->type != SEQ_PLUGIN) return;
190 sh = get_sequence_effect(last_seq);
192 sh.init_plugin(last_seq, str);
194 last_seq->machine = MAX3(last_seq->seq1->machine,
195 last_seq->seq2->machine,
196 last_seq->seq3->machine);
198 if( seq_test_overlap(ed->seqbasep, last_seq) ) shuffle_seq(ed->seqbasep, last_seq);
203 void boundbox_seq(Scene *scene, rctf *rect)
206 Editing *ed= seq_give_editing(scene, FALSE);
207 float min[2], max[2];
217 seq= ed->seqbasep->first;
220 if( min[0] > seq->startdisp-1) min[0]= seq->startdisp-1;
221 if( max[0] < seq->enddisp+1) max[0]= seq->enddisp+1;
222 if( max[1] < seq->machine+2.0) max[1]= seq->machine+2.0;
234 int mouse_frame_side(View2D *v2d, short mouse_x, int frame )
242 /* choose the side based on which side of the playhead the mouse is on */
243 UI_view2d_region_to_view(v2d, mval[0], mval[1], &mouseloc[0], &mouseloc[1]);
245 return mouseloc[0] > frame ? SEQ_SIDE_RIGHT : SEQ_SIDE_LEFT;
249 Sequence *find_neighboring_sequence(Scene *scene, Sequence *test, int lr, int sel)
251 /* sel - 0==unselected, 1==selected, -1==done care*/
253 Editing *ed= seq_give_editing(scene, FALSE);
255 if(ed==NULL) return NULL;
257 if (sel>0) sel = SELECT;
259 for(seq= ed->seqbasep->first; seq; seq= seq->next) {
261 (test->machine==seq->machine) &&
262 ((sel == -1) || (sel && (seq->flag & SELECT)) || (sel==0 && (seq->flag & SELECT)==0) ))
266 if (test->startdisp == (seq->enddisp)) {
271 if (test->enddisp == (seq->startdisp)) {
281 Sequence *find_next_prev_sequence(Scene *scene, Sequence *test, int lr, int sel)
283 /* sel - 0==unselected, 1==selected, -1==done care*/
284 Sequence *seq,*best_seq = NULL;
285 Editing *ed= seq_give_editing(scene, FALSE);
288 best_dist = MAXFRAME*2;
291 if(ed==NULL) return NULL;
293 seq= ed->seqbasep->first;
296 (test->machine==seq->machine) &&
297 (test->depth==seq->depth) &&
298 ((sel == -1) || (sel==(seq->flag & SELECT))))
304 if (seq->enddisp <= test->startdisp) {
305 dist = test->enddisp - seq->startdisp;
309 if (seq->startdisp >= test->enddisp) {
310 dist = seq->startdisp - test->enddisp;
318 } else if (dist < best_dist) {
325 return best_seq; /* can be null */
329 Sequence *find_nearest_seq(Scene *scene, View2D *v2d, int *hand, short mval[2])
332 Editing *ed= seq_give_editing(scene, FALSE);
337 *hand= SEQ_SIDE_NONE;
340 if(ed==NULL) return NULL;
342 pixelx = (v2d->cur.xmax - v2d->cur.xmin)/(v2d->mask.xmax - v2d->mask.xmin);
344 UI_view2d_region_to_view(v2d, mval[0], mval[1], &x, &y);
346 seq= ed->seqbasep->first;
349 if(seq->machine == (int)y) {
350 /* check for both normal strips, and strips that have been flipped horizontally */
351 if( ((seq->startdisp < seq->enddisp) && (seq->startdisp<=x && seq->enddisp>=x)) ||
352 ((seq->startdisp > seq->enddisp) && (seq->startdisp>=x && seq->enddisp<=x)) )
354 if(seq_tx_test(seq)) {
356 /* clamp handles to defined size in pixel space */
358 handsize = seq->handsize;
359 displen = (float)abs(seq->startdisp - seq->enddisp);
361 if (displen / pixelx > 16) { /* dont even try to grab the handles of small strips */
362 /* Set the max value to handle to 1/3 of the total len when its less then 28.
363 * This is important because otherwise selecting handles happens even when you click in the middle */
365 if ((displen/3) < 30*pixelx) {
366 handsize = displen/3;
368 CLAMP(handsize, 7*pixelx, 30*pixelx);
371 if( handsize+seq->startdisp >=x )
372 *hand= SEQ_SIDE_LEFT;
373 else if( -handsize+seq->enddisp <=x )
374 *hand= SEQ_SIDE_RIGHT;
385 void update_seq_ipo_rect(Scene *scene, View2D *v2d, Sequence *seq)
390 if (!seq || !seq->ipo) {
397 /* Adjust IPO window to sequence and
398 avoid annoying snap-back to startframe
399 when Lock Time is on */
400 if (0) { // XXX v2d->flag & V2D_VIEWLOCK) {
401 if ((seq->flag & SEQ_IPO_FRAME_LOCKED) != 0) {
402 start = -5.0 + seq->startdisp;
403 end = 5.0 + seq->enddisp;
405 start = (float)scene->r.sfra - 0.1;
410 seq->ipo->cur.xmin= start;
411 seq->ipo->cur.xmax= end;
414 void update_seq_icu_rects(Sequence * seq)
417 struct SeqEffectHandle sh;
419 if (!seq || !seq->ipo) {
423 if(!(seq->type & SEQ_EFFECT)) {
427 sh = get_sequence_effect(seq);
429 for(icu= seq->ipo->curve.first; icu; icu= icu->next) {
430 sh.store_icu_yrange(seq, icu->adrcode, &icu->ymin, &icu->ymax);
435 static int seq_is_parent(Sequence *par, Sequence *seq)
437 return ((par->seq1 == seq) || (par->seq2 == seq) || (par->seq3 == seq));
440 static int seq_is_predecessor(Sequence *pred, Sequence *seq)
443 if(pred == seq) return 0;
444 else if(seq_is_parent(pred, seq)) return 1;
445 else if(pred->seq1 && seq_is_predecessor(pred->seq1, seq)) return 1;
446 else if(pred->seq2 && seq_is_predecessor(pred->seq2, seq)) return 1;
447 else if(pred->seq3 && seq_is_predecessor(pred->seq3, seq)) return 1;
452 void deselect_all_seq(Scene *scene)
455 Editing *ed= seq_give_editing(scene, FALSE);
460 SEQP_BEGIN(ed, seq) {
461 seq->flag &= SEQ_DESEL;
467 void recurs_sel_seq(Sequence *seqm)
471 seq= seqm->seqbase.first;
474 if(seqm->flag & (SEQ_LEFTSEL+SEQ_RIGHTSEL)) seq->flag &= SEQ_DESEL;
475 else if(seqm->flag & SELECT) seq->flag |= SELECT;
476 else seq->flag &= SEQ_DESEL;
478 if(seq->seqbase.first) recurs_sel_seq(seq);
484 int event_to_efftype(int event)
486 if(event==2) return SEQ_CROSS;
487 if(event==3) return SEQ_GAMCROSS;
488 if(event==4) return SEQ_ADD;
489 if(event==5) return SEQ_SUB;
490 if(event==6) return SEQ_MUL;
491 if(event==7) return SEQ_ALPHAOVER;
492 if(event==8) return SEQ_ALPHAUNDER;
493 if(event==9) return SEQ_OVERDROP;
494 if(event==10) return SEQ_PLUGIN;
495 if(event==13) return SEQ_WIPE;
496 if(event==14) return SEQ_GLOW;
497 if(event==15) return SEQ_TRANSFORM;
498 if(event==16) return SEQ_COLOR;
499 if(event==17) return SEQ_SPEED;
504 static void reload_sound_strip(Scene *scene, char *name)
507 Sequence *seq, *seqact;
509 Sequence *last_seq= active_seq_get(scene);
513 if(last_seq==0 || last_seq->type!=SEQ_SOUND) return;
514 seqact= last_seq; /* last_seq changes in alloc_sequence */
517 // sfile= scrarea_find_space_of_type(curarea, SPACE_FILE);
522 seq = sfile_to_snd_sequence(sfile, seqact->start, seqact->machine);
523 printf("seq->type: %i\n", seq->type);
524 if(seq && seq!=seqact) {
525 /* i'm not sure about this one, seems to work without it -- sgefant */
526 seq_free_strip(seqact->strip);
528 seqact->strip= seq->strip;
530 seqact->len= seq->len;
531 calc_sequence(seqact);
534 seq_free_sequence(scene, seq);
535 BLI_remlink(ed->seqbasep, seq);
537 seq= ed->seqbasep->first;
546 static void reload_image_strip(Scene *scene, char *name)
548 Editing *ed= seq_give_editing(scene, FALSE);
549 Sequence *seq=NULL, *seqact;
550 SpaceFile *sfile=NULL;
551 Sequence *last_seq= active_seq_get(scene);
555 if(last_seq==0 || last_seq->type!=SEQ_IMAGE) return;
556 seqact= last_seq; /* last_seq changes in alloc_sequence */
559 // sfile= scrarea_find_space_of_type(curarea, SPACE_FILE);
564 // seq= sfile_to_sequence(scene, sfile, seqact->start, seqact->machine, 1); // XXX ADD BACK
565 if(seq && seq!=seqact) {
566 seq_free_strip(seqact->strip);
568 seqact->strip= seq->strip;
570 seqact->len= seq->len;
571 calc_sequence(seqact);
574 seq_free_sequence(scene, seq);
575 BLI_remlink(ed->seqbasep, seq);
577 update_changed_seq_and_deps(scene, seqact, 1, 1);
584 void change_sequence(Scene *scene)
586 Editing *ed= seq_give_editing(scene, FALSE);
587 Sequence *last_seq= active_seq_get(scene);
591 if(last_seq==0) return;
593 if(last_seq->type & SEQ_EFFECT) {
594 event = pupmenu("Change Effect%t"
595 "|Switch A <-> B %x1"
596 "|Switch B <-> C %x10"
606 "|Alpha Over Drop%x9"
610 "|Color Generator%x16"
611 "|Speed Control%x17");
614 SWAP(Sequence *,last_seq->seq1,last_seq->seq2);
617 SWAP(Sequence *,last_seq->seq2,last_seq->seq3);
621 FILE_SPECIAL, "Select Plugin",
622 U.plugseqdir, change_plugin_seq);
625 /* recalculate: only new_stripdata */
627 /* free previous effect and init new effect */
628 struct SeqEffectHandle sh;
630 if (get_sequence_effect_num_inputs(
632 < get_sequence_effect_num_inputs(
633 event_to_efftype(event))) {
634 error("New effect needs more "
637 sh = get_sequence_effect(last_seq);
641 = event_to_efftype(event);
643 sh = get_sequence_effect(last_seq);
648 update_changed_seq_and_deps(scene, last_seq, 0, 1);
651 else if(last_seq->type == SEQ_IMAGE) {
652 if(okee("Change images")) {
653 activate_fileselect(FILE_SPECIAL,
659 else if(last_seq->type == SEQ_MOVIE) {
662 else if(last_seq->type == SEQ_SCENE) {
663 event= pupmenu("Change Scene%t|Update Start and End");
666 sce= last_seq->scene;
668 last_seq->len= sce->r.efra - sce->r.sfra + 1;
669 last_seq->sfra= sce->r.sfra;
671 /* bad code to change seq->len? update_changed_seq_and_deps() expects the strip->len to be OK */
672 new_tstripdata(last_seq);
674 update_changed_seq_and_deps(scene, last_seq, 1, 1);
681 int seq_effect_find_selected(Scene *scene, Sequence *activeseq, int type, Sequence **selseq1, Sequence **selseq2, Sequence **selseq3, char **error_str)
683 Editing *ed = seq_give_editing(scene, FALSE);
684 Sequence *seq1= 0, *seq2= 0, *seq3= 0, *seq;
689 seq2= active_seq_get(scene);
691 for(seq=ed->seqbasep->first; seq; seq=seq->next) {
692 if(seq->flag & SELECT) {
693 if (seq->type == SEQ_SOUND) {
694 *error_str= "Can't apply effects to audio sequence strips";
697 if((seq != activeseq) && (seq != seq2)) {
698 if(seq2==0) seq2= seq;
699 else if(seq1==0) seq1= seq;
700 else if(seq3==0) seq3= seq;
702 *error_str= "Can't apply effect to more than 3 sequence strips";
709 /* make sequence selection a little bit more intuitive
710 for 3 strips: the last-strip should be sequence3 */
711 if (seq3 != 0 && seq2 != 0) {
712 Sequence *tmp = seq2;
718 switch(get_sequence_effect_num_inputs(type)) {
720 *selseq1 = *selseq2 = *selseq3 = 0;
721 return 1; /* succsess */
724 *error_str= "Need at least one selected sequence strip";
727 if(seq1==0) seq1= seq2;
728 if(seq3==0) seq3= seq2;
730 if(seq1==0 || seq2==0) {
731 *error_str= "Need 2 selected sequence strips";
734 if(seq3==0) seq3= seq2;
737 if (seq1==NULL && seq2==NULL && seq3==NULL) {
738 *error_str= "TODO: in what cases does this happen?";
749 void reassign_inputs_seq_effect(Scene *scene)
751 Editing *ed= seq_give_editing(scene, FALSE);
752 Sequence *seq1, *seq2, *seq3, *last_seq = active_seq_get(scene);
755 if(last_seq==0 || !(last_seq->type & SEQ_EFFECT)) return;
758 if(!seq_effect_find_selected(scene, last_seq, last_seq->type, &seq1, &seq2, &seq3, &error_msg)) {
759 //BKE_report(op->reports, RPT_ERROR, error_msg); // XXX operatorify
762 /* see reassigning would create a cycle */
763 if( seq_is_predecessor(seq1, last_seq) ||
764 seq_is_predecessor(seq2, last_seq) ||
765 seq_is_predecessor(seq3, last_seq)
767 //BKE_report(op->reports, RPT_ERROR, "Can't reassign inputs: no cycles allowed"); // XXX operatorify
771 last_seq->seq1 = seq1;
772 last_seq->seq2 = seq2;
773 last_seq->seq3 = seq3;
775 update_changed_seq_and_deps(scene, last_seq, 1, 1);
779 static Sequence *del_seq_find_replace_recurs(Scene *scene, Sequence *seq)
781 Sequence *seq1, *seq2, *seq3;
783 /* try to find a replacement input sequence, and flag for later deletion if
784 no replacement can be found */
788 else if(!(seq->type & SEQ_EFFECT))
789 return ((seq->flag & SELECT)? NULL: seq);
790 else if(!(seq->flag & SELECT)) {
791 /* try to find replacement for effect inputs */
792 seq1= del_seq_find_replace_recurs(scene, seq->seq1);
793 seq2= del_seq_find_replace_recurs(scene, seq->seq2);
794 seq3= del_seq_find_replace_recurs(scene, seq->seq3);
796 if(seq1==seq->seq1 && seq2==seq->seq2 && seq3==seq->seq3);
797 else if(seq1 || seq2 || seq3) {
798 seq->seq1= (seq1)? seq1: (seq2)? seq2: seq3;
799 seq->seq2= (seq2)? seq2: (seq1)? seq1: seq3;
800 seq->seq3= (seq3)? seq3: (seq1)? seq1: seq2;
802 update_changed_seq_and_deps(scene, seq, 1, 1);
805 seq->flag |= SELECT; /* mark for delete */
808 if (seq->flag & SELECT) {
809 if((seq1 = del_seq_find_replace_recurs(scene, seq->seq1))) return seq1;
810 if((seq2 = del_seq_find_replace_recurs(scene, seq->seq2))) return seq2;
811 if((seq3 = del_seq_find_replace_recurs(scene, seq->seq3))) return seq3;
818 static void recurs_del_seq_flag(Scene *scene, ListBase *lb, short flag, short deleteall)
820 Sequence *seq, *seqn;
821 Sequence *last_seq = active_seq_get(scene);
826 if((seq->flag & flag) || deleteall) {
827 if(seq->type==SEQ_SOUND && seq->sound)
830 BLI_remlink(lb, seq);
831 if(seq==last_seq) active_seq_set(scene, NULL);
832 if(seq->type==SEQ_META) recurs_del_seq_flag(scene, &seq->seqbase, flag, 1);
833 if(seq->ipo) seq->ipo->id.us--;
834 seq_free_sequence(scene, seq);
840 static Sequence *dupli_seq(struct Scene *scene, Sequence *seq)
842 Sequence *seqn = MEM_dupallocN(seq);
843 // XXX animato: ID *id;
847 seqn->strip= MEM_dupallocN(seq->strip);
852 if (U.dupflag & USER_DUP_IPO) {
854 seqn->ipo= copy_ipo(seqn->ipo);
855 /* we don't need to decrease the number
856 * of the ipo because we never increase it,
857 * for example, adduplicate need decrease
858 * the number but only because copy_object
859 * call id_us_plus for the ipo block and
860 * single_ipo_users only work if id->us > 1.
862 * need call ipo_idnew here, for drivers ??
871 seqn->strip->tstripdata = 0;
872 seqn->strip->tstripdata_startstill = 0;
873 seqn->strip->tstripdata_endstill = 0;
874 seqn->strip->ibuf_startstill = 0;
875 seqn->strip->ibuf_endstill = 0;
877 if (seq->strip->crop) {
878 seqn->strip->crop = MEM_dupallocN(seq->strip->crop);
881 if (seq->strip->transform) {
882 seqn->strip->transform = MEM_dupallocN(seq->strip->transform);
885 if (seq->strip->proxy) {
886 seqn->strip->proxy = MEM_dupallocN(seq->strip->proxy);
889 if (seq->strip->color_balance) {
890 seqn->strip->color_balance
891 = MEM_dupallocN(seq->strip->color_balance);
894 if(seq->type==SEQ_META) {
895 seqn->strip->stripdata = 0;
897 seqn->seqbase.first= seqn->seqbase.last= 0;
898 /* WATCH OUT!!! - This metastrip is not recursively duplicated here - do this after!!! */
899 /* - recurs_dupli_seq(&seq->seqbase,&seqn->seqbase);*/
900 } else if(seq->type == SEQ_SCENE) {
901 seqn->strip->stripdata = 0;
902 } else if(seq->type == SEQ_MOVIE) {
903 seqn->strip->stripdata =
904 MEM_dupallocN(seq->strip->stripdata);
906 } else if(seq->type == SEQ_SOUND) {
907 seqn->strip->stripdata =
908 MEM_dupallocN(seq->strip->stripdata);
909 if(seq->sound_handle)
910 seqn->sound_handle = sound_new_handle(scene, seqn->sound, seq->sound_handle->startframe, seq->sound_handle->endframe, seq->sound_handle->frameskip);
912 seqn->sound->id.us++;
913 } else if(seq->type == SEQ_IMAGE) {
914 seqn->strip->stripdata =
915 MEM_dupallocN(seq->strip->stripdata);
916 } else if(seq->type >= SEQ_EFFECT) {
917 if(seq->seq1 && seq->seq1->tmp) seqn->seq1= seq->seq1->tmp;
918 if(seq->seq2 && seq->seq2->tmp) seqn->seq2= seq->seq2->tmp;
919 if(seq->seq3 && seq->seq3->tmp) seqn->seq3= seq->seq3->tmp;
921 if (seq->type & SEQ_EFFECT) {
922 struct SeqEffectHandle sh;
923 sh = get_sequence_effect(seq);
928 seqn->strip->stripdata = 0;
931 fprintf(stderr, "Aiiiiekkk! sequence type not "
932 "handled in duplicate!\nExpect a crash"
936 seqUniqueName(scene->ed->seqbasep, seqn);
941 static Sequence * deep_dupli_seq(struct Scene *scene, Sequence * seq)
943 Sequence * seqn = dupli_seq(scene, seq);
944 if (seq->type == SEQ_META) {
946 for(s= seq->seqbase.first; s; s = s->next) {
947 Sequence * n = deep_dupli_seq(scene, s);
949 BLI_addtail(&seqn->seqbase, n);
957 static void recurs_dupli_seq(Scene *scene, ListBase *old, ListBase *new, int do_context)
961 Sequence *last_seq = active_seq_get(scene);
963 for(seq= old->first; seq; seq= seq->next) {
965 if(seq->flag & SELECT) {
966 seqn = dupli_seq(scene, seq);
967 if (seqn) { /*should never fail */
969 seq->flag &= SEQ_DESEL;
970 seqn->flag &= ~(SEQ_LEFTSEL+SEQ_RIGHTSEL+SEQ_LOCK);
973 BLI_addtail(new, seqn);
974 if(seq->type==SEQ_META)
975 recurs_dupli_seq(scene, &seq->seqbase,&seqn->seqbase, do_context);
978 if (seq == last_seq) {
979 active_seq_set(scene, seqn);
987 static Sequence *cut_seq_hard(Scene *scene, Sequence * seq, int cutframe)
991 int skip_dup = FALSE;
994 ts.start= seq->start;
995 ts.machine= seq->machine;
996 ts.startstill= seq->startstill;
997 ts.endstill= seq->endstill;
998 ts.startdisp= seq->startdisp;
999 ts.enddisp= seq->enddisp;
1000 ts.startofs= seq->anim_startofs;
1001 ts.endofs= seq->anim_endofs;
1005 /* strips with extended stillfames before */
1007 if ((seq->startstill) && (cutframe <seq->start)) {
1008 /* don't do funny things with METAs ... */
1009 if (seq->type == SEQ_META) {
1011 seq->startstill = seq->start - cutframe;
1013 seq->start= cutframe -1;
1014 seq->startstill= cutframe -seq->startdisp -1;
1015 seq->anim_endofs += seq->len - 1;
1020 else if ((cutframe >=seq->start)&&(cutframe <=(seq->start+seq->len))) {
1023 seq->anim_endofs += (seq->start+seq->len) - cutframe;
1025 /* strips with extended stillframes after */
1026 else if (((seq->start+seq->len) < cutframe) && (seq->endstill)) {
1027 seq->endstill -= seq->enddisp - cutframe;
1028 /* don't do funny things with METAs ... */
1029 if (seq->type == SEQ_META) {
1034 reload_sequence_new_file(scene, seq);
1038 /* Duplicate AFTER the first change */
1039 seqn = deep_dupli_seq(scene, seq);
1043 seqn->flag |= SELECT;
1046 /* strips with extended stillframes before */
1047 if ((seqn->startstill) && (cutframe == seqn->start + 1)) {
1048 seqn->start = ts.start;
1049 seqn->startstill= ts.start- cutframe;
1050 seqn->anim_endofs = ts.endofs;
1051 seqn->endstill = ts.endstill;
1055 else if ((cutframe>=seqn->start)&&(cutframe<=(seqn->start+seqn->len))) {
1056 seqn->start = cutframe;
1057 seqn->startstill = 0;
1059 seqn->anim_startofs += cutframe - ts.start;
1060 seqn->anim_endofs = ts.endofs;
1061 seqn->endstill = ts.endstill;
1064 /* strips with extended stillframes after */
1065 else if (((seqn->start+seqn->len) < cutframe) && (seqn->endstill)) {
1066 seqn->start = cutframe;
1068 seqn->anim_startofs += ts.len-1;
1069 seqn->endstill = ts.enddisp - cutframe -1;
1070 seqn->startstill = 0;
1073 reload_sequence_new_file(scene, seqn);
1074 calc_sequence(seqn);
1079 static Sequence *cut_seq_soft(Scene *scene, Sequence * seq, int cutframe)
1083 int skip_dup = FALSE;
1086 ts.start= seq->start;
1087 ts.machine= seq->machine;
1088 ts.startstill= seq->startstill;
1089 ts.endstill= seq->endstill;
1090 ts.startdisp= seq->startdisp;
1091 ts.enddisp= seq->enddisp;
1092 ts.startofs= seq->startofs;
1093 ts.endofs= seq->endofs;
1097 /* strips with extended stillfames before */
1099 if ((seq->startstill) && (cutframe <seq->start)) {
1100 /* don't do funny things with METAs ... */
1101 if (seq->type == SEQ_META) {
1103 seq->startstill = seq->start - cutframe;
1105 seq->start= cutframe -1;
1106 seq->startstill= cutframe -seq->startdisp -1;
1107 seq->endofs = seq->len - 1;
1112 else if ((cutframe >=seq->start)&&(cutframe <=(seq->start+seq->len))) {
1113 seq->endofs = (seq->start+seq->len) - cutframe;
1115 /* strips with extended stillframes after */
1116 else if (((seq->start+seq->len) < cutframe) && (seq->endstill)) {
1117 seq->endstill -= seq->enddisp - cutframe;
1118 /* don't do funny things with METAs ... */
1119 if (seq->type == SEQ_META) {
1127 /* Duplicate AFTER the first change */
1128 seqn = deep_dupli_seq(scene, seq);
1132 seqn->flag |= SELECT;
1135 /* strips with extended stillframes before */
1136 if ((seqn->startstill) && (cutframe == seqn->start + 1)) {
1137 seqn->start = ts.start;
1138 seqn->startstill= ts.start- cutframe;
1139 seqn->endofs = ts.endofs;
1140 seqn->endstill = ts.endstill;
1144 else if ((cutframe>=seqn->start)&&(cutframe<=(seqn->start+seqn->len))) {
1145 seqn->startstill = 0;
1146 seqn->startofs = cutframe - ts.start;
1147 seqn->endofs = ts.endofs;
1148 seqn->endstill = ts.endstill;
1151 /* strips with extended stillframes after */
1152 else if (((seqn->start+seqn->len) < cutframe) && (seqn->endstill)) {
1153 seqn->start = cutframe - ts.len +1;
1154 seqn->startofs = ts.len-1;
1155 seqn->endstill = ts.enddisp - cutframe -1;
1156 seqn->startstill = 0;
1159 calc_sequence(seqn);
1165 /* like duplicate, but only duplicate and cut overlapping strips,
1166 * strips to the left of the cutframe are ignored and strips to the right are moved into the new list */
1167 static int cut_seq_list(Scene *scene, ListBase *old, ListBase *new, int cutframe,
1168 Sequence * (*cut_seq)(Scene *, Sequence *, int))
1170 int did_something = FALSE;
1171 Sequence *seq, *seq_next;
1176 seq_next = seq->next; /* we need this because we may remove seq */
1179 if(seq->flag & SELECT) {
1180 if(cutframe > seq->startdisp &&
1181 cutframe < seq->enddisp) {
1182 Sequence * seqn = cut_seq(scene, seq, cutframe);
1184 BLI_addtail(new, seqn);
1186 did_something = TRUE;
1187 } else if (seq->enddisp <= cutframe) {
1189 } else if (seq->startdisp >= cutframe) {
1190 /* move into new list */
1191 BLI_remlink(old, seq);
1192 BLI_addtail(new, seq);
1197 return did_something;
1200 int insert_gap(Scene *scene, int gap, int cfra)
1203 Editing *ed= seq_give_editing(scene, FALSE);
1206 /* all strips >= cfra are shifted */
1208 if(ed==NULL) return 0;
1210 SEQP_BEGIN(ed, seq) {
1211 if(seq->startdisp >= cfra) {
1222 void touch_seq_files(Scene *scene)
1225 Editing *ed= seq_give_editing(scene, FALSE);
1228 /* touch all strips with movies */
1230 if(ed==NULL) return;
1232 if(okee("Touch and print selected movies")==0) return;
1236 SEQP_BEGIN(ed, seq) {
1237 if(seq->flag & SELECT) {
1238 if(seq->type==SEQ_MOVIE) {
1239 if(seq->strip && seq->strip->stripdata) {
1240 BLI_make_file_string(G.sce, str, seq->strip->dir, seq->strip->stripdata->name);
1241 BLI_touch(seq->name);
1252 void set_filter_seq(Scene *scene)
1255 Editing *ed= seq_give_editing(scene, FALSE);
1258 if(ed==NULL) return;
1260 if(okee("Set Deinterlace")==0) return;
1262 SEQP_BEGIN(ed, seq) {
1263 if(seq->flag & SELECT) {
1264 if(seq->type==SEQ_MOVIE) {
1265 seq->flag |= SEQ_FILTERY;
1266 reload_sequence_new_file(scene, seq);
1275 void seq_remap_paths(Scene *scene)
1277 Sequence *seq, *last_seq = active_seq_get(scene);
1278 Editing *ed= seq_give_editing(scene, FALSE);
1279 char from[FILE_MAX], to[FILE_MAX], stripped[FILE_MAX];
1285 BLI_strncpy(from, last_seq->strip->dir, FILE_MAX);
1286 // XXX if (0==sbutton(from, 0, sizeof(from)-1, "From: "))
1290 // XXX if (0==sbutton(to, 0, sizeof(to)-1, "To: "))
1293 if (strcmp(to, from)==0)
1296 SEQP_BEGIN(ed, seq) {
1297 if(seq->flag & SELECT) {
1298 if(strncmp(seq->strip->dir, from, strlen(from))==0) {
1299 printf("found %s\n", seq->strip->dir);
1301 /* strip off the beginning */
1303 BLI_strncpy(stripped, seq->strip->dir + strlen(from), FILE_MAX);
1306 BLI_strncpy(seq->strip->dir, to, FILE_MAX);
1307 strcat(seq->strip->dir, stripped);
1308 printf("new %s\n", seq->strip->dir);
1317 void no_gaps(Scene *scene)
1319 Editing *ed= seq_give_editing(scene, FALSE);
1320 int cfra, first= 0, done;
1323 if(ed==NULL) return;
1325 for(cfra= CFRA; cfra<=EFRA; cfra++) {
1327 if( evaluate_seq_frame(scene, cfra) ) first= 1;
1331 while( evaluate_seq_frame(scene, cfra) == 0) {
1332 done= insert_gap(scene, -1, cfra);
1342 static int seq_get_snaplimit(View2D *v2d)
1344 /* fake mouse coords to get the snap value
1345 a bit lazy but its only done once pre transform */
1346 float xmouse, ymouse, x;
1347 short mval[2] = {24, 0}; /* 24 screen px snap */
1349 UI_view2d_region_to_view(v2d, mval[0], mval[1], &xmouse, &ymouse);
1352 UI_view2d_region_to_view(v2d, mval[0], mval[1], &xmouse, &ymouse);
1353 return (int)(x - xmouse);
1357 /* Operator functions */
1360 static int sequencer_snap_exec(bContext *C, wmOperator *op)
1362 Scene *scene= CTX_data_scene(C);
1364 Editing *ed= seq_give_editing(scene, FALSE);
1368 if(ed==NULL) return OPERATOR_CANCELLED;
1370 snap_frame= RNA_int_get(op->ptr, "frame");
1372 /* problem: contents of meta's are all shifted to the same position... */
1374 /* also check metas */
1375 SEQP_BEGIN(ed, seq) {
1376 if (seq->flag & SELECT && !(seq->depth==0 && seq->flag & SEQ_LOCK) &&
1378 if((seq->flag & (SEQ_LEFTSEL+SEQ_RIGHTSEL))==0) {
1379 seq->start= snap_frame-seq->startofs+seq->startstill;
1381 if(seq->flag & SEQ_LEFTSEL) {
1382 seq_tx_set_final_left(seq, snap_frame);
1383 } else { /* SEQ_RIGHTSEL */
1384 seq_tx_set_final_right(seq, snap_frame);
1386 seq_tx_handle_xlimits(seq, seq->flag & SEQ_LEFTSEL, seq->flag & SEQ_RIGHTSEL);
1393 /* test for effects and overlap */
1394 SEQP_BEGIN(ed, seq) {
1395 if(seq->flag & SELECT && !(seq->depth==0 && seq->flag & SEQ_LOCK)) {
1396 seq->flag &= ~SEQ_OVERLAP;
1397 if( seq_test_overlap(ed->seqbasep, seq) ) {
1398 shuffle_seq(ed->seqbasep, seq);
1401 else if(seq->type & SEQ_EFFECT) {
1402 if(seq->seq1 && (seq->seq1->flag & SELECT))
1404 else if(seq->seq2 && (seq->seq2->flag & SELECT))
1406 else if(seq->seq3 && (seq->seq3->flag & SELECT))
1415 WM_event_add_notifier(C, NC_SCENE|ND_SEQUENCER, scene);
1417 return OPERATOR_FINISHED;
1420 static int sequencer_snap_invoke(bContext *C, wmOperator *op, wmEvent *event)
1422 Scene *scene = CTX_data_scene(C);
1428 RNA_int_set(op->ptr, "frame", snap_frame);
1429 return sequencer_snap_exec(C, op);
1432 void SEQUENCER_OT_snap(struct wmOperatorType *ot)
1435 ot->name= "Snap strips";
1436 ot->idname= "SEQUENCER_OT_snap";
1437 ot->description="Frame where selected strips will be snapped.";
1440 ot->invoke= sequencer_snap_invoke;
1441 ot->exec= sequencer_snap_exec;
1443 ot->poll= ED_operator_sequencer_active;
1446 ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO;
1448 RNA_def_int(ot->srna, "frame", 0, INT_MIN, INT_MAX, "Frame", "Frame where selected strips will be snapped", INT_MIN, INT_MAX);
1452 static int sequencer_mute_exec(bContext *C, wmOperator *op)
1454 Scene *scene= CTX_data_scene(C);
1455 Editing *ed= seq_give_editing(scene, FALSE);
1460 return OPERATOR_CANCELLED;
1462 selected= !RNA_boolean_get(op->ptr, "unselected");
1464 for(seq= ed->seqbasep->first; seq; seq= seq->next) {
1465 if ((seq->flag & SEQ_LOCK)==0) {
1466 if(selected){ /* mute unselected */
1467 if(seq->flag & SELECT)
1468 seq->flag |= SEQ_MUTE;
1471 if((seq->flag & SELECT)==0)
1472 seq->flag |= SEQ_MUTE;
1477 seq_update_muting(ed);
1478 WM_event_add_notifier(C, NC_SCENE|ND_SEQUENCER, scene);
1480 return OPERATOR_FINISHED;
1483 void SEQUENCER_OT_mute(struct wmOperatorType *ot)
1486 ot->name= "Mute Strips";
1487 ot->idname= "SEQUENCER_OT_mute";
1488 ot->description="Mute selected strips.";
1491 ot->exec= sequencer_mute_exec;
1493 ot->poll= ED_operator_sequencer_active;
1496 ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO;
1498 RNA_def_boolean(ot->srna, "unselected", 0, "Unselected", "Mute unselected rather than selected strips.");
1502 /* unmute operator */
1503 static int sequencer_unmute_exec(bContext *C, wmOperator *op)
1505 Scene *scene= CTX_data_scene(C);
1506 Editing *ed= seq_give_editing(scene, FALSE);
1511 return OPERATOR_CANCELLED;
1513 selected= !RNA_boolean_get(op->ptr, "unselected");
1515 for(seq= ed->seqbasep->first; seq; seq= seq->next) {
1516 if ((seq->flag & SEQ_LOCK)==0) {
1517 if(selected){ /* unmute unselected */
1518 if(seq->flag & SELECT)
1519 seq->flag &= ~SEQ_MUTE;
1522 if((seq->flag & SELECT)==0)
1523 seq->flag &= ~SEQ_MUTE;
1528 seq_update_muting(ed);
1529 WM_event_add_notifier(C, NC_SCENE|ND_SEQUENCER, scene);
1531 return OPERATOR_FINISHED;
1534 void SEQUENCER_OT_unmute(struct wmOperatorType *ot)
1537 ot->name= "UnMute Strips";
1538 ot->idname= "SEQUENCER_OT_unmute";
1539 ot->description="UnMute unselected rather than selected strips.";
1542 ot->exec= sequencer_unmute_exec;
1544 ot->poll= ED_operator_sequencer_active;
1547 ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO;
1549 RNA_def_boolean(ot->srna, "unselected", 0, "Unselected", "UnMute unselected rather than selected strips.");
1554 static int sequencer_lock_exec(bContext *C, wmOperator *op)
1556 Scene *scene= CTX_data_scene(C);
1557 Editing *ed= seq_give_editing(scene, FALSE);
1561 return OPERATOR_CANCELLED;
1563 for(seq= ed->seqbasep->first; seq; seq= seq->next) {
1564 if (seq->flag & SELECT) {
1565 seq->flag |= SEQ_LOCK;
1569 WM_event_add_notifier(C, NC_SCENE|ND_SEQUENCER, scene);
1571 return OPERATOR_FINISHED;
1574 void SEQUENCER_OT_lock(struct wmOperatorType *ot)
1577 ot->name= "Lock Strips";
1578 ot->idname= "SEQUENCER_OT_lock";
1579 ot->description="Lock the active strip so that it can't be transformed.";
1582 ot->exec= sequencer_lock_exec;
1584 ot->poll= ED_operator_sequencer_active;
1587 ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO;
1590 /* unlock operator */
1591 static int sequencer_unlock_exec(bContext *C, wmOperator *op)
1593 Scene *scene= CTX_data_scene(C);
1594 Editing *ed= seq_give_editing(scene, FALSE);
1598 return OPERATOR_CANCELLED;
1600 for(seq= ed->seqbasep->first; seq; seq= seq->next) {
1601 if (seq->flag & SELECT) {
1602 seq->flag &= ~SEQ_LOCK;
1606 WM_event_add_notifier(C, NC_SCENE|ND_SEQUENCER, scene);
1608 return OPERATOR_FINISHED;
1611 void SEQUENCER_OT_unlock(struct wmOperatorType *ot)
1614 ot->name= "UnLock Strips";
1615 ot->idname= "SEQUENCER_OT_unlock";
1616 ot->description="Unlock the active strip so that it can't be transformed.";
1619 ot->exec= sequencer_unlock_exec;
1621 ot->poll= ED_operator_sequencer_active;
1624 ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO;
1627 /* reload operator */
1628 static int sequencer_reload_exec(bContext *C, wmOperator *op)
1630 Scene *scene= CTX_data_scene(C);
1631 Editing *ed= seq_give_editing(scene, FALSE);
1635 return OPERATOR_CANCELLED;
1637 for(seq= ed->seqbasep->first; seq; seq= seq->next) {
1638 if(seq->flag & SELECT) {
1639 update_changed_seq_and_deps(scene, seq, 0, 1);
1643 WM_event_add_notifier(C, NC_SCENE|ND_SEQUENCER, scene);
1645 return OPERATOR_FINISHED;
1648 void SEQUENCER_OT_reload(struct wmOperatorType *ot)
1651 ot->name= "Reload Strips";
1652 ot->idname= "SEQUENCER_OT_reload";
1653 ot->description="Reload strips in the sequencer.";
1656 ot->exec= sequencer_reload_exec;
1658 ot->poll= ED_operator_sequencer_active;
1661 ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO;
1664 /* reload operator */
1665 static int sequencer_refresh_all_exec(bContext *C, wmOperator *op)
1667 Scene *scene= CTX_data_scene(C);
1668 Editing *ed= seq_give_editing(scene, FALSE);
1671 return OPERATOR_CANCELLED;
1673 free_imbuf_seq(scene, &ed->seqbase, FALSE);
1675 seqbase_sound_reload(scene, &ed->seqbase);
1677 WM_event_add_notifier(C, NC_SCENE|ND_SEQUENCER, scene);
1679 return OPERATOR_FINISHED;
1682 void SEQUENCER_OT_refresh_all(struct wmOperatorType *ot)
1685 ot->name= "Refresh Sequencer";
1686 ot->idname= "SEQUENCER_OT_refresh_all";
1687 ot->description="Refresh the sequencer editor.";
1690 ot->exec= sequencer_refresh_all_exec;
1692 ot->poll= ED_operator_sequencer_active;
1695 ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO;
1699 static EnumPropertyItem prop_cut_types[] = {
1700 {SEQ_CUT_SOFT, "SOFT", 0, "Soft", ""},
1701 {SEQ_CUT_HARD, "HARD", 0, "Hard", ""},
1702 {0, NULL, 0, NULL, NULL}
1705 static int sequencer_cut_exec(bContext *C, wmOperator *op)
1707 Scene *scene= CTX_data_scene(C);
1708 Editing *ed= seq_give_editing(scene, FALSE);
1709 int cut_side, cut_hard, cut_frame;
1715 return OPERATOR_CANCELLED;
1717 cut_frame= RNA_int_get(op->ptr, "frame");
1718 cut_hard= RNA_enum_get(op->ptr, "type");
1719 cut_side= RNA_enum_get(op->ptr, "side");
1721 newlist.first= newlist.last= NULL;
1723 if (cut_hard==SEQ_CUT_HARD) {
1724 changed = cut_seq_list(scene,
1725 ed->seqbasep, &newlist, cut_frame, cut_seq_hard);
1727 changed = cut_seq_list(scene,
1728 ed->seqbasep, &newlist, cut_frame, cut_seq_soft);
1731 if (newlist.first) { /* got new strips ? */
1733 addlisttolist(ed->seqbasep, &newlist);
1735 if (cut_side != SEQ_SIDE_BOTH) {
1736 SEQP_BEGIN(ed, seq) {
1737 if (cut_side==SEQ_SIDE_LEFT) {
1738 if ( seq->startdisp >= cut_frame ) {
1739 seq->flag &= SEQ_DESEL;
1742 if ( seq->enddisp <= cut_frame ) {
1743 seq->flag &= SEQ_DESEL;
1753 WM_event_add_notifier(C, NC_SCENE|ND_SEQUENCER, scene);
1755 return OPERATOR_FINISHED;
1759 static int sequencer_cut_invoke(bContext *C, wmOperator *op, wmEvent *event)
1761 Scene *scene = CTX_data_scene(C);
1762 ARegion *ar= CTX_wm_region(C);
1763 View2D *v2d= UI_view2d_fromcontext(C);
1765 int cut_side, cut_frame;
1768 cut_side= mouse_frame_side(v2d, event->x - ar->winrct.xmin, cut_frame);
1770 RNA_int_set(op->ptr, "frame", cut_frame);
1771 RNA_enum_set(op->ptr, "side", cut_side);
1772 /*RNA_enum_set(op->ptr, "type", cut_hard); */ /*This type is set from the key shortcut */
1774 return sequencer_cut_exec(C, op);
1778 void SEQUENCER_OT_cut(struct wmOperatorType *ot)
1781 ot->name= "Cut Strips";
1782 ot->idname= "SEQUENCER_OT_cut";
1783 ot->description="Cut the selected strips.";
1786 ot->invoke= sequencer_cut_invoke;
1787 ot->exec= sequencer_cut_exec;
1789 ot->poll= ED_operator_sequencer_active;
1792 ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO;
1794 RNA_def_int(ot->srna, "frame", 0, INT_MIN, INT_MAX, "Frame", "Frame where selected strips will be cut", INT_MIN, INT_MAX);
1795 RNA_def_enum(ot->srna, "type", prop_cut_types, SEQ_CUT_SOFT, "Type", "The type of cut operation to perform on strips");
1796 RNA_def_enum(ot->srna, "side", prop_side_types, SEQ_SIDE_BOTH, "Side", "The side that remains selected after cutting");
1799 /* duplicate operator */
1800 static int sequencer_add_duplicate_exec(bContext *C, wmOperator *op)
1802 Scene *scene= CTX_data_scene(C);
1803 Editing *ed= seq_give_editing(scene, FALSE);
1805 ListBase new= {NULL, NULL};
1808 return OPERATOR_CANCELLED;
1810 recurs_dupli_seq(scene, ed->seqbasep, &new, TRUE);
1811 addlisttolist(ed->seqbasep, &new);
1813 WM_event_add_notifier(C, NC_SCENE|ND_SEQUENCER, scene);
1815 return OPERATOR_FINISHED;
1818 static int sequencer_add_duplicate_invoke(bContext *C, wmOperator *op, wmEvent *event)
1820 sequencer_add_duplicate_exec(C, op);
1822 RNA_int_set(op->ptr, "mode", TFM_TRANSLATION);
1823 WM_operator_name_call(C, "TRANSFORM_OT_transform", WM_OP_INVOKE_REGION_WIN, op->ptr);
1825 return OPERATOR_FINISHED;
1828 void SEQUENCER_OT_duplicate(wmOperatorType *ot)
1832 ot->name= "Duplicate";
1833 ot->idname= "SEQUENCER_OT_duplicate";
1834 ot->description="Duplicate the selected strips.";
1837 ot->invoke= sequencer_add_duplicate_invoke;
1838 ot->exec= sequencer_add_duplicate_exec;
1840 ot->poll= ED_operator_sequencer_active;
1843 ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO;
1845 /* to give to transform */
1846 RNA_def_int(ot->srna, "mode", TFM_TRANSLATION, 0, INT_MAX, "Mode", "", 0, INT_MAX);
1849 /* delete operator */
1850 static int sequencer_delete_exec(bContext *C, wmOperator *op)
1852 Scene *scene= CTX_data_scene(C);
1853 Editing *ed= seq_give_editing(scene, FALSE);
1856 int nothingSelected = TRUE;
1859 return OPERATOR_CANCELLED;
1861 seq=active_seq_get(scene);
1862 if (seq && seq->flag & SELECT) { /* avoid a loop since this is likely to be selected */
1863 nothingSelected = FALSE;
1865 for (seq = ed->seqbasep->first; seq; seq = seq->next) {
1866 if (seq->flag & SELECT) {
1867 nothingSelected = FALSE;
1873 if (nothingSelected)
1874 return OPERATOR_FINISHED;
1876 /* free imbufs of all dependent strips */
1877 for(seq=ed->seqbasep->first; seq; seq=seq->next)
1878 if(seq->flag & SELECT)
1879 update_changed_seq_and_deps(scene, seq, 1, 0);
1881 /* for effects, try to find a replacement input */
1882 for(seq=ed->seqbasep->first; seq; seq=seq->next)
1883 if((seq->type & SEQ_EFFECT) && !(seq->flag & SELECT))
1884 del_seq_find_replace_recurs(scene, seq);
1886 /* delete all selected strips */
1887 recurs_del_seq_flag(scene, ed->seqbasep, SELECT, 0);
1889 /* updates lengths etc */
1890 seq= ed->seqbasep->first;
1896 /* free parent metas */
1897 ms= ed->metastack.last;
1899 ms->parseq->strip->len= 0; /* force new alloc */
1900 calc_sequence(ms->parseq);
1904 WM_event_add_notifier(C, NC_SCENE|ND_SEQUENCER, scene);
1906 return OPERATOR_FINISHED;
1910 void SEQUENCER_OT_delete(wmOperatorType *ot)
1914 ot->name= "Erase Strips";
1915 ot->idname= "SEQUENCER_OT_delete";
1916 ot->description="Erase selected strips from the sequencer.";
1919 ot->invoke= WM_operator_confirm;
1920 ot->exec= sequencer_delete_exec;
1922 ot->poll= ED_operator_sequencer_active;
1925 ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO;
1929 /* separate_images operator */
1930 static int sequencer_separate_images_exec(bContext *C, wmOperator *op)
1932 Scene *scene= CTX_data_scene(C);
1933 Editing *ed= seq_give_editing(scene, FALSE);
1935 Sequence *seq, *seq_new, *seq_next;
1937 StripElem *se, *se_new;
1938 int start_ofs, cfra, frame_end;
1939 int step= RNA_int_get(op->ptr, "length");
1942 return OPERATOR_CANCELLED;
1944 seq= ed->seqbasep->first;
1947 if((seq->flag & SELECT) && (seq->type == SEQ_IMAGE) && (seq->len > 1)) {
1948 /* remove seq so overlap tests dont conflict,
1949 see seq_free_sequence below for the real free'ing */
1950 seq_next = seq->next;
1951 BLI_remlink(ed->seqbasep, seq);
1952 if(seq->ipo) seq->ipo->id.us--;
1954 start_ofs = cfra = seq_tx_get_final_left(seq, 0);
1955 frame_end = seq_tx_get_final_right(seq, 0);
1957 while (cfra < frame_end) {
1959 se = give_stripelem(seq, cfra);
1961 seq_new= alloc_sequence(ed->seqbasep, start_ofs, seq->machine);
1962 seq_new->type= SEQ_IMAGE;
1964 seq_new->endstill = step-1;
1967 seq_new->strip= strip_new= MEM_callocN(sizeof(Strip)*1, "strip");
1970 strncpy(strip_new->dir, seq->strip->dir, FILE_MAXDIR-1);
1973 strip_new->stripdata= se_new= MEM_callocN(sizeof(StripElem)*1, "stripelem");
1974 strncpy(se_new->name, se->name, FILE_MAXFILE-1);
1975 calc_sequence(seq_new);
1976 seq_new->flag &= ~SEQ_OVERLAP;
1977 if (seq_test_overlap(ed->seqbasep, seq_new)) {
1978 shuffle_seq(ed->seqbasep, seq_new);
1981 seqUniqueName(scene->ed->seqbasep, seq_new);
1987 seq_free_sequence(scene, seq);
1997 WM_event_add_notifier(C, NC_SCENE|ND_SEQUENCER, scene);
1999 return OPERATOR_FINISHED;
2003 void SEQUENCER_OT_images_separate(wmOperatorType *ot)
2006 ot->name= "Separate Images";
2007 ot->idname= "SEQUENCER_OT_images_separate";
2008 ot->description="On image sequences strips, it return a strip for each image.";
2011 ot->invoke= WM_operator_props_popup;
2012 ot->exec= sequencer_separate_images_exec;
2014 ot->poll= ED_operator_sequencer_active;
2017 ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO;
2019 RNA_def_int(ot->srna, "length", 1, 1, 1000, "Length", "Length of each frame", 1, INT_MAX);
2023 /* META Operators */
2025 /* separate_meta_toggle operator */
2026 static int sequencer_meta_toggle_exec(bContext *C, wmOperator *op)
2028 Scene *scene= CTX_data_scene(C);
2029 Editing *ed= seq_give_editing(scene, FALSE);
2030 Sequence *last_seq= active_seq_get(scene);
2034 return OPERATOR_CANCELLED;
2036 if(last_seq && last_seq->type==SEQ_META && last_seq->flag & SELECT) {
2037 /* Enter Metastrip */
2038 ms= MEM_mallocN(sizeof(MetaStack), "metastack");
2039 BLI_addtail(&ed->metastack, ms);
2040 ms->parseq= last_seq;
2041 ms->oldbasep= ed->seqbasep;
2043 ed->seqbasep= &last_seq->seqbase;
2045 active_seq_set(scene, NULL);
2049 /* Exit Metastrip (if possible) */
2053 if(ed->metastack.first==NULL)
2054 return OPERATOR_CANCELLED;
2056 ms= ed->metastack.last;
2057 BLI_remlink(&ed->metastack, ms);
2059 ed->seqbasep= ms->oldbasep;
2061 /* recalc all: the meta can have effects connected to it */
2062 for(seq= ed->seqbasep->first; seq; seq= seq->next)
2065 active_seq_set(scene, ms->parseq);
2067 ms->parseq->flag |= SELECT;
2068 recurs_sel_seq(ms->parseq);
2074 seq_update_muting(ed);
2075 WM_event_add_notifier(C, NC_SCENE|ND_SEQUENCER, scene);
2077 return OPERATOR_FINISHED;
2080 void SEQUENCER_OT_meta_toggle(wmOperatorType *ot)
2083 ot->name= "Toggle Meta Strip";
2084 ot->idname= "SEQUENCER_OT_meta_toggle";
2085 ot->description="Toggle a metastrip (to edit enclosed strips).";
2088 ot->exec= sequencer_meta_toggle_exec;
2090 ot->poll= ED_operator_sequencer_active;
2093 ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO;
2097 /* separate_meta_make operator */
2098 static int sequencer_meta_make_exec(bContext *C, wmOperator *op)
2100 Scene *scene= CTX_data_scene(C);
2101 Editing *ed= seq_give_editing(scene, FALSE);
2103 Sequence *seq, *seqm, *next;
2105 int tot, channel_max= 1;
2108 return OPERATOR_CANCELLED;
2110 if(seqbase_isolated_sel_check(ed->seqbasep)==FALSE) {
2111 BKE_report(op->reports, RPT_ERROR, "Please select all related strips");
2112 return OPERATOR_CANCELLED;
2115 /* remove all selected from main list, and put in meta */
2117 seqm= alloc_sequence(ed->seqbasep, 1, 1); /* channel number set later */
2118 strcpy(seqm->name+2, "MetaStrip");
2119 seqm->type= SEQ_META;
2122 seq= ed->seqbasep->first;
2125 if(seq!=seqm && (seq->flag & SELECT)) {
2126 channel_max= MAX2(seq->machine, channel_max);
2127 BLI_remlink(ed->seqbasep, seq);
2128 BLI_addtail(&seqm->seqbase, seq);
2132 seqm->machine= channel_max;
2133 calc_sequence(seqm);
2135 seqm->strip= MEM_callocN(sizeof(Strip), "metastrip");
2136 seqm->strip->len= seqm->len;
2139 active_seq_set(scene, seqm);
2141 if( seq_test_overlap(ed->seqbasep, seqm) ) shuffle_seq(ed->seqbasep, seqm);
2143 seq_update_muting(ed);
2145 seqUniqueName(scene->ed->seqbasep, seqm);
2147 WM_event_add_notifier(C, NC_SCENE|ND_SEQUENCER, scene);
2149 return OPERATOR_FINISHED;
2152 void SEQUENCER_OT_meta_make(wmOperatorType *ot)
2155 ot->name= "Make Meta Strip";
2156 ot->idname= "SEQUENCER_OT_meta_make";
2157 ot->description="Group selected strips into a metastrip.";
2160 ot->invoke= WM_operator_confirm;
2161 ot->exec= sequencer_meta_make_exec;
2163 ot->poll= ED_operator_sequencer_active;
2166 ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO;
2170 static int seq_depends_on_meta(Sequence *seq, Sequence *seqm)
2172 if (seq == seqm) return 1;
2173 else if (seq->seq1 && seq_depends_on_meta(seq->seq1, seqm)) return 1;
2174 else if (seq->seq2 && seq_depends_on_meta(seq->seq2, seqm)) return 1;
2175 else if (seq->seq3 && seq_depends_on_meta(seq->seq3, seqm)) return 1;
2179 /* separate_meta_make operator */
2180 static int sequencer_meta_separate_exec(bContext *C, wmOperator *op)
2182 Scene *scene= CTX_data_scene(C);
2183 Editing *ed= seq_give_editing(scene, FALSE);
2185 Sequence *seq, *last_seq = active_seq_get(scene); /* last_seq checks ed==NULL */
2187 if(last_seq==NULL || last_seq->type!=SEQ_META)
2188 return OPERATOR_CANCELLED;
2190 addlisttolist(ed->seqbasep, &last_seq->seqbase);
2192 last_seq->seqbase.first= 0;
2193 last_seq->seqbase.last= 0;
2195 BLI_remlink(ed->seqbasep, last_seq);
2196 seq_free_sequence(scene, last_seq);
2198 /* emtpy meta strip, delete all effects depending on it */
2199 for(seq=ed->seqbasep->first; seq; seq=seq->next)
2200 if((seq->type & SEQ_EFFECT) && seq_depends_on_meta(seq, last_seq))
2201 seq->flag |= SEQ_FLAG_DELETE;
2203 recurs_del_seq_flag(scene, ed->seqbasep, SEQ_FLAG_DELETE, 0);
2205 /* test for effects and overlap */
2206 SEQP_BEGIN(ed, seq) {
2207 if(seq->flag & SELECT) {
2208 seq->flag &= ~SEQ_OVERLAP;
2209 if( seq_test_overlap(ed->seqbasep, seq) ) {
2210 shuffle_seq(ed->seqbasep, seq);
2217 seq_update_muting(ed);
2219 WM_event_add_notifier(C, NC_SCENE|ND_SEQUENCER, scene);
2221 return OPERATOR_FINISHED;
2224 void SEQUENCER_OT_meta_separate(wmOperatorType *ot)
2227 ot->name= "UnMeta Strip";
2228 ot->idname= "SEQUENCER_OT_meta_separate";
2229 ot->description="Put the contents of a metastrip back in the sequencer.";
2232 ot->invoke= WM_operator_confirm;
2233 ot->exec= sequencer_meta_separate_exec;
2235 ot->poll= ED_operator_sequencer_active;
2238 ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO;
2241 /* view_all operator */
2242 static int sequencer_view_all_exec(bContext *C, wmOperator *op)
2244 Scene *scene= CTX_data_scene(C);
2245 bScreen *sc= CTX_wm_screen(C);
2246 ScrArea *area= CTX_wm_area(C);
2247 ARegion *ar= CTX_wm_region(C);
2248 View2D *v2d= UI_view2d_fromcontext(C);
2251 UI_view2d_curRect_validate(v2d);
2252 UI_view2d_sync(sc, area, v2d, V2D_LOCK_COPY);
2254 ED_area_tag_redraw(CTX_wm_area(C));
2255 return OPERATOR_FINISHED;
2258 void SEQUENCER_OT_view_all(wmOperatorType *ot)
2261 ot->name= "View All";
2262 ot->idname= "SEQUENCER_OT_view_all";
2263 ot->description="View all the strips in the sequencer.";
2266 ot->exec= sequencer_view_all_exec;
2268 ot->poll= ED_operator_sequencer_active;
2271 ot->flag= OPTYPE_REGISTER;
2274 /* view_all operator */
2275 static int sequencer_view_all_preview_exec(bContext *C, wmOperator *op)
2277 Scene *scene= CTX_data_scene(C);
2278 bScreen *sc= CTX_wm_screen(C);
2279 ScrArea *area= CTX_wm_area(C);
2280 ARegion *ar= CTX_wm_region(C);
2281 SpaceSeq *sseq= area->spacedata.first;
2282 View2D *v2d= UI_view2d_fromcontext(C);
2285 /* Like zooming on an image view */
2287 int width, height, imgwidth, imgheight;
2292 seq_reset_imageofs(sseq);
2294 imgwidth= (scene->r.size*scene->r.xsch)/100;
2295 imgheight= (scene->r.size*scene->r.ysch)/100;
2297 /* Apply aspect, dosnt need to be that accurate */
2298 imgwidth= (int)(imgwidth * ((float)scene->r.xasp / (float)scene->r.yasp));
2300 if (((imgwidth >= width) || (imgheight >= height)) &&
2301 ((width > 0) && (height > 0))) {
2303 /* Find the zoom value that will fit the image in the image space */
2304 zoomX = ((float)width) / ((float)imgwidth);
2305 zoomY = ((float)height) / ((float)imgheight);
2306 sseq->zoom= (zoomX < zoomY) ? zoomX : zoomY;
2308 sseq->zoom = 1.0f / power_of_2(1/ MIN2(zoomX, zoomY) );
2314 ED_area_tag_redraw(CTX_wm_area(C));
2315 return OPERATOR_FINISHED;
2318 void SEQUENCER_OT_view_all_preview(wmOperatorType *ot)
2321 ot->name= "View All";
2322 ot->idname= "SEQUENCER_OT_view_all_preview";
2323 ot->description="Zoom preview to fit in the area.";
2326 ot->exec= sequencer_view_all_preview_exec;
2328 ot->poll= ED_operator_sequencer_active;
2331 ot->flag= OPTYPE_REGISTER;
2334 static EnumPropertyItem view_type_items[] = {
2335 {SEQ_VIEW_SEQUENCE, "SEQUENCER", ICON_SEQ_SEQUENCER, "Sequencer", ""},
2336 {SEQ_VIEW_PREVIEW, "PREVIEW", ICON_SEQ_PREVIEW, "Image Preview", ""},
2337 {SEQ_VIEW_SEQUENCE_PREVIEW, "SEQUENCER_PREVIEW", ICON_SEQ_SEQUENCER, "Sequencer and Image Preview", ""},
2338 {0, NULL, 0, NULL, NULL}};
2340 /* view_all operator */
2341 static int sequencer_view_toggle_exec(bContext *C, wmOperator *op)
2343 SpaceSeq *sseq= (SpaceSeq *)CTX_wm_space_data(C);
2346 if (sseq->view > SEQ_VIEW_SEQUENCE_PREVIEW) sseq->view = SEQ_VIEW_SEQUENCE;
2348 ED_sequencer_update_view(C, sseq->view);
2350 return OPERATOR_FINISHED;
2353 void SEQUENCER_OT_view_toggle(wmOperatorType *ot)
2356 ot->name= "View Toggle";
2357 ot->idname= "SEQUENCER_OT_view_toggle";
2358 ot->description="Toggle between sequencer views (sequence, preview, both).";
2361 ot->exec= sequencer_view_toggle_exec;
2362 ot->poll= ED_operator_sequencer_active;
2365 ot->flag= OPTYPE_REGISTER;
2369 /* view_selected operator */
2370 static int sequencer_view_selected_exec(bContext *C, wmOperator *op)
2372 Scene *scene= CTX_data_scene(C);
2373 View2D *v2d= UI_view2d_fromcontext(C);
2374 ScrArea *area= CTX_wm_area(C);
2375 bScreen *sc= CTX_wm_screen(C);
2376 Editing *ed= seq_give_editing(scene, FALSE);
2379 int xmin= MAXFRAME*2;
2380 int xmax= -MAXFRAME*2;
2389 return OPERATOR_CANCELLED;
2391 for(seq=ed->seqbasep->first; seq; seq=seq->next) {
2392 if(seq->flag & SELECT) {
2393 xmin= MIN2(xmin, seq->startdisp);
2394 xmax= MAX2(xmax, seq->enddisp);
2396 ymin= MIN2(ymin, seq->machine);
2397 ymax= MAX2(ymax, seq->machine);
2408 orig_height= v2d->cur.ymax - v2d->cur.ymin;
2410 v2d->cur.xmin= xmin;
2411 v2d->cur.xmax= xmax;
2413 v2d->cur.ymin= ymin;
2414 v2d->cur.ymax= ymax;
2416 /* only zoom out vertically */
2417 if (orig_height > v2d->cur.ymax - v2d->cur.ymin) {
2418 ymid= (v2d->cur.ymax + v2d->cur.ymin) / 2;
2420 v2d->cur.ymin= ymid - (orig_height/2);
2421 v2d->cur.ymax= ymid + (orig_height/2);
2424 UI_view2d_curRect_validate(v2d);
2425 UI_view2d_sync(sc, area, v2d, V2D_LOCK_COPY);
2427 ED_area_tag_redraw(CTX_wm_area(C));
2430 return OPERATOR_FINISHED;
2433 void SEQUENCER_OT_view_selected(wmOperatorType *ot)
2436 ot->name= "View Selected";
2437 ot->idname= "SEQUENCER_OT_view_selected";
2438 ot->description="Zoom the sequencer on the selected strips.";
2441 ot->exec= sequencer_view_selected_exec;
2443 ot->poll= ED_operator_sequencer_active;
2446 ot->flag= OPTYPE_REGISTER;
2450 static int find_next_prev_edit(Scene *scene, int cfra, int side)
2452 Editing *ed= seq_give_editing(scene, FALSE);
2453 Sequence *seq,*best_seq = NULL,*frame_seq = NULL;
2455 int dist, best_dist;
2456 best_dist = MAXFRAME*2;
2458 if(ed==NULL) return cfra;
2460 for(seq= ed->seqbasep->first; seq; seq= seq->next) {
2465 if (seq->startdisp < cfra) {
2466 dist = cfra - seq->startdisp;
2469 case SEQ_SIDE_RIGHT:
2470 if (seq->startdisp > cfra) {
2471 dist = seq->startdisp - cfra;
2472 } else if (seq->startdisp == cfra) {
2478 if (dist < best_dist) {
2484 /* if no sequence to the right is found and the
2485 frame is on the start of the last sequence,
2486 move to the end of the last sequence */
2487 if (frame_seq) cfra = frame_seq->enddisp;
2489 return best_seq ? best_seq->startdisp : cfra;
2492 static int next_prev_edit_internal(Scene *scene, int side)
2496 int nfra= find_next_prev_edit(scene, cfra, side);
2506 /* move frame to next edit point operator */
2507 static int sequencer_next_edit_exec(bContext *C, wmOperator *op)
2509 Scene *scene= CTX_data_scene(C);
2511 if(!next_prev_edit_internal(scene, SEQ_SIDE_RIGHT))
2512 return OPERATOR_CANCELLED;
2514 WM_event_add_notifier(C, NC_SCENE|ND_FRAME, scene);
2516 return OPERATOR_FINISHED;
2519 void SEQUENCER_OT_next_edit(wmOperatorType *ot)
2522 ot->name= "Next Edit";
2523 ot->idname= "SEQUENCER_OT_next_edit";
2524 ot->description="Move frame to next edit point.";
2527 ot->exec= sequencer_next_edit_exec;
2528 ot->poll= ED_operator_sequencer_active;
2531 ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO;
2536 /* move frame to previous edit point operator */
2537 static int sequencer_previous_edit_exec(bContext *C, wmOperator *op)
2539 Scene *scene= CTX_data_scene(C);
2541 if(!next_prev_edit_internal(scene, SEQ_SIDE_LEFT))
2542 return OPERATOR_CANCELLED;
2544 WM_event_add_notifier(C, NC_SCENE|ND_FRAME, scene);
2546 return OPERATOR_FINISHED;
2549 void SEQUENCER_OT_previous_edit(wmOperatorType *ot)
2552 ot->name= "Previous Edit";
2553 ot->idname= "SEQUENCER_OT_previous_edit";
2554 ot->description="Move frame to previous edit point.";
2557 ot->exec= sequencer_previous_edit_exec;
2558 ot->poll= ED_operator_sequencer_active;
2561 ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO;
2566 static void swap_sequence(Sequence* seqa, Sequence* seqb)
2568 int gap = seqb->startdisp - seqa->enddisp;
2569 seqb->start = seqa->start;
2570 calc_sequence(seqb);
2571 seqa->start = seqb->enddisp + gap;
2572 calc_sequence(seqa);
2575 static Sequence* sequence_find_parent(Scene* scene, Sequence* child)
2577 Editing *ed= seq_give_editing(scene, FALSE);
2578 Sequence *parent= NULL;
2581 if(ed==NULL) return NULL;
2583 for(seq= ed->seqbasep->first; seq; seq= seq->next) {
2584 if ( (seq != child) && seq_is_parent(seq, child) ) {
2593 static int sequencer_swap_exec(bContext *C, wmOperator *op)
2595 Scene *scene= CTX_data_scene(C);
2596 Editing *ed= seq_give_editing(scene, FALSE);
2597 Sequence *active_seq = active_seq_get(scene);
2598 Sequence *seq, *iseq;
2599 int side= RNA_enum_get(op->ptr, "side");
2601 if(ed==NULL) return OPERATOR_CANCELLED;
2602 if(active_seq==NULL) return OPERATOR_CANCELLED;
2604 seq = find_next_prev_sequence(scene, active_seq, side, -1);
2608 /* disallow effect strips */
2609 if ((seq->type!=SEQ_COLOR) && (seq->effectdata || seq->seq1 || seq->seq2 || seq->seq3))
2610 return OPERATOR_CANCELLED;
2611 if ((active_seq->type!=SEQ_COLOR) && (active_seq->effectdata || active_seq->seq1 || active_seq->seq2 || active_seq->seq3))
2612 return OPERATOR_CANCELLED;
2616 swap_sequence(seq, active_seq);
2618 case SEQ_SIDE_RIGHT:
2619 swap_sequence(active_seq, seq);
2623 // XXX - should be a generic function
2624 for(iseq= scene->ed->seqbasep->first; iseq; iseq= iseq->next) {
2625 if((iseq->type & SEQ_EFFECT) && (seq_is_parent(iseq, active_seq) || seq_is_parent(iseq, seq))) {
2626 calc_sequence(iseq);
2630 /* do this in a new loop since both effects need to be calculated first */
2631 for(iseq= scene->ed->seqbasep->first; iseq; iseq= iseq->next) {
2632 if((iseq->type & SEQ_EFFECT) && (seq_is_parent(iseq, active_seq) || seq_is_parent(iseq, seq))) {
2633 /* this may now overlap */
2634 if( seq_test_overlap(ed->seqbasep, iseq) ) {
2635 shuffle_seq(ed->seqbasep, iseq);
2644 WM_event_add_notifier(C, NC_SCENE|ND_SEQUENCER, scene);
2646 return OPERATOR_FINISHED;
2649 return OPERATOR_CANCELLED;
2652 void SEQUENCER_OT_swap(wmOperatorType *ot)
2655 ot->name= "Swap Strip";
2656 ot->idname= "SEQUENCER_OT_swap";
2657 ot->description="Swap active strip with strip to the left.";
2660 ot->exec= sequencer_swap_exec;
2661 ot->poll= ED_operator_sequencer_active;
2664 ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO;
2667 RNA_def_enum(ot->srna, "side", prop_side_lr_types, SEQ_SIDE_RIGHT, "Side", "Side of the strip to swap");
2670 static int sequencer_rendersize_exec(bContext *C, wmOperator *op)
2672 int retval = OPERATOR_CANCELLED;
2673 Scene *scene= CTX_data_scene(C);
2674 Sequence *active_seq = active_seq_get(scene);
2676 if(active_seq==NULL)
2677 return OPERATOR_CANCELLED;
2679 switch (active_seq->type) {
2682 if (active_seq->strip) {
2683 // prevent setting the render size if sequence values aren't initialized
2684 if ( (active_seq->strip->orx>0) && (active_seq->strip->ory>0) ) {
2685 scene->r.xsch= active_seq->strip->orx;
2686 scene->r.ysch= active_seq->strip->ory;
2687 WM_event_add_notifier(C, NC_SCENE|ND_RENDER_OPTIONS, scene);
2688 retval = OPERATOR_FINISHED;
2702 void SEQUENCER_OT_rendersize(wmOperatorType *ot)
2705 ot->name= "Set Render Size";
2706 ot->idname= "SEQUENCER_OT_rendersize";
2707 ot->description="Set render size and aspect from active sequence.";
2710 ot->exec= sequencer_rendersize_exec;
2711 ot->poll= ED_operator_sequencer_active;
2714 ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO;
2719 static void seq_del_sound(Scene *scene, Sequence *seq)
2721 if(seq->type == SEQ_META) {
2723 for(iseq= seq->seqbase.first; iseq; iseq= iseq->next) {
2724 seq_del_sound(scene, iseq);
2727 else if(seq->sound_handle) {
2728 sound_delete_handle(scene, seq->sound_handle);
2729 seq->sound_handle= NULL;
2733 /* TODO, validate scenes */
2734 static int sequencer_copy_exec(bContext *C, wmOperator *op)
2736 Scene *scene= CTX_data_scene(C);
2737 Editing *ed= seq_give_editing(scene, FALSE);
2738 Sequence *seq, *seq_act;
2741 return OPERATOR_CANCELLED;
2743 seq_free_clipboard();
2745 if(seqbase_isolated_sel_check(ed->seqbasep)==FALSE) {
2746 BKE_report(op->reports, RPT_ERROR, "Please select all related strips");
2747 return OPERATOR_CANCELLED;
2750 recurs_dupli_seq(scene, ed->seqbasep, &seqbase_clipboard, FALSE);
2751 seqbase_clipboard_frame= scene->r.cfra;
2753 /* Need to remove anything that references the current scene */
2754 for(seq= seqbase_clipboard.first; seq; seq= seq->next) {
2755 seq_del_sound(scene, seq);
2758 return OPERATOR_FINISHED;
2761 void SEQUENCER_OT_copy(wmOperatorType *ot)
2765 ot->idname= "SEQUENCER_OT_copy";
2769 ot->exec= sequencer_copy_exec;
2770 ot->poll= ED_operator_sequencer_active;
2773 ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO;
2778 static void seq_offset(Sequence *seq, int ofs)
2780 if(seq->type == SEQ_META) {
2782 for(iseq= seq->seqbase.first; iseq; iseq= iseq->next) {
2783 seq_offset(iseq, ofs);
2790 calc_sequence_disp(seq);
2793 static int sequencer_paste_exec(bContext *C, wmOperator *op)
2795 Scene *scene= CTX_data_scene(C);
2796 Editing *ed= seq_give_editing(scene, TRUE); /* create if needed */
2797 ListBase new = {NULL, NULL};
2801 deselect_all_seq(scene);
2802 ofs = scene->r.cfra - seqbase_clipboard_frame;
2804 recurs_dupli_seq(scene, &seqbase_clipboard, &new, FALSE);
2806 /* transform pasted strips before adding */
2808 for(iseq= new.first; iseq; iseq= iseq->next) {
2809 seq_offset(iseq, ofs);
2813 addlisttolist(ed->seqbasep, &new);
2815 WM_event_add_notifier(C, NC_SCENE|ND_SEQUENCER, scene);
2817 return OPERATOR_FINISHED;
2820 void SEQUENCER_OT_paste(wmOperatorType *ot)
2824 ot->idname= "SEQUENCER_OT_paste";
2828 ot->exec= sequencer_paste_exec;
2829 ot->poll= ED_operator_sequencer_active;
2832 ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO;