1 /*
2  * This program is free software; you can redistribute it and/or
3  * modify it under the terms of the GNU General Public License
4  * as published by the Free Software Foundation; either version 2
5  * of the License, or (at your option) any later version.
6  *
7  * This program is distributed in the hope that it will be useful,
8  * but WITHOUT ANY WARRANTY; without even the implied warranty of
9  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
10  * GNU General Public License for more details.
11  *
12  * You should have received a copy of the GNU General Public License
13  * along with this program; if not, write to the Free Software Foundation,
14  * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
15  *
16  * The Original Code is Copyright (C) 2001-2002 by NaN Holding BV.
17  * All rights reserved.
18  */
19 
20 /** \file
21  * \ingroup spseq
22  */
23 
24 #include <math.h>
25 #include <stdlib.h>
26 #include <string.h>
27 
28 #include "MEM_guardedalloc.h"
29 
30 #include "BLI_blenlib.h"
31 #include "BLI_ghash.h"
32 #include "BLI_math.h"
33 #include "BLI_timecode.h"
34 #include "BLI_utildefines.h"
35 
36 #include "BLT_translation.h"
37 
38 #include "DNA_scene_types.h"
39 #include "DNA_sound_types.h"
40 
41 #include "BKE_context.h"
42 #include "BKE_global.h"
43 #include "BKE_lib_id.h"
44 #include "BKE_main.h"
45 #include "BKE_report.h"
46 #include "BKE_sequencer.h"
47 #include "BKE_sound.h"
48 
49 #include "WM_api.h"
50 #include "WM_types.h"
51 
52 #include "RNA_define.h"
53 
54 /* For menu, popup, icons, etc. */
55 #include "ED_numinput.h"
56 #include "ED_outliner.h"
57 #include "ED_screen.h"
58 #include "ED_sequencer.h"
59 
60 #include "UI_interface.h"
61 #include "UI_resources.h"
62 #include "UI_view2d.h"
63 
64 #include "DEG_depsgraph.h"
65 #include "DEG_depsgraph_build.h"
66 
67 /* Own include. */
68 #include "sequencer_intern.h"
69 
70 /* -------------------------------------------------------------------- */
71 /** \name Structs & Enums
72  * \{ */
73 
74 /* RNA Enums, used in multiple files. */
75 EnumPropertyItem sequencer_prop_effect_types[] = {
76     {SEQ_TYPE_CROSS, "CROSS", 0, "Crossfade", "Crossfade effect strip type"},
77     {SEQ_TYPE_ADD, "ADD", 0, "Add", "Add effect strip type"},
78     {SEQ_TYPE_SUB, "SUBTRACT", 0, "Subtract", "Subtract effect strip type"},
79     {SEQ_TYPE_ALPHAOVER, "ALPHA_OVER", 0, "Alpha Over", "Alpha Over effect strip type"},
80     {SEQ_TYPE_ALPHAUNDER, "ALPHA_UNDER", 0, "Alpha Under", "Alpha Under effect strip type"},
81     {SEQ_TYPE_GAMCROSS, "GAMMA_CROSS", 0, "Gamma Cross", "Gamma Cross effect strip type"},
82     {SEQ_TYPE_MUL, "MULTIPLY", 0, "Multiply", "Multiply effect strip type"},
83     {SEQ_TYPE_OVERDROP, "OVER_DROP", 0, "Alpha Over Drop", "Alpha Over Drop effect strip type"},
84     {SEQ_TYPE_WIPE, "WIPE", 0, "Wipe", "Wipe effect strip type"},
85     {SEQ_TYPE_GLOW, "GLOW", 0, "Glow", "Glow effect strip type"},
86     {SEQ_TYPE_TRANSFORM, "TRANSFORM", 0, "Transform", "Transform effect strip type"},
87     {SEQ_TYPE_COLOR, "COLOR", 0, "Color", "Color effect strip type"},
88     {SEQ_TYPE_SPEED, "SPEED", 0, "Speed", "Color effect strip type"},
89     {SEQ_TYPE_MULTICAM, "MULTICAM", 0, "Multicam Selector", ""},
90     {SEQ_TYPE_ADJUSTMENT, "ADJUSTMENT", 0, "Adjustment Layer", ""},
91     {SEQ_TYPE_GAUSSIAN_BLUR, "GAUSSIAN_BLUR", 0, "Gaussian Blur", ""},
92     {SEQ_TYPE_TEXT, "TEXT", 0, "Text", ""},
93     {SEQ_TYPE_COLORMIX, "COLORMIX", 0, "Color Mix", ""},
94     {0, NULL, 0, NULL, NULL},
95 };
96 
97 #define SEQ_SIDE_MOUSE -1
98 
99 EnumPropertyItem prop_side_types[] = {
100     {SEQ_SIDE_MOUSE, "MOUSE", 0, "Mouse position", ""},
101     {SEQ_SIDE_LEFT, "LEFT", 0, "Left", ""},
102     {SEQ_SIDE_RIGHT, "RIGHT", 0, "Right", ""},
103     {SEQ_SIDE_BOTH, "BOTH", 0, "Both", ""},
104     {SEQ_SIDE_NO_CHANGE, "NO_CHANGE", 0, "No change", ""},
105     {0, NULL, 0, NULL, NULL},
106 };
107 
108 static const EnumPropertyItem prop_side_lr_types[] = {
109     {SEQ_SIDE_LEFT, "LEFT", 0, "Left", ""},
110     {SEQ_SIDE_RIGHT, "RIGHT", 0, "Right", ""},
111     {0, NULL, 0, NULL, NULL},
112 };
113 
114 typedef struct TransSeq {
115   int start, machine;
116   int startstill, endstill;
117   int startdisp, enddisp;
118   int startofs, endofs;
119   int anim_startofs, anim_endofs;
120   /* int final_left, final_right; */ /* UNUSED */
121   int len;
122 } TransSeq;
123 
124 /** \} */
125 
126 /* -------------------------------------------------------------------- */
127 /** \name Proxy Job Manager
128  * \{ */
129 
130 typedef struct ProxyBuildJob {
131   struct Main *main;
132   struct Depsgraph *depsgraph;
133   Scene *scene;
134   ListBase queue;
135   int stop;
136 } ProxyJob;
137 
proxy_freejob(void * pjv)138 static void proxy_freejob(void *pjv)
139 {
140   ProxyJob *pj = pjv;
141 
142   BLI_freelistN(&pj->queue);
143 
144   MEM_freeN(pj);
145 }
146 
147 /* Only this runs inside thread. */
proxy_startjob(void * pjv,short * stop,short * do_update,float * progress)148 static void proxy_startjob(void *pjv, short *stop, short *do_update, float *progress)
149 {
150   ProxyJob *pj = pjv;
151   LinkData *link;
152 
153   for (link = pj->queue.first; link; link = link->next) {
154     struct SeqIndexBuildContext *context = link->data;
155 
156     BKE_sequencer_proxy_rebuild(context, stop, do_update, progress);
157 
158     if (*stop) {
159       pj->stop = 1;
160       fprintf(stderr, "Canceling proxy rebuild on users request...\n");
161       break;
162     }
163   }
164 }
165 
proxy_endjob(void * pjv)166 static void proxy_endjob(void *pjv)
167 {
168   ProxyJob *pj = pjv;
169   Editing *ed = BKE_sequencer_editing_get(pj->scene, false);
170   LinkData *link;
171 
172   for (link = pj->queue.first; link; link = link->next) {
173     BKE_sequencer_proxy_rebuild_finish(link->data, pj->stop);
174   }
175 
176   BKE_sequencer_free_imbuf(pj->scene, &ed->seqbase, false);
177 
178   WM_main_add_notifier(NC_SCENE | ND_SEQUENCER, pj->scene);
179 }
180 
seq_proxy_build_job(const bContext * C,ReportList * reports)181 static void seq_proxy_build_job(const bContext *C, ReportList *reports)
182 {
183   wmJob *wm_job;
184   ProxyJob *pj;
185   struct Depsgraph *depsgraph = CTX_data_depsgraph_pointer(C);
186   Scene *scene = CTX_data_scene(C);
187   Editing *ed = BKE_sequencer_editing_get(scene, false);
188   ScrArea *area = CTX_wm_area(C);
189   Sequence *seq;
190   GSet *file_list;
191 
192   if (ed == NULL) {
193     return;
194   }
195 
196   wm_job = WM_jobs_get(CTX_wm_manager(C),
197                        CTX_wm_window(C),
198                        scene,
199                        "Building Proxies",
200                        WM_JOB_PROGRESS,
201                        WM_JOB_TYPE_SEQ_BUILD_PROXY);
202 
203   pj = WM_jobs_customdata_get(wm_job);
204 
205   if (!pj) {
206     pj = MEM_callocN(sizeof(ProxyJob), "proxy rebuild job");
207 
208     pj->depsgraph = depsgraph;
209     pj->scene = scene;
210     pj->main = CTX_data_main(C);
211 
212     WM_jobs_customdata_set(wm_job, pj, proxy_freejob);
213     WM_jobs_timer(wm_job, 0.1, NC_SCENE | ND_SEQUENCER, NC_SCENE | ND_SEQUENCER);
214     WM_jobs_callbacks(wm_job, proxy_startjob, NULL, NULL, proxy_endjob);
215   }
216 
217   file_list = BLI_gset_new(BLI_ghashutil_strhash_p, BLI_ghashutil_strcmp, "file list");
218   bool selected = false; /* Check for no selected strips */
219 
220   SEQ_CURRENT_BEGIN (ed, seq) {
221     if (!ELEM(seq->type, SEQ_TYPE_MOVIE, SEQ_TYPE_IMAGE, SEQ_TYPE_META) ||
222         (seq->flag & SELECT) == 0) {
223       continue;
224     }
225 
226     selected = true;
227     if (!(seq->flag & SEQ_USE_PROXY)) {
228       BKE_reportf(reports, RPT_WARNING, "Proxy is not enabled for %s, skipping", seq->name);
229       continue;
230     }
231     if (seq->strip->proxy->build_size_flags == 0) {
232       BKE_reportf(reports, RPT_WARNING, "Resolution is not selected for %s, skipping", seq->name);
233       continue;
234     }
235 
236     bool success = BKE_sequencer_proxy_rebuild_context(
237         pj->main, pj->depsgraph, pj->scene, seq, file_list, &pj->queue);
238 
239     if (!success && (seq->strip->proxy->build_flags & SEQ_PROXY_SKIP_EXISTING) != 0) {
240       BKE_reportf(reports, RPT_WARNING, "Overwrite is not checked for %s, skipping", seq->name);
241     }
242   }
243   SEQ_CURRENT_END;
244 
245   if (!selected) {
246     BKE_reportf(reports, RPT_WARNING, "Select movie or image strips");
247     return;
248   }
249 
250   BLI_gset_free(file_list, MEM_freeN);
251 
252   if (selected && !WM_jobs_is_running(wm_job)) {
253     G.is_break = false;
254     WM_jobs_start(CTX_wm_manager(C), wm_job);
255   }
256 
257   ED_area_tag_redraw(area);
258 }
259 
260 /** \} */
261 
262 /* -------------------------------------------------------------------- */
263 /** \name Sequence Query Utilities
264  * \{ */
265 
seq_rectf(Sequence * seq,rctf * rect)266 void seq_rectf(Sequence *seq, rctf *rect)
267 {
268   rect->xmin = seq->startdisp;
269   rect->xmax = seq->enddisp;
270   rect->ymin = seq->machine + SEQ_STRIP_OFSBOTTOM;
271   rect->ymax = seq->machine + SEQ_STRIP_OFSTOP;
272 }
273 
boundbox_seq(Scene * scene,rctf * rect)274 void boundbox_seq(Scene *scene, rctf *rect)
275 {
276   Sequence *seq;
277   Editing *ed = BKE_sequencer_editing_get(scene, false);
278   float min[2], max[2];
279 
280   if (ed == NULL) {
281     return;
282   }
283 
284   min[0] = SFRA;
285   max[0] = EFRA + 1;
286   min[1] = 0.0;
287   max[1] = 8.0;
288 
289   seq = ed->seqbasep->first;
290   while (seq) {
291 
292     if (min[0] > seq->startdisp - 1) {
293       min[0] = seq->startdisp - 1;
294     }
295     if (max[0] < seq->enddisp + 1) {
296       max[0] = seq->enddisp + 1;
297     }
298     if (max[1] < seq->machine + 2) {
299       max[1] = seq->machine + 2;
300     }
301 
302     seq = seq->next;
303   }
304 
305   rect->xmin = min[0];
306   rect->xmax = max[0];
307   rect->ymin = min[1];
308   rect->ymax = max[1];
309 }
310 
mouse_frame_side(View2D * v2d,short mouse_x,int frame)311 static int mouse_frame_side(View2D *v2d, short mouse_x, int frame)
312 {
313   int mval[2];
314   float mouseloc[2];
315 
316   mval[0] = mouse_x;
317   mval[1] = 0;
318 
319   /* Choose the side based on which side of the current frame the mouse is on. */
320   UI_view2d_region_to_view(v2d, mval[0], mval[1], &mouseloc[0], &mouseloc[1]);
321 
322   return mouseloc[0] > frame ? SEQ_SIDE_RIGHT : SEQ_SIDE_LEFT;
323 }
324 
find_neighboring_sequence(Scene * scene,Sequence * test,int lr,int sel)325 Sequence *find_neighboring_sequence(Scene *scene, Sequence *test, int lr, int sel)
326 {
327   /* sel: 0==unselected, 1==selected, -1==don't care. */
328   Sequence *seq;
329   Editing *ed = BKE_sequencer_editing_get(scene, false);
330 
331   if (ed == NULL) {
332     return NULL;
333   }
334 
335   if (sel > 0) {
336     sel = SELECT;
337   }
338 
339   for (seq = ed->seqbasep->first; seq; seq = seq->next) {
340     if ((seq != test) && (test->machine == seq->machine) &&
341         ((sel == -1) || (sel && (seq->flag & SELECT)) ||
342          (sel == 0 && (seq->flag & SELECT) == 0))) {
343       switch (lr) {
344         case SEQ_SIDE_LEFT:
345           if (test->startdisp == (seq->enddisp)) {
346             return seq;
347           }
348           break;
349         case SEQ_SIDE_RIGHT:
350           if (test->enddisp == (seq->startdisp)) {
351             return seq;
352           }
353           break;
354       }
355     }
356   }
357   return NULL;
358 }
359 
find_next_prev_sequence(Scene * scene,Sequence * test,int lr,int sel)360 static Sequence *find_next_prev_sequence(Scene *scene, Sequence *test, int lr, int sel)
361 {
362   /* sel: 0==unselected, 1==selected, -1==don't care. */
363   Sequence *seq, *best_seq = NULL;
364   Editing *ed = BKE_sequencer_editing_get(scene, false);
365 
366   int dist, best_dist;
367   best_dist = MAXFRAME * 2;
368 
369   if (ed == NULL) {
370     return NULL;
371   }
372 
373   seq = ed->seqbasep->first;
374   while (seq) {
375     if ((seq != test) && (test->machine == seq->machine) && (test->depth == seq->depth) &&
376         ((sel == -1) || (sel == (seq->flag & SELECT)))) {
377       dist = MAXFRAME * 2;
378 
379       switch (lr) {
380         case SEQ_SIDE_LEFT:
381           if (seq->enddisp <= test->startdisp) {
382             dist = test->enddisp - seq->startdisp;
383           }
384           break;
385         case SEQ_SIDE_RIGHT:
386           if (seq->startdisp >= test->enddisp) {
387             dist = seq->startdisp - test->enddisp;
388           }
389           break;
390       }
391 
392       if (dist == 0) {
393         best_seq = seq;
394         break;
395       }
396       if (dist < best_dist) {
397         best_dist = dist;
398         best_seq = seq;
399       }
400     }
401     seq = seq->next;
402   }
403   return best_seq; /* Can be null. */
404 }
405 
find_nearest_seq(Scene * scene,View2D * v2d,int * hand,const int mval[2])406 Sequence *find_nearest_seq(Scene *scene, View2D *v2d, int *hand, const int mval[2])
407 {
408   Sequence *seq;
409   Editing *ed = BKE_sequencer_editing_get(scene, false);
410   float x, y;
411   float pixelx;
412   float handsize;
413   float displen;
414   *hand = SEQ_SIDE_NONE;
415 
416   if (ed == NULL) {
417     return NULL;
418   }
419 
420   pixelx = BLI_rctf_size_x(&v2d->cur) / BLI_rcti_size_x(&v2d->mask);
421 
422   UI_view2d_region_to_view(v2d, mval[0], mval[1], &x, &y);
423 
424   seq = ed->seqbasep->first;
425 
426   while (seq) {
427     if (seq->machine == (int)y) {
428       /* Check for both normal strips, and strips that have been flipped horizontally. */
429       if (((seq->startdisp < seq->enddisp) && (seq->startdisp <= x && seq->enddisp >= x)) ||
430           ((seq->startdisp > seq->enddisp) && (seq->startdisp >= x && seq->enddisp <= x))) {
431         if (BKE_sequence_tx_test(seq)) {
432 
433           /* Clamp handles to defined size in pixel space. */
434           handsize = 2.0f * sequence_handle_size_get_clamped(seq, pixelx);
435           displen = (float)abs(seq->startdisp - seq->enddisp);
436 
437           /* Don't even try to grab the handles of small strips. */
438           if (displen / pixelx > 16) {
439 
440             /* Set the max value to handle to 1/3 of the total len when its
441              * less than 28. This is important because otherwise selecting
442              * handles happens even when you click in the middle. */
443             if ((displen / 3) < 30 * pixelx) {
444               handsize = displen / 3;
445             }
446             else {
447               CLAMP(handsize, 7 * pixelx, 30 * pixelx);
448             }
449 
450             if (handsize + seq->startdisp >= x) {
451               *hand = SEQ_SIDE_LEFT;
452             }
453             else if (-handsize + seq->enddisp <= x) {
454               *hand = SEQ_SIDE_RIGHT;
455             }
456           }
457         }
458         return seq;
459       }
460     }
461     seq = seq->next;
462   }
463   return NULL;
464 }
465 
seq_is_parent(Sequence * par,Sequence * seq)466 static bool seq_is_parent(Sequence *par, Sequence *seq)
467 {
468   return ((par->seq1 == seq) || (par->seq2 == seq) || (par->seq3 == seq));
469 }
470 
471 /** \} */
472 
473 /* -------------------------------------------------------------------- */
474 /** \name Selection Utilities
475  * \{ */
476 
ED_sequencer_deselect_all(Scene * scene)477 void ED_sequencer_deselect_all(Scene *scene)
478 {
479   Sequence *seq;
480   Editing *ed = BKE_sequencer_editing_get(scene, false);
481 
482   if (ed == NULL) {
483     return;
484   }
485 
486   SEQ_CURRENT_BEGIN (ed, seq) {
487     seq->flag &= ~SEQ_ALLSEL;
488   }
489   SEQ_CURRENT_END;
490 }
491 
recurs_sel_seq(Sequence * seqm)492 void recurs_sel_seq(Sequence *seqm)
493 {
494   Sequence *seq;
495 
496   seq = seqm->seqbase.first;
497   while (seq) {
498 
499     if (seqm->flag & (SEQ_LEFTSEL + SEQ_RIGHTSEL)) {
500       seq->flag &= ~SEQ_ALLSEL;
501     }
502     else if (seqm->flag & SELECT) {
503       seq->flag |= SELECT;
504     }
505     else {
506       seq->flag &= ~SEQ_ALLSEL;
507     }
508 
509     if (seq->seqbase.first) {
510       recurs_sel_seq(seq);
511     }
512 
513     seq = seq->next;
514   }
515 }
516 
517 /** \} */
518 
519 /* -------------------------------------------------------------------- */
520 /** \name Public Context Checks
521  * \{ */
522 
ED_space_sequencer_maskedit_mask_poll(bContext * C)523 bool ED_space_sequencer_maskedit_mask_poll(bContext *C)
524 {
525   return ED_space_sequencer_maskedit_poll(C);
526 }
527 
ED_space_sequencer_check_show_maskedit(SpaceSeq * sseq,Scene * scene)528 bool ED_space_sequencer_check_show_maskedit(SpaceSeq *sseq, Scene *scene)
529 {
530   if (sseq && sseq->mainb == SEQ_DRAW_IMG_IMBUF) {
531     return (BKE_sequencer_mask_get(scene) != NULL);
532   }
533 
534   return false;
535 }
536 
ED_space_sequencer_maskedit_poll(bContext * C)537 bool ED_space_sequencer_maskedit_poll(bContext *C)
538 {
539   SpaceSeq *sseq = CTX_wm_space_seq(C);
540 
541   if (sseq) {
542     Scene *scene = CTX_data_scene(C);
543     return ED_space_sequencer_check_show_maskedit(sseq, scene);
544   }
545 
546   return false;
547 }
548 
549 /* Are we displaying the seq output (not channels or histogram). */
ED_space_sequencer_check_show_imbuf(SpaceSeq * sseq)550 bool ED_space_sequencer_check_show_imbuf(SpaceSeq *sseq)
551 {
552   return (ELEM(sseq->view, SEQ_VIEW_PREVIEW, SEQ_VIEW_SEQUENCE_PREVIEW) &&
553           ELEM(sseq->mainb, SEQ_DRAW_SEQUENCE, SEQ_DRAW_IMG_IMBUF));
554 }
555 
ED_space_sequencer_check_show_strip(SpaceSeq * sseq)556 bool ED_space_sequencer_check_show_strip(SpaceSeq *sseq)
557 {
558   return (ELEM(sseq->view, SEQ_VIEW_SEQUENCE, SEQ_VIEW_SEQUENCE_PREVIEW) &&
559           ELEM(sseq->mainb, SEQ_DRAW_SEQUENCE, SEQ_DRAW_IMG_IMBUF));
560 }
561 
562 /** \} */
563 
564 /* -------------------------------------------------------------------- */
565 /** \name Find Selected Strips as Inputs to an Effects Strip
566  * \{ */
567 
seq_effect_find_selected(Scene * scene,Sequence * activeseq,int type,Sequence ** r_selseq1,Sequence ** r_selseq2,Sequence ** r_selseq3,const char ** r_error_str)568 int seq_effect_find_selected(Scene *scene,
569                              Sequence *activeseq,
570                              int type,
571                              Sequence **r_selseq1,
572                              Sequence **r_selseq2,
573                              Sequence **r_selseq3,
574                              const char **r_error_str)
575 {
576   Editing *ed = BKE_sequencer_editing_get(scene, false);
577   Sequence *seq1 = NULL, *seq2 = NULL, *seq3 = NULL, *seq;
578 
579   *r_error_str = NULL;
580 
581   if (!activeseq) {
582     seq2 = BKE_sequencer_active_get(scene);
583   }
584 
585   for (seq = ed->seqbasep->first; seq; seq = seq->next) {
586     if (seq->flag & SELECT) {
587       if (seq->type == SEQ_TYPE_SOUND_RAM && BKE_sequence_effect_get_num_inputs(type) != 0) {
588         *r_error_str = N_("Cannot apply effects to audio sequence strips");
589         return 0;
590       }
591       if ((seq != activeseq) && (seq != seq2)) {
592         if (seq2 == NULL) {
593           seq2 = seq;
594         }
595         else if (seq1 == NULL) {
596           seq1 = seq;
597         }
598         else if (seq3 == NULL) {
599           seq3 = seq;
600         }
601         else {
602           *r_error_str = N_("Cannot apply effect to more than 3 sequence strips");
603           return 0;
604         }
605       }
606     }
607   }
608 
609   /* Make sequence selection a little bit more intuitive
610    * for 3 strips: the last-strip should be seq3. */
611   if (seq3 != NULL && seq2 != NULL) {
612     Sequence *tmp = seq2;
613     seq2 = seq3;
614     seq3 = tmp;
615   }
616 
617   switch (BKE_sequence_effect_get_num_inputs(type)) {
618     case 0:
619       *r_selseq1 = *r_selseq2 = *r_selseq3 = NULL;
620       return 1; /* Success. */
621     case 1:
622       if (seq2 == NULL) {
623         *r_error_str = N_("At least one selected sequence strip is needed");
624         return 0;
625       }
626       if (seq1 == NULL) {
627         seq1 = seq2;
628       }
629       if (seq3 == NULL) {
630         seq3 = seq2;
631       }
632       ATTR_FALLTHROUGH;
633     case 2:
634       if (seq1 == NULL || seq2 == NULL) {
635         *r_error_str = N_("2 selected sequence strips are needed");
636         return 0;
637       }
638       if (seq3 == NULL) {
639         seq3 = seq2;
640       }
641       break;
642   }
643 
644   if (seq1 == NULL && seq2 == NULL && seq3 == NULL) {
645     *r_error_str = N_("TODO: in what cases does this happen?");
646     return 0;
647   }
648 
649   *r_selseq1 = seq1;
650   *r_selseq2 = seq2;
651   *r_selseq3 = seq3;
652 
653   /* TODO(Richard): This function needs some refactoring, this is just quick hack for T73828. */
654   if (BKE_sequence_effect_get_num_inputs(type) < 3) {
655     *r_selseq3 = NULL;
656   }
657   if (BKE_sequence_effect_get_num_inputs(type) < 2) {
658     *r_selseq2 = NULL;
659   }
660 
661   return 1;
662 }
663 
664 /** \} */
665 
666 /* -------------------------------------------------------------------- */
667 /** \name Delete Utilities
668  * \{ */
669 
recurs_del_seq_flag(Scene * scene,ListBase * lb,short flag,short deleteall)670 static void recurs_del_seq_flag(Scene *scene, ListBase *lb, short flag, short deleteall)
671 {
672   Sequence *seq, *seqn;
673   Sequence *last_seq = BKE_sequencer_active_get(scene);
674 
675   seq = lb->first;
676   while (seq) {
677     seqn = seq->next;
678     if ((seq->flag & flag) || deleteall) {
679       BLI_remlink(lb, seq);
680       if (seq == last_seq) {
681         BKE_sequencer_active_set(scene, NULL);
682       }
683       if (seq->type == SEQ_TYPE_META) {
684         recurs_del_seq_flag(scene, &seq->seqbase, flag, 1);
685       }
686       BKE_sequence_free(scene, seq, true);
687     }
688     seq = seqn;
689   }
690 }
691 
692 /** \} */
693 
694 /* -------------------------------------------------------------------- */
695 /** \name Split (Hard) Utility
696  * \{ */
697 
split_seq_hard(Main * bmain,Scene * scene,Sequence * seq,ListBase * new_seq_list,int split_frame)698 static Sequence *split_seq_hard(
699     Main *bmain, Scene *scene, Sequence *seq, ListBase *new_seq_list, int split_frame)
700 {
701   TransSeq ts;
702   Sequence *seqn = NULL;
703   bool skip_dup = false;
704 
705   /* Unlike soft-split, it's important to use the same value for both strips. */
706   const bool is_end_exact = ((seq->start + seq->len) == split_frame);
707 
708   /* Backup values. */
709   ts.start = seq->start;
710   ts.machine = seq->machine;
711   ts.startstill = seq->startstill;
712   ts.endstill = seq->endstill;
713   ts.startdisp = seq->startdisp;
714   ts.enddisp = seq->enddisp;
715   ts.startofs = seq->startofs;
716   ts.endofs = seq->endofs;
717   ts.anim_startofs = seq->anim_startofs;
718   ts.anim_endofs = seq->anim_endofs;
719   ts.len = seq->len;
720 
721   if (seq->type != SEQ_TYPE_META) {
722     /* Precaution, needed because the length saved on-disk may not match the length saved in the
723      * blend file, or our code may have minor differences reading file length between versions.
724      * This causes hard-split to fail, see: T47862. */
725     BKE_sequence_reload_new_file(bmain, scene, seq, true);
726     BKE_sequence_calc(scene, seq);
727   }
728 
729   /* First Strip. */
730   /* Important to offset the start when 'split_frame == seq->start'
731    * because we need at least one frame of content after start/end still have clipped it. */
732   if ((seq->startstill) && (split_frame <= seq->start)) {
733     /* Don't do funny things with METAs. */
734     if (seq->type == SEQ_TYPE_META) {
735       skip_dup = true;
736       seq->startstill = seq->start - split_frame;
737     }
738     else {
739       seq->start = split_frame - 1;
740       seq->startstill = split_frame - seq->startdisp - 1;
741       seq->anim_endofs += seq->len - 1;
742       seq->endstill = 0;
743     }
744   }
745   /* Normal strip. */
746   else if ((is_end_exact == false) &&
747            ((split_frame >= seq->start) && (split_frame <= (seq->start + seq->len)))) {
748     seq->endofs = 0;
749     seq->endstill = 0;
750     seq->anim_endofs += (seq->start + seq->len) - split_frame;
751   }
752   /* Strips with extended stillframes. */
753   else if ((is_end_exact == true) ||
754            (((seq->start + seq->len) < split_frame) && (seq->endstill))) {
755     seq->endstill -= seq->enddisp - split_frame;
756     /* Don't do funny things with METAs. */
757     if (seq->type == SEQ_TYPE_META) {
758       skip_dup = true;
759     }
760   }
761 
762   BKE_sequence_reload_new_file(bmain, scene, seq, false);
763   BKE_sequence_calc(scene, seq);
764 
765   if (!skip_dup) {
766     /* Duplicate AFTER the first change. */
767     seqn = BKE_sequence_dupli_recursive(
768         scene, scene, new_seq_list, seq, SEQ_DUPE_UNIQUE_NAME | SEQ_DUPE_ANIM);
769   }
770 
771   if (seqn) {
772     seqn->flag |= SELECT;
773 
774 #if 0
775     is_end_exact = ((seqn->start + seqn->len) == split_frame);
776 #endif
777     /* Second Strip. */
778     /* strips with extended stillframes. */
779     if ((seqn->startstill) && (split_frame == seqn->start + 1)) {
780       seqn->start = ts.start;
781       seqn->startstill = ts.start - split_frame;
782       seqn->anim_endofs = ts.anim_endofs;
783       seqn->endstill = ts.endstill;
784     }
785 
786     /* Normal strip. */
787     else if ((is_end_exact == false) &&
788              ((split_frame >= seqn->start) && (split_frame <= (seqn->start + seqn->len)))) {
789       seqn->start = split_frame;
790       seqn->startstill = 0;
791       seqn->startofs = 0;
792       seqn->endofs = ts.endofs;
793       seqn->anim_startofs += split_frame - ts.start;
794       seqn->anim_endofs = ts.anim_endofs;
795       seqn->endstill = ts.endstill;
796     }
797 
798     /* Strips with extended stillframes after. */
799     else if ((is_end_exact == true) ||
800              (((seqn->start + seqn->len) < split_frame) && (seqn->endstill))) {
801       seqn->start = split_frame;
802       seqn->startofs = 0;
803       seqn->anim_startofs += ts.len - 1;
804       seqn->endstill = ts.enddisp - split_frame - 1;
805       seqn->startstill = 0;
806     }
807 
808     BKE_sequence_reload_new_file(bmain, scene, seqn, false);
809     BKE_sequence_calc(scene, seqn);
810     BKE_sequence_invalidate_cache_in_range(scene, seq, seqn, SEQ_CACHE_ALL_TYPES);
811   }
812   return seqn;
813 }
814 
815 /** \} */
816 
817 /* -------------------------------------------------------------------- */
818 /** \name Split (Soft) Utility
819  * \{ */
820 
split_seq_soft(Main * UNUSED (bmain),Scene * scene,Sequence * seq,ListBase * new_seq_list,int split_frame)821 static Sequence *split_seq_soft(
822     Main *UNUSED(bmain), Scene *scene, Sequence *seq, ListBase *new_seq_list, int split_frame)
823 {
824   TransSeq ts;
825   Sequence *seqn = NULL;
826   bool skip_dup = false;
827 
828   bool is_end_exact = ((seq->start + seq->len) == split_frame);
829 
830   /* Backup values. */
831   ts.start = seq->start;
832   ts.machine = seq->machine;
833   ts.startstill = seq->startstill;
834   ts.endstill = seq->endstill;
835   ts.startdisp = seq->startdisp;
836   ts.enddisp = seq->enddisp;
837   ts.startofs = seq->startofs;
838   ts.endofs = seq->endofs;
839   ts.anim_startofs = seq->anim_startofs;
840   ts.anim_endofs = seq->anim_endofs;
841   ts.len = seq->len;
842 
843   /* First Strip. */
844   /* Strips with extended stillfames. */
845   /* Important to offset the start when 'split_frame == seq->start'
846    * because we need at least one frame of content after start/end still have clipped it. */
847   if ((seq->startstill) && (split_frame <= seq->start)) {
848     /* don't do funny things with METAs ... */
849     if (seq->type == SEQ_TYPE_META) {
850       skip_dup = true;
851       seq->startstill = seq->start - split_frame;
852     }
853     else {
854       seq->start = split_frame - 1;
855       seq->startstill = split_frame - seq->startdisp - 1;
856       seq->endofs = seq->len - 1;
857       seq->endstill = 0;
858     }
859   }
860   /* Normal strip. */
861   else if ((is_end_exact == false) && (split_frame >= seq->start) &&
862            (split_frame <= (seq->start + seq->len))) {
863     seq->endofs = (seq->start + seq->len) - split_frame;
864   }
865   /* Strips with extended stillframes. */
866   else if ((is_end_exact == true) ||
867            (((seq->start + seq->len) < split_frame) && (seq->endstill))) {
868     seq->endstill -= seq->enddisp - split_frame;
869     /* Don't do funny things with METAs. */
870     if (seq->type == SEQ_TYPE_META) {
871       skip_dup = true;
872     }
873   }
874 
875   BKE_sequence_calc(scene, seq);
876 
877   if (!skip_dup) {
878     /* Duplicate AFTER the first change. */
879     seqn = BKE_sequence_dupli_recursive(
880         scene, scene, new_seq_list, seq, SEQ_DUPE_UNIQUE_NAME | SEQ_DUPE_ANIM);
881   }
882 
883   if (seqn) {
884     seqn->flag |= SELECT;
885 
886     is_end_exact = ((seqn->start + seqn->len) == split_frame);
887 
888     /* Second Strip. */
889     /* Strips with extended stillframes. */
890     if ((seqn->startstill) && (split_frame == seqn->start + 1)) {
891       seqn->start = ts.start;
892       seqn->startstill = ts.start - split_frame;
893       seqn->endofs = ts.endofs;
894       seqn->endstill = ts.endstill;
895     }
896 
897     /* Normal strip. */
898     else if ((is_end_exact == false) && (split_frame >= seqn->start) &&
899              (split_frame <= (seqn->start + seqn->len))) {
900       seqn->startstill = 0;
901       seqn->startofs = split_frame - ts.start;
902       seqn->endofs = ts.endofs;
903       seqn->endstill = ts.endstill;
904     }
905 
906     /* Strips with extended stillframes. */
907     else if ((is_end_exact == true) ||
908              (((seqn->start + seqn->len) < split_frame) && (seqn->endstill))) {
909       seqn->start = split_frame - ts.len + 1;
910       seqn->startofs = ts.len - 1;
911       seqn->endstill = ts.enddisp - split_frame - 1;
912       seqn->startstill = 0;
913     }
914 
915     BKE_sequence_calc(scene, seqn);
916     BKE_sequence_invalidate_cache_in_range(scene, seq, seqn, SEQ_CACHE_ALL_TYPES);
917   }
918   return seqn;
919 }
920 
921 /* Like duplicate, but only duplicate and split overlapping strips,
922  * strips to the left of the split_frame are ignored and strips to the right
923  * are moved to the end of slist.
924  * We have to work on the same slist (not using a separate list), since
925  * otherwise dupli_seq can't check for duplicate names properly and
926  * may generate strips with the same name which will mess up animdata.
927  */
928 
split_seq_list(Main * bmain,Scene * scene,ListBase * slist,int split_frame,int channel,bool use_cursor_position,Sequence * (* split_seq)(Main * bmain,Scene *,Sequence *,ListBase *,int))929 static bool split_seq_list(
930     Main *bmain,
931     Scene *scene,
932     ListBase *slist,
933     int split_frame,
934     int channel,
935     bool use_cursor_position,
936     Sequence *(*split_seq)(Main *bmain, Scene *, Sequence *, ListBase *, int))
937 
938 {
939   Sequence *seq, *seq_next_iter;
940   Sequence *seq_first_new = NULL;
941 
942   seq = slist->first;
943 
944   while (seq && seq != seq_first_new) {
945     seq_next_iter = seq->next; /* We need this because we may remove seq. */
946     seq->tmp = NULL;
947     if (use_cursor_position) {
948       if (seq->machine == channel && seq->startdisp < split_frame && seq->enddisp > split_frame) {
949         Sequence *seqn = split_seq(bmain, scene, seq, slist, split_frame);
950         if (seqn) {
951           if (seq_first_new == NULL) {
952             seq_first_new = seqn;
953           }
954         }
955       }
956     }
957     else {
958       if (seq->flag & SELECT) {
959         if (split_frame > seq->startdisp && split_frame < seq->enddisp) {
960           Sequence *seqn = split_seq(bmain, scene, seq, slist, split_frame);
961           if (seqn) {
962             if (seq_first_new == NULL) {
963               seq_first_new = seqn;
964             }
965           }
966         }
967         else if (seq->enddisp <= split_frame) {
968           /* Pass. */
969         }
970         else if (seq->startdisp >= split_frame) {
971           /* Move to tail. */
972           BLI_remlink(slist, seq);
973           BLI_addtail(slist, seq);
974 
975           if (seq_first_new == NULL) {
976             seq_first_new = seq;
977           }
978         }
979       }
980     }
981     seq = seq_next_iter;
982   }
983 
984   return (seq_first_new != NULL);
985 }
986 
sequence_offset_after_frame(Scene * scene,const int delta,const int cfra)987 static bool sequence_offset_after_frame(Scene *scene, const int delta, const int cfra)
988 {
989   Sequence *seq;
990   Editing *ed = BKE_sequencer_editing_get(scene, false);
991   bool done = false;
992   TimeMarker *marker;
993 
994   /* All strips >= cfra are shifted. */
995 
996   if (ed == NULL) {
997     return 0;
998   }
999 
1000   for (seq = ed->seqbasep->first; seq; seq = seq->next) {
1001     if (seq->startdisp >= cfra) {
1002       BKE_sequence_translate(scene, seq, delta);
1003       BKE_sequence_calc(scene, seq);
1004       BKE_sequence_invalidate_cache_preprocessed(scene, seq);
1005       done = true;
1006     }
1007   }
1008 
1009   if (!scene->toolsettings->lock_markers) {
1010     for (marker = scene->markers.first; marker; marker = marker->next) {
1011       if (marker->frame >= cfra) {
1012         marker->frame += delta;
1013       }
1014     }
1015   }
1016 
1017   return done;
1018 }
1019 
1020 #if 0
1021 static void set_filter_seq(Scene *scene)
1022 {
1023   Sequence *seq;
1024   Editing *ed = BKE_sequencer_editing_get(scene, false);
1025 
1026   if (ed == NULL) {
1027     return;
1028   }
1029 
1030   if (okee("Set Deinterlace") == 0) {
1031     return;
1032   }
1033 
1034   SEQ_CURRENT_BEGIN (ed, seq) {
1035     if (seq->flag & SELECT) {
1036       if (seq->type == SEQ_TYPE_MOVIE) {
1037         seq->flag |= SEQ_FILTERY;
1038         BKE_sequence_reload_new_file(bmain, scene, seq, false);
1039         BKE_sequence_calc(scene, seq);
1040       }
1041     }
1042   }
1043   SEQ_CURRENT_END;
1044 }
1045 #endif
1046 
UNUSED_FUNCTION(seq_remap_paths)1047 static void UNUSED_FUNCTION(seq_remap_paths)(Scene *scene)
1048 {
1049   Sequence *seq, *last_seq = BKE_sequencer_active_get(scene);
1050   Editing *ed = BKE_sequencer_editing_get(scene, false);
1051   char from[FILE_MAX], to[FILE_MAX], stripped[FILE_MAX];
1052 
1053   if (last_seq == NULL) {
1054     return;
1055   }
1056 
1057   BLI_strncpy(from, last_seq->strip->dir, sizeof(from));
1058   /* XXX  if (0 == sbutton(from, 0, sizeof(from) - 1, "From: "))
1059    *      return; */
1060 
1061   BLI_strncpy(to, from, sizeof(to));
1062   /* XXX  if (0 == sbutton(to, 0, sizeof(to) - 1, "To: "))
1063    *      return; */
1064 
1065   if (STREQ(to, from)) {
1066     return;
1067   }
1068 
1069   SEQ_CURRENT_BEGIN (ed, seq) {
1070     if (seq->flag & SELECT) {
1071       if (STREQLEN(seq->strip->dir, from, strlen(from))) {
1072         printf("found %s\n", seq->strip->dir);
1073 
1074         /* Strip off the beginning. */
1075         stripped[0] = 0;
1076         BLI_strncpy(stripped, seq->strip->dir + strlen(from), FILE_MAX);
1077 
1078         /* New path. */
1079         BLI_snprintf(seq->strip->dir, sizeof(seq->strip->dir), "%s%s", to, stripped);
1080         printf("new %s\n", seq->strip->dir);
1081       }
1082     }
1083   }
1084   SEQ_CURRENT_END;
1085 }
1086 
1087 /** \} */
1088 
1089 /* -------------------------------------------------------------------- */
1090 /** \name Remove Gaps Operator
1091  * \{ */
1092 
sequencer_gap_remove_exec(bContext * C,wmOperator * op)1093 static int sequencer_gap_remove_exec(bContext *C, wmOperator *op)
1094 {
1095   Scene *scene = CTX_data_scene(C);
1096   rctf rectf;
1097   int cfra, efra, sfra;
1098   bool first = false, done;
1099   bool do_all = RNA_boolean_get(op->ptr, "all");
1100 
1101   /* Get first and last frame. */
1102   boundbox_seq(scene, &rectf);
1103   sfra = (int)rectf.xmin;
1104   efra = (int)rectf.xmax;
1105 
1106   /* Check if the current frame has a gap already. */
1107   for (cfra = CFRA; cfra >= sfra; cfra--) {
1108     if (BKE_sequencer_evaluate_frame(scene, cfra)) {
1109       first = true;
1110       break;
1111     }
1112   }
1113 
1114   for (; cfra < efra; cfra++) {
1115     /* There's still no strip to remove a gap for. */
1116     if (first == false) {
1117       if (BKE_sequencer_evaluate_frame(scene, cfra)) {
1118         first = true;
1119       }
1120     }
1121     else if (BKE_sequencer_evaluate_frame(scene, cfra) == 0) {
1122       done = true;
1123       while (BKE_sequencer_evaluate_frame(scene, cfra) == 0) {
1124         done = sequence_offset_after_frame(scene, -1, cfra);
1125         if (done == false) {
1126           break;
1127         }
1128       }
1129       if (done == false || do_all == false) {
1130         break;
1131       }
1132     }
1133   }
1134 
1135   WM_event_add_notifier(C, NC_SCENE | ND_SEQUENCER, scene);
1136   DEG_id_tag_update(&scene->id, ID_RECALC_SEQUENCER_STRIPS);
1137 
1138   return OPERATOR_FINISHED;
1139 }
1140 
SEQUENCER_OT_gap_remove(struct wmOperatorType * ot)1141 void SEQUENCER_OT_gap_remove(struct wmOperatorType *ot)
1142 {
1143   /* Identifiers. */
1144   ot->name = "Remove Gaps";
1145   ot->idname = "SEQUENCER_OT_gap_remove";
1146   ot->description =
1147       "Remove gap at current frame to first strip at the right, independent of selection or "
1148       "locked state of strips";
1149 
1150   /* Api callbacks. */
1151   //  ot->invoke = sequencer_snap_invoke;
1152   ot->exec = sequencer_gap_remove_exec;
1153   ot->poll = sequencer_edit_poll;
1154 
1155   /* Flags. */
1156   ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
1157 
1158   RNA_def_boolean(ot->srna, "all", 0, "All Gaps", "Do all gaps to right of current frame");
1159 }
1160 
1161 /** \} */
1162 
1163 /* -------------------------------------------------------------------- */
1164 /** \name Insert Gaps Operator
1165  * \{ */
1166 
sequencer_gap_insert_exec(bContext * C,wmOperator * op)1167 static int sequencer_gap_insert_exec(bContext *C, wmOperator *op)
1168 {
1169   Scene *scene = CTX_data_scene(C);
1170   int frames = RNA_int_get(op->ptr, "frames");
1171 
1172   sequence_offset_after_frame(scene, frames, CFRA);
1173 
1174   WM_event_add_notifier(C, NC_SCENE | ND_SEQUENCER, scene);
1175 
1176   return OPERATOR_FINISHED;
1177 }
1178 
SEQUENCER_OT_gap_insert(struct wmOperatorType * ot)1179 void SEQUENCER_OT_gap_insert(struct wmOperatorType *ot)
1180 {
1181   /* Identifiers. */
1182   ot->name = "Insert Gaps";
1183   ot->idname = "SEQUENCER_OT_gap_insert";
1184   ot->description =
1185       "Insert gap at current frame to first strips at the right, independent of selection or "
1186       "locked state of strips";
1187 
1188   /* Api callbacks. */
1189   //  ot->invoke = sequencer_snap_invoke;
1190   ot->exec = sequencer_gap_insert_exec;
1191   ot->poll = sequencer_edit_poll;
1192 
1193   /* Flags. */
1194   ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
1195 
1196   RNA_def_int(ot->srna,
1197               "frames",
1198               10,
1199               0,
1200               INT_MAX,
1201               "Frames",
1202               "Frames to insert after current strip",
1203               0,
1204               1000);
1205 }
1206 
1207 /** \} */
1208 
1209 /* -------------------------------------------------------------------- */
1210 /** \name Shared Poll Functions
1211  * \{ */
1212 
1213 #if 0
1214 static int seq_get_snaplimit(View2D *v2d)
1215 {
1216   /* fake mouse coords to get the snap value
1217    * a bit lazy but its only done once pre transform */
1218   float xmouse, ymouse, x;
1219   int mval[2] = {24, 0}; /* 24 screen px snap */
1220 
1221   UI_view2d_region_to_view(v2d, mval[0], mval[1], &xmouse, &ymouse);
1222   x = xmouse;
1223   mval[0] = 0;
1224   UI_view2d_region_to_view(v2d, mval[0], mval[1], &xmouse, &ymouse);
1225   return (int)(x - xmouse);
1226 }
1227 #endif
1228 
1229 /* Operator functions. */
sequencer_edit_poll(bContext * C)1230 bool sequencer_edit_poll(bContext *C)
1231 {
1232   return (BKE_sequencer_editing_get(CTX_data_scene(C), false) != NULL);
1233 }
1234 
1235 #if 0 /* UNUSED */
1236 bool sequencer_strip_poll(bContext *C)
1237 {
1238   Editing *ed;
1239   return (((ed = BKE_sequencer_editing_get(CTX_data_scene(C), false)) != NULL) &&
1240           (ed->act_seq != NULL));
1241 }
1242 #endif
1243 
sequencer_strip_has_path_poll(bContext * C)1244 bool sequencer_strip_has_path_poll(bContext *C)
1245 {
1246   Editing *ed;
1247   Sequence *seq;
1248   return (((ed = BKE_sequencer_editing_get(CTX_data_scene(C), false)) != NULL) &&
1249           ((seq = ed->act_seq) != NULL) && (SEQ_HAS_PATH(seq)));
1250 }
1251 
sequencer_view_preview_poll(bContext * C)1252 bool sequencer_view_preview_poll(bContext *C)
1253 {
1254   SpaceSeq *sseq = CTX_wm_space_seq(C);
1255   Editing *ed = BKE_sequencer_editing_get(CTX_data_scene(C), false);
1256   if (ed && sseq && (sseq->mainb == SEQ_DRAW_IMG_IMBUF)) {
1257     return 1;
1258   }
1259 
1260   return 0;
1261 }
1262 
sequencer_view_strips_poll(bContext * C)1263 bool sequencer_view_strips_poll(bContext *C)
1264 {
1265   SpaceSeq *sseq = CTX_wm_space_seq(C);
1266   if (sseq && ED_space_sequencer_check_show_strip(sseq)) {
1267     return 1;
1268   }
1269 
1270   return 0;
1271 }
1272 
1273 /** \} */
1274 
1275 /* -------------------------------------------------------------------- */
1276 /** \name Snap Strips to the Current Frame Operator
1277  * \{ */
1278 
sequencer_snap_exec(bContext * C,wmOperator * op)1279 static int sequencer_snap_exec(bContext *C, wmOperator *op)
1280 {
1281   Scene *scene = CTX_data_scene(C);
1282 
1283   Editing *ed = BKE_sequencer_editing_get(scene, false);
1284   Sequence *seq;
1285   int snap_frame;
1286 
1287   snap_frame = RNA_int_get(op->ptr, "frame");
1288 
1289   /* Check metas. */
1290   for (seq = ed->seqbasep->first; seq; seq = seq->next) {
1291     if (seq->flag & SELECT && !(seq->depth == 0 && seq->flag & SEQ_LOCK) &&
1292         BKE_sequence_tx_test(seq)) {
1293       if ((seq->flag & (SEQ_LEFTSEL + SEQ_RIGHTSEL)) == 0) {
1294         BKE_sequence_translate(
1295             scene, seq, (snap_frame - seq->startofs + seq->startstill) - seq->start);
1296       }
1297       else {
1298         if (seq->flag & SEQ_LEFTSEL) {
1299           BKE_sequence_tx_set_final_left(seq, snap_frame);
1300         }
1301         else { /* SEQ_RIGHTSEL */
1302           BKE_sequence_tx_set_final_right(seq, snap_frame);
1303         }
1304         BKE_sequence_tx_handle_xlimits(seq, seq->flag & SEQ_LEFTSEL, seq->flag & SEQ_RIGHTSEL);
1305         BKE_sequence_single_fix(seq);
1306       }
1307       BKE_sequence_calc(scene, seq);
1308     }
1309   }
1310 
1311   /* Test for effects and overlap.
1312    * Don't use SEQ_CURRENT_BEGIN since that would be recursive. */
1313   for (seq = ed->seqbasep->first; seq; seq = seq->next) {
1314     if (seq->flag & SELECT && !(seq->depth == 0 && seq->flag & SEQ_LOCK)) {
1315       seq->flag &= ~SEQ_OVERLAP;
1316       if (BKE_sequence_test_overlap(ed->seqbasep, seq)) {
1317         BKE_sequence_base_shuffle(ed->seqbasep, seq, scene);
1318       }
1319     }
1320   }
1321 
1322   /* Recalculate bounds of effect strips. */
1323   for (seq = ed->seqbasep->first; seq; seq = seq->next) {
1324     if (seq->type & SEQ_TYPE_EFFECT) {
1325       if (seq->seq1 && (seq->seq1->flag & SELECT)) {
1326         BKE_sequencer_offset_animdata(scene, seq, (snap_frame - seq->startdisp));
1327         BKE_sequence_calc(scene, seq);
1328       }
1329       else if (seq->seq2 && (seq->seq2->flag & SELECT)) {
1330         BKE_sequencer_offset_animdata(scene, seq, (snap_frame - seq->startdisp));
1331         BKE_sequence_calc(scene, seq);
1332       }
1333       else if (seq->seq3 && (seq->seq3->flag & SELECT)) {
1334         BKE_sequencer_offset_animdata(scene, seq, (snap_frame - seq->startdisp));
1335         BKE_sequence_calc(scene, seq);
1336       }
1337     }
1338   }
1339 
1340   BKE_sequencer_sort(scene);
1341 
1342   DEG_id_tag_update(&scene->id, ID_RECALC_SEQUENCER_STRIPS);
1343   WM_event_add_notifier(C, NC_SCENE | ND_SEQUENCER, scene);
1344 
1345   return OPERATOR_FINISHED;
1346 }
1347 
sequencer_snap_invoke(bContext * C,wmOperator * op,const wmEvent * UNUSED (event))1348 static int sequencer_snap_invoke(bContext *C, wmOperator *op, const wmEvent *UNUSED(event))
1349 {
1350   Scene *scene = CTX_data_scene(C);
1351 
1352   int snap_frame;
1353 
1354   snap_frame = CFRA;
1355 
1356   RNA_int_set(op->ptr, "frame", snap_frame);
1357   return sequencer_snap_exec(C, op);
1358 }
1359 
SEQUENCER_OT_snap(struct wmOperatorType * ot)1360 void SEQUENCER_OT_snap(struct wmOperatorType *ot)
1361 {
1362   /* Identifiers. */
1363   ot->name = "Snap Strips to the Current Frame";
1364   ot->idname = "SEQUENCER_OT_snap";
1365   ot->description = "Frame where selected strips will be snapped";
1366 
1367   /* Api callbacks. */
1368   ot->invoke = sequencer_snap_invoke;
1369   ot->exec = sequencer_snap_exec;
1370   ot->poll = sequencer_edit_poll;
1371 
1372   /* Flags. */
1373   ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
1374 
1375   RNA_def_int(ot->srna,
1376               "frame",
1377               0,
1378               INT_MIN,
1379               INT_MAX,
1380               "Frame",
1381               "Frame where selected strips will be snapped",
1382               INT_MIN,
1383               INT_MAX);
1384 }
1385 
1386 /** \} */
1387 
1388 /* -------------------------------------------------------------------- */
1389 /** \name Trim Strips Operator
1390  * \{ */
1391 
1392 typedef struct SlipData {
1393   int init_mouse[2];
1394   float init_mouseloc[2];
1395   TransSeq *ts;
1396   Sequence **seq_array;
1397   bool *trim;
1398   int num_seq;
1399   bool slow;
1400   int slow_offset; /* Offset at the point where offset was turned on. */
1401   NumInput num_input;
1402 } SlipData;
1403 
transseq_backup(TransSeq * ts,Sequence * seq)1404 static void transseq_backup(TransSeq *ts, Sequence *seq)
1405 {
1406   ts->start = seq->start;
1407   ts->machine = seq->machine;
1408   ts->startstill = seq->startstill;
1409   ts->endstill = seq->endstill;
1410   ts->startdisp = seq->startdisp;
1411   ts->enddisp = seq->enddisp;
1412   ts->startofs = seq->startofs;
1413   ts->endofs = seq->endofs;
1414   ts->anim_startofs = seq->anim_startofs;
1415   ts->anim_endofs = seq->anim_endofs;
1416   ts->len = seq->len;
1417 }
1418 
transseq_restore(TransSeq * ts,Sequence * seq)1419 static void transseq_restore(TransSeq *ts, Sequence *seq)
1420 {
1421   seq->start = ts->start;
1422   seq->machine = ts->machine;
1423   seq->startstill = ts->startstill;
1424   seq->endstill = ts->endstill;
1425   seq->startdisp = ts->startdisp;
1426   seq->enddisp = ts->enddisp;
1427   seq->startofs = ts->startofs;
1428   seq->endofs = ts->endofs;
1429   seq->anim_startofs = ts->anim_startofs;
1430   seq->anim_endofs = ts->anim_endofs;
1431   seq->len = ts->len;
1432 }
1433 
slip_add_sequences_recursive(ListBase * seqbasep,Sequence ** seq_array,bool * trim,int offset,bool do_trim)1434 static int slip_add_sequences_recursive(
1435     ListBase *seqbasep, Sequence **seq_array, bool *trim, int offset, bool do_trim)
1436 {
1437   Sequence *seq;
1438   int num_items = 0;
1439 
1440   for (seq = seqbasep->first; seq; seq = seq->next) {
1441     if (!do_trim || (!(seq->type & SEQ_TYPE_EFFECT) && (seq->flag & SELECT))) {
1442       seq_array[offset + num_items] = seq;
1443       trim[offset + num_items] = do_trim;
1444       num_items++;
1445 
1446       if (seq->type == SEQ_TYPE_META) {
1447         /* Trim the sub-sequences. */
1448         num_items += slip_add_sequences_recursive(
1449             &seq->seqbase, seq_array, trim, num_items + offset, false);
1450       }
1451       else if (seq->type & SEQ_TYPE_EFFECT) {
1452         trim[offset + num_items] = false;
1453       }
1454     }
1455   }
1456 
1457   return num_items;
1458 }
1459 
slip_count_sequences_recursive(ListBase * seqbasep,bool first_level)1460 static int slip_count_sequences_recursive(ListBase *seqbasep, bool first_level)
1461 {
1462   Sequence *seq;
1463   int trimmed_sequences = 0;
1464 
1465   for (seq = seqbasep->first; seq; seq = seq->next) {
1466     if (!first_level || (!(seq->type & SEQ_TYPE_EFFECT) && (seq->flag & SELECT))) {
1467       trimmed_sequences++;
1468 
1469       if (seq->type == SEQ_TYPE_META) {
1470         /* Trim the sub-sequences. */
1471         trimmed_sequences += slip_count_sequences_recursive(&seq->seqbase, false);
1472       }
1473     }
1474   }
1475 
1476   return trimmed_sequences;
1477 }
1478 
sequencer_slip_invoke(bContext * C,wmOperator * op,const wmEvent * event)1479 static int sequencer_slip_invoke(bContext *C, wmOperator *op, const wmEvent *event)
1480 {
1481   SlipData *data;
1482   Scene *scene = CTX_data_scene(C);
1483   Editing *ed = BKE_sequencer_editing_get(scene, false);
1484   float mouseloc[2];
1485   int num_seq;
1486   View2D *v2d = UI_view2d_fromcontext(C);
1487 
1488   /* Recursively count the trimmed elements. */
1489   num_seq = slip_count_sequences_recursive(ed->seqbasep, true);
1490 
1491   if (num_seq == 0) {
1492     return OPERATOR_CANCELLED;
1493   }
1494 
1495   data = op->customdata = MEM_mallocN(sizeof(SlipData), "trimdata");
1496   data->ts = MEM_mallocN(num_seq * sizeof(TransSeq), "trimdata_transform");
1497   data->seq_array = MEM_mallocN(num_seq * sizeof(Sequence *), "trimdata_sequences");
1498   data->trim = MEM_mallocN(num_seq * sizeof(bool), "trimdata_trim");
1499   data->num_seq = num_seq;
1500 
1501   initNumInput(&data->num_input);
1502   data->num_input.idx_max = 0;
1503   data->num_input.val_flag[0] |= NUM_NO_FRACTION;
1504   data->num_input.unit_sys = USER_UNIT_NONE;
1505   data->num_input.unit_type[0] = 0;
1506 
1507   slip_add_sequences_recursive(ed->seqbasep, data->seq_array, data->trim, 0, true);
1508 
1509   for (int i = 0; i < num_seq; i++) {
1510     transseq_backup(data->ts + i, data->seq_array[i]);
1511   }
1512 
1513   UI_view2d_region_to_view(v2d, event->mval[0], event->mval[1], &mouseloc[0], &mouseloc[1]);
1514 
1515   copy_v2_v2_int(data->init_mouse, event->mval);
1516   copy_v2_v2(data->init_mouseloc, mouseloc);
1517 
1518   data->slow = false;
1519 
1520   WM_event_add_modal_handler(C, op);
1521 
1522   /* Notify so we draw extensions immediately. */
1523   WM_event_add_notifier(C, NC_SCENE | ND_SEQUENCER, scene);
1524 
1525   return OPERATOR_RUNNING_MODAL;
1526 }
1527 
sequencer_slip_recursively(Scene * scene,SlipData * data,int offset)1528 static bool sequencer_slip_recursively(Scene *scene, SlipData *data, int offset)
1529 {
1530   /* Only data types supported for now. */
1531   Editing *ed = BKE_sequencer_editing_get(scene, false);
1532   bool changed = false;
1533 
1534   /* Iterate in reverse so meta-strips are iterated after their children. */
1535   for (int i = data->num_seq - 1; i >= 0; i--) {
1536     Sequence *seq = data->seq_array[i];
1537     int endframe;
1538 
1539     /* Offset seq start. */
1540     seq->start = data->ts[i].start + offset;
1541 
1542     if (data->trim[i]) {
1543       /* Find the end-frame. */
1544       endframe = seq->start + seq->len;
1545 
1546       /* Compute the sequence offsets. */
1547       if (endframe > seq->enddisp) {
1548         seq->endstill = 0;
1549         seq->endofs = endframe - seq->enddisp;
1550         changed = true;
1551       }
1552       else if (endframe <= seq->enddisp) {
1553         seq->endstill = seq->enddisp - endframe;
1554         seq->endofs = 0;
1555         changed = true;
1556       }
1557 
1558       if (seq->start > seq->startdisp) {
1559         seq->startstill = seq->start - seq->startdisp;
1560         seq->startofs = 0;
1561         changed = true;
1562       }
1563       else if (seq->start <= seq->startdisp) {
1564         seq->startstill = 0;
1565         seq->startofs = seq->startdisp - seq->start;
1566         changed = true;
1567       }
1568     }
1569     else {
1570       /* No transform data (likely effect strip). Only move start and end. */
1571       seq->startdisp = data->ts[i].startdisp + offset;
1572       seq->enddisp = data->ts[i].enddisp + offset;
1573       changed = true;
1574     }
1575 
1576     /* Effects are only added if we they are in a meta-strip.
1577      * In this case, dependent strips will just be transformed and
1578      * we can skip calculating for effects.
1579      * This way we can avoid an extra loop just for effects. */
1580     if (!(seq->type & SEQ_TYPE_EFFECT)) {
1581       BKE_sequence_calc(scene, seq);
1582     }
1583   }
1584   if (changed) {
1585     BKE_sequencer_free_imbuf(scene, &ed->seqbase, false);
1586   }
1587   return changed;
1588 }
1589 
1590 /* Make sure, that each strip contains at least 1 frame of content. */
sequencer_slip_apply_limits(SlipData * data,int * offset)1591 static void sequencer_slip_apply_limits(SlipData *data, int *offset)
1592 {
1593   for (int i = 0; i < data->num_seq; i++) {
1594     if (data->trim[i]) {
1595       Sequence *seq = data->seq_array[i];
1596       int seq_content_start = data->ts[i].start + *offset;
1597       int seq_content_end = seq_content_start + seq->len + seq->anim_startofs + seq->anim_endofs;
1598       int diff = 0;
1599 
1600       if (seq_content_start >= seq->enddisp) {
1601         diff = seq->enddisp - seq_content_start - 1;
1602       }
1603 
1604       if (seq_content_end <= seq->startdisp) {
1605         diff = seq->startdisp - seq_content_end + 1;
1606       }
1607       *offset += diff;
1608     }
1609   }
1610 }
1611 
sequencer_slip_exec(bContext * C,wmOperator * op)1612 static int sequencer_slip_exec(bContext *C, wmOperator *op)
1613 {
1614   Scene *scene = CTX_data_scene(C);
1615   Editing *ed = BKE_sequencer_editing_get(scene, false);
1616   int offset = RNA_int_get(op->ptr, "offset");
1617   bool success = false;
1618 
1619   /* Recursively count the trimmed elements. */
1620   int num_seq = slip_count_sequences_recursive(ed->seqbasep, true);
1621 
1622   if (num_seq == 0) {
1623     return OPERATOR_CANCELLED;
1624   }
1625 
1626   SlipData *data = op->customdata = MEM_mallocN(sizeof(SlipData), "trimdata");
1627   data->ts = MEM_mallocN(num_seq * sizeof(TransSeq), "trimdata_transform");
1628   data->seq_array = MEM_mallocN(num_seq * sizeof(Sequence *), "trimdata_sequences");
1629   data->trim = MEM_mallocN(num_seq * sizeof(bool), "trimdata_trim");
1630   data->num_seq = num_seq;
1631 
1632   slip_add_sequences_recursive(ed->seqbasep, data->seq_array, data->trim, 0, true);
1633 
1634   for (int i = 0; i < num_seq; i++) {
1635     transseq_backup(data->ts + i, data->seq_array[i]);
1636   }
1637 
1638   sequencer_slip_apply_limits(data, &offset);
1639   success = sequencer_slip_recursively(scene, data, offset);
1640 
1641   MEM_freeN(data->seq_array);
1642   MEM_freeN(data->trim);
1643   MEM_freeN(data->ts);
1644   MEM_freeN(data);
1645 
1646   if (success) {
1647     WM_event_add_notifier(C, NC_SCENE | ND_SEQUENCER, scene);
1648     DEG_id_tag_update(&scene->id, ID_RECALC_SEQUENCER_STRIPS);
1649     return OPERATOR_FINISHED;
1650   }
1651   return OPERATOR_CANCELLED;
1652 }
1653 
sequencer_slip_update_header(Scene * scene,ScrArea * area,SlipData * data,int offset)1654 static void sequencer_slip_update_header(Scene *scene, ScrArea *area, SlipData *data, int offset)
1655 {
1656   char msg[UI_MAX_DRAW_STR];
1657 
1658   if (area) {
1659     if (hasNumInput(&data->num_input)) {
1660       char num_str[NUM_STR_REP_LEN];
1661       outputNumInput(&data->num_input, num_str, &scene->unit);
1662       BLI_snprintf(msg, sizeof(msg), TIP_("Slip offset: %s"), num_str);
1663     }
1664     else {
1665       BLI_snprintf(msg, sizeof(msg), TIP_("Slip offset: %d"), offset);
1666     }
1667   }
1668 
1669   ED_area_status_text(area, msg);
1670 }
1671 
sequencer_slip_modal(bContext * C,wmOperator * op,const wmEvent * event)1672 static int sequencer_slip_modal(bContext *C, wmOperator *op, const wmEvent *event)
1673 {
1674   Main *bmain = CTX_data_main(C);
1675   Scene *scene = CTX_data_scene(C);
1676   SlipData *data = (SlipData *)op->customdata;
1677   ScrArea *area = CTX_wm_area(C);
1678   const bool has_numInput = hasNumInput(&data->num_input);
1679   bool handled = true;
1680 
1681   /* Modal numinput active, try to handle numeric inputs. */
1682   if (event->val == KM_PRESS && has_numInput && handleNumInput(C, &data->num_input, event)) {
1683     float offset_fl;
1684     applyNumInput(&data->num_input, &offset_fl);
1685     int offset = round_fl_to_int(offset_fl);
1686 
1687     sequencer_slip_apply_limits(data, &offset);
1688     sequencer_slip_update_header(scene, area, data, offset);
1689 
1690     RNA_int_set(op->ptr, "offset", offset);
1691 
1692     if (sequencer_slip_recursively(scene, data, offset)) {
1693       WM_event_add_notifier(C, NC_SCENE | ND_SEQUENCER, scene);
1694     }
1695 
1696     return OPERATOR_RUNNING_MODAL;
1697   }
1698 
1699   switch (event->type) {
1700     case MOUSEMOVE: {
1701       if (!has_numInput) {
1702         float mouseloc[2];
1703         int offset;
1704         int mouse_x;
1705         View2D *v2d = UI_view2d_fromcontext(C);
1706 
1707         if (data->slow) {
1708           mouse_x = event->mval[0] - data->slow_offset;
1709           mouse_x *= 0.1f;
1710           mouse_x += data->slow_offset;
1711         }
1712         else {
1713           mouse_x = event->mval[0];
1714         }
1715 
1716         /* Choose the side based on which side of the current frame the mouse is. */
1717         UI_view2d_region_to_view(v2d, mouse_x, 0, &mouseloc[0], &mouseloc[1]);
1718         offset = mouseloc[0] - data->init_mouseloc[0];
1719 
1720         sequencer_slip_apply_limits(data, &offset);
1721         sequencer_slip_update_header(scene, area, data, offset);
1722 
1723         RNA_int_set(op->ptr, "offset", offset);
1724 
1725         if (sequencer_slip_recursively(scene, data, offset)) {
1726           WM_event_add_notifier(C, NC_SCENE | ND_SEQUENCER, scene);
1727         }
1728       }
1729       break;
1730     }
1731 
1732     case LEFTMOUSE:
1733     case EVT_RETKEY:
1734     case EVT_SPACEKEY: {
1735       MEM_freeN(data->seq_array);
1736       MEM_freeN(data->trim);
1737       MEM_freeN(data->ts);
1738       MEM_freeN(data);
1739       op->customdata = NULL;
1740       if (area) {
1741         ED_area_status_text(area, NULL);
1742       }
1743       DEG_id_tag_update(&scene->id, ID_RECALC_SEQUENCER_STRIPS);
1744       WM_event_add_notifier(C, NC_SCENE | ND_SEQUENCER, scene);
1745       return OPERATOR_FINISHED;
1746     }
1747 
1748     case EVT_ESCKEY:
1749     case RIGHTMOUSE: {
1750       Editing *ed = BKE_sequencer_editing_get(scene, false);
1751 
1752       for (int i = 0; i < data->num_seq; i++) {
1753         transseq_restore(data->ts + i, data->seq_array[i]);
1754       }
1755 
1756       for (int i = 0; i < data->num_seq; i++) {
1757         Sequence *seq = data->seq_array[i];
1758         BKE_sequence_reload_new_file(bmain, scene, seq, false);
1759         BKE_sequence_calc(scene, seq);
1760       }
1761 
1762       MEM_freeN(data->seq_array);
1763       MEM_freeN(data->ts);
1764       MEM_freeN(data->trim);
1765       MEM_freeN(data);
1766       op->customdata = NULL;
1767 
1768       WM_event_add_notifier(C, NC_SCENE | ND_SEQUENCER, scene);
1769 
1770       BKE_sequencer_free_imbuf(scene, &ed->seqbase, false);
1771 
1772       if (area) {
1773         ED_area_status_text(area, NULL);
1774       }
1775 
1776       return OPERATOR_CANCELLED;
1777     }
1778 
1779     case EVT_RIGHTSHIFTKEY:
1780     case EVT_LEFTSHIFTKEY:
1781       if (!has_numInput) {
1782         if (event->val == KM_PRESS) {
1783           data->slow = true;
1784           data->slow_offset = event->mval[0];
1785         }
1786         else if (event->val == KM_RELEASE) {
1787           data->slow = false;
1788         }
1789       }
1790       break;
1791 
1792     default:
1793       handled = false;
1794       break;
1795   }
1796 
1797   /* Modal numinput inactive, try to handle numeric inputs. */
1798   if (!handled && event->val == KM_PRESS && handleNumInput(C, &data->num_input, event)) {
1799     float offset_fl;
1800     applyNumInput(&data->num_input, &offset_fl);
1801     int offset = round_fl_to_int(offset_fl);
1802 
1803     sequencer_slip_apply_limits(data, &offset);
1804     sequencer_slip_update_header(scene, area, data, offset);
1805 
1806     RNA_int_set(op->ptr, "offset", offset);
1807 
1808     if (sequencer_slip_recursively(scene, data, offset)) {
1809       WM_event_add_notifier(C, NC_SCENE | ND_SEQUENCER, scene);
1810     }
1811   }
1812 
1813   return OPERATOR_RUNNING_MODAL;
1814 }
1815 
SEQUENCER_OT_slip(struct wmOperatorType * ot)1816 void SEQUENCER_OT_slip(struct wmOperatorType *ot)
1817 {
1818   /* Identifiers. */
1819   ot->name = "Trim Strips";
1820   ot->idname = "SEQUENCER_OT_slip";
1821   ot->description = "Trim the contents of the active strip";
1822 
1823   /* Api callbacks. */
1824   ot->invoke = sequencer_slip_invoke;
1825   ot->modal = sequencer_slip_modal;
1826   ot->exec = sequencer_slip_exec;
1827   ot->poll = sequencer_edit_poll;
1828 
1829   /* Flags. */
1830   ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
1831 
1832   RNA_def_int(ot->srna,
1833               "offset",
1834               0,
1835               INT32_MIN,
1836               INT32_MAX,
1837               "Offset",
1838               "Offset to the data of the strip",
1839               INT32_MIN,
1840               INT32_MAX);
1841 }
1842 
1843 /** \} */
1844 
1845 /* -------------------------------------------------------------------- */
1846 /** \name Mute Strips Operator
1847  * \{ */
1848 
sequencer_mute_exec(bContext * C,wmOperator * op)1849 static int sequencer_mute_exec(bContext *C, wmOperator *op)
1850 {
1851   Scene *scene = CTX_data_scene(C);
1852   Editing *ed = BKE_sequencer_editing_get(scene, false);
1853   Sequence *seq;
1854   bool selected;
1855 
1856   selected = !RNA_boolean_get(op->ptr, "unselected");
1857 
1858   for (seq = ed->seqbasep->first; seq; seq = seq->next) {
1859     if ((seq->flag & SEQ_LOCK) == 0) {
1860       if (selected) {
1861         if (seq->flag & SELECT) {
1862           seq->flag |= SEQ_MUTE;
1863           BKE_sequence_invalidate_dependent(scene, seq);
1864         }
1865       }
1866       else {
1867         if ((seq->flag & SELECT) == 0) {
1868           seq->flag |= SEQ_MUTE;
1869           BKE_sequence_invalidate_dependent(scene, seq);
1870         }
1871       }
1872     }
1873   }
1874 
1875   DEG_id_tag_update(&scene->id, ID_RECALC_SEQUENCER_STRIPS);
1876   WM_event_add_notifier(C, NC_SCENE | ND_SEQUENCER, scene);
1877 
1878   return OPERATOR_FINISHED;
1879 }
1880 
SEQUENCER_OT_mute(struct wmOperatorType * ot)1881 void SEQUENCER_OT_mute(struct wmOperatorType *ot)
1882 {
1883   /* Identifiers. */
1884   ot->name = "Mute Strips";
1885   ot->idname = "SEQUENCER_OT_mute";
1886   ot->description = "Mute (un)selected strips";
1887 
1888   /* Api callbacks. */
1889   ot->exec = sequencer_mute_exec;
1890   ot->poll = sequencer_edit_poll;
1891 
1892   /* Flags. */
1893   ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
1894 
1895   RNA_def_boolean(
1896       ot->srna, "unselected", 0, "Unselected", "Mute unselected rather than selected strips");
1897 }
1898 
1899 /** \} */
1900 
1901 /* -------------------------------------------------------------------- */
1902 /** \name Unmute Strips Operator
1903  * \{ */
1904 
sequencer_unmute_exec(bContext * C,wmOperator * op)1905 static int sequencer_unmute_exec(bContext *C, wmOperator *op)
1906 {
1907   Scene *scene = CTX_data_scene(C);
1908   Editing *ed = BKE_sequencer_editing_get(scene, false);
1909   Sequence *seq;
1910   bool selected;
1911 
1912   selected = !RNA_boolean_get(op->ptr, "unselected");
1913 
1914   for (seq = ed->seqbasep->first; seq; seq = seq->next) {
1915     if ((seq->flag & SEQ_LOCK) == 0) {
1916       if (selected) {
1917         if (seq->flag & SELECT) {
1918           seq->flag &= ~SEQ_MUTE;
1919           BKE_sequence_invalidate_dependent(scene, seq);
1920         }
1921       }
1922       else {
1923         if ((seq->flag & SELECT) == 0) {
1924           seq->flag &= ~SEQ_MUTE;
1925           BKE_sequence_invalidate_dependent(scene, seq);
1926         }
1927       }
1928     }
1929   }
1930 
1931   DEG_id_tag_update(&scene->id, ID_RECALC_SEQUENCER_STRIPS);
1932   WM_event_add_notifier(C, NC_SCENE | ND_SEQUENCER, scene);
1933 
1934   return OPERATOR_FINISHED;
1935 }
1936 
SEQUENCER_OT_unmute(struct wmOperatorType * ot)1937 void SEQUENCER_OT_unmute(struct wmOperatorType *ot)
1938 {
1939   /* Identifiers. */
1940   ot->name = "Unmute Strips";
1941   ot->idname = "SEQUENCER_OT_unmute";
1942   ot->description = "Unmute (un)selected strips";
1943 
1944   /* Api callbacks. */
1945   ot->exec = sequencer_unmute_exec;
1946   ot->poll = sequencer_edit_poll;
1947 
1948   /* Flags. */
1949   ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
1950 
1951   RNA_def_boolean(
1952       ot->srna, "unselected", 0, "Unselected", "Unmute unselected rather than selected strips");
1953 }
1954 
1955 /** \} */
1956 
1957 /* -------------------------------------------------------------------- */
1958 /** \name Lock Strips Operator
1959  * \{ */
1960 
sequencer_lock_exec(bContext * C,wmOperator * UNUSED (op))1961 static int sequencer_lock_exec(bContext *C, wmOperator *UNUSED(op))
1962 {
1963   Scene *scene = CTX_data_scene(C);
1964   Editing *ed = BKE_sequencer_editing_get(scene, false);
1965   Sequence *seq;
1966 
1967   for (seq = ed->seqbasep->first; seq; seq = seq->next) {
1968     if (seq->flag & SELECT) {
1969       seq->flag |= SEQ_LOCK;
1970     }
1971   }
1972 
1973   WM_event_add_notifier(C, NC_SCENE | ND_SEQUENCER, scene);
1974 
1975   return OPERATOR_FINISHED;
1976 }
1977 
SEQUENCER_OT_lock(struct wmOperatorType * ot)1978 void SEQUENCER_OT_lock(struct wmOperatorType *ot)
1979 {
1980   /* Identifiers. */
1981   ot->name = "Lock Strips";
1982   ot->idname = "SEQUENCER_OT_lock";
1983   ot->description = "Lock strips so they can't be transformed";
1984 
1985   /* Api callbacks. */
1986   ot->exec = sequencer_lock_exec;
1987   ot->poll = sequencer_edit_poll;
1988 
1989   /* Flags. */
1990   ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
1991 }
1992 
1993 /** \} */
1994 
1995 /* -------------------------------------------------------------------- */
1996 /** \name Unlock Strips Operator
1997  * \{ */
1998 
sequencer_unlock_exec(bContext * C,wmOperator * UNUSED (op))1999 static int sequencer_unlock_exec(bContext *C, wmOperator *UNUSED(op))
2000 {
2001   Scene *scene = CTX_data_scene(C);
2002   Editing *ed = BKE_sequencer_editing_get(scene, false);
2003   Sequence *seq;
2004 
2005   for (seq = ed->seqbasep->first; seq; seq = seq->next) {
2006     if (seq->flag & SELECT) {
2007       seq->flag &= ~SEQ_LOCK;
2008     }
2009   }
2010 
2011   WM_event_add_notifier(C, NC_SCENE | ND_SEQUENCER, scene);
2012 
2013   return OPERATOR_FINISHED;
2014 }
2015 
SEQUENCER_OT_unlock(struct wmOperatorType * ot)2016 void SEQUENCER_OT_unlock(struct wmOperatorType *ot)
2017 {
2018   /* Identifiers. */
2019   ot->name = "Unlock Strips";
2020   ot->idname = "SEQUENCER_OT_unlock";
2021   ot->description = "Unlock strips so they can be transformed";
2022 
2023   /* Api callbacks. */
2024   ot->exec = sequencer_unlock_exec;
2025   ot->poll = sequencer_edit_poll;
2026 
2027   /* Flags. */
2028   ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
2029 }
2030 
2031 /** \} */
2032 
2033 /* -------------------------------------------------------------------- */
2034 /** \name Reload Strips Operator
2035  * \{ */
2036 
sequencer_reload_exec(bContext * C,wmOperator * op)2037 static int sequencer_reload_exec(bContext *C, wmOperator *op)
2038 {
2039   Main *bmain = CTX_data_main(C);
2040   Scene *scene = CTX_data_scene(C);
2041   Editing *ed = BKE_sequencer_editing_get(scene, false);
2042   Sequence *seq;
2043   const bool adjust_length = RNA_boolean_get(op->ptr, "adjust_length");
2044 
2045   for (seq = ed->seqbasep->first; seq; seq = seq->next) {
2046     if (seq->flag & SELECT) {
2047       BKE_sequencer_update_changed_seq_and_deps(scene, seq, 0, 1);
2048       BKE_sequence_reload_new_file(bmain, scene, seq, !adjust_length);
2049 
2050       if (adjust_length) {
2051         if (BKE_sequence_test_overlap(ed->seqbasep, seq)) {
2052           BKE_sequence_base_shuffle(ed->seqbasep, seq, scene);
2053         }
2054       }
2055     }
2056   }
2057 
2058   WM_event_add_notifier(C, NC_SCENE | ND_SEQUENCER, scene);
2059 
2060   return OPERATOR_FINISHED;
2061 }
2062 
SEQUENCER_OT_reload(struct wmOperatorType * ot)2063 void SEQUENCER_OT_reload(struct wmOperatorType *ot)
2064 {
2065   PropertyRNA *prop;
2066 
2067   /* Identifiers. */
2068   ot->name = "Reload Strips";
2069   ot->idname = "SEQUENCER_OT_reload";
2070   ot->description = "Reload strips in the sequencer";
2071 
2072   /* Api callbacks. */
2073   ot->exec = sequencer_reload_exec;
2074   ot->poll = sequencer_edit_poll;
2075 
2076   /* Flags. */
2077   ot->flag = OPTYPE_REGISTER; /* No undo, the data changed is stored outside 'main'. */
2078 
2079   prop = RNA_def_boolean(ot->srna,
2080                          "adjust_length",
2081                          0,
2082                          "Adjust Length",
2083                          "Adjust length of strips to their data length");
2084   RNA_def_property_flag(prop, PROP_SKIP_SAVE);
2085 }
2086 
2087 /** \} */
2088 
2089 /* -------------------------------------------------------------------- */
2090 /** \name Refresh Sequencer Operator
2091  * \{ */
2092 
sequencer_refresh_all_poll(bContext * C)2093 static bool sequencer_refresh_all_poll(bContext *C)
2094 {
2095   if (G.is_rendering) {
2096     return 0;
2097   }
2098   return sequencer_edit_poll(C);
2099 }
2100 
sequencer_refresh_all_exec(bContext * C,wmOperator * UNUSED (op))2101 static int sequencer_refresh_all_exec(bContext *C, wmOperator *UNUSED(op))
2102 {
2103   Scene *scene = CTX_data_scene(C);
2104   Editing *ed = BKE_sequencer_editing_get(scene, false);
2105 
2106   BKE_sequencer_free_imbuf(scene, &ed->seqbase, false);
2107 
2108   WM_event_add_notifier(C, NC_SCENE | ND_SEQUENCER, scene);
2109 
2110   return OPERATOR_FINISHED;
2111 }
2112 
SEQUENCER_OT_refresh_all(struct wmOperatorType * ot)2113 void SEQUENCER_OT_refresh_all(struct wmOperatorType *ot)
2114 {
2115   /* Identifiers. */
2116   ot->name = "Refresh Sequencer";
2117   ot->idname = "SEQUENCER_OT_refresh_all";
2118   ot->description = "Refresh the sequencer editor";
2119 
2120   /* Api callbacks. */
2121   ot->exec = sequencer_refresh_all_exec;
2122   ot->poll = sequencer_refresh_all_poll;
2123 }
2124 
2125 /** \} */
2126 
2127 /* -------------------------------------------------------------------- */
2128 /** \name Reassign Inputs Operator
2129  * \{ */
2130 
sequencer_reassign_inputs_exec(bContext * C,wmOperator * op)2131 static int sequencer_reassign_inputs_exec(bContext *C, wmOperator *op)
2132 {
2133   Scene *scene = CTX_data_scene(C);
2134   Sequence *seq1, *seq2, *seq3, *last_seq = BKE_sequencer_active_get(scene);
2135   const char *error_msg;
2136 
2137   if (BKE_sequence_effect_get_num_inputs(last_seq->type) == 0) {
2138     BKE_report(op->reports, RPT_ERROR, "Cannot reassign inputs: strip has no inputs");
2139     return OPERATOR_CANCELLED;
2140   }
2141 
2142   if (!seq_effect_find_selected(
2143           scene, last_seq, last_seq->type, &seq1, &seq2, &seq3, &error_msg) ||
2144       BKE_sequence_effect_get_num_inputs(last_seq->type) == 0) {
2145     BKE_report(op->reports, RPT_ERROR, error_msg);
2146     return OPERATOR_CANCELLED;
2147   }
2148   /* Check if reassigning would create recursivity. */
2149   if (BKE_sequencer_render_loop_check(seq1, last_seq) ||
2150       BKE_sequencer_render_loop_check(seq2, last_seq) ||
2151       BKE_sequencer_render_loop_check(seq3, last_seq)) {
2152     BKE_report(op->reports, RPT_ERROR, "Cannot reassign inputs: recursion detected");
2153     return OPERATOR_CANCELLED;
2154   }
2155 
2156   last_seq->seq1 = seq1;
2157   last_seq->seq2 = seq2;
2158   last_seq->seq3 = seq3;
2159 
2160   BKE_sequencer_update_changed_seq_and_deps(scene, last_seq, 1, 1);
2161 
2162   WM_event_add_notifier(C, NC_SCENE | ND_SEQUENCER, scene);
2163 
2164   return OPERATOR_FINISHED;
2165 }
2166 
sequencer_effect_poll(bContext * C)2167 static bool sequencer_effect_poll(bContext *C)
2168 {
2169   Scene *scene = CTX_data_scene(C);
2170   Editing *ed = BKE_sequencer_editing_get(scene, false);
2171 
2172   if (ed) {
2173     Sequence *last_seq = BKE_sequencer_active_get(scene);
2174     if (last_seq && (last_seq->type & SEQ_TYPE_EFFECT)) {
2175       return 1;
2176     }
2177   }
2178 
2179   return 0;
2180 }
2181 
SEQUENCER_OT_reassign_inputs(struct wmOperatorType * ot)2182 void SEQUENCER_OT_reassign_inputs(struct wmOperatorType *ot)
2183 {
2184   /* Identifiers. */
2185   ot->name = "Reassign Inputs";
2186   ot->idname = "SEQUENCER_OT_reassign_inputs";
2187   ot->description = "Reassign the inputs for the effect strip";
2188 
2189   /* Api callbacks. */
2190   ot->exec = sequencer_reassign_inputs_exec;
2191   ot->poll = sequencer_effect_poll;
2192 
2193   /* Flags. */
2194   ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
2195 }
2196 
2197 /** \} */
2198 
2199 /* -------------------------------------------------------------------- */
2200 /** \name Swap Inputs Operator
2201  * \{ */
2202 
sequencer_swap_inputs_exec(bContext * C,wmOperator * op)2203 static int sequencer_swap_inputs_exec(bContext *C, wmOperator *op)
2204 {
2205   Scene *scene = CTX_data_scene(C);
2206   Sequence *seq, *last_seq = BKE_sequencer_active_get(scene);
2207 
2208   if (last_seq->seq1 == NULL || last_seq->seq2 == NULL) {
2209     BKE_report(op->reports, RPT_ERROR, "No valid inputs to swap");
2210     return OPERATOR_CANCELLED;
2211   }
2212 
2213   seq = last_seq->seq1;
2214   last_seq->seq1 = last_seq->seq2;
2215   last_seq->seq2 = seq;
2216 
2217   BKE_sequencer_update_changed_seq_and_deps(scene, last_seq, 1, 1);
2218 
2219   WM_event_add_notifier(C, NC_SCENE | ND_SEQUENCER, scene);
2220 
2221   return OPERATOR_FINISHED;
2222 }
SEQUENCER_OT_swap_inputs(struct wmOperatorType * ot)2223 void SEQUENCER_OT_swap_inputs(struct wmOperatorType *ot)
2224 {
2225   /* Identifiers. */
2226   ot->name = "Swap Inputs";
2227   ot->idname = "SEQUENCER_OT_swap_inputs";
2228   ot->description = "Swap the first two inputs for the effect strip";
2229 
2230   /* Api callbacks. */
2231   ot->exec = sequencer_swap_inputs_exec;
2232   ot->poll = sequencer_effect_poll;
2233 
2234   /* Flags. */
2235   ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
2236 }
2237 
2238 /** \} */
2239 
2240 /* -------------------------------------------------------------------- */
2241 /** \name Split Strips Operator
2242  * \{ */
2243 
2244 enum {
2245   SEQ_SPLIT_SOFT,
2246   SEQ_SPLIT_HARD,
2247 };
2248 
2249 static const EnumPropertyItem prop_split_types[] = {
2250     {SEQ_SPLIT_SOFT, "SOFT", 0, "Soft", ""},
2251     {SEQ_SPLIT_HARD, "HARD", 0, "Hard", ""},
2252     {0, NULL, 0, NULL, NULL},
2253 };
2254 
sequencer_split_exec(bContext * C,wmOperator * op)2255 static int sequencer_split_exec(bContext *C, wmOperator *op)
2256 {
2257   Main *bmain = CTX_data_main(C);
2258   Scene *scene = CTX_data_scene(C);
2259   Editing *ed = BKE_sequencer_editing_get(scene, false);
2260   int split_side, split_hard, split_frame, split_channel;
2261   bool changed, use_cursor_position, ignore_selection;
2262   bool seq_selected = false;
2263 
2264   split_frame = RNA_int_get(op->ptr, "frame");
2265   split_channel = RNA_int_get(op->ptr, "channel");
2266   use_cursor_position = RNA_boolean_get(op->ptr, "use_cursor_position");
2267   split_hard = RNA_enum_get(op->ptr, "type");
2268   split_side = RNA_enum_get(op->ptr, "side");
2269   ignore_selection = RNA_boolean_get(op->ptr, "ignore_selection");
2270 
2271   BKE_sequencer_prefetch_stop(scene);
2272 
2273   if (split_hard == SEQ_SPLIT_HARD) {
2274     changed = split_seq_list(bmain,
2275                              scene,
2276                              ed->seqbasep,
2277                              split_frame,
2278                              split_channel,
2279                              use_cursor_position,
2280                              split_seq_hard);
2281   }
2282   else {
2283     changed = split_seq_list(bmain,
2284                              scene,
2285                              ed->seqbasep,
2286                              split_frame,
2287                              split_channel,
2288                              use_cursor_position,
2289                              split_seq_soft);
2290   }
2291   if (changed) { /* Got new strips? */
2292     Sequence *seq;
2293     if (ignore_selection) {
2294       if (use_cursor_position) {
2295         SEQ_CURRENT_BEGIN (ed, seq) {
2296           if (seq->enddisp == split_frame && seq->machine == split_channel) {
2297             seq_selected = seq->flag & SEQ_ALLSEL;
2298           }
2299         }
2300         SEQ_CURRENT_END;
2301         if (!seq_selected) {
2302           SEQ_CURRENT_BEGIN (ed, seq) {
2303             if (seq->startdisp == split_frame && seq->machine == split_channel) {
2304               seq->flag &= ~SEQ_ALLSEL;
2305             }
2306           }
2307           SEQ_CURRENT_END;
2308         }
2309       }
2310     }
2311     else {
2312       if (split_side != SEQ_SIDE_BOTH) {
2313         SEQ_CURRENT_BEGIN (ed, seq) {
2314           if (split_side == SEQ_SIDE_LEFT) {
2315             if (seq->startdisp >= split_frame) {
2316               seq->flag &= ~SEQ_ALLSEL;
2317             }
2318           }
2319           else {
2320             if (seq->enddisp <= split_frame) {
2321               seq->flag &= ~SEQ_ALLSEL;
2322             }
2323           }
2324         }
2325         SEQ_CURRENT_END;
2326       }
2327     }
2328     SEQ_CURRENT_BEGIN (ed, seq) {
2329       if (seq->seq1 || seq->seq2 || seq->seq3) {
2330         BKE_sequence_calc(scene, seq);
2331       }
2332     }
2333     SEQ_CURRENT_END;
2334 
2335     BKE_sequencer_sort(scene);
2336   }
2337   if (changed) {
2338     WM_event_add_notifier(C, NC_SCENE | ND_SEQUENCER, scene);
2339     return OPERATOR_FINISHED;
2340   }
2341 
2342   /* Passthrough to selection if used as tool. */
2343   return OPERATOR_CANCELLED | OPERATOR_PASS_THROUGH;
2344 }
2345 
sequencer_split_invoke(bContext * C,wmOperator * op,const wmEvent * event)2346 static int sequencer_split_invoke(bContext *C, wmOperator *op, const wmEvent *event)
2347 {
2348   Scene *scene = CTX_data_scene(C);
2349   View2D *v2d = UI_view2d_fromcontext(C);
2350 
2351   int split_side = RNA_enum_get(op->ptr, "side");
2352   int split_frame = CFRA;
2353 
2354   if (split_side == SEQ_SIDE_MOUSE) {
2355     if (ED_operator_sequencer_active(C) && v2d) {
2356       split_side = mouse_frame_side(v2d, event->mval[0], split_frame);
2357     }
2358     else {
2359       split_side = SEQ_SIDE_BOTH;
2360     }
2361   }
2362   float mouseloc[2];
2363   UI_view2d_region_to_view(v2d, event->mval[0], event->mval[1], &mouseloc[0], &mouseloc[1]);
2364   if (RNA_boolean_get(op->ptr, "use_cursor_position")) {
2365     RNA_int_set(op->ptr, "frame", mouseloc[0]);
2366   }
2367   else {
2368     RNA_int_set(op->ptr, "frame", split_frame);
2369   }
2370   RNA_int_set(op->ptr, "channel", mouseloc[1]);
2371   RNA_enum_set(op->ptr, "side", split_side);
2372   /*RNA_enum_set(op->ptr, "type", split_hard); */
2373 
2374   return sequencer_split_exec(C, op);
2375 }
2376 
sequencer_split_ui(bContext * UNUSED (C),wmOperator * op)2377 static void sequencer_split_ui(bContext *UNUSED(C), wmOperator *op)
2378 {
2379   uiLayout *layout = op->layout;
2380   uiLayoutSetPropSep(layout, true);
2381   uiLayoutSetPropDecorate(layout, false);
2382 
2383   PointerRNA ptr;
2384   RNA_pointer_create(NULL, op->type->srna, op->properties, &ptr);
2385 
2386   uiLayout *row = uiLayoutRow(layout, false);
2387   uiItemR(row, &ptr, "type", UI_ITEM_R_EXPAND, NULL, ICON_NONE);
2388   uiItemR(layout, &ptr, "frame", 0, NULL, ICON_NONE);
2389   uiItemR(layout, &ptr, "side", 0, NULL, ICON_NONE);
2390 
2391   uiItemS(layout);
2392 
2393   uiItemR(layout, &ptr, "use_cursor_position", 0, NULL, ICON_NONE);
2394   if (RNA_boolean_get(&ptr, "use_cursor_position")) {
2395     uiItemR(layout, &ptr, "channel", 0, NULL, ICON_NONE);
2396   }
2397 }
2398 
SEQUENCER_OT_split(struct wmOperatorType * ot)2399 void SEQUENCER_OT_split(struct wmOperatorType *ot)
2400 {
2401   /* Identifiers. */
2402   ot->name = "Split Strips";
2403   ot->idname = "SEQUENCER_OT_split";
2404   ot->description = "Split the selected strips in two";
2405 
2406   /* Api callbacks. */
2407   ot->invoke = sequencer_split_invoke;
2408   ot->exec = sequencer_split_exec;
2409   ot->poll = sequencer_edit_poll;
2410   ot->ui = sequencer_split_ui;
2411 
2412   /* Flags. */
2413   ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
2414 
2415   PropertyRNA *prop;
2416   RNA_def_int(ot->srna,
2417               "frame",
2418               0,
2419               INT_MIN,
2420               INT_MAX,
2421               "Frame",
2422               "Frame where selected strips will be split",
2423               INT_MIN,
2424               INT_MAX);
2425   RNA_def_int(ot->srna,
2426               "channel",
2427               0,
2428               INT_MIN,
2429               INT_MAX,
2430               "Channel",
2431               "Channel in which strip will be cut",
2432               INT_MIN,
2433               INT_MAX);
2434   RNA_def_enum(ot->srna,
2435                "type",
2436                prop_split_types,
2437                SEQ_SPLIT_SOFT,
2438                "Type",
2439                "The type of split operation to perform on strips");
2440 
2441   RNA_def_boolean(ot->srna,
2442                   "use_cursor_position",
2443                   0,
2444                   "Use Cursor Position",
2445                   "Split at position of the cursor instead of current frame");
2446 
2447   prop = RNA_def_enum(ot->srna,
2448                       "side",
2449                       prop_side_types,
2450                       SEQ_SIDE_MOUSE,
2451                       "Side",
2452                       "The side that remains selected after splitting");
2453 
2454   RNA_def_property_flag(prop, PROP_SKIP_SAVE);
2455 
2456   prop = RNA_def_boolean(
2457       ot->srna,
2458       "ignore_selection",
2459       false,
2460       "Ignore Selection",
2461       "Make cut event if strip is not selected preserving selection state after cut");
2462 
2463   RNA_def_property_flag(prop, PROP_HIDDEN);
2464 }
2465 
2466 #undef SEQ_SIDE_MOUSE
2467 
2468 /** \} */
2469 
2470 /* -------------------------------------------------------------------- */
2471 /** \name Duplicate Strips Operator
2472  * \{ */
2473 
apply_unique_name_fn(Sequence * seq,void * arg_pt)2474 static int apply_unique_name_fn(Sequence *seq, void *arg_pt)
2475 {
2476   Scene *scene = (Scene *)arg_pt;
2477   char name[sizeof(seq->name) - 2];
2478 
2479   BLI_strncpy_utf8(name, seq->name + 2, sizeof(name));
2480   BKE_sequence_base_unique_name_recursive(&scene->ed->seqbase, seq);
2481   BKE_sequencer_dupe_animdata(scene, name, seq->name + 2);
2482   return 1;
2483 }
2484 
sequencer_add_duplicate_exec(bContext * C,wmOperator * UNUSED (op))2485 static int sequencer_add_duplicate_exec(bContext *C, wmOperator *UNUSED(op))
2486 {
2487   Scene *scene = CTX_data_scene(C);
2488   Editing *ed = BKE_sequencer_editing_get(scene, false);
2489 
2490   ListBase nseqbase = {NULL, NULL};
2491 
2492   if (ed == NULL) {
2493     return OPERATOR_CANCELLED;
2494   }
2495 
2496   BKE_sequence_base_dupli_recursive(scene, scene, &nseqbase, ed->seqbasep, SEQ_DUPE_CONTEXT, 0);
2497 
2498   if (nseqbase.first) {
2499     Sequence *seq = nseqbase.first;
2500     /* Rely on the nseqbase list being added at the end.
2501      * Their UUIDs has been re-generated by the BKE_sequence_base_dupli_recursive(), */
2502     BLI_movelisttolist(ed->seqbasep, &nseqbase);
2503 
2504     for (; seq; seq = seq->next) {
2505       BKE_sequencer_recursive_apply(seq, apply_unique_name_fn, scene);
2506     }
2507 
2508     WM_event_add_notifier(C, NC_SCENE | ND_SEQUENCER, scene);
2509     return OPERATOR_FINISHED;
2510   }
2511 
2512   return OPERATOR_CANCELLED;
2513 }
2514 
SEQUENCER_OT_duplicate(wmOperatorType * ot)2515 void SEQUENCER_OT_duplicate(wmOperatorType *ot)
2516 {
2517   /* Identifiers. */
2518   ot->name = "Duplicate Strips";
2519   ot->idname = "SEQUENCER_OT_duplicate";
2520   ot->description = "Duplicate the selected strips";
2521 
2522   /* Api callbacks. */
2523   ot->exec = sequencer_add_duplicate_exec;
2524   ot->poll = ED_operator_sequencer_active;
2525 
2526   /* Flags. */
2527   ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
2528 }
2529 
2530 /** \} */
2531 
2532 /* -------------------------------------------------------------------- */
2533 /** \name Erase Strips Operator
2534  * \{ */
2535 
sequencer_delete_exec(bContext * C,wmOperator * UNUSED (op))2536 static int sequencer_delete_exec(bContext *C, wmOperator *UNUSED(op))
2537 {
2538   Main *bmain = CTX_data_main(C);
2539   Scene *scene = CTX_data_scene(C);
2540   Editing *ed = BKE_sequencer_editing_get(scene, false);
2541   Sequence *seq;
2542 
2543   BKE_sequencer_prefetch_stop(scene);
2544 
2545   SEQ_CURRENT_BEGIN (scene->ed, seq) {
2546     if (seq->flag & SELECT) {
2547       BKE_sequencer_flag_for_removal(scene, ed->seqbasep, seq);
2548     }
2549   }
2550   SEQ_CURRENT_END;
2551   BKE_sequencer_remove_flagged_sequences(scene, ed->seqbasep);
2552 
2553   DEG_id_tag_update(&scene->id, ID_RECALC_SEQUENCER_STRIPS);
2554   DEG_relations_tag_update(bmain);
2555   WM_event_add_notifier(C, NC_SCENE | ND_SEQUENCER, scene);
2556   return OPERATOR_FINISHED;
2557 }
2558 
sequencer_delete_invoke(bContext * C,wmOperator * op,const wmEvent * event)2559 static int sequencer_delete_invoke(bContext *C, wmOperator *op, const wmEvent *event)
2560 {
2561   ARegion *region = CTX_wm_region(C);
2562 
2563   if (region->regiontype == RGN_TYPE_WINDOW) {
2564     /* Bounding box of 30 pixels is used for markers shortcuts,
2565      * prevent conflict with markers shortcuts here.
2566      */
2567     if (event->mval[1] <= 30) {
2568       return OPERATOR_PASS_THROUGH;
2569     }
2570   }
2571 
2572   return sequencer_delete_exec(C, op);
2573 }
2574 
SEQUENCER_OT_delete(wmOperatorType * ot)2575 void SEQUENCER_OT_delete(wmOperatorType *ot)
2576 {
2577 
2578   /* Identifiers. */
2579   ot->name = "Erase Strips";
2580   ot->idname = "SEQUENCER_OT_delete";
2581   ot->description = "Erase selected strips from the sequencer";
2582 
2583   /* Api callbacks. */
2584   ot->invoke = sequencer_delete_invoke;
2585   ot->exec = sequencer_delete_exec;
2586   ot->poll = sequencer_edit_poll;
2587 
2588   /* Flags. */
2589   ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
2590 }
2591 
2592 /** \} */
2593 
2594 /* -------------------------------------------------------------------- */
2595 /** \name Clear Strip Offset Operator
2596  * \{ */
2597 
sequencer_offset_clear_exec(bContext * C,wmOperator * UNUSED (op))2598 static int sequencer_offset_clear_exec(bContext *C, wmOperator *UNUSED(op))
2599 {
2600   Scene *scene = CTX_data_scene(C);
2601   Editing *ed = BKE_sequencer_editing_get(scene, false);
2602   Sequence *seq;
2603 
2604   /* For effects, try to find a replacement input. */
2605   for (seq = ed->seqbasep->first; seq; seq = seq->next) {
2606     if ((seq->type & SEQ_TYPE_EFFECT) == 0 && (seq->flag & SELECT)) {
2607       seq->startofs = seq->endofs = seq->startstill = seq->endstill = 0;
2608     }
2609   }
2610 
2611   /* Update lengths, etc. */
2612   seq = ed->seqbasep->first;
2613   while (seq) {
2614     BKE_sequence_calc(scene, seq);
2615     seq = seq->next;
2616   }
2617 
2618   for (seq = ed->seqbasep->first; seq; seq = seq->next) {
2619     if ((seq->type & SEQ_TYPE_EFFECT) == 0 && (seq->flag & SELECT)) {
2620       if (BKE_sequence_test_overlap(ed->seqbasep, seq)) {
2621         BKE_sequence_base_shuffle(ed->seqbasep, seq, scene);
2622       }
2623     }
2624   }
2625 
2626   WM_event_add_notifier(C, NC_SCENE | ND_SEQUENCER, scene);
2627 
2628   return OPERATOR_FINISHED;
2629 }
2630 
SEQUENCER_OT_offset_clear(wmOperatorType * ot)2631 void SEQUENCER_OT_offset_clear(wmOperatorType *ot)
2632 {
2633 
2634   /* Identifiers. */
2635   ot->name = "Clear Strip Offset";
2636   ot->idname = "SEQUENCER_OT_offset_clear";
2637   ot->description = "Clear strip offsets from the start and end frames";
2638 
2639   /* Api callbacks. */
2640   ot->exec = sequencer_offset_clear_exec;
2641   ot->poll = sequencer_edit_poll;
2642 
2643   /* Flags. */
2644   ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
2645 }
2646 
2647 /** \} */
2648 
2649 /* -------------------------------------------------------------------- */
2650 /** \name Separate Images Operator
2651  * \{ */
2652 
sequencer_separate_images_exec(bContext * C,wmOperator * op)2653 static int sequencer_separate_images_exec(bContext *C, wmOperator *op)
2654 {
2655   Scene *scene = CTX_data_scene(C);
2656   Editing *ed = BKE_sequencer_editing_get(scene, false);
2657 
2658   Sequence *seq, *seq_new;
2659   Strip *strip_new;
2660   StripElem *se, *se_new;
2661   int start_ofs, cfra, frame_end;
2662   int step = RNA_int_get(op->ptr, "length");
2663 
2664   seq = ed->seqbasep->first; /* Poll checks this is valid. */
2665 
2666   BKE_sequencer_prefetch_stop(scene);
2667 
2668   while (seq) {
2669     if ((seq->flag & SELECT) && (seq->type == SEQ_TYPE_IMAGE) && (seq->len > 1)) {
2670       Sequence *seq_next;
2671 
2672       /* Remove seq so overlap tests don't conflict,
2673        * see seq_free_sequence below for the real freeing. */
2674       BLI_remlink(ed->seqbasep, seq);
2675       /* if (seq->ipo) id_us_min(&seq->ipo->id); */
2676       /* XXX, remove fcurve and assign to split image strips */
2677 
2678       start_ofs = cfra = BKE_sequence_tx_get_final_left(seq, false);
2679       frame_end = BKE_sequence_tx_get_final_right(seq, false);
2680 
2681       while (cfra < frame_end) {
2682         /* New seq. */
2683         se = BKE_sequencer_give_stripelem(seq, cfra);
2684 
2685         seq_new = BKE_sequence_dupli_recursive(
2686             scene, scene, ed->seqbasep, seq, SEQ_DUPE_UNIQUE_NAME);
2687 
2688         seq_new->start = start_ofs;
2689         seq_new->type = SEQ_TYPE_IMAGE;
2690         seq_new->len = 1;
2691         seq_new->endstill = step - 1;
2692 
2693         /* New strip. */
2694         strip_new = seq_new->strip;
2695         strip_new->us = 1;
2696 
2697         /* New stripdata, only one element now. */
2698         /* Note this assume all elements (images) have the same dimension,
2699          * since we only copy the name here. */
2700         se_new = MEM_reallocN(strip_new->stripdata, sizeof(*se_new));
2701         BLI_strncpy(se_new->name, se->name, sizeof(se_new->name));
2702         strip_new->stripdata = se_new;
2703 
2704         BKE_sequence_calc(scene, seq_new);
2705 
2706         if (step > 1) {
2707           seq_new->flag &= ~SEQ_OVERLAP;
2708           if (BKE_sequence_test_overlap(ed->seqbasep, seq_new)) {
2709             BKE_sequence_base_shuffle(ed->seqbasep, seq_new, scene);
2710           }
2711         }
2712 
2713         /* XXX, COPY FCURVES */
2714 
2715         cfra++;
2716         start_ofs += step;
2717       }
2718 
2719       seq_next = seq->next;
2720       BKE_sequence_free(scene, seq, true);
2721       seq = seq_next;
2722     }
2723     else {
2724       seq = seq->next;
2725     }
2726   }
2727 
2728   BKE_sequencer_sort(scene);
2729 
2730   WM_event_add_notifier(C, NC_SCENE | ND_SEQUENCER, scene);
2731 
2732   return OPERATOR_FINISHED;
2733 }
2734 
SEQUENCER_OT_images_separate(wmOperatorType * ot)2735 void SEQUENCER_OT_images_separate(wmOperatorType *ot)
2736 {
2737   /* Identifiers. */
2738   ot->name = "Separate Images";
2739   ot->idname = "SEQUENCER_OT_images_separate";
2740   ot->description = "On image sequence strips, it returns a strip for each image";
2741 
2742   /* Api callbacks. */
2743   ot->exec = sequencer_separate_images_exec;
2744   ot->invoke = WM_operator_props_popup_confirm;
2745   ot->poll = sequencer_edit_poll;
2746 
2747   /* Flags. */
2748   ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
2749 
2750   RNA_def_int(ot->srna, "length", 1, 1, INT_MAX, "Length", "Length of each frame", 1, 1000);
2751 }
2752 
2753 /** \} */
2754 
2755 /* -------------------------------------------------------------------- */
2756 /** \name Toggle Meta Strip Operator
2757  * \{ */
2758 
sequencer_meta_toggle_exec(bContext * C,wmOperator * UNUSED (op))2759 static int sequencer_meta_toggle_exec(bContext *C, wmOperator *UNUSED(op))
2760 {
2761   Scene *scene = CTX_data_scene(C);
2762   Editing *ed = BKE_sequencer_editing_get(scene, false);
2763   Sequence *last_seq = BKE_sequencer_active_get(scene);
2764   MetaStack *ms;
2765 
2766   if (last_seq && last_seq->type == SEQ_TYPE_META && last_seq->flag & SELECT) {
2767     /* Enter metastrip. */
2768     ms = MEM_mallocN(sizeof(MetaStack), "metastack");
2769     BLI_addtail(&ed->metastack, ms);
2770     ms->parseq = last_seq;
2771     ms->oldbasep = ed->seqbasep;
2772     copy_v2_v2_int(ms->disp_range, &ms->parseq->startdisp);
2773 
2774     ed->seqbasep = &last_seq->seqbase;
2775 
2776     BKE_sequencer_active_set(scene, NULL);
2777   }
2778   else {
2779     /* Exit metastrip if possible. */
2780 
2781     Sequence *seq;
2782 
2783     if (BLI_listbase_is_empty(&ed->metastack)) {
2784       return OPERATOR_CANCELLED;
2785     }
2786 
2787     ms = ed->metastack.last;
2788     BLI_remlink(&ed->metastack, ms);
2789 
2790     ed->seqbasep = ms->oldbasep;
2791 
2792     /* For old files, update from meta. */
2793     if (ms->disp_range[0] == ms->disp_range[1]) {
2794       copy_v2_v2_int(ms->disp_range, &ms->parseq->startdisp);
2795     }
2796 
2797     /* Recalc all: the meta can have effects connected to it. */
2798     for (seq = ed->seqbasep->first; seq; seq = seq->next) {
2799       BKE_sequence_calc(scene, seq);
2800     }
2801 
2802     /* 2.73+, keeping endpoints is important!
2803      * Moving them around means you can't usefully use metas in a complex edit. */
2804 #if 1
2805     BKE_sequence_tx_set_final_left(ms->parseq, ms->disp_range[0]);
2806     BKE_sequence_tx_set_final_right(ms->parseq, ms->disp_range[1]);
2807     BKE_sequence_single_fix(ms->parseq);
2808     BKE_sequence_calc(scene, ms->parseq);
2809 #else
2810     if (BKE_sequence_test_overlap(ed->seqbasep, ms->parseq)) {
2811       BKE_sequence_base_shuffle(ed->seqbasep, ms->parseq, scene);
2812     }
2813 #endif
2814 
2815     BKE_sequencer_active_set(scene, ms->parseq);
2816 
2817     ms->parseq->flag |= SELECT;
2818     recurs_sel_seq(ms->parseq);
2819 
2820     MEM_freeN(ms);
2821   }
2822 
2823   DEG_id_tag_update(&scene->id, ID_RECALC_SEQUENCER_STRIPS);
2824   WM_event_add_notifier(C, NC_SCENE | ND_SEQUENCER, scene);
2825 
2826   return OPERATOR_FINISHED;
2827 }
2828 
SEQUENCER_OT_meta_toggle(wmOperatorType * ot)2829 void SEQUENCER_OT_meta_toggle(wmOperatorType *ot)
2830 {
2831   /* Identifiers. */
2832   ot->name = "Toggle Meta Strip";
2833   ot->idname = "SEQUENCER_OT_meta_toggle";
2834   ot->description = "Toggle a metastrip (to edit enclosed strips)";
2835 
2836   /* Api callbacks. */
2837   ot->exec = sequencer_meta_toggle_exec;
2838   ot->poll = sequencer_edit_poll;
2839 
2840   /* Flags. */
2841   ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
2842 }
2843 
2844 /** \} */
2845 
2846 /* -------------------------------------------------------------------- */
2847 /** \name Make Meta Strip Operator
2848  * \{ */
2849 
sequencer_meta_make_exec(bContext * C,wmOperator * op)2850 static int sequencer_meta_make_exec(bContext *C, wmOperator *op)
2851 {
2852   Scene *scene = CTX_data_scene(C);
2853   Editing *ed = BKE_sequencer_editing_get(scene, false);
2854 
2855   Sequence *seq, *seqm, *next, *last_seq = BKE_sequencer_active_get(scene);
2856   int channel_max = 1;
2857 
2858   if (BKE_sequence_base_isolated_sel_check(ed->seqbasep) == false) {
2859     BKE_report(op->reports, RPT_ERROR, "Please select all related strips");
2860     return OPERATOR_CANCELLED;
2861   }
2862 
2863   BKE_sequencer_prefetch_stop(scene);
2864 
2865   /* Remove all selected from main list, and put in meta. */
2866 
2867   seqm = BKE_sequence_alloc(ed->seqbasep, 1, 1, SEQ_TYPE_META); /* Channel number set later. */
2868   strcpy(seqm->name + 2, "MetaStrip");
2869   seqm->flag = SELECT;
2870 
2871   seq = ed->seqbasep->first;
2872   while (seq) {
2873     next = seq->next;
2874     if (seq != seqm && (seq->flag & SELECT)) {
2875       BKE_sequence_invalidate_cache_composite(scene, seq);
2876       channel_max = max_ii(seq->machine, channel_max);
2877       /* Sequence is moved within the same edit, no need to re-generate the UUID. */
2878       BLI_remlink(ed->seqbasep, seq);
2879       BLI_addtail(&seqm->seqbase, seq);
2880     }
2881     seq = next;
2882   }
2883   seqm->machine = last_seq ? last_seq->machine : channel_max;
2884   BKE_sequence_calc(scene, seqm);
2885 
2886   BKE_sequencer_active_set(scene, seqm);
2887 
2888   if (BKE_sequence_test_overlap(ed->seqbasep, seqm)) {
2889     BKE_sequence_base_shuffle(ed->seqbasep, seqm, scene);
2890   }
2891 
2892   DEG_id_tag_update(&scene->id, ID_RECALC_SEQUENCER_STRIPS);
2893 
2894   BKE_sequence_base_unique_name_recursive(&scene->ed->seqbase, seqm);
2895   BKE_sequence_invalidate_cache_composite(scene, seqm);
2896   WM_event_add_notifier(C, NC_SCENE | ND_SEQUENCER, scene);
2897 
2898   return OPERATOR_FINISHED;
2899 }
2900 
SEQUENCER_OT_meta_make(wmOperatorType * ot)2901 void SEQUENCER_OT_meta_make(wmOperatorType *ot)
2902 {
2903   /* Identifiers. */
2904   ot->name = "Make Meta Strip";
2905   ot->idname = "SEQUENCER_OT_meta_make";
2906   ot->description = "Group selected strips into a metastrip";
2907 
2908   /* Api callbacks. */
2909   ot->exec = sequencer_meta_make_exec;
2910   ot->poll = sequencer_edit_poll;
2911 
2912   /* Flags. */
2913   ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
2914 }
2915 
2916 /** \} */
2917 
2918 /* -------------------------------------------------------------------- */
2919 /** \name UnMeta Strip Operator
2920  * \{ */
2921 
seq_depends_on_meta(Sequence * seq,Sequence * seqm)2922 static int seq_depends_on_meta(Sequence *seq, Sequence *seqm)
2923 {
2924   if (seq == seqm) {
2925     return 1;
2926   }
2927   if (seq->seq1 && seq_depends_on_meta(seq->seq1, seqm)) {
2928     return 1;
2929   }
2930   if (seq->seq2 && seq_depends_on_meta(seq->seq2, seqm)) {
2931     return 1;
2932   }
2933   if (seq->seq3 && seq_depends_on_meta(seq->seq3, seqm)) {
2934     return 1;
2935   }
2936   return 0;
2937 }
2938 
sequencer_meta_separate_exec(bContext * C,wmOperator * UNUSED (op))2939 static int sequencer_meta_separate_exec(bContext *C, wmOperator *UNUSED(op))
2940 {
2941   Scene *scene = CTX_data_scene(C);
2942   Editing *ed = BKE_sequencer_editing_get(scene, false);
2943 
2944   Sequence *seq, *last_seq = BKE_sequencer_active_get(scene); /* last_seq checks (ed == NULL) */
2945 
2946   if (last_seq == NULL || last_seq->type != SEQ_TYPE_META) {
2947     return OPERATOR_CANCELLED;
2948   }
2949 
2950   BKE_sequencer_prefetch_stop(scene);
2951 
2952   for (seq = last_seq->seqbase.first; seq != NULL; seq = seq->next) {
2953     BKE_sequence_invalidate_cache_composite(scene, seq);
2954   }
2955 
2956   /* This moves strips from meta to parent, sating within same edit and no new strips are
2957    * allocated. If the UUID was unique already (as it should) it will stay unique.
2958    * No need to re-generate the UUIDs. */
2959   BLI_movelisttolist(ed->seqbasep, &last_seq->seqbase);
2960 
2961   BLI_listbase_clear(&last_seq->seqbase);
2962 
2963   BLI_remlink(ed->seqbasep, last_seq);
2964   BKE_sequence_free(scene, last_seq, true);
2965 
2966   /* Empty meta strip, delete all effects depending on it. */
2967   for (seq = ed->seqbasep->first; seq; seq = seq->next) {
2968     if ((seq->type & SEQ_TYPE_EFFECT) && seq_depends_on_meta(seq, last_seq)) {
2969       seq->flag |= SEQ_FLAG_DELETE;
2970     }
2971   }
2972 
2973   recurs_del_seq_flag(scene, ed->seqbasep, SEQ_FLAG_DELETE, 0);
2974 
2975   /* Test for effects and overlap
2976    * don't use SEQ_CURRENT_BEGIN since that would be recursive. */
2977   for (seq = ed->seqbasep->first; seq; seq = seq->next) {
2978     if (seq->flag & SELECT) {
2979       seq->flag &= ~SEQ_OVERLAP;
2980       if (BKE_sequence_test_overlap(ed->seqbasep, seq)) {
2981         BKE_sequence_base_shuffle(ed->seqbasep, seq, scene);
2982       }
2983     }
2984   }
2985 
2986   BKE_sequencer_sort(scene);
2987   DEG_id_tag_update(&scene->id, ID_RECALC_SEQUENCER_STRIPS);
2988 
2989   WM_event_add_notifier(C, NC_SCENE | ND_SEQUENCER, scene);
2990 
2991   return OPERATOR_FINISHED;
2992 }
2993 
SEQUENCER_OT_meta_separate(wmOperatorType * ot)2994 void SEQUENCER_OT_meta_separate(wmOperatorType *ot)
2995 {
2996   /* Identifiers. */
2997   ot->name = "UnMeta Strip";
2998   ot->idname = "SEQUENCER_OT_meta_separate";
2999   ot->description = "Put the contents of a metastrip back in the sequencer";
3000 
3001   /* Api callbacks. */
3002   ot->exec = sequencer_meta_separate_exec;
3003   ot->poll = sequencer_edit_poll;
3004 
3005   /* Flags. */
3006   ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
3007 }
3008 
3009 /** \} */
3010 
3011 /* -------------------------------------------------------------------- */
3012 /** \name Jump to Strip Operator
3013  * \{ */
3014 
strip_jump_internal(Scene * scene,const short side,const bool do_skip_mute,const bool do_center)3015 static bool strip_jump_internal(Scene *scene,
3016                                 const short side,
3017                                 const bool do_skip_mute,
3018                                 const bool do_center)
3019 {
3020   bool changed = false;
3021   int cfra = CFRA;
3022   int nfra = BKE_sequencer_find_next_prev_edit(scene, cfra, side, do_skip_mute, do_center, false);
3023 
3024   if (nfra != cfra) {
3025     CFRA = nfra;
3026     changed = true;
3027   }
3028 
3029   return changed;
3030 }
3031 
sequencer_strip_jump_poll(bContext * C)3032 static bool sequencer_strip_jump_poll(bContext *C)
3033 {
3034   /* Prevent changes during render. */
3035   if (G.is_rendering) {
3036     return 0;
3037   }
3038 
3039   return sequencer_edit_poll(C);
3040 }
3041 
sequencer_strip_jump_exec(bContext * C,wmOperator * op)3042 static int sequencer_strip_jump_exec(bContext *C, wmOperator *op)
3043 {
3044   Scene *scene = CTX_data_scene(C);
3045   const bool next = RNA_boolean_get(op->ptr, "next");
3046   const bool center = RNA_boolean_get(op->ptr, "center");
3047 
3048   /* Currently do_skip_mute is always true. */
3049   if (!strip_jump_internal(scene, next ? SEQ_SIDE_RIGHT : SEQ_SIDE_LEFT, true, center)) {
3050     return OPERATOR_CANCELLED;
3051   }
3052 
3053   WM_event_add_notifier(C, NC_SCENE | ND_FRAME, scene);
3054 
3055   return OPERATOR_FINISHED;
3056 }
3057 
SEQUENCER_OT_strip_jump(wmOperatorType * ot)3058 void SEQUENCER_OT_strip_jump(wmOperatorType *ot)
3059 {
3060   /* Identifiers. */
3061   ot->name = "Jump to Strip";
3062   ot->idname = "SEQUENCER_OT_strip_jump";
3063   ot->description = "Move frame to previous edit point";
3064 
3065   /* Api callbacks. */
3066   ot->exec = sequencer_strip_jump_exec;
3067   ot->poll = sequencer_strip_jump_poll;
3068 
3069   /* Flags. */
3070   ot->flag = OPTYPE_UNDO;
3071 
3072   /* Properties. */
3073   RNA_def_boolean(ot->srna, "next", true, "Next Strip", "");
3074   RNA_def_boolean(ot->srna, "center", true, "Use strip center", "");
3075 }
3076 
3077 /** \} */
3078 
3079 /* -------------------------------------------------------------------- */
3080 /** \name Swap Strip Operator
3081  * \{ */
3082 
swap_sequence(Scene * scene,Sequence * seqa,Sequence * seqb)3083 static void swap_sequence(Scene *scene, Sequence *seqa, Sequence *seqb)
3084 {
3085   int gap = seqb->startdisp - seqa->enddisp;
3086   int seq_a_start;
3087   int seq_b_start;
3088 
3089   seq_b_start = (seqb->start - seqb->startdisp) + seqa->startdisp;
3090   BKE_sequence_translate(scene, seqb, seq_b_start - seqb->start);
3091   BKE_sequence_calc(scene, seqb);
3092 
3093   seq_a_start = (seqa->start - seqa->startdisp) + seqb->enddisp + gap;
3094   BKE_sequence_translate(scene, seqa, seq_a_start - seqa->start);
3095   BKE_sequence_calc(scene, seqa);
3096 }
3097 
3098 #if 0
3099 static Sequence *sequence_find_parent(Scene *scene, Sequence *child)
3100 {
3101   Editing *ed = BKE_sequencer_editing_get(scene, false);
3102   Sequence *parent = NULL;
3103   Sequence *seq;
3104 
3105   if (ed == NULL) {
3106     return NULL;
3107   }
3108 
3109   for (seq = ed->seqbasep->first; seq; seq = seq->next) {
3110     if ((seq != child) && seq_is_parent(seq, child)) {
3111       parent = seq;
3112       break;
3113     }
3114   }
3115 
3116   return parent;
3117 }
3118 #endif
3119 
sequencer_swap_exec(bContext * C,wmOperator * op)3120 static int sequencer_swap_exec(bContext *C, wmOperator *op)
3121 {
3122   Scene *scene = CTX_data_scene(C);
3123   Editing *ed = BKE_sequencer_editing_get(scene, false);
3124   Sequence *active_seq = BKE_sequencer_active_get(scene);
3125   Sequence *seq, *iseq;
3126   int side = RNA_enum_get(op->ptr, "side");
3127 
3128   if (active_seq == NULL) {
3129     return OPERATOR_CANCELLED;
3130   }
3131 
3132   seq = find_next_prev_sequence(scene, active_seq, side, -1);
3133 
3134   if (seq) {
3135 
3136     /* Disallow effect strips. */
3137     if (BKE_sequence_effect_get_num_inputs(seq->type) >= 1 &&
3138         (seq->effectdata || seq->seq1 || seq->seq2 || seq->seq3)) {
3139       return OPERATOR_CANCELLED;
3140     }
3141     if ((BKE_sequence_effect_get_num_inputs(active_seq->type) >= 1) &&
3142         (active_seq->effectdata || active_seq->seq1 || active_seq->seq2 || active_seq->seq3)) {
3143       return OPERATOR_CANCELLED;
3144     }
3145 
3146     switch (side) {
3147       case SEQ_SIDE_LEFT:
3148         swap_sequence(scene, seq, active_seq);
3149         break;
3150       case SEQ_SIDE_RIGHT:
3151         swap_sequence(scene, active_seq, seq);
3152         break;
3153     }
3154 
3155     /* XXX - Should be a generic function. */
3156     for (iseq = scene->ed->seqbasep->first; iseq; iseq = iseq->next) {
3157       if ((iseq->type & SEQ_TYPE_EFFECT) &&
3158           (seq_is_parent(iseq, active_seq) || seq_is_parent(iseq, seq))) {
3159         BKE_sequence_calc(scene, iseq);
3160       }
3161     }
3162 
3163     /* Do this in a new loop since both effects need to be calculated first. */
3164     for (iseq = scene->ed->seqbasep->first; iseq; iseq = iseq->next) {
3165       if ((iseq->type & SEQ_TYPE_EFFECT) &&
3166           (seq_is_parent(iseq, active_seq) || seq_is_parent(iseq, seq))) {
3167         /* This may now overlap. */
3168         if (BKE_sequence_test_overlap(ed->seqbasep, iseq)) {
3169           BKE_sequence_base_shuffle(ed->seqbasep, iseq, scene);
3170         }
3171       }
3172     }
3173 
3174     BKE_sequencer_sort(scene);
3175 
3176     WM_event_add_notifier(C, NC_SCENE | ND_SEQUENCER, scene);
3177 
3178     return OPERATOR_FINISHED;
3179   }
3180 
3181   return OPERATOR_CANCELLED;
3182 }
3183 
SEQUENCER_OT_swap(wmOperatorType * ot)3184 void SEQUENCER_OT_swap(wmOperatorType *ot)
3185 {
3186   /* Identifiers. */
3187   ot->name = "Swap Strip";
3188   ot->idname = "SEQUENCER_OT_swap";
3189   ot->description = "Swap active strip with strip to the right or left";
3190 
3191   /* Api callbacks. */
3192   ot->exec = sequencer_swap_exec;
3193   ot->poll = sequencer_edit_poll;
3194 
3195   /* Flags. */
3196   ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
3197 
3198   /* Properties. */
3199   RNA_def_enum(
3200       ot->srna, "side", prop_side_lr_types, SEQ_SIDE_RIGHT, "Side", "Side of the strip to swap");
3201 }
3202 
3203 /** \} */
3204 
3205 /* -------------------------------------------------------------------- */
3206 /** \name Set Render Size Operator
3207  * \{ */
3208 
sequencer_rendersize_exec(bContext * C,wmOperator * UNUSED (op))3209 static int sequencer_rendersize_exec(bContext *C, wmOperator *UNUSED(op))
3210 {
3211   int retval = OPERATOR_CANCELLED;
3212   Scene *scene = CTX_data_scene(C);
3213   Sequence *active_seq = BKE_sequencer_active_get(scene);
3214   StripElem *se = NULL;
3215 
3216   if (active_seq == NULL) {
3217     return OPERATOR_CANCELLED;
3218   }
3219 
3220   if (active_seq->strip) {
3221     switch (active_seq->type) {
3222       case SEQ_TYPE_IMAGE:
3223         se = BKE_sequencer_give_stripelem(active_seq, scene->r.cfra);
3224         break;
3225       case SEQ_TYPE_MOVIE:
3226         se = active_seq->strip->stripdata;
3227         break;
3228       case SEQ_TYPE_SCENE:
3229       case SEQ_TYPE_META:
3230       case SEQ_TYPE_SOUND_RAM:
3231       case SEQ_TYPE_SOUND_HD:
3232       default:
3233         break;
3234     }
3235   }
3236 
3237   if (se) {
3238     /* Prevent setting the render size if sequence values aren't initialized. */
3239     if ((se->orig_width > 0) && (se->orig_height > 0)) {
3240       scene->r.xsch = se->orig_width;
3241       scene->r.ysch = se->orig_height;
3242       WM_event_add_notifier(C, NC_SCENE | ND_RENDER_OPTIONS, scene);
3243       retval = OPERATOR_FINISHED;
3244     }
3245   }
3246 
3247   return retval;
3248 }
3249 
SEQUENCER_OT_rendersize(wmOperatorType * ot)3250 void SEQUENCER_OT_rendersize(wmOperatorType *ot)
3251 {
3252   /* Identifiers. */
3253   ot->name = "Set Render Size";
3254   ot->idname = "SEQUENCER_OT_rendersize";
3255   ot->description = "Set render size and aspect from active sequence";
3256 
3257   /* Api callbacks. */
3258   ot->exec = sequencer_rendersize_exec;
3259   ot->poll = sequencer_edit_poll;
3260 
3261   /* Flags. */
3262   ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
3263 }
3264 
3265 /** \} */
3266 
3267 /* -------------------------------------------------------------------- */
3268 /** \name Copy Operator
3269  * \{ */
3270 
seq_copy_del_sound(Scene * scene,Sequence * seq)3271 static void seq_copy_del_sound(Scene *scene, Sequence *seq)
3272 {
3273   if (seq->type == SEQ_TYPE_META) {
3274     Sequence *iseq;
3275     for (iseq = seq->seqbase.first; iseq; iseq = iseq->next) {
3276       seq_copy_del_sound(scene, iseq);
3277     }
3278   }
3279   else if (seq->scene_sound) {
3280     BKE_sound_remove_scene_sound(scene, seq->scene_sound);
3281     seq->scene_sound = NULL;
3282   }
3283 }
3284 
sequencer_copy_exec(bContext * C,wmOperator * op)3285 static int sequencer_copy_exec(bContext *C, wmOperator *op)
3286 {
3287   Main *bmain = CTX_data_main(C);
3288   Scene *scene = CTX_data_scene(C);
3289   Editing *ed = BKE_sequencer_editing_get(scene, false);
3290 
3291   BKE_sequencer_free_clipboard();
3292 
3293   if (BKE_sequence_base_isolated_sel_check(ed->seqbasep) == false) {
3294     BKE_report(op->reports, RPT_ERROR, "Please select all related strips");
3295     return OPERATOR_CANCELLED;
3296   }
3297 
3298   /* NOTE: The UUID is re-generated on paste, so we can keep UUID in the clipboard since
3299    * nobody can reach them anyway.
3300    * This reduces chance or running out of UUIDs if a cat falls asleep on Ctrl-C. */
3301   BKE_sequence_base_dupli_recursive(scene,
3302                                     scene,
3303                                     &seqbase_clipboard,
3304                                     ed->seqbasep,
3305                                     0,
3306                                     (LIB_ID_CREATE_NO_USER_REFCOUNT | LIB_ID_FREE_NO_MAIN));
3307 
3308   seqbase_clipboard_frame = scene->r.cfra;
3309 
3310   /* Remove anything that references the current scene. */
3311   LISTBASE_FOREACH (Sequence *, seq, &seqbase_clipboard) {
3312     seq_copy_del_sound(scene, seq);
3313   }
3314 
3315   /* Replace datablock pointers with copies, to keep things working in case
3316    * data-blocks get deleted or another .blend file is opened. */
3317   BKE_sequencer_base_clipboard_pointers_store(bmain, &seqbase_clipboard);
3318 
3319   return OPERATOR_FINISHED;
3320 }
3321 
SEQUENCER_OT_copy(wmOperatorType * ot)3322 void SEQUENCER_OT_copy(wmOperatorType *ot)
3323 {
3324   /* Identifiers. */
3325   ot->name = "Copy";
3326   ot->idname = "SEQUENCER_OT_copy";
3327   ot->description = "Copy selected strips to clipboard";
3328 
3329   /* Api callbacks. */
3330   ot->exec = sequencer_copy_exec;
3331   ot->poll = sequencer_edit_poll;
3332 
3333   /* Flags. */
3334   ot->flag = OPTYPE_REGISTER;
3335 }
3336 
3337 /** \} */
3338 
3339 /* -------------------------------------------------------------------- */
3340 /** \name Paste Operator
3341  * \{ */
3342 
sequencer_paste_exec(bContext * C,wmOperator * UNUSED (op))3343 static int sequencer_paste_exec(bContext *C, wmOperator *UNUSED(op))
3344 {
3345   Main *bmain = CTX_data_main(C);
3346   Scene *scene = CTX_data_scene(C);
3347   Editing *ed = BKE_sequencer_editing_get(scene, true); /* Create if needed. */
3348   ListBase nseqbase = {NULL, NULL};
3349   int ofs;
3350   Sequence *iseq, *iseq_first;
3351 
3352   ED_sequencer_deselect_all(scene);
3353   ofs = scene->r.cfra - seqbase_clipboard_frame;
3354 
3355   /* Copy strips, temporarily restoring pointers to actual data-blocks. This
3356    * must happen on the clipboard itself, so that copying does user counting
3357    * on the actual data-blocks. */
3358   BKE_sequencer_base_clipboard_pointers_restore(&seqbase_clipboard, bmain);
3359   BKE_sequence_base_dupli_recursive(scene, scene, &nseqbase, &seqbase_clipboard, 0, 0);
3360   BKE_sequencer_base_clipboard_pointers_store(bmain, &seqbase_clipboard);
3361 
3362   iseq_first = nseqbase.first;
3363 
3364   /* NOTE: BKE_sequence_base_dupli_recursive() takes care of generating new UUIDs for sequences
3365    * in the new list. */
3366   BLI_movelisttolist(ed->seqbasep, &nseqbase);
3367 
3368   for (iseq = iseq_first; iseq; iseq = iseq->next) {
3369     /* Make sure, that pasted strips have unique names. */
3370     BKE_sequencer_recursive_apply(iseq, apply_unique_name_fn, scene);
3371     /* Translate after name has been changed, otherwise this will affect animdata of original
3372      * strip. */
3373     BKE_sequence_translate(scene, iseq, ofs);
3374     /* Ensure, that pasted strips don't overlap. */
3375     if (BKE_sequence_test_overlap(ed->seqbasep, iseq)) {
3376       BKE_sequence_base_shuffle(ed->seqbasep, iseq, scene);
3377     }
3378   }
3379 
3380   DEG_id_tag_update(&scene->id, ID_RECALC_SEQUENCER_STRIPS);
3381   DEG_relations_tag_update(bmain);
3382   WM_event_add_notifier(C, NC_SCENE | ND_SEQUENCER, scene);
3383   ED_outliner_select_sync_from_sequence_tag(C);
3384 
3385   return OPERATOR_FINISHED;
3386 }
3387 
SEQUENCER_OT_paste(wmOperatorType * ot)3388 void SEQUENCER_OT_paste(wmOperatorType *ot)
3389 {
3390   /* Identifiers. */
3391   ot->name = "Paste";
3392   ot->idname = "SEQUENCER_OT_paste";
3393   ot->description = "Paste strips from clipboard";
3394 
3395   /* Api callbacks. */
3396   ot->exec = sequencer_paste_exec;
3397   ot->poll = ED_operator_sequencer_active;
3398 
3399   /* Flags. */
3400   ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
3401 }
3402 
3403 /** \} */
3404 
3405 /* -------------------------------------------------------------------- */
3406 /** \name Sequencer Swap Data Operator
3407  * \{ */
3408 
sequencer_swap_data_exec(bContext * C,wmOperator * op)3409 static int sequencer_swap_data_exec(bContext *C, wmOperator *op)
3410 {
3411   Scene *scene = CTX_data_scene(C);
3412   Sequence *seq_act;
3413   Sequence *seq_other;
3414   const char *error_msg;
3415 
3416   if (BKE_sequencer_active_get_pair(scene, &seq_act, &seq_other) == 0) {
3417     BKE_report(op->reports, RPT_ERROR, "Please select two strips");
3418     return OPERATOR_CANCELLED;
3419   }
3420 
3421   if (BKE_sequence_swap(seq_act, seq_other, &error_msg) == 0) {
3422     BKE_report(op->reports, RPT_ERROR, error_msg);
3423     return OPERATOR_CANCELLED;
3424   }
3425 
3426   if (seq_act->scene_sound) {
3427     BKE_sound_remove_scene_sound(scene, seq_act->scene_sound);
3428   }
3429 
3430   if (seq_other->scene_sound) {
3431     BKE_sound_remove_scene_sound(scene, seq_other->scene_sound);
3432   }
3433 
3434   seq_act->scene_sound = NULL;
3435   seq_other->scene_sound = NULL;
3436 
3437   BKE_sequence_calc(scene, seq_act);
3438   BKE_sequence_calc(scene, seq_other);
3439 
3440   if (seq_act->sound) {
3441     BKE_sound_add_scene_sound_defaults(scene, seq_act);
3442   }
3443   if (seq_other->sound) {
3444     BKE_sound_add_scene_sound_defaults(scene, seq_other);
3445   }
3446 
3447   BKE_sequence_invalidate_cache_raw(scene, seq_act);
3448   BKE_sequence_invalidate_cache_raw(scene, seq_other);
3449 
3450   WM_event_add_notifier(C, NC_SCENE | ND_SEQUENCER, scene);
3451 
3452   return OPERATOR_FINISHED;
3453 }
3454 
SEQUENCER_OT_swap_data(wmOperatorType * ot)3455 void SEQUENCER_OT_swap_data(wmOperatorType *ot)
3456 {
3457   /* Identifiers. */
3458   ot->name = "Sequencer Swap Data";
3459   ot->idname = "SEQUENCER_OT_swap_data";
3460   ot->description = "Swap 2 sequencer strips";
3461 
3462   /* Api callbacks. */
3463   ot->exec = sequencer_swap_data_exec;
3464   ot->poll = ED_operator_sequencer_active;
3465 
3466   /* Flags. */
3467   ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
3468 }
3469 
3470 /** \} */
3471 
3472 /* -------------------------------------------------------------------- */
3473 /** \name Rebuild Proxy and Timecode Indices Operator
3474  * \{ */
3475 
sequencer_rebuild_proxy_invoke(bContext * C,wmOperator * op,const wmEvent * UNUSED (event))3476 static int sequencer_rebuild_proxy_invoke(bContext *C,
3477                                           wmOperator *op,
3478                                           const wmEvent *UNUSED(event))
3479 {
3480   seq_proxy_build_job(C, op->reports);
3481 
3482   return OPERATOR_FINISHED;
3483 }
3484 
sequencer_rebuild_proxy_exec(bContext * C,wmOperator * UNUSED (op))3485 static int sequencer_rebuild_proxy_exec(bContext *C, wmOperator *UNUSED(op))
3486 {
3487   Main *bmain = CTX_data_main(C);
3488   struct Depsgraph *depsgraph = CTX_data_ensure_evaluated_depsgraph(C);
3489   Scene *scene = CTX_data_scene(C);
3490   Editing *ed = BKE_sequencer_editing_get(scene, false);
3491   Sequence *seq;
3492   GSet *file_list;
3493 
3494   if (ed == NULL) {
3495     return OPERATOR_CANCELLED;
3496   }
3497 
3498   file_list = BLI_gset_new(BLI_ghashutil_strhash_p, BLI_ghashutil_strcmp, "file list");
3499 
3500   SEQ_CURRENT_BEGIN (ed, seq) {
3501     if ((seq->flag & SELECT)) {
3502       ListBase queue = {NULL, NULL};
3503       LinkData *link;
3504       short stop = 0, do_update;
3505       float progress;
3506 
3507       BKE_sequencer_proxy_rebuild_context(bmain, depsgraph, scene, seq, file_list, &queue);
3508 
3509       for (link = queue.first; link; link = link->next) {
3510         struct SeqIndexBuildContext *context = link->data;
3511         BKE_sequencer_proxy_rebuild(context, &stop, &do_update, &progress);
3512         BKE_sequencer_proxy_rebuild_finish(context, 0);
3513       }
3514       BKE_sequencer_free_imbuf(scene, &ed->seqbase, false);
3515     }
3516   }
3517   SEQ_CURRENT_END;
3518 
3519   BLI_gset_free(file_list, MEM_freeN);
3520 
3521   return OPERATOR_FINISHED;
3522 }
3523 
SEQUENCER_OT_rebuild_proxy(wmOperatorType * ot)3524 void SEQUENCER_OT_rebuild_proxy(wmOperatorType *ot)
3525 {
3526   /* Identifiers. */
3527   ot->name = "Rebuild Proxy and Timecode Indices";
3528   ot->idname = "SEQUENCER_OT_rebuild_proxy";
3529   ot->description = "Rebuild all selected proxies and timecode indices using the job system";
3530 
3531   /* Api callbacks. */
3532   ot->invoke = sequencer_rebuild_proxy_invoke;
3533   ot->exec = sequencer_rebuild_proxy_exec;
3534 
3535   /* Flags. */
3536   ot->flag = OPTYPE_REGISTER;
3537 }
3538 
3539 /** \} */
3540 
3541 /* -------------------------------------------------------------------- */
3542 /** \name Set Selected Strip Proxies Operator
3543  * \{ */
3544 
sequencer_enable_proxies_invoke(bContext * C,wmOperator * op,const wmEvent * UNUSED (event))3545 static int sequencer_enable_proxies_invoke(bContext *C,
3546                                            wmOperator *op,
3547                                            const wmEvent *UNUSED(event))
3548 {
3549   return WM_operator_props_dialog_popup(C, op, 200);
3550 }
3551 
sequencer_enable_proxies_exec(bContext * C,wmOperator * op)3552 static int sequencer_enable_proxies_exec(bContext *C, wmOperator *op)
3553 {
3554   Scene *scene = CTX_data_scene(C);
3555   Editing *ed = BKE_sequencer_editing_get(scene, false);
3556   Sequence *seq;
3557   bool proxy_25 = RNA_boolean_get(op->ptr, "proxy_25");
3558   bool proxy_50 = RNA_boolean_get(op->ptr, "proxy_50");
3559   bool proxy_75 = RNA_boolean_get(op->ptr, "proxy_75");
3560   bool proxy_100 = RNA_boolean_get(op->ptr, "proxy_100");
3561   bool overwrite = RNA_boolean_get(op->ptr, "overwrite");
3562   bool turnon = true;
3563 
3564   if (ed == NULL || !(proxy_25 || proxy_50 || proxy_75 || proxy_100)) {
3565     turnon = false;
3566   }
3567 
3568   SEQ_CURRENT_BEGIN (ed, seq) {
3569     if ((seq->flag & SELECT)) {
3570       if (ELEM(seq->type, SEQ_TYPE_MOVIE, SEQ_TYPE_IMAGE, SEQ_TYPE_META)) {
3571         BKE_sequencer_proxy_set(seq, turnon);
3572         if (seq->strip->proxy == NULL) {
3573           continue;
3574         }
3575 
3576         if (proxy_25) {
3577           seq->strip->proxy->build_size_flags |= SEQ_PROXY_IMAGE_SIZE_25;
3578         }
3579         else {
3580           seq->strip->proxy->build_size_flags &= ~SEQ_PROXY_IMAGE_SIZE_25;
3581         }
3582 
3583         if (proxy_50) {
3584           seq->strip->proxy->build_size_flags |= SEQ_PROXY_IMAGE_SIZE_50;
3585         }
3586         else {
3587           seq->strip->proxy->build_size_flags &= ~SEQ_PROXY_IMAGE_SIZE_50;
3588         }
3589 
3590         if (proxy_75) {
3591           seq->strip->proxy->build_size_flags |= SEQ_PROXY_IMAGE_SIZE_75;
3592         }
3593         else {
3594           seq->strip->proxy->build_size_flags &= ~SEQ_PROXY_IMAGE_SIZE_75;
3595         }
3596 
3597         if (proxy_100) {
3598           seq->strip->proxy->build_size_flags |= SEQ_PROXY_IMAGE_SIZE_100;
3599         }
3600         else {
3601           seq->strip->proxy->build_size_flags &= ~SEQ_PROXY_IMAGE_SIZE_100;
3602         }
3603 
3604         if (!overwrite) {
3605           seq->strip->proxy->build_flags |= SEQ_PROXY_SKIP_EXISTING;
3606         }
3607         else {
3608           seq->strip->proxy->build_flags &= ~SEQ_PROXY_SKIP_EXISTING;
3609         }
3610       }
3611     }
3612   }
3613   SEQ_CURRENT_END;
3614 
3615   WM_event_add_notifier(C, NC_SCENE | ND_SEQUENCER, scene);
3616 
3617   return OPERATOR_FINISHED;
3618 }
3619 
SEQUENCER_OT_enable_proxies(wmOperatorType * ot)3620 void SEQUENCER_OT_enable_proxies(wmOperatorType *ot)
3621 {
3622   /* Identifiers. */
3623   ot->name = "Set Selected Strip Proxies";
3624   ot->idname = "SEQUENCER_OT_enable_proxies";
3625   ot->description = "Enable selected proxies on all selected Movie, Image and Meta strips";
3626 
3627   /* Api callbacks. */
3628   ot->invoke = sequencer_enable_proxies_invoke;
3629   ot->exec = sequencer_enable_proxies_exec;
3630 
3631   /* Flags. */
3632   ot->flag = OPTYPE_REGISTER;
3633 
3634   RNA_def_boolean(ot->srna, "proxy_25", false, "25%", "");
3635   RNA_def_boolean(ot->srna, "proxy_50", false, "50%", "");
3636   RNA_def_boolean(ot->srna, "proxy_75", false, "75%", "");
3637   RNA_def_boolean(ot->srna, "proxy_100", false, "100%", "");
3638   RNA_def_boolean(ot->srna, "overwrite", false, "Overwrite", "");
3639 }
3640 
3641 /** \} */
3642 
3643 /* -------------------------------------------------------------------- */
3644 /** \name Change Effect Input Operator
3645  * \{ */
3646 
3647 static const EnumPropertyItem prop_change_effect_input_types[] = {
3648     {0, "A_B", 0, "A -> B", ""},
3649     {1, "B_C", 0, "B -> C", ""},
3650     {2, "A_C", 0, "A -> C", ""},
3651     {0, NULL, 0, NULL, NULL},
3652 };
3653 
sequencer_change_effect_input_exec(bContext * C,wmOperator * op)3654 static int sequencer_change_effect_input_exec(bContext *C, wmOperator *op)
3655 {
3656   Scene *scene = CTX_data_scene(C);
3657   Editing *ed = BKE_sequencer_editing_get(scene, false);
3658   Sequence *seq = BKE_sequencer_active_get(scene);
3659 
3660   Sequence **seq_1, **seq_2;
3661 
3662   switch (RNA_enum_get(op->ptr, "swap")) {
3663     case 0:
3664       seq_1 = &seq->seq1;
3665       seq_2 = &seq->seq2;
3666       break;
3667     case 1:
3668       seq_1 = &seq->seq2;
3669       seq_2 = &seq->seq3;
3670       break;
3671     default: /* 2 */
3672       seq_1 = &seq->seq1;
3673       seq_2 = &seq->seq3;
3674       break;
3675   }
3676 
3677   if (*seq_1 == NULL || *seq_2 == NULL) {
3678     BKE_report(op->reports, RPT_ERROR, "One of the effect inputs is unset, cannot swap");
3679     return OPERATOR_CANCELLED;
3680   }
3681 
3682   SWAP(Sequence *, *seq_1, *seq_2);
3683 
3684   BKE_sequencer_update_changed_seq_and_deps(scene, seq, 0, 1);
3685 
3686   /* Invalidate cache. */
3687   BKE_sequencer_free_imbuf(scene, &ed->seqbase, false);
3688   WM_event_add_notifier(C, NC_SCENE | ND_SEQUENCER, scene);
3689 
3690   return OPERATOR_FINISHED;
3691 }
3692 
SEQUENCER_OT_change_effect_input(struct wmOperatorType * ot)3693 void SEQUENCER_OT_change_effect_input(struct wmOperatorType *ot)
3694 {
3695   /* Identifiers. */
3696   ot->name = "Change Effect Input";
3697   ot->idname = "SEQUENCER_OT_change_effect_input";
3698 
3699   /* Api callbacks. */
3700   ot->exec = sequencer_change_effect_input_exec;
3701   ot->poll = sequencer_effect_poll;
3702 
3703   /* Flags. */
3704   ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
3705 
3706   ot->prop = RNA_def_enum(
3707       ot->srna, "swap", prop_change_effect_input_types, 0, "Swap", "The effect inputs to swap");
3708 }
3709 
3710 /** \} */
3711 
3712 /* -------------------------------------------------------------------- */
3713 /** \name Change Effect Type Operator
3714  * \{ */
3715 
sequencer_change_effect_type_exec(bContext * C,wmOperator * op)3716 static int sequencer_change_effect_type_exec(bContext *C, wmOperator *op)
3717 {
3718   Scene *scene = CTX_data_scene(C);
3719   Editing *ed = BKE_sequencer_editing_get(scene, false);
3720   Sequence *seq = BKE_sequencer_active_get(scene);
3721   const int new_type = RNA_enum_get(op->ptr, "type");
3722 
3723   /* Free previous effect and init new effect. */
3724   struct SeqEffectHandle sh;
3725 
3726   if ((seq->type & SEQ_TYPE_EFFECT) == 0) {
3727     return OPERATOR_CANCELLED;
3728   }
3729 
3730   /* Can someone explain the logic behind only allowing to increase this,
3731    * copied from 2.4x - campbell */
3732   if (BKE_sequence_effect_get_num_inputs(seq->type) <
3733       BKE_sequence_effect_get_num_inputs(new_type)) {
3734     BKE_report(op->reports, RPT_ERROR, "New effect needs more input strips");
3735     return OPERATOR_CANCELLED;
3736   }
3737 
3738   sh = BKE_sequence_get_effect(seq);
3739   sh.free(seq, true);
3740 
3741   seq->type = new_type;
3742 
3743   sh = BKE_sequence_get_effect(seq);
3744   sh.init(seq);
3745 
3746   BKE_sequencer_update_changed_seq_and_deps(scene, seq, 0, 1);
3747   /* Invalidate cache. */
3748   BKE_sequencer_free_imbuf(scene, &ed->seqbase, false);
3749 
3750   WM_event_add_notifier(C, NC_SCENE | ND_SEQUENCER, scene);
3751 
3752   return OPERATOR_FINISHED;
3753 }
3754 
SEQUENCER_OT_change_effect_type(struct wmOperatorType * ot)3755 void SEQUENCER_OT_change_effect_type(struct wmOperatorType *ot)
3756 {
3757   /* Identifiers. */
3758   ot->name = "Change Effect Type";
3759   ot->idname = "SEQUENCER_OT_change_effect_type";
3760 
3761   /* Api callbacks. */
3762   ot->exec = sequencer_change_effect_type_exec;
3763   ot->poll = sequencer_effect_poll;
3764 
3765   /* Flags. */
3766   ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
3767 
3768   ot->prop = RNA_def_enum(ot->srna,
3769                           "type",
3770                           sequencer_prop_effect_types,
3771                           SEQ_TYPE_CROSS,
3772                           "Type",
3773                           "Sequencer effect type");
3774 }
3775 
3776 /** \} */
3777 
3778 /* -------------------------------------------------------------------- */
3779 /** \name Change Data/Files Operator
3780  * \{ */
3781 
sequencer_change_path_exec(bContext * C,wmOperator * op)3782 static int sequencer_change_path_exec(bContext *C, wmOperator *op)
3783 {
3784   Main *bmain = CTX_data_main(C);
3785   Scene *scene = CTX_data_scene(C);
3786   Editing *ed = BKE_sequencer_editing_get(scene, false);
3787   Sequence *seq = BKE_sequencer_active_get(scene);
3788   const bool is_relative_path = RNA_boolean_get(op->ptr, "relative_path");
3789   const bool use_placeholders = RNA_boolean_get(op->ptr, "use_placeholders");
3790   int minframe, numdigits;
3791 
3792   if (seq->type == SEQ_TYPE_IMAGE) {
3793     char directory[FILE_MAX];
3794     int len;
3795     StripElem *se;
3796 
3797     /* Need to find min/max frame for placeholders. */
3798     if (use_placeholders) {
3799       len = sequencer_image_seq_get_minmax_frame(op, seq->sfra, &minframe, &numdigits);
3800     }
3801     else {
3802       len = RNA_property_collection_length(op->ptr, RNA_struct_find_property(op->ptr, "files"));
3803     }
3804     if (len == 0) {
3805       return OPERATOR_CANCELLED;
3806     }
3807 
3808     RNA_string_get(op->ptr, "directory", directory);
3809     if (is_relative_path) {
3810       /* TODO, shouldn't this already be relative from the filesel?
3811        * (as the 'filepath' is) for now just make relative here,
3812        * but look into changing after 2.60 - campbell */
3813       BLI_path_rel(directory, BKE_main_blendfile_path(bmain));
3814     }
3815     BLI_strncpy(seq->strip->dir, directory, sizeof(seq->strip->dir));
3816 
3817     if (seq->strip->stripdata) {
3818       MEM_freeN(seq->strip->stripdata);
3819     }
3820     seq->strip->stripdata = se = MEM_callocN(len * sizeof(StripElem), "stripelem");
3821 
3822     if (use_placeholders) {
3823       sequencer_image_seq_reserve_frames(op, se, len, minframe, numdigits);
3824     }
3825     else {
3826       RNA_BEGIN (op->ptr, itemptr, "files") {
3827         char *filename = RNA_string_get_alloc(&itemptr, "name", NULL, 0);
3828         BLI_strncpy(se->name, filename, sizeof(se->name));
3829         MEM_freeN(filename);
3830         se++;
3831       }
3832       RNA_END;
3833     }
3834 
3835     /* Reset these else we wont see all the images. */
3836     seq->anim_startofs = seq->anim_endofs = 0;
3837 
3838     /* Correct start/end frames so we don't move.
3839      * Important not to set seq->len = len; allow the function to handle it. */
3840     BKE_sequence_reload_new_file(bmain, scene, seq, true);
3841 
3842     BKE_sequence_calc(scene, seq);
3843 
3844     /* Invalidate cache. */
3845     BKE_sequencer_free_imbuf(scene, &ed->seqbase, false);
3846   }
3847   else if (ELEM(seq->type, SEQ_TYPE_SOUND_RAM, SEQ_TYPE_SOUND_HD)) {
3848     bSound *sound = seq->sound;
3849     if (sound == NULL) {
3850       return OPERATOR_CANCELLED;
3851     }
3852     char filepath[FILE_MAX];
3853     RNA_string_get(op->ptr, "filepath", filepath);
3854     BLI_strncpy(sound->filepath, filepath, sizeof(sound->filepath));
3855     BKE_sound_load(bmain, sound);
3856   }
3857   else {
3858     /* Lame, set rna filepath. */
3859     PointerRNA seq_ptr;
3860     PropertyRNA *prop;
3861     char filepath[FILE_MAX];
3862 
3863     RNA_pointer_create(&scene->id, &RNA_Sequence, seq, &seq_ptr);
3864 
3865     RNA_string_get(op->ptr, "filepath", filepath);
3866     prop = RNA_struct_find_property(&seq_ptr, "filepath");
3867     RNA_property_string_set(&seq_ptr, prop, filepath);
3868     RNA_property_update(C, &seq_ptr, prop);
3869   }
3870 
3871   WM_event_add_notifier(C, NC_SCENE | ND_SEQUENCER, scene);
3872 
3873   return OPERATOR_FINISHED;
3874 }
3875 
sequencer_change_path_invoke(bContext * C,wmOperator * op,const wmEvent * UNUSED (event))3876 static int sequencer_change_path_invoke(bContext *C, wmOperator *op, const wmEvent *UNUSED(event))
3877 {
3878   Scene *scene = CTX_data_scene(C);
3879   Sequence *seq = BKE_sequencer_active_get(scene);
3880   char filepath[FILE_MAX];
3881 
3882   BLI_join_dirfile(filepath, sizeof(filepath), seq->strip->dir, seq->strip->stripdata->name);
3883 
3884   RNA_string_set(op->ptr, "directory", seq->strip->dir);
3885   RNA_string_set(op->ptr, "filepath", filepath);
3886 
3887   /* Set default display depending on seq type. */
3888   if (seq->type == SEQ_TYPE_IMAGE) {
3889     RNA_boolean_set(op->ptr, "filter_movie", false);
3890   }
3891   else {
3892     RNA_boolean_set(op->ptr, "filter_image", false);
3893   }
3894 
3895   WM_event_add_fileselect(C, op);
3896 
3897   return OPERATOR_RUNNING_MODAL;
3898 }
3899 
SEQUENCER_OT_change_path(struct wmOperatorType * ot)3900 void SEQUENCER_OT_change_path(struct wmOperatorType *ot)
3901 {
3902   /* Identifiers. */
3903   ot->name = "Change Data/Files";
3904   ot->idname = "SEQUENCER_OT_change_path";
3905 
3906   /* Api callbacks. */
3907   ot->exec = sequencer_change_path_exec;
3908   ot->invoke = sequencer_change_path_invoke;
3909   ot->poll = sequencer_strip_has_path_poll;
3910 
3911   /* Flags. */
3912   ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
3913 
3914   WM_operator_properties_filesel(ot,
3915                                  FILE_TYPE_FOLDER,
3916                                  FILE_SPECIAL,
3917                                  FILE_OPENFILE,
3918                                  WM_FILESEL_DIRECTORY | WM_FILESEL_RELPATH | WM_FILESEL_FILEPATH |
3919                                      WM_FILESEL_FILES,
3920                                  FILE_DEFAULTDISPLAY,
3921                                  FILE_SORT_ALPHA);
3922   RNA_def_boolean(ot->srna,
3923                   "use_placeholders",
3924                   false,
3925                   "Use Placeholders",
3926                   "Use placeholders for missing frames of the strip");
3927 }
3928 
3929 /** \} */
3930 
3931 /* -------------------------------------------------------------------- */
3932 /** \name Export Subtitles Operator
3933  * \{ */
3934 
sequencer_export_subtitles_invoke(bContext * C,wmOperator * op,const wmEvent * UNUSED (event))3935 static int sequencer_export_subtitles_invoke(bContext *C,
3936                                              wmOperator *op,
3937                                              const wmEvent *UNUSED(event))
3938 {
3939   Main *bmain = CTX_data_main(C);
3940   if (!RNA_struct_property_is_set(op->ptr, "filepath")) {
3941     char filepath[FILE_MAX];
3942 
3943     if (BKE_main_blendfile_path(bmain)[0] == '\0') {
3944       BLI_strncpy(filepath, "untitled", sizeof(filepath));
3945     }
3946     else {
3947       BLI_strncpy(filepath, BKE_main_blendfile_path(bmain), sizeof(filepath));
3948     }
3949 
3950     BLI_path_extension_replace(filepath, sizeof(filepath), ".srt");
3951     RNA_string_set(op->ptr, "filepath", filepath);
3952   }
3953 
3954   WM_event_add_fileselect(C, op);
3955 
3956   return OPERATOR_RUNNING_MODAL;
3957 }
3958 
sequencer_export_subtitles_exec(bContext * C,wmOperator * op)3959 static int sequencer_export_subtitles_exec(bContext *C, wmOperator *op)
3960 {
3961   Scene *scene = CTX_data_scene(C);
3962   Sequence *seq, *seq_next;
3963   Editing *ed = BKE_sequencer_editing_get(scene, false);
3964   ListBase text_seq = {0};
3965   int iter = 0;
3966   FILE *file;
3967   char filepath[FILE_MAX];
3968 
3969   if (!RNA_struct_property_is_set(op->ptr, "filepath")) {
3970     BKE_report(op->reports, RPT_ERROR, "No filename given");
3971     return OPERATOR_CANCELLED;
3972   }
3973 
3974   RNA_string_get(op->ptr, "filepath", filepath);
3975   BLI_path_extension_ensure(filepath, sizeof(filepath), ".srt");
3976 
3977   /* Avoid File write exceptions. */
3978   if (!BLI_exists(filepath)) {
3979     BLI_make_existing_file(filepath);
3980     if (!BLI_file_touch(filepath)) {
3981       BKE_report(op->reports, RPT_ERROR, "Can't create subtitle file");
3982       return OPERATOR_CANCELLED;
3983     }
3984   }
3985   else if (!BLI_file_is_writable(filepath)) {
3986     BKE_report(op->reports, RPT_ERROR, "Can't overwrite export file");
3987     return OPERATOR_CANCELLED;
3988   }
3989 
3990   SEQ_ALL_BEGIN (ed, seq) {
3991     if (seq->type == SEQ_TYPE_TEXT) {
3992       BLI_addtail(&text_seq, MEM_dupallocN(seq));
3993     }
3994   }
3995   SEQ_ALL_END;
3996 
3997   if (BLI_listbase_is_empty(&text_seq)) {
3998     BKE_report(op->reports, RPT_ERROR, "No subtitles (text strips) to export");
3999     return OPERATOR_CANCELLED;
4000   }
4001 
4002   BLI_listbase_sort(&text_seq, BKE_sequencer_cmp_time_startdisp);
4003 
4004   /* Open and write file. */
4005   file = BLI_fopen(filepath, "w");
4006 
4007   for (seq = text_seq.first; seq; seq = seq_next) {
4008     TextVars *data = seq->effectdata;
4009     char timecode_str_start[32];
4010     char timecode_str_end[32];
4011 
4012     BLI_timecode_string_from_time(timecode_str_start,
4013                                   sizeof(timecode_str_start),
4014                                   -2,
4015                                   FRA2TIME(seq->startdisp),
4016                                   FPS,
4017                                   USER_TIMECODE_SUBRIP);
4018     BLI_timecode_string_from_time(timecode_str_end,
4019                                   sizeof(timecode_str_end),
4020                                   -2,
4021                                   FRA2TIME(seq->enddisp),
4022                                   FPS,
4023                                   USER_TIMECODE_SUBRIP);
4024 
4025     fprintf(
4026         file, "%d\n%s --> %s\n%s\n\n", iter++, timecode_str_start, timecode_str_end, data->text);
4027 
4028     seq_next = seq->next;
4029     MEM_freeN(seq);
4030   }
4031 
4032   fclose(file);
4033 
4034   return OPERATOR_FINISHED;
4035 }
4036 
sequencer_strip_is_text_poll(bContext * C)4037 static bool sequencer_strip_is_text_poll(bContext *C)
4038 {
4039   Editing *ed;
4040   Sequence *seq;
4041   return (((ed = BKE_sequencer_editing_get(CTX_data_scene(C), false)) != NULL) &&
4042           ((seq = ed->act_seq) != NULL) && (seq->type == SEQ_TYPE_TEXT));
4043 }
4044 
SEQUENCER_OT_export_subtitles(struct wmOperatorType * ot)4045 void SEQUENCER_OT_export_subtitles(struct wmOperatorType *ot)
4046 {
4047   /* Identifiers. */
4048   ot->name = "Export Subtitles";
4049   ot->idname = "SEQUENCER_OT_export_subtitles";
4050   ot->description = "Export .srt file containing text strips";
4051 
4052   /* Api callbacks. */
4053   ot->exec = sequencer_export_subtitles_exec;
4054   ot->invoke = sequencer_export_subtitles_invoke;
4055   ot->poll = sequencer_strip_is_text_poll;
4056 
4057   /* Flags. */
4058   ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
4059 
4060   WM_operator_properties_filesel(ot,
4061                                  FILE_TYPE_FOLDER,
4062                                  FILE_BLENDER,
4063                                  FILE_SAVE,
4064                                  WM_FILESEL_FILEPATH,
4065                                  FILE_DEFAULTDISPLAY,
4066                                  FILE_SORT_ALPHA);
4067 }
4068 
4069 /** \} */
4070 
4071 /* -------------------------------------------------------------------- */
4072 /** \name Set Range to Strips Operator
4073  * \{ */
4074 
sequencer_set_range_to_strips_exec(bContext * C,wmOperator * op)4075 static int sequencer_set_range_to_strips_exec(bContext *C, wmOperator *op)
4076 {
4077   Scene *scene = CTX_data_scene(C);
4078   Editing *ed = BKE_sequencer_editing_get(scene, false);
4079   Sequence *seq;
4080 
4081   int sfra = MAXFRAME;
4082   int efra = -MAXFRAME;
4083   bool selected = false;
4084   const bool preview = RNA_boolean_get(op->ptr, "preview");
4085 
4086   for (seq = ed->seqbasep->first; seq; seq = seq->next) {
4087     if (seq->flag & SELECT) {
4088       selected = true;
4089       sfra = min_ii(sfra, seq->startdisp);
4090       efra = max_ii(efra, seq->enddisp - 1);
4091     }
4092   }
4093 
4094   if (!selected) {
4095     BKE_report(op->reports, RPT_WARNING, "Select one or more strips");
4096     return OPERATOR_CANCELLED;
4097   }
4098   if (efra < 0) {
4099     BKE_report(op->reports, RPT_ERROR, "Can't set a negative range");
4100     return OPERATOR_CANCELLED;
4101   }
4102 
4103   if (preview) {
4104     scene->r.flag |= SCER_PRV_RANGE;
4105     scene->r.psfra = max_ii(0, sfra);
4106     scene->r.pefra = efra;
4107   }
4108   else {
4109     scene->r.flag &= ~SCER_PRV_RANGE;
4110     scene->r.sfra = max_ii(0, sfra);
4111     scene->r.efra = efra;
4112   }
4113 
4114   WM_event_add_notifier(C, NC_SCENE | ND_FRAME, scene);
4115 
4116   return OPERATOR_FINISHED;
4117 }
4118 
SEQUENCER_OT_set_range_to_strips(struct wmOperatorType * ot)4119 void SEQUENCER_OT_set_range_to_strips(struct wmOperatorType *ot)
4120 {
4121   PropertyRNA *prop;
4122 
4123   /* Identifiers. */
4124   ot->name = "Set Range to Strips";
4125   ot->idname = "SEQUENCER_OT_set_range_to_strips";
4126   ot->description = "Set the frame range to the selected strips start and end";
4127 
4128   /* Api callbacks. */
4129   ot->exec = sequencer_set_range_to_strips_exec;
4130   ot->poll = sequencer_edit_poll;
4131 
4132   /* Flags. */
4133   ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
4134 
4135   prop = RNA_def_boolean(ot->srna, "preview", false, "Preview", "Set the preview range instead");
4136   RNA_def_property_flag(prop, PROP_SKIP_SAVE | PROP_HIDDEN);
4137 }
4138 
4139 /** \} */
4140