Blender V4.3
sequencer_add.cc
Go to the documentation of this file.
1/* SPDX-FileCopyrightText: 2001-2002 NaN Holding BV. All rights reserved.
2 *
3 * SPDX-License-Identifier: GPL-2.0-or-later */
4
9#include <cctype>
10#include <cmath>
11#include <cstdlib>
12#include <cstring>
13
14#include "MEM_guardedalloc.h"
15
16#include "BLI_blenlib.h"
17#include "BLI_utildefines.h"
18
19#include "BLT_translation.hh"
20
21#include "DNA_scene_types.h"
22#include "DNA_space_types.h"
23
24#include "BKE_context.hh"
25#include "BKE_global.hh"
26#include "BKE_main.hh"
27#include "BKE_report.hh"
28#include "BKE_scene.hh"
29
30#include "IMB_imbuf.hh"
31
32#include "WM_api.hh"
33#include "WM_types.hh"
34
35#include "RNA_define.hh"
36#include "RNA_enum_types.hh"
37#include "RNA_prototypes.hh"
38
39#include "SEQ_add.hh"
40#include "SEQ_connect.hh"
41#include "SEQ_effects.hh"
42#include "SEQ_proxy.hh"
43#include "SEQ_select.hh"
44#include "SEQ_sequencer.hh"
45#include "SEQ_time.hh"
46#include "SEQ_transform.hh"
47
48#include "ED_scene.hh"
49/* For menu, popup, icons, etc. */
50#include "ED_screen.hh"
51#include "ED_sequencer.hh"
52
53#include "UI_interface.hh"
54#include "UI_view2d.hh"
55
56#ifdef WITH_AUDASPACE
57# include <AUD_Sequence.h>
58#endif
59
60#include "DEG_depsgraph.hh"
62
63/* Own include. */
64#include "sequencer_intern.hh"
65
69
70/* Generic functions, reused by add strip operators. */
71
72/* Avoid passing multiple args and be more verbose. */
73#define SEQPROP_STARTFRAME (1 << 0)
74#define SEQPROP_ENDFRAME (1 << 1)
75#define SEQPROP_NOPATHS (1 << 2)
76#define SEQPROP_NOCHAN (1 << 3)
77#define SEQPROP_FIT_METHOD (1 << 4)
78#define SEQPROP_VIEW_TRANSFORM (1 << 5)
79#define SEQPROP_PLAYBACK_RATE (1 << 6)
80
82 {SEQ_SCALE_TO_FIT, "FIT", 0, "Scale to Fit", "Scale image to fit within the canvas"},
83 {SEQ_SCALE_TO_FILL, "FILL", 0, "Scale to Fill", "Scale image to completely fill the canvas"},
84 {SEQ_STRETCH_TO_FILL, "STRETCH", 0, "Stretch to Fill", "Stretch image to fill the canvas"},
85 {SEQ_USE_ORIGINAL_SIZE, "ORIGINAL", 0, "Use Original Size", "Keep image at its original size"},
86 {0, nullptr, 0, nullptr, nullptr},
87};
88
90{
91 PropertyRNA *prop;
92
95 "frame_start",
96 0,
97 INT_MIN,
98 INT_MAX,
99 "Start Frame",
100 "Start frame of the sequence strip",
101 -MAXFRAME,
102 MAXFRAME);
103 }
104
105 if (flag & SEQPROP_ENDFRAME) {
106 /* Not usual since most strips have a fixed length. */
108 "frame_end",
109 0,
110 INT_MIN,
111 INT_MAX,
112 "End Frame",
113 "End frame for the color strip",
114 -MAXFRAME,
115 MAXFRAME);
116 }
117
119 "channel",
120 1,
121 1,
123 "Channel",
124 "Channel to place this strip into",
125 1,
127
129 ot->srna, "replace_sel", true, "Replace Selection", "Deselect previously selected strips");
130
131 /* Only for python scripts which import strips and place them after. */
132 prop = RNA_def_boolean(
133 ot->srna, "overlap", false, "Allow Overlap", "Don't correct overlap on new sequence strips");
135
136 prop = RNA_def_boolean(
137 ot->srna,
138 "overlap_shuffle_override",
139 false,
140 "Override Overlap Shuffle Behavior",
141 "Use the overlap_mode tool settings to determine how to shuffle overlapping strips");
143
144 if (flag & SEQPROP_FIT_METHOD) {
146 "fit_method",
149 "Fit Method",
150 "Scale fit method");
151 }
152
155 "set_view_transform",
156 true,
157 "Set View Transform",
158 "Set appropriate view transform based on media color space");
159 }
160
163 "adjust_playback_rate",
164 true,
165 "Adjust Playback Rate",
166 "Play at normal speed regardless of scene FPS");
167 }
168}
169
171 wmOperator *op,
172 const char *identifier)
173{
174 if (RNA_struct_find_property(op->ptr, identifier)) {
175 Scene *scene = CTX_data_scene(C);
176 Sequence *last_seq = SEQ_select_active_get(scene);
177 if (last_seq && last_seq->strip && SEQ_HAS_PATH(last_seq)) {
178 Main *bmain = CTX_data_main(C);
179 char dirpath[FILE_MAX];
180 STRNCPY(dirpath, last_seq->strip->dirpath);
181 BLI_path_abs(dirpath, BKE_main_blendfile_path(bmain));
182 RNA_string_set(op->ptr, identifier, dirpath);
183 }
184 }
185}
186
188{
189 Sequence *tgt = nullptr;
190 Scene *scene = CTX_data_scene(C);
191 Editing *ed = SEQ_editing_ensure(scene);
192 int timeline_frame = int(scene->r.cfra);
193 int proximity = INT_MAX;
194
195 if (!ed || !ed->seqbasep) {
196 return 1;
197 }
198
199 LISTBASE_FOREACH (Sequence *, seq, ed->seqbasep) {
200 const int strip_end = SEQ_time_right_handle_frame_get(scene, seq);
201 if (ELEM(type, -1, seq->type) && (strip_end <= timeline_frame) &&
202 (timeline_frame - strip_end < proximity))
203 {
204 tgt = seq;
205 proximity = timeline_frame - strip_end;
206 }
207 }
208
209 if (tgt) {
210 return (type == SEQ_TYPE_MOVIE) ? tgt->machine - 1 : tgt->machine;
211 }
212 return 1;
213}
214
215/* Sets `channel` and `frame_start` properties when the operator is likely to have been invoked
216 * with drag-and-drop data. */
218 wmOperator *op,
219 const wmEvent *event)
220{
222 !RNA_collection_is_empty(op->ptr, "files")) ||
223 RNA_struct_property_is_set(op->ptr, "filepath"));
224
225 if (RNA_struct_property_is_set(op->ptr, "channel") ||
226 RNA_struct_property_is_set(op->ptr, "frame_start"))
227 {
228 return;
229 }
230
231 ARegion *region = CTX_wm_region(C);
232 if (!region || region->regiontype != RGN_TYPE_WINDOW) {
233 return;
234 }
235
236 float frame_start, channel;
237 UI_view2d_region_to_view(&region->v2d, event->mval[0], event->mval[1], &frame_start, &channel);
238 RNA_int_set(op->ptr, "channel", int(channel));
239 RNA_int_set(op->ptr, "frame_start", int(frame_start));
240}
241
243 bContext *C, wmOperator *op, int flag, int type, const wmEvent *event = nullptr)
244{
245 Scene *scene = CTX_data_scene(C);
246
247 int timeline_frame = int(scene->r.cfra);
248 if ((flag & SEQPROP_NOPATHS) && event) {
250 }
251
252 /* Effect strips don't need a channel initialized from the mouse. */
253 if (!(flag & SEQPROP_NOCHAN) && RNA_struct_property_is_set(op->ptr, "channel") == 0) {
255 }
256
257 if (!RNA_struct_property_is_set(op->ptr, "frame_start")) {
258 RNA_int_set(op->ptr, "frame_start", timeline_frame);
259 }
260
261 if ((flag & SEQPROP_ENDFRAME) && RNA_struct_property_is_set(op->ptr, "frame_end") == 0) {
263 op->ptr, "frame_end", RNA_int_get(op->ptr, "frame_start") + DEFAULT_IMG_STRIP_LENGTH);
264 }
265
266 if (!(flag & SEQPROP_NOPATHS)) {
268 sequencer_generic_invoke_path__internal(C, op, "directory");
269 }
270}
271
273{
274 Main *bmain = CTX_data_main(C);
275
276 PropertyRNA *prop;
277 const bool relative = (prop = RNA_struct_find_property(op->ptr, "relative_path")) &&
278 RNA_property_boolean_get(op->ptr, prop);
279 memset(load_data, 0, sizeof(SeqLoadData));
280
281 load_data->start_frame = RNA_int_get(op->ptr, "frame_start");
282 load_data->channel = RNA_int_get(op->ptr, "channel");
283 load_data->image.end_frame = load_data->start_frame;
284 load_data->image.len = 1;
285
286 if ((prop = RNA_struct_find_property(op->ptr, "fit_method"))) {
287 load_data->fit_method = eSeqImageFitMethod(RNA_enum_get(op->ptr, "fit_method"));
289 }
290
291 if ((prop = RNA_struct_find_property(op->ptr, "adjust_playback_rate"))) {
292 load_data->adjust_playback_rate = RNA_boolean_get(op->ptr, "adjust_playback_rate");
293 }
294
295 if ((prop = RNA_struct_find_property(op->ptr, "filepath"))) {
296 RNA_property_string_get(op->ptr, prop, load_data->path);
297 STRNCPY(load_data->name, BLI_path_basename(load_data->path));
298 }
299 else if ((prop = RNA_struct_find_property(op->ptr, "directory"))) {
300 char *directory = RNA_string_get_alloc(op->ptr, "directory", nullptr, 0, nullptr);
301
302 if ((prop = RNA_struct_find_property(op->ptr, "files"))) {
303 RNA_PROP_BEGIN (op->ptr, itemptr, prop) {
304 char *filename = RNA_string_get_alloc(&itemptr, "name", nullptr, 0, nullptr);
305 STRNCPY(load_data->name, filename);
306 BLI_path_join(load_data->path, sizeof(load_data->path), directory, filename);
307 MEM_freeN(filename);
308 break;
309 }
311 }
312 MEM_freeN(directory);
313 }
314
315 if (relative) {
316 BLI_path_rel(load_data->path, BKE_main_blendfile_path(bmain));
317 }
318
319 if ((prop = RNA_struct_find_property(op->ptr, "frame_end"))) {
320 load_data->image.end_frame = RNA_property_int_get(op->ptr, prop);
321 load_data->effect.end_frame = load_data->image.end_frame;
322 }
323
324 if ((prop = RNA_struct_find_property(op->ptr, "cache")) &&
325 RNA_property_boolean_get(op->ptr, prop))
326 {
327 load_data->flags |= SEQ_LOAD_SOUND_CACHE;
328 }
329
330 if ((prop = RNA_struct_find_property(op->ptr, "mono")) &&
331 RNA_property_boolean_get(op->ptr, prop))
332 {
333 load_data->flags |= SEQ_LOAD_SOUND_MONO;
334 }
335
336 if ((prop = RNA_struct_find_property(op->ptr, "use_framerate")) &&
337 RNA_property_boolean_get(op->ptr, prop))
338 {
339 load_data->flags |= SEQ_LOAD_MOVIE_SYNC_FPS;
340 }
341
342 if ((prop = RNA_struct_find_property(op->ptr, "set_view_transform")) &&
343 RNA_property_boolean_get(op->ptr, prop))
344 {
346 }
347
348 if ((prop = RNA_struct_find_property(op->ptr, "use_multiview")) &&
349 RNA_property_boolean_get(op->ptr, prop))
350 {
351 if (op->customdata) {
352 SequencerAddData *sad = static_cast<SequencerAddData *>(op->customdata);
353 ImageFormatData *imf = static_cast<ImageFormatData *>(&sad->im_format);
354
355 load_data->use_multiview = true;
356 load_data->views_format = imf->views_format;
357 load_data->stereo3d_format = &imf->stereo3d_format;
358 }
359 }
360}
361
363{
364 Scene *scene = CTX_data_scene(C);
365 Editing *ed = SEQ_editing_get(scene);
366
367 if (seq == nullptr) {
368 return;
369 }
370
371 if (RNA_boolean_get(op->ptr, "replace_sel")) {
372 seq->flag |= SELECT;
373 SEQ_select_active_set(scene, seq);
374 }
375
376 if (RNA_boolean_get(op->ptr, "overlap") == true ||
377 !SEQ_transform_test_overlap(scene, ed->seqbasep, seq))
378 {
379 /* No overlap should be handled or the strip is not overlapping, exit early. */
380 return;
381 }
382
383 if (RNA_boolean_get(op->ptr, "overlap_shuffle_override")) {
384 /* Use set overlap_mode to fix overlaps. */
386 strip_col.add(seq);
387
388 ScrArea *area = CTX_wm_area(C);
389 const bool use_sync_markers = (((SpaceSeq *)area->spacedata.first)->flag & SEQ_MARKER_TRANS) !=
390 0;
391 SEQ_transform_handle_overlap(scene, ed->seqbasep, strip_col, use_sync_markers);
392 }
393 else {
394 /* Shuffle strip channel to fix overlaps. */
396 }
397}
398
399/* In this alternative version we only check for overlap, but do not do anything about them. */
401 wmOperator *op,
402 Sequence *seq)
403{
404 Scene *scene = CTX_data_scene(C);
405 Editing *ed = SEQ_editing_get(scene);
406
407 if (seq == nullptr) {
408 return false;
409 }
410
411 if (RNA_boolean_get(op->ptr, "replace_sel")) {
412 seq->flag |= SELECT;
413 SEQ_select_active_set(scene, seq);
414 }
415
416 return SEQ_transform_test_overlap(scene, ed->seqbasep, seq);
417}
418
419static bool seq_effect_add_properties_poll(const bContext * /*C*/,
420 wmOperator *op,
421 const PropertyRNA *prop)
422{
423 const char *prop_id = RNA_property_identifier(prop);
424 int type = RNA_enum_get(op->ptr, "type");
425
426 /* Hide start/end frames for effect strips that are locked to their parents' location. */
427 if (SEQ_effect_get_num_inputs(type) != 0) {
428 if (STR_ELEM(prop_id, "frame_start", "frame_end")) {
429 return false;
430 }
431 }
432 if ((type != SEQ_TYPE_COLOR) && STREQ(prop_id, "color")) {
433 return false;
434 }
435
436 return true;
437}
438
440{
441 Main *bmain = CTX_data_main(C);
442 Scene *scene = CTX_data_scene(C);
443 const Editing *ed = SEQ_editing_ensure(scene);
444 Scene *sce_seq = static_cast<Scene *>(
445 BLI_findlink(&bmain->scenes, RNA_enum_get(op->ptr, "scene")));
446
447 if (sce_seq == nullptr) {
448 BKE_report(op->reports, RPT_ERROR, "Scene not found");
449 return OPERATOR_CANCELLED;
450 }
451
452 if (RNA_boolean_get(op->ptr, "replace_sel")) {
454 }
455
456 SeqLoadData load_data;
457 load_data_init_from_operator(&load_data, C, op);
458 load_data.scene = sce_seq;
459
460 Sequence *seq = SEQ_add_scene_strip(scene, ed->seqbasep, &load_data);
462
466
467 return OPERATOR_FINISHED;
468}
469
471{
473 /* Disable following properties if there are any existing strips, unless overridden by user. */
474 if (ed && ed->seqbasep && ed->seqbasep->first) {
475 if (RNA_struct_find_property(op->ptr, "use_framerate")) {
476 RNA_boolean_set(op->ptr, "use_framerate", false);
477 }
478 if (RNA_struct_find_property(op->ptr, "set_view_transform")) {
479 RNA_boolean_set(op->ptr, "set_view_transform", false);
480 }
481 }
482}
483
485{
487 if (!RNA_struct_property_is_set(op->ptr, "scene")) {
488 return WM_enum_search_invoke(C, op, event);
489 }
490
492 return sequencer_add_scene_strip_exec(C, op);
493}
494
496{
497 PropertyRNA *prop;
498
499 /* Identifiers. */
500 ot->name = "Add Scene Strip";
501 ot->idname = "SEQUENCER_OT_scene_strip_add";
502 ot->description = "Add a strip to the sequencer using a Blender scene as a source";
503
504 /* Api callbacks. */
508
509 /* Flags. */
511
513 prop = RNA_def_enum(ot->srna, "scene", rna_enum_dummy_NULL_items, 0, "Scene", "");
516 ot->prop = prop;
517}
518
520 {SCE_COPY_NEW, "NEW", 0, "New", "Add new Strip with a new empty Scene with default settings"},
522 "EMPTY",
523 0,
524 "Copy Settings",
525 "Add a new Strip, with an empty scene, and copy settings from the current scene"},
527 "LINK_COPY",
528 0,
529 "Linked Copy",
530 "Add a Strip and link in the collections from the current scene (shallow copy)"},
532 "FULL_COPY",
533 0,
534 "Full Copy",
535 "Add a Strip and make a full copy of the current scene"},
536 {0, nullptr, 0, nullptr, nullptr},
537};
538
540{
541 Main *bmain = CTX_data_main(C);
542 Scene *scene = CTX_data_scene(C);
543 const Editing *ed = SEQ_editing_ensure(scene);
544
545 if (RNA_boolean_get(op->ptr, "replace_sel")) {
547 }
548
549 SeqLoadData load_data;
550 load_data_init_from_operator(&load_data, C, op);
551
552 int type = RNA_enum_get(op->ptr, "type");
553 Scene *scene_new = ED_scene_sequencer_add(bmain, C, eSceneCopyMethod(type), false);
554 if (scene_new == nullptr) {
555 return OPERATOR_CANCELLED;
556 }
557 load_data.scene = scene_new;
558
559 Sequence *seq = SEQ_add_scene_strip(scene, ed->seqbasep, &load_data);
561
565
566 return OPERATOR_FINISHED;
567}
568
577
579 PointerRNA * /*ptr*/,
580 PropertyRNA * /*prop*/,
581 bool *r_free)
582{
583 EnumPropertyItem *item = nullptr;
584 int totitem = 0;
585 uint item_index;
586
588 RNA_enum_item_add(&item, &totitem, &strip_new_scene_items[item_index]);
589
590 bool has_scene_or_no_context = false;
591 if (C == nullptr) {
592 /* For documentation generation. */
593 has_scene_or_no_context = true;
594 }
595 else {
596 Scene *scene = CTX_data_scene(C);
597 Sequence *seq = SEQ_select_active_get(scene);
598 if (seq && (seq->type == SEQ_TYPE_SCENE) && (seq->scene != nullptr)) {
599 has_scene_or_no_context = true;
600 }
601 }
602
603 if (has_scene_or_no_context) {
605 for (int i = 0; i < ARRAY_SIZE(values); i++) {
606 item_index = RNA_enum_from_value(strip_new_scene_items, values[i]);
607 RNA_enum_item_add(&item, &totitem, &strip_new_scene_items[item_index]);
608 }
609 }
610
611 RNA_enum_item_end(&item, &totitem);
612 *r_free = true;
613 return item;
614}
615
617{
618 /* Identifiers. */
619 ot->name = "Add Strip with a new Scene";
620 ot->idname = "SEQUENCER_OT_scene_strip_add_new";
621 ot->description = "Create a new Strip and assign a new Scene as source";
622
623 /* Api callbacks. */
627
628 /* Flags. */
630
632
633 ot->prop = RNA_def_enum(ot->srna, "type", strip_new_scene_items, SCE_COPY_NEW, "Type", "");
636}
637
639{
640 Main *bmain = CTX_data_main(C);
641 Scene *scene = CTX_data_scene(C);
642 const Editing *ed = SEQ_editing_ensure(scene);
643 MovieClip *clip = static_cast<MovieClip *>(
644 BLI_findlink(&bmain->movieclips, RNA_enum_get(op->ptr, "clip")));
645
646 if (clip == nullptr) {
647 BKE_report(op->reports, RPT_ERROR, "Movie clip not found");
648 return OPERATOR_CANCELLED;
649 }
650
651 if (RNA_boolean_get(op->ptr, "replace_sel")) {
653 }
654
655 SeqLoadData load_data;
656 load_data_init_from_operator(&load_data, C, op);
657 load_data.clip = clip;
658
659 Sequence *seq = SEQ_add_movieclip_strip(scene, ed->seqbasep, &load_data);
661
664
665 return OPERATOR_FINISHED;
666}
667
669{
670 if (!RNA_struct_property_is_set(op->ptr, "clip")) {
671 return WM_enum_search_invoke(C, op, event);
672 }
673
676}
677
679{
680 PropertyRNA *prop;
681
682 /* Identifiers. */
683 ot->name = "Add MovieClip Strip";
684 ot->idname = "SEQUENCER_OT_movieclip_strip_add";
685 ot->description = "Add a movieclip strip to the sequencer";
686
687 /* Api callbacks. */
691
692 /* Flags. */
694
696 prop = RNA_def_enum(ot->srna, "clip", rna_enum_dummy_NULL_items, 0, "Clip", "");
700 ot->prop = prop;
701}
702
704{
705 Main *bmain = CTX_data_main(C);
706 Scene *scene = CTX_data_scene(C);
707 const Editing *ed = SEQ_editing_ensure(scene);
708 Mask *mask = static_cast<Mask *>(BLI_findlink(&bmain->masks, RNA_enum_get(op->ptr, "mask")));
709
710 if (mask == nullptr) {
711 BKE_report(op->reports, RPT_ERROR, "Mask not found");
712 return OPERATOR_CANCELLED;
713 }
714
715 if (RNA_boolean_get(op->ptr, "replace_sel")) {
717 }
718
719 SeqLoadData load_data;
720 load_data_init_from_operator(&load_data, C, op);
721 load_data.mask = mask;
722
723 Sequence *seq = SEQ_add_mask_strip(scene, ed->seqbasep, &load_data);
725
728
729 return OPERATOR_FINISHED;
730}
731
733{
734 if (!RNA_struct_property_is_set(op->ptr, "mask")) {
735 return WM_enum_search_invoke(C, op, event);
736 }
737
739 return sequencer_add_mask_strip_exec(C, op);
740}
741
743{
744 PropertyRNA *prop;
745
746 /* Identifiers. */
747 ot->name = "Add Mask Strip";
748 ot->idname = "SEQUENCER_OT_mask_strip_add";
749 ot->description = "Add a mask strip to the sequencer";
750
751 /* Api callbacks. */
755
756 /* Flags. */
758
760 prop = RNA_def_enum(ot->srna, "mask", rna_enum_dummy_NULL_items, 0, "Mask", "");
763 ot->prop = prop;
764}
765
766static void sequencer_add_init(bContext * /*C*/, wmOperator *op)
767{
768 op->customdata = MEM_callocN(sizeof(SequencerAddData), __func__);
769}
770
771static void sequencer_add_cancel(bContext * /*C*/, wmOperator *op)
772{
774}
775
777 PropertyRNA *prop,
778 void * /*user_data*/)
779{
780 const char *prop_id = RNA_property_identifier(prop);
781
782 return !STR_ELEM(prop_id, "filepath", "directory", "filename");
783}
784
785/* Strips are added in context of timeline which has different preview size than actual preview. We
786 * must search for preview area. In most cases there will be only one preview area, but there can
787 * be more with different preview sizes. */
789{
790 bScreen *screen = CTX_wm_screen(C);
792 LISTBASE_FOREACH (ScrArea *, area, &screen->areabase) {
793 LISTBASE_FOREACH (SpaceLink *, sl, &area->spacedata) {
794 switch (sl->spacetype) {
795 case SPACE_SEQ: {
796 SpaceSeq *sseq = (SpaceSeq *)sl;
798 continue;
799 }
801 }
802 }
803 }
804 }
805 return proxy_sizes;
806}
807
809{
810 if (U.sequencer_proxy_setup != USER_SEQ_PROXY_SETUP_AUTOMATIC) {
811 return;
812 }
813
814 wmJob *wm_job = ED_seq_proxy_wm_job_get(C);
815 ProxyJob *pj = ED_seq_proxy_job_get(C, wm_job);
816
817 for (Sequence *seq : movie_strips) {
818 /* Enable and set proxy size. */
819 SEQ_proxy_set(seq, true);
820 seq->strip->proxy->build_size_flags = seq_get_proxy_size_flags(C);
821 seq->strip->proxy->build_flags |= SEQ_PROXY_SKIP_EXISTING;
822 SEQ_proxy_rebuild_context(pj->main, pj->depsgraph, pj->scene, seq, nullptr, &pj->queue, true);
823 }
824
825 if (!WM_jobs_is_running(wm_job)) {
826 G.is_break = false;
827 WM_jobs_start(CTX_wm_manager(C), wm_job);
828 }
830}
831
833 Main *bmain, Scene *scene, Sequence *seq_movie, Sequence *seq_sound, SeqLoadData *load_data)
834{
835 if (ELEM(nullptr, seq_movie, seq_sound)) {
836 return;
837 }
838
839 /* Make sure that the sound strip start time relative to the movie is taken into account. */
840 SEQ_add_sound_av_sync(bmain, scene, seq_sound, load_data);
841
842 /* Ensure that the sound strip start/end matches the movie strip even if the actual
843 * length and true position of the sound doesn't match up exactly.
844 */
846 scene, seq_sound, SEQ_time_right_handle_frame_get(scene, seq_movie));
848 scene, seq_sound, SEQ_time_left_handle_frame_get(scene, seq_movie));
849}
850
852 wmOperator *op,
853 SeqLoadData *load_data,
854 blender::VectorSet<Sequence *> &r_movie_strips)
855{
856 Main *bmain = CTX_data_main(C);
857 Scene *scene = CTX_data_scene(C);
858 const Editing *ed = SEQ_editing_ensure(scene);
859 bool overlap_shuffle_override = RNA_boolean_get(op->ptr, "overlap") == false &&
860 RNA_boolean_get(op->ptr, "overlap_shuffle_override");
861 bool has_seq_overlap = false;
862 blender::Vector<Sequence *> added_strips;
863
864 RNA_BEGIN (op->ptr, itemptr, "files") {
865 char dir_only[FILE_MAX];
866 char file_only[FILE_MAX];
867 RNA_string_get(op->ptr, "directory", dir_only);
868 RNA_string_get(&itemptr, "name", file_only);
869 BLI_path_join(load_data->path, sizeof(load_data->path), dir_only, file_only);
870 STRNCPY(load_data->name, file_only);
871 Sequence *seq_movie = nullptr;
872 Sequence *seq_sound = nullptr;
873
874 seq_movie = SEQ_add_movie_strip(bmain, scene, ed->seqbasep, load_data);
875
876 if (seq_movie == nullptr) {
877 BKE_reportf(op->reports, RPT_ERROR, "File '%s' could not be loaded", load_data->path);
878 }
879 else {
880 if (RNA_boolean_get(op->ptr, "sound")) {
881 seq_sound = SEQ_add_sound_strip(bmain, scene, ed->seqbasep, load_data);
882 sequencer_add_movie_sync_sound_strip(bmain, scene, seq_movie, seq_sound, load_data);
883 added_strips.append(seq_movie);
884
885 if (seq_sound) {
886 /* The video has sound, shift the video strip up a channel to make room for the sound
887 * strip. */
888 added_strips.append(seq_sound);
889 seq_movie->machine++;
890 }
891 }
892
893 load_data->start_frame += SEQ_time_right_handle_frame_get(scene, seq_movie) -
894 SEQ_time_left_handle_frame_get(scene, seq_movie);
895 if (overlap_shuffle_override) {
896 has_seq_overlap |= seq_load_apply_generic_options_only_test_overlap(C, op, seq_sound);
897 has_seq_overlap |= seq_load_apply_generic_options_only_test_overlap(C, op, seq_movie);
898 }
899 else {
900 seq_load_apply_generic_options(C, op, seq_sound);
901 seq_load_apply_generic_options(C, op, seq_movie);
902 }
903
904 if (U.sequencer_editor_flag & USER_SEQ_ED_CONNECT_STRIPS_BY_DEFAULT) {
905 SEQ_connect(seq_movie, seq_sound);
906 }
907
908 r_movie_strips.add(seq_movie);
909 }
910 }
911 RNA_END;
912
913 if (overlap_shuffle_override) {
914 if (has_seq_overlap) {
915 ScrArea *area = CTX_wm_area(C);
916 const bool use_sync_markers = (((SpaceSeq *)area->spacedata.first)->flag &
917 SEQ_MARKER_TRANS) != 0;
918 SEQ_transform_handle_overlap(scene, ed->seqbasep, added_strips, use_sync_markers);
919 }
920 }
921}
922
924 wmOperator *op,
925 SeqLoadData *load_data,
926 blender::VectorSet<Sequence *> &r_movie_strips)
927{
928 Main *bmain = CTX_data_main(C);
929 Scene *scene = CTX_data_scene(C);
930 const Editing *ed = SEQ_editing_ensure(scene);
931
932 Sequence *seq_movie = nullptr;
933 Sequence *seq_sound = nullptr;
934 blender::Vector<Sequence *> added_strips;
935
936 seq_movie = SEQ_add_movie_strip(bmain, scene, ed->seqbasep, load_data);
937
938 if (seq_movie == nullptr) {
939 BKE_reportf(op->reports, RPT_ERROR, "File '%s' could not be loaded", load_data->path);
940 return false;
941 }
942 if (RNA_boolean_get(op->ptr, "sound")) {
943 seq_sound = SEQ_add_sound_strip(bmain, scene, ed->seqbasep, load_data);
944 sequencer_add_movie_sync_sound_strip(bmain, scene, seq_movie, seq_sound, load_data);
945 added_strips.append(seq_movie);
946
947 if (seq_sound) {
948 added_strips.append(seq_sound);
949 /* The video has sound, shift the video strip up a channel to make room for the sound
950 * strip. */
951 seq_movie->machine++;
952 }
953 }
954
955 bool overlap_shuffle_override = RNA_boolean_get(op->ptr, "overlap") == false &&
956 RNA_boolean_get(op->ptr, "overlap_shuffle_override");
957 if (overlap_shuffle_override) {
958 bool has_seq_overlap = false;
959
960 has_seq_overlap |= seq_load_apply_generic_options_only_test_overlap(C, op, seq_sound);
961 has_seq_overlap |= seq_load_apply_generic_options_only_test_overlap(C, op, seq_movie);
962
963 if (has_seq_overlap) {
964 ScrArea *area = CTX_wm_area(C);
965 const bool use_sync_markers = (((SpaceSeq *)area->spacedata.first)->flag &
966 SEQ_MARKER_TRANS) != 0;
967 SEQ_transform_handle_overlap(scene, ed->seqbasep, added_strips, use_sync_markers);
968 }
969 }
970 else {
971 seq_load_apply_generic_options(C, op, seq_sound);
972 seq_load_apply_generic_options(C, op, seq_movie);
973 }
974
975 if (U.sequencer_editor_flag & USER_SEQ_ED_CONNECT_STRIPS_BY_DEFAULT) {
976 SEQ_connect(seq_movie, seq_sound);
977 }
978
979 r_movie_strips.add(seq_movie);
980
981 return true;
982}
983
985{
986 Main *bmain = CTX_data_main(C);
987 Scene *scene = CTX_data_scene(C);
988 SeqLoadData load_data;
989
990 load_data_init_from_operator(&load_data, C, op);
991
992 if (RNA_boolean_get(op->ptr, "replace_sel")) {
994 }
995
997 const int tot_files = RNA_property_collection_length(op->ptr,
998 RNA_struct_find_property(op->ptr, "files"));
999 if (tot_files > 1) {
1000 sequencer_add_movie_multiple_strips(C, op, &load_data, movie_strips);
1001 }
1002 else {
1003 sequencer_add_movie_single_strip(C, op, &load_data, movie_strips);
1004 }
1005
1006 if (movie_strips.is_empty()) {
1007 sequencer_add_cancel(C, op);
1008 return OPERATOR_CANCELLED;
1009 }
1010
1011 seq_build_proxy(C, movie_strips);
1015
1016 /* Free custom data. */
1017 sequencer_add_cancel(C, op);
1018
1019 return OPERATOR_FINISHED;
1020}
1021
1023{
1024 PropertyRNA *prop;
1025 Scene *scene = CTX_data_scene(C);
1026
1028
1029 RNA_enum_set(op->ptr, "fit_method", SEQ_tool_settings_fit_method_get(scene));
1030 RNA_boolean_set(op->ptr, "adjust_playback_rate", true);
1031
1032 /* This is for drag and drop. */
1033 if ((RNA_struct_property_is_set(op->ptr, "files") &&
1034 !RNA_collection_is_empty(op->ptr, "files")) ||
1035 RNA_struct_property_is_set(op->ptr, "filepath"))
1036 {
1038 return sequencer_add_movie_strip_exec(C, op);
1039 }
1040
1042 sequencer_add_init(C, op);
1043
1044 /* Show multiview save options only if scene use multiview. */
1045 prop = RNA_struct_find_property(op->ptr, "show_multiview");
1046 RNA_property_boolean_set(op->ptr, prop, (scene->r.scemode & R_MULTIVIEW) != 0);
1047
1050}
1051
1052static void sequencer_add_draw(bContext * /*C*/, wmOperator *op)
1053{
1054 uiLayout *layout = op->layout;
1055 SequencerAddData *sad = static_cast<SequencerAddData *>(op->customdata);
1056 ImageFormatData *imf = &sad->im_format;
1057
1058 /* Main draw call. */
1059 uiDefAutoButsRNA(layout,
1060 op->ptr,
1062 nullptr,
1063 nullptr,
1065 false);
1066
1067 /* Image template. */
1068 PointerRNA imf_ptr = RNA_pointer_create(nullptr, &RNA_ImageFormatSettings, imf);
1069
1070 /* Multiview template. */
1071 if (RNA_boolean_get(op->ptr, "show_multiview")) {
1072 uiTemplateImageFormatViews(layout, &imf_ptr, op->ptr);
1073 }
1074}
1075
1077{
1078
1079 /* Identifiers. */
1080 ot->name = "Add Movie Strip";
1081 ot->idname = "SEQUENCER_OT_movie_strip_add";
1082 ot->description = "Add a movie strip to the sequencer";
1083
1084 /* Api callbacks. */
1090
1091 /* Flags. */
1093
1105 RNA_def_boolean(ot->srna, "sound", true, "Sound", "Load sound with the movie");
1107 "use_framerate",
1108 true,
1109 "Set Scene Frame Rate",
1110 "Set frame rate of the current scene to the frame rate of the movie");
1111}
1112
1114 wmOperator *op,
1115 SeqLoadData *load_data)
1116{
1117 Main *bmain = CTX_data_main(C);
1118 Scene *scene = CTX_data_scene(C);
1119 Editing *ed = SEQ_editing_ensure(scene);
1120
1121 RNA_BEGIN (op->ptr, itemptr, "files") {
1122 char dir_only[FILE_MAX];
1123 char file_only[FILE_MAX];
1124 RNA_string_get(op->ptr, "directory", dir_only);
1125 RNA_string_get(&itemptr, "name", file_only);
1126 BLI_path_join(load_data->path, sizeof(load_data->path), dir_only, file_only);
1127 STRNCPY(load_data->name, file_only);
1128 Sequence *seq = SEQ_add_sound_strip(bmain, scene, ed->seqbasep, load_data);
1129 if (seq == nullptr) {
1130 BKE_reportf(op->reports, RPT_ERROR, "File '%s' could not be loaded", load_data->path);
1131 }
1132 else {
1134 load_data->start_frame += SEQ_time_right_handle_frame_get(scene, seq) -
1136 }
1137 }
1138 RNA_END;
1139}
1140
1142{
1143 Main *bmain = CTX_data_main(C);
1144 Scene *scene = CTX_data_scene(C);
1145 Editing *ed = SEQ_editing_ensure(scene);
1146
1147 Sequence *seq = SEQ_add_sound_strip(bmain, scene, ed->seqbasep, load_data);
1148 if (seq == nullptr) {
1149 BKE_reportf(op->reports, RPT_ERROR, "File '%s' could not be loaded", load_data->path);
1150 return false;
1151 }
1153
1154 return true;
1155}
1156
1158{
1159 Main *bmain = CTX_data_main(C);
1160 Scene *scene = CTX_data_scene(C);
1161 SeqLoadData load_data;
1162 load_data_init_from_operator(&load_data, C, op);
1163
1164 if (RNA_boolean_get(op->ptr, "replace_sel")) {
1166 }
1167
1168 const int tot_files = RNA_property_collection_length(op->ptr,
1169 RNA_struct_find_property(op->ptr, "files"));
1170 if (tot_files > 1) {
1171 sequencer_add_sound_multiple_strips(C, op, &load_data);
1172 }
1173 else {
1174 if (!sequencer_add_sound_single_strip(C, op, &load_data)) {
1175 return OPERATOR_CANCELLED;
1176 }
1177 }
1178
1179 if (op->customdata) {
1180 MEM_freeN(op->customdata);
1181 }
1182
1186
1187 return OPERATOR_FINISHED;
1188}
1189
1191{
1192 /* This is for drag and drop. */
1193 if ((RNA_struct_property_is_set(op->ptr, "files") &&
1194 !RNA_collection_is_empty(op->ptr, "files")) ||
1195 RNA_struct_property_is_set(op->ptr, "filepath"))
1196 {
1198 return sequencer_add_sound_strip_exec(C, op);
1199 }
1200
1202
1205}
1206
1208{
1209
1210 /* Identifiers. */
1211 ot->name = "Add Sound Strip";
1212 ot->idname = "SEQUENCER_OT_sound_strip_add";
1213 ot->description = "Add a sound strip to the sequencer";
1214
1215 /* Api callbacks. */
1219
1220 /* Flags. */
1222
1232 RNA_def_boolean(ot->srna, "cache", false, "Cache", "Cache the sound in memory");
1233 RNA_def_boolean(ot->srna, "mono", false, "Mono", "Merge all the sound's channels into one");
1234}
1235
1237 int sfra,
1238 int *r_minframe,
1239 int *r_numdigits)
1240{
1241 int minframe = INT32_MAX, maxframe = INT32_MIN;
1242 int numdigits = 0;
1243
1244 RNA_BEGIN (op->ptr, itemptr, "files") {
1245 char *filename;
1246 int frame;
1247 filename = RNA_string_get_alloc(&itemptr, "name", nullptr, 0, nullptr);
1248
1249 if (filename) {
1250 if (BLI_path_frame_get(filename, &frame, &numdigits)) {
1251 minframe = min_ii(minframe, frame);
1252 maxframe = max_ii(maxframe, frame);
1253 }
1254
1255 MEM_freeN(filename);
1256 }
1257 }
1258 RNA_END;
1259
1260 if (minframe == INT32_MAX) {
1261 minframe = sfra;
1262 maxframe = minframe + 1;
1263 }
1264
1265 *r_minframe = minframe;
1266 *r_numdigits = numdigits;
1267
1268 return maxframe - minframe + 1;
1269}
1270
1272 wmOperator *op, StripElem *se, int len, int minframe, int numdigits)
1273{
1274 char *filename = nullptr;
1275 RNA_BEGIN (op->ptr, itemptr, "files") {
1276 filename = RNA_string_get_alloc(&itemptr, "name", nullptr, 0, nullptr);
1277 break;
1278 }
1279 RNA_END;
1280
1281 if (filename) {
1282 char ext[FILE_MAX];
1283 char filename_stripped[FILE_MAX];
1284 /* Strip the frame from filename and substitute with `#`. */
1285 BLI_path_frame_strip(filename, ext, sizeof(ext));
1286
1287 for (int i = 0; i < len; i++, se++) {
1288 STRNCPY(filename_stripped, filename);
1289 BLI_path_frame(filename_stripped, sizeof(filename_stripped), minframe + i, numdigits);
1290 SNPRINTF(se->filename, "%s%s", filename_stripped, ext);
1291 }
1292
1293 MEM_freeN(filename);
1294 }
1295}
1296
1298 const int start_frame,
1299 int *minframe,
1300 int *numdigits)
1301{
1302 const bool use_placeholders = RNA_boolean_get(op->ptr, "use_placeholders");
1303
1304 if (use_placeholders) {
1305 return sequencer_image_seq_get_minmax_frame(op, start_frame, minframe, numdigits);
1306 }
1308}
1309
1311 Scene *scene,
1312 Sequence *seq,
1313 SeqLoadData *load_data,
1314 const int minframe,
1315 const int numdigits)
1316{
1317 const bool use_placeholders = RNA_boolean_get(op->ptr, "use_placeholders");
1318 char dirpath[sizeof(seq->strip->dirpath)];
1319 BLI_path_split_dir_part(load_data->path, dirpath, sizeof(dirpath));
1320 SEQ_add_image_set_directory(seq, dirpath);
1321
1322 if (use_placeholders) {
1324 op, seq->strip->stripdata, load_data->image.len, minframe, numdigits);
1325 }
1326 else {
1327 size_t strip_frame = 0;
1328 RNA_BEGIN (op->ptr, itemptr, "files") {
1329 char *filename = RNA_string_get_alloc(&itemptr, "name", nullptr, 0, nullptr);
1330 SEQ_add_image_load_file(scene, seq, strip_frame, filename);
1331 MEM_freeN(filename);
1332 strip_frame++;
1333 }
1334 RNA_END;
1335 }
1336}
1337
1339{
1340 Scene *scene = CTX_data_scene(C);
1341 Editing *ed = SEQ_editing_ensure(scene);
1342
1343 SeqLoadData load_data;
1344 load_data_init_from_operator(&load_data, C, op);
1345
1346 int minframe, numdigits;
1348 op, load_data.start_frame, &minframe, &numdigits);
1349 if (load_data.image.len == 0) {
1350 sequencer_add_cancel(C, op);
1351 return OPERATOR_CANCELLED;
1352 }
1353
1354 if (RNA_boolean_get(op->ptr, "replace_sel")) {
1356 }
1357
1358 Sequence *seq = SEQ_add_image_strip(CTX_data_main(C), scene, ed->seqbasep, &load_data);
1359 sequencer_add_image_strip_load_files(op, scene, seq, &load_data, minframe, numdigits);
1361
1362 /* Adjust length. */
1363 if (load_data.image.len == 1) {
1364 SEQ_time_right_handle_frame_set(scene, seq, load_data.image.end_frame);
1365 }
1366
1368
1371
1372 /* Free custom data. */
1373 sequencer_add_cancel(C, op);
1374
1375 return OPERATOR_FINISHED;
1376}
1377
1379{
1380 PropertyRNA *prop;
1381 Scene *scene = CTX_data_scene(C);
1382
1384
1385 RNA_enum_set(op->ptr, "fit_method", SEQ_tool_settings_fit_method_get(scene));
1386
1387 /* Name set already by drag and drop. */
1388 if (RNA_struct_property_is_set(op->ptr, "files") && !RNA_collection_is_empty(op->ptr, "files")) {
1391 return sequencer_add_image_strip_exec(C, op);
1392 }
1393
1395 sequencer_add_init(C, op);
1396
1397 /* Show multiview save options only if scene use multiview. */
1398 prop = RNA_struct_find_property(op->ptr, "show_multiview");
1399 RNA_property_boolean_set(op->ptr, prop, (scene->r.scemode & R_MULTIVIEW) != 0);
1400
1403}
1404
1406{
1407
1408 /* Identifiers. */
1409 ot->name = "Add Image Strip";
1410 ot->idname = "SEQUENCER_OT_image_strip_add";
1411 ot->description = "Add an image or image sequence to the sequencer";
1412
1413 /* Api callbacks. */
1419
1420 /* Flags. */
1422
1424 ot,
1433
1435 "use_placeholders",
1436 false,
1437 "Use Placeholders",
1438 "Use placeholders for missing frames of the strip");
1439}
1440
1442{
1443 Scene *scene = CTX_data_scene(C);
1444 Editing *ed = SEQ_editing_ensure(scene);
1445 const char *error_msg;
1446
1447 SeqLoadData load_data;
1448 load_data_init_from_operator(&load_data, C, op);
1449 load_data.effect.type = RNA_enum_get(op->ptr, "type");
1450
1451 Sequence *seq1, *seq2;
1452 if (!seq_effect_find_selected(scene, nullptr, load_data.effect.type, &seq1, &seq2, &error_msg)) {
1453 BKE_report(op->reports, RPT_ERROR, error_msg);
1454 return OPERATOR_CANCELLED;
1455 }
1456
1457 if (RNA_boolean_get(op->ptr, "replace_sel")) {
1459 }
1460
1461 load_data.effect.seq1 = seq1;
1462 load_data.effect.seq2 = seq2;
1463
1464 /* Set channel. If unset, use lowest free one above strips. */
1465 if (!RNA_struct_property_is_set(op->ptr, "channel")) {
1466 if (seq1 != nullptr) {
1467 int chan = max_ii(seq1 ? seq1->machine : 0, seq2 ? seq2->machine : 0);
1468 if (chan < SEQ_MAX_CHANNELS) {
1469 load_data.channel = chan;
1470 }
1471 }
1472 }
1473
1474 Sequence *seq = SEQ_add_effect_strip(scene, ed->seqbasep, &load_data);
1476
1477 if (seq->type == SEQ_TYPE_COLOR) {
1478 SolidColorVars *colvars = (SolidColorVars *)seq->effectdata;
1479 RNA_float_get_array(op->ptr, "color", colvars->col);
1480 }
1481
1484
1485 return OPERATOR_FINISHED;
1486}
1487
1489 wmOperator *op,
1490 const wmEvent * /*event*/)
1491{
1492 bool is_type_set = RNA_struct_property_is_set(op->ptr, "type");
1493 int type = -1;
1494 int prop_flag = SEQPROP_ENDFRAME | SEQPROP_NOPATHS;
1495
1496 if (is_type_set) {
1497 type = RNA_enum_get(op->ptr, "type");
1498
1499 /* When invoking an effect strip which uses inputs, skip initializing the channel from the
1500 * mouse. */
1501 if (SEQ_effect_get_num_inputs(type) != 0) {
1502 prop_flag |= SEQPROP_NOCHAN;
1503 }
1504 }
1505
1506 sequencer_generic_invoke_xy__internal(C, op, prop_flag, type);
1507
1508 return sequencer_add_effect_strip_exec(C, op);
1509}
1510
1512 wmOperatorType * /*ot*/,
1513 PointerRNA *ptr)
1514{
1515 const int type = RNA_enum_get(ptr, "type");
1516
1517 switch (type) {
1518 case SEQ_TYPE_CROSS:
1519 return TIP_("Add a crossfade transition to the sequencer");
1520 case SEQ_TYPE_ADD:
1521 return TIP_("Add an add effect strip to the sequencer");
1522 case SEQ_TYPE_SUB:
1523 return TIP_("Add a subtract effect strip to the sequencer");
1524 case SEQ_TYPE_ALPHAOVER:
1525 return TIP_("Add an alpha over effect strip to the sequencer");
1527 return TIP_("Add an alpha under effect strip to the sequencer");
1528 case SEQ_TYPE_GAMCROSS:
1529 return TIP_("Add a gamma cross transition to the sequencer");
1530 case SEQ_TYPE_MUL:
1531 return TIP_("Add a multiply effect strip to the sequencer");
1532 case SEQ_TYPE_OVERDROP:
1533 return TIP_("Add an alpha over drop effect strip to the sequencer");
1534 case SEQ_TYPE_WIPE:
1535 return TIP_("Add a wipe transition to the sequencer");
1536 case SEQ_TYPE_GLOW:
1537 return TIP_("Add a glow effect strip to the sequencer");
1538 case SEQ_TYPE_TRANSFORM:
1539 return TIP_("Add a transform effect strip to the sequencer");
1540 case SEQ_TYPE_COLOR:
1541 return TIP_("Add a color strip to the sequencer");
1542 case SEQ_TYPE_SPEED:
1543 return TIP_("Add a speed effect strip to the sequencer");
1544 case SEQ_TYPE_MULTICAM:
1545 return TIP_("Add a multicam selector effect strip to the sequencer");
1547 return TIP_("Add an adjustment layer effect strip to the sequencer");
1549 return TIP_("Add a gaussian blur effect strip to the sequencer");
1550 case SEQ_TYPE_TEXT:
1551 return TIP_("Add a text strip to the sequencer");
1552 case SEQ_TYPE_COLORMIX:
1553 return TIP_("Add a color mix effect strip to the sequencer");
1554 default:
1555 break;
1556 }
1557
1558 /* Use default description. */
1559 return "";
1560}
1561
1563{
1564 PropertyRNA *prop;
1565
1566 /* Identifiers. */
1567 ot->name = "Add Effect Strip";
1568 ot->idname = "SEQUENCER_OT_effect_strip_add";
1569 ot->description = "Add an effect to the sequencer, most are applied on top of existing strips";
1570
1571 /* Api callbacks. */
1577
1578 /* Flags. */
1580
1581 prop = RNA_def_enum(ot->srna,
1582 "type",
1585 "Type",
1586 "Sequencer effect type");
1589 /* Only used when strip is of the Color type. */
1590 prop = RNA_def_float_color(ot->srna,
1591 "color",
1592 3,
1593 nullptr,
1594 0.0f,
1595 1.0f,
1596 "Color",
1597 "Initialize the strip with this color",
1598 0.0f,
1599 1.0f);
1601}
bScreen * CTX_wm_screen(const bContext *C)
ScrArea * CTX_wm_area(const bContext *C)
Scene * CTX_data_scene(const bContext *C)
Main * CTX_data_main(const bContext *C)
ARegion * CTX_wm_region(const bContext *C)
wmWindowManager * CTX_wm_manager(const bContext *C)
const char * BKE_main_blendfile_path(const Main *bmain) ATTR_NONNULL()
Definition main.cc:832
void BKE_reportf(ReportList *reports, eReportType type, const char *format,...) ATTR_PRINTF_FORMAT(3
void BKE_report(ReportList *reports, eReportType type, const char *message)
Definition report.cc:125
eSceneCopyMethod
Definition BKE_scene.hh:29
@ SCE_COPY_EMPTY
Definition BKE_scene.hh:31
@ SCE_COPY_NEW
Definition BKE_scene.hh:30
@ SCE_COPY_FULL
Definition BKE_scene.hh:33
@ SCE_COPY_LINK_COLLECTION
Definition BKE_scene.hh:32
#define BLI_assert(a)
Definition BLI_assert.h:50
#define LISTBASE_FOREACH(type, var, list)
void * BLI_findlink(const struct ListBase *listbase, int number) ATTR_WARN_UNUSED_RESULT ATTR_NONNULL(1)
MINLINE int min_ii(int a, int b)
MINLINE int max_ii(int a, int b)
bool BLI_path_abs(char path[FILE_MAX], const char *basepath) ATTR_NONNULL(1
bool void BLI_path_frame_strip(char *path, char *r_ext, size_t ext_maxncpy) ATTR_NONNULL(1
void void void const char * BLI_path_basename(const char *path) ATTR_NONNULL(1) ATTR_WARN_UNUSED_RESULT
#define FILE_MAX
#define BLI_path_join(...)
bool BLI_path_frame_get(const char *path, int *r_frame, int *r_digits_len) ATTR_NONNULL(1
void void BLI_path_split_dir_part(const char *filepath, char *dir, size_t dir_maxncpy) ATTR_NONNULL(1
bool void BLI_path_rel(char path[FILE_MAX], const char *basepath) ATTR_NONNULL(1)
bool BLI_path_frame(char *path, size_t path_maxncpy, int frame, int digits) ATTR_NONNULL(1)
#define STR_ELEM(...)
Definition BLI_string.h:653
#define STRNCPY(dst, src)
Definition BLI_string.h:593
#define SNPRINTF(dst, format,...)
Definition BLI_string.h:597
unsigned int uint
#define ARRAY_SIZE(arr)
#define ELEM(...)
#define STREQ(a, b)
#define BLT_I18NCONTEXT_ID_SEQUENCE
#define TIP_(msgid)
#define BLT_I18NCONTEXT_ID_MOVIECLIP
void DEG_id_tag_update(ID *id, unsigned int flags)
void DEG_relations_tag_update(Main *bmain)
@ ID_RECALC_SEQUENCER_STRIPS
Definition DNA_ID.h:1089
eSeqImageFitMethod
@ SEQ_SCALE_TO_FILL
@ SEQ_STRETCH_TO_FILL
@ SEQ_USE_ORIGINAL_SIZE
@ SEQ_SCALE_TO_FIT
@ R_MULTIVIEW
#define MAXFRAME
@ RGN_TYPE_WINDOW
@ SEQ_TYPE_TRANSFORM
@ SEQ_TYPE_SOUND_RAM
@ SEQ_TYPE_CROSS
@ SEQ_TYPE_GLOW
@ SEQ_TYPE_COLORMIX
@ SEQ_TYPE_WIPE
@ SEQ_TYPE_OVERDROP
@ SEQ_TYPE_ALPHAUNDER
@ SEQ_TYPE_SCENE
@ SEQ_TYPE_GAMCROSS
@ SEQ_TYPE_MULTICAM
@ SEQ_TYPE_MOVIECLIP
@ SEQ_TYPE_MUL
@ SEQ_TYPE_GAUSSIAN_BLUR
@ SEQ_TYPE_ADD
@ SEQ_TYPE_ALPHAOVER
@ SEQ_TYPE_TEXT
@ SEQ_TYPE_IMAGE
@ SEQ_TYPE_SUB
@ SEQ_TYPE_SPEED
@ SEQ_TYPE_COLOR
@ SEQ_TYPE_MOVIE
@ SEQ_TYPE_MASK
@ SEQ_TYPE_ADJUSTMENT
#define SEQ_HAS_PATH(_seq)
@ SEQ_PROXY_SKIP_EXISTING
@ FILE_SORT_DEFAULT
@ FILE_SPECIAL
@ FILE_TYPE_MOVIE
@ FILE_TYPE_SOUND
@ FILE_TYPE_FOLDER
@ FILE_TYPE_IMAGE
@ SPACE_SEQ
@ SEQ_VIEW_SEQUENCE_PREVIEW
@ SEQ_VIEW_PREVIEW
@ FILE_DEFAULTDISPLAY
@ SEQ_MARKER_TRANS
@ USER_SEQ_PROXY_SETUP_AUTOMATIC
@ USER_SEQ_ED_CONNECT_STRIPS_BY_DEFAULT
@ OPERATOR_RUNNING_MODAL
Scene * ED_scene_sequencer_add(Main *bmain, bContext *C, eSceneCopyMethod method, bool assign_strip)
Definition scene_edit.cc:69
void ED_area_tag_redraw(ScrArea *area)
Definition area.cc:708
bool ED_operator_sequencer_active_editable(bContext *C)
bool ED_sequencer_deselect_all(Scene *scene)
IMB_Proxy_Size
Read Guarded memory(de)allocation.
#define MEM_SAFE_FREE(v)
#define RNA_PROP_END
#define RNA_BEGIN(sptr, itemptr, propname)
#define RNA_END
#define RNA_PROP_BEGIN(sptr, itemptr, prop)
const EnumPropertyItem * RNA_movieclip_itemf(bContext *C, PointerRNA *ptr, PropertyRNA *prop, bool *r_free)
const EnumPropertyItem * RNA_scene_without_active_itemf(bContext *C, PointerRNA *ptr, PropertyRNA *prop, bool *r_free)
const EnumPropertyItem * RNA_mask_itemf(bContext *C, PointerRNA *ptr, PropertyRNA *prop, bool *r_free)
@ PROP_ENUM_NO_TRANSLATE
Definition RNA_types.hh:321
@ PROP_SKIP_SAVE
Definition RNA_types.hh:245
@ PROP_HIDDEN
Definition RNA_types.hh:239
@ PROP_COLOR_GAMMA
Definition RNA_types.hh:175
@ SEQ_LOAD_SOUND_MONO
Definition SEQ_add.hh:26
@ SEQ_LOAD_SOUND_CACHE
Definition SEQ_add.hh:25
@ SEQ_LOAD_SET_VIEW_TRANSFORM
Definition SEQ_add.hh:28
@ SEQ_LOAD_MOVIE_SYNC_FPS
Definition SEQ_add.hh:27
constexpr int SEQ_MAX_CHANNELS
@ UI_BUT_LABEL_ALIGN_NONE
eAutoPropButsReturn uiDefAutoButsRNA(uiLayout *layout, PointerRNA *ptr, bool(*check_prop)(PointerRNA *ptr, PropertyRNA *prop, void *user_data), void *user_data, PropertyRNA *prop_activate_init, eButLabelAlign label_align, bool compact)
void uiTemplateImageFormatViews(uiLayout *layout, PointerRNA *imfptr, PointerRNA *ptr)
void UI_view2d_region_to_view(const View2D *v2d, float x, float y, float *r_view_x, float *r_view_y) ATTR_NONNULL()
Definition view2d.cc:1663
@ WM_FILESEL_FILES
Definition WM_api.hh:937
@ WM_FILESEL_DIRECTORY
Definition WM_api.hh:934
@ WM_FILESEL_RELPATH
Definition WM_api.hh:933
@ WM_FILESEL_SHOW_PROPS
Definition WM_api.hh:939
@ WM_FILESEL_FILEPATH
Definition WM_api.hh:936
@ FILE_OPENFILE
Definition WM_api.hh:945
#define ND_SEQUENCER
Definition WM_types.hh:404
@ OPTYPE_UNDO
Definition WM_types.hh:162
@ OPTYPE_REGISTER
Definition WM_types.hh:160
#define NC_SCENE
Definition WM_types.hh:345
unsigned int U
Definition btGjkEpa3.h:78
bool add(const Key &key)
void append(const T &value)
#define SELECT
int len
draw_view push_constant(Type::INT, "radiance_src") .push_constant(Type capture_info_buf storage_buf(1, Qualifier::READ, "ObjectBounds", "bounds_buf[]") .push_constant(Type draw_view int
int SEQ_effect_get_num_inputs(int seq_type)
Definition effects.cc:3467
static const IMB_Proxy_Size proxy_sizes[]
Definition indexer.cc:47
void MEM_freeN(void *vmemh)
Definition mallocn.cc:105
void *(* MEM_callocN)(size_t len, const char *str)
Definition mallocn.cc:42
ccl_device_inline float4 mask(const int4 mask, const float4 a)
#define G(x, y, z)
bool SEQ_proxy_rebuild_context(Main *bmain, Depsgraph *depsgraph, Scene *scene, Sequence *seq, GSet *file_list, ListBase *queue, bool build_only_on_bad_performance)
Definition proxy.cc:420
void SEQ_proxy_set(Sequence *seq, bool value)
Definition proxy.cc:591
int SEQ_rendersize_to_proxysize(int render_size)
Definition proxy.cc:67
ProxyJob * ED_seq_proxy_job_get(const bContext *C, wmJob *wm_job)
Definition proxy_job.cc:66
wmJob * ED_seq_proxy_wm_job_get(const bContext *C)
Definition proxy_job.cc:83
void RNA_string_set(PointerRNA *ptr, const char *name, const char *value)
PropertyRNA * RNA_struct_find_property(PointerRNA *ptr, const char *identifier)
bool RNA_collection_is_empty(PointerRNA *ptr, const char *name)
void RNA_boolean_set(PointerRNA *ptr, const char *name, bool value)
void RNA_int_set(PointerRNA *ptr, const char *name, int value)
void RNA_float_get_array(PointerRNA *ptr, const char *name, float *values)
bool RNA_property_boolean_get(PointerRNA *ptr, PropertyRNA *prop)
int RNA_property_int_get(PointerRNA *ptr, PropertyRNA *prop)
void RNA_string_get(PointerRNA *ptr, const char *name, char *value)
int RNA_int_get(PointerRNA *ptr, const char *name)
char * RNA_string_get_alloc(PointerRNA *ptr, const char *name, char *fixedbuf, int fixedlen, int *r_len)
void RNA_property_boolean_set(PointerRNA *ptr, PropertyRNA *prop, bool value)
std::string RNA_property_string_get(PointerRNA *ptr, PropertyRNA *prop)
int RNA_enum_from_value(const EnumPropertyItem *item, const int value)
bool RNA_struct_property_is_set(PointerRNA *ptr, const char *identifier)
bool RNA_boolean_get(PointerRNA *ptr, const char *name)
void RNA_enum_set(PointerRNA *ptr, const char *name, int value)
PointerRNA RNA_pointer_create(ID *id, StructRNA *type, void *data)
int RNA_enum_get(PointerRNA *ptr, const char *name)
const char * RNA_property_identifier(const PropertyRNA *prop)
int RNA_property_collection_length(PointerRNA *ptr, PropertyRNA *prop)
PropertyRNA * RNA_def_float_color(StructOrFunctionRNA *cont_, const char *identifier, const int len, const float *default_value, const float hardmin, const float hardmax, const char *ui_name, const char *ui_description, const float softmin, const float softmax)
PropertyRNA * RNA_def_enum(StructOrFunctionRNA *cont_, const char *identifier, const EnumPropertyItem *items, const int default_value, const char *ui_name, const char *ui_description)
void RNA_enum_item_end(EnumPropertyItem **items, int *totitem)
void RNA_enum_item_add(EnumPropertyItem **items, int *totitem, const EnumPropertyItem *item)
PropertyRNA * RNA_def_boolean(StructOrFunctionRNA *cont_, const char *identifier, const bool default_value, const char *ui_name, const char *ui_description)
void RNA_def_property_translation_context(PropertyRNA *prop, const char *context)
void RNA_def_property_flag(PropertyRNA *prop, PropertyFlag flag)
void RNA_def_enum_funcs(PropertyRNA *prop, EnumPropertyItemFunc itemfunc)
void RNA_def_property_subtype(PropertyRNA *prop, PropertySubType subtype)
PropertyRNA * RNA_def_int(StructOrFunctionRNA *cont_, const char *identifier, const int default_value, const int hardmin, const int hardmax, const char *ui_name, const char *ui_description, const int softmin, const int softmax)
const EnumPropertyItem rna_enum_dummy_NULL_items[]
Definition rna_rna.cc:29
Editing * SEQ_editing_ensure(Scene *scene)
Definition sequencer.cc:267
eSeqImageFitMethod SEQ_tool_settings_fit_method_get(Scene *scene)
Definition sequencer.cc:374
void SEQ_tool_settings_fit_method_set(Scene *scene, eSeqImageFitMethod fit_method)
Definition sequencer.cc:398
Editing * SEQ_editing_get(const Scene *scene)
Definition sequencer.cc:262
static bool sequencer_add_movie_single_strip(bContext *C, wmOperator *op, SeqLoadData *load_data, blender::VectorSet< Sequence * > &r_movie_strips)
void SEQUENCER_OT_movie_strip_add(wmOperatorType *ot)
static int sequencer_add_movie_strip_invoke(bContext *C, wmOperator *op, const wmEvent *event)
static void sequencer_add_sound_multiple_strips(bContext *C, wmOperator *op, SeqLoadData *load_data)
static void load_data_init_from_operator(SeqLoadData *load_data, bContext *C, wmOperator *op)
static int sequencer_add_scene_strip_new_invoke(bContext *C, wmOperator *op, const wmEvent *)
#define SEQPROP_NOPATHS
static int sequencer_add_effect_strip_exec(bContext *C, wmOperator *op)
static std::string sequencer_add_effect_strip_get_description(bContext *, wmOperatorType *, PointerRNA *ptr)
static bool sequencer_add_draw_check_fn(PointerRNA *, PropertyRNA *prop, void *)
static int sequencer_add_mask_strip_exec(bContext *C, wmOperator *op)
#define SEQPROP_ENDFRAME
void SEQUENCER_OT_mask_strip_add(wmOperatorType *ot)
static IMB_Proxy_Size seq_get_proxy_size_flags(bContext *C)
static void sequencer_generic_invoke_path__internal(bContext *C, wmOperator *op, const char *identifier)
static int sequencer_add_mask_strip_invoke(bContext *C, wmOperator *op, const wmEvent *event)
static void sequencer_generic_invoke_xy__internal(bContext *C, wmOperator *op, int flag, int type, const wmEvent *event=nullptr)
static EnumPropertyItem strip_new_scene_items[]
static void sequencer_add_init(bContext *, wmOperator *op)
static void sequencer_add_cancel(bContext *, wmOperator *op)
static int sequencer_add_image_strip_calculate_length(wmOperator *op, const int start_frame, int *minframe, int *numdigits)
void SEQUENCER_OT_sound_strip_add(wmOperatorType *ot)
#define SEQPROP_VIEW_TRANSFORM
static const EnumPropertyItem * strip_new_sequencer_enum_itemf(bContext *C, PointerRNA *, PropertyRNA *, bool *r_free)
static const EnumPropertyItem scale_fit_methods[]
static bool sequencer_add_sound_single_strip(bContext *C, wmOperator *op, SeqLoadData *load_data)
static void sequencer_add_movie_multiple_strips(bContext *C, wmOperator *op, SeqLoadData *load_data, blender::VectorSet< Sequence * > &r_movie_strips)
static int sequencer_add_movieclip_strip_exec(bContext *C, wmOperator *op)
static int sequencer_add_scene_strip_invoke(bContext *C, wmOperator *op, const wmEvent *event)
static int sequencer_add_scene_strip_exec(bContext *C, wmOperator *op)
static void sequencer_generic_props__internal(wmOperatorType *ot, int flag)
static void sequencer_add_image_strip_load_files(wmOperator *op, Scene *scene, Sequence *seq, SeqLoadData *load_data, const int minframe, const int numdigits)
static int sequencer_add_movieclip_strip_invoke(bContext *C, wmOperator *op, const wmEvent *event)
static void seq_load_apply_generic_options(bContext *C, wmOperator *op, Sequence *seq)
static void sequencer_file_drop_channel_frame_set(bContext *C, wmOperator *op, const wmEvent *event)
static int sequencer_add_sound_strip_invoke(bContext *C, wmOperator *op, const wmEvent *event)
static int sequencer_add_scene_strip_new_exec(bContext *C, wmOperator *op)
void SEQUENCER_OT_movieclip_strip_add(wmOperatorType *ot)
void SEQUENCER_OT_image_strip_add(wmOperatorType *ot)
void SEQUENCER_OT_effect_strip_add(wmOperatorType *ot)
#define SEQPROP_STARTFRAME
static bool seq_load_apply_generic_options_only_test_overlap(bContext *C, wmOperator *op, Sequence *seq)
static int sequencer_add_sound_strip_exec(bContext *C, wmOperator *op)
void sequencer_image_seq_reserve_frames(wmOperator *op, StripElem *se, int len, int minframe, int numdigits)
#define SEQPROP_NOCHAN
static void seq_build_proxy(bContext *C, blender::Span< Sequence * > movie_strips)
static void sequencer_add_draw(bContext *, wmOperator *op)
#define SEQPROP_PLAYBACK_RATE
static bool seq_effect_add_properties_poll(const bContext *, wmOperator *op, const PropertyRNA *prop)
void SEQUENCER_OT_scene_strip_add(wmOperatorType *ot)
static int sequencer_generic_invoke_xy_guess_channel(bContext *C, int type)
static void sequencer_add_movie_sync_sound_strip(Main *bmain, Scene *scene, Sequence *seq_movie, Sequence *seq_sound, SeqLoadData *load_data)
static int sequencer_add_image_strip_exec(bContext *C, wmOperator *op)
void SEQUENCER_OT_scene_strip_add_new(wmOperatorType *ot)
#define SEQPROP_FIT_METHOD
int sequencer_image_seq_get_minmax_frame(wmOperator *op, int sfra, int *r_minframe, int *r_numdigits)
static int sequencer_add_image_strip_invoke(bContext *C, wmOperator *op, const wmEvent *event)
static int sequencer_add_movie_strip_exec(bContext *C, wmOperator *op)
static void sequencer_disable_one_time_properties(bContext *C, wmOperator *op)
static int sequencer_add_effect_strip_invoke(bContext *C, wmOperator *op, const wmEvent *)
int seq_effect_find_selected(Scene *scene, Sequence *activeseq, int type, Sequence **r_selseq1, Sequence **r_selseq2, const char **r_error_str)
const EnumPropertyItem sequencer_prop_effect_types[]
#define DEFAULT_IMG_STRIP_LENGTH
#define INT32_MAX
Definition stdint.h:137
#define INT32_MIN
Definition stdint.h:136
Sequence * SEQ_add_scene_strip(Scene *scene, ListBase *seqbase, SeqLoadData *load_data)
Definition strip_add.cc:124
Sequence * SEQ_add_movieclip_strip(Scene *scene, ListBase *seqbase, SeqLoadData *load_data)
Definition strip_add.cc:136
Sequence * SEQ_add_effect_strip(Scene *scene, ListBase *seqbase, SeqLoadData *load_data)
Definition strip_add.cc:160
void SEQ_add_sound_av_sync(Main *, Scene *, Sequence *, SeqLoadData *)
Definition strip_add.cc:357
Sequence * SEQ_add_mask_strip(Scene *scene, ListBase *seqbase, SeqLoadData *load_data)
Definition strip_add.cc:148
Sequence * SEQ_add_movie_strip(Main *bmain, Scene *scene, ListBase *seqbase, SeqLoadData *load_data)
Definition strip_add.cc:391
void SEQ_add_image_set_directory(Sequence *seq, const char *dirpath)
Definition strip_add.cc:188
void SEQ_add_image_init_alpha_mode(Sequence *seq)
Definition strip_add.cc:200
void SEQ_add_image_load_file(Scene *scene, Sequence *seq, size_t strip_frame, const char *filename)
Definition strip_add.cc:193
Sequence * SEQ_add_sound_strip(Main *, Scene *, ListBase *, SeqLoadData *)
Definition strip_add.cc:364
Sequence * SEQ_add_image_strip(Main *bmain, Scene *scene, ListBase *seqbase, SeqLoadData *load_data)
Definition strip_add.cc:230
void SEQ_connect(Sequence *seq1, Sequence *seq2)
void SEQ_select_active_set(Scene *scene, Sequence *seq)
Sequence * SEQ_select_active_get(const Scene *scene)
void SEQ_time_right_handle_frame_set(const Scene *scene, Sequence *seq, int timeline_frame)
void SEQ_time_left_handle_frame_set(const Scene *scene, Sequence *seq, int timeline_frame)
int SEQ_time_left_handle_frame_get(const Scene *, const Sequence *seq)
int SEQ_time_right_handle_frame_get(const Scene *scene, const Sequence *seq)
bool SEQ_transform_seqbase_shuffle(ListBase *seqbasep, Sequence *test, Scene *evil_scene)
bool SEQ_transform_test_overlap(const Scene *scene, ListBase *seqbasep, Sequence *test)
void SEQ_transform_handle_overlap(Scene *scene, ListBase *seqbasep, blender::Span< Sequence * > transformed_strips, bool use_sync_markers)
ListBase * seqbasep
Stereo3dFormat stereo3d_format
void * first
ListBase masks
Definition BKE_main.hh:243
ListBase scenes
Definition BKE_main.hh:210
ListBase movieclips
Definition BKE_main.hh:242
Main * main
Definition clip_ops.cc:1177
Depsgraph * depsgraph
Definition SEQ_proxy.hh:38
Scene * scene
Definition clip_ops.cc:1176
ListBase queue
Definition SEQ_proxy.hh:40
char views_format
Definition SEQ_add.hh:55
bool use_multiview
Definition SEQ_add.hh:54
Scene * scene
Definition SEQ_add.hh:43
struct SeqLoadData::@1364 effect
eSeqImageFitMethod fit_method
Definition SEQ_add.hh:53
Sequence * seq1
Definition SEQ_add.hh:49
int channel
Definition SEQ_add.hh:35
bool adjust_playback_rate
Definition SEQ_add.hh:59
char path[1024]
Definition SEQ_add.hh:38
Stereo3dFormat * stereo3d_format
Definition SEQ_add.hh:56
Sequence * seq2
Definition SEQ_add.hh:50
int end_frame
Definition SEQ_add.hh:41
MovieClip * clip
Definition SEQ_add.hh:44
int start_frame
Definition SEQ_add.hh:34
Mask * mask
Definition SEQ_add.hh:45
char name[64]
Definition SEQ_add.hh:36
eSeqLoadFlags flags
Definition SEQ_add.hh:52
struct SeqLoadData::@1363 image
struct Scene * scene
ImageFormatData im_format
short render_size
char filename[256]
char dirpath[768]
StripElem * stripdata
int mval[2]
Definition WM_types.hh:728
const char * name
Definition WM_types.hh:990
bool(* poll_property)(const bContext *C, wmOperator *op, const PropertyRNA *prop) ATTR_WARN_UNUSED_RESULT
Definition WM_types.hh:1048
bool(* poll)(bContext *C) ATTR_WARN_UNUSED_RESULT
Definition WM_types.hh:1042
std::string(* get_description)(bContext *C, wmOperatorType *ot, PointerRNA *ptr)
Definition WM_types.hh:1074
const char * idname
Definition WM_types.hh:992
int(* invoke)(bContext *C, wmOperator *op, const wmEvent *event) ATTR_WARN_UNUSED_RESULT
Definition WM_types.hh:1022
int(* exec)(bContext *C, wmOperator *op) ATTR_WARN_UNUSED_RESULT
Definition WM_types.hh:1006
const char * description
Definition WM_types.hh:996
void(* ui)(bContext *C, wmOperator *op)
Definition WM_types.hh:1053
PropertyRNA * prop
Definition WM_types.hh:1092
StructRNA * srna
Definition WM_types.hh:1080
void(* cancel)(bContext *C, wmOperator *op)
Definition WM_types.hh:1028
struct ReportList * reports
struct uiLayout * layout
struct PointerRNA * ptr
void WM_event_add_fileselect(bContext *C, wmOperator *op)
void WM_event_add_notifier(const bContext *C, uint type, void *reference)
PointerRNA * ptr
Definition wm_files.cc:4126
wmOperatorType * ot
Definition wm_files.cc:4125
bool WM_jobs_is_running(const wmJob *wm_job)
Definition wm_jobs.cc:317
void WM_jobs_start(wmWindowManager *wm, wmJob *wm_job)
Definition wm_jobs.cc:455
void WM_operator_properties_filesel(wmOperatorType *ot, const int filter, const short type, const eFileSel_Action action, const eFileSel_Flag flag, const short display, const short sort)
int WM_enum_search_invoke(bContext *C, wmOperator *op, const wmEvent *)
uint8_t flag
Definition wm_window.cc:138