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