Blender V5.0
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
8
9#include <cctype>
10#include <cstdlib>
11#include <cstring>
12
14
15#include "DNA_sequence_types.h"
16#include "MEM_guardedalloc.h"
17
18#include "BLI_listbase.h"
19#include "BLI_math_base.h"
20#include "BLI_path_utils.hh"
21#include "BLI_string.h"
22#include "BLI_string_utf8.h"
23#include "BLI_utildefines.h"
24
25#include "BLT_translation.hh"
26
27#include "DNA_scene_types.h"
28#include "DNA_space_types.h"
29
30#include "BKE_context.hh"
31#include "BKE_global.hh"
32#include "BKE_lib_id.hh"
33#include "BKE_main.hh"
34#include "BKE_report.hh"
35#include "BKE_scene.hh"
36
37#include "IMB_imbuf_enums.h"
38
39#include "SEQ_channels.hh"
40#include "WM_api.hh"
41#include "WM_types.hh"
42
43#include "RNA_define.hh"
44#include "RNA_enum_types.hh"
45#include "RNA_prototypes.hh"
46
47#include "SEQ_add.hh"
48#include "SEQ_connect.hh"
49#include "SEQ_effects.hh"
50#include "SEQ_proxy.hh"
51#include "SEQ_select.hh"
52#include "SEQ_sequencer.hh"
53#include "SEQ_time.hh"
54#include "SEQ_transform.hh"
55
56#include "ED_asset.hh"
58#include "ED_image.hh"
59#include "ED_scene.hh"
60#include "ED_screen.hh"
61#include "ED_sequencer.hh"
62#include "ED_time_scrub_ui.hh"
63
64#include "UI_interface.hh"
66#include "UI_view2d.hh"
67
68#ifdef WITH_AUDASPACE
69# include <AUD_Sequence.h>
70#endif
71
72#include "DEG_depsgraph.hh"
74
75/* Own include. */
76#include "sequencer_intern.hh"
77
78namespace blender::ed::vse {
79
84
85/* Avoid passing multiple args and be more verbose. */
86#define SEQPROP_STARTFRAME (1 << 0)
87/* For image and effect strips only. */
88#define SEQPROP_LENGTH (1 << 1)
89/* Skips setting filepath or directory properties to active strip media directory,
90 * since they have already been set by the file browser or by drag and drop. */
91#define SEQPROP_NOPATHS (1 << 2)
92/* Skips guessing channel for effect strips only. */
93#define SEQPROP_NOCHAN (1 << 3)
94#define SEQPROP_FIT_METHOD (1 << 4)
95#define SEQPROP_VIEW_TRANSFORM (1 << 5)
96#define SEQPROP_PLAYBACK_RATE (1 << 6)
97#define SEQPROP_MOVE (1 << 7)
98
99/* -------------------------------------------------------------------- */
102
103static void sequencer_add_init(bContext * /*C*/, wmOperator *op)
104{
105 op->customdata = MEM_new<SequencerAddData>(__func__);
106}
107
108static void sequencer_add_free(bContext * /*C*/, wmOperator *op)
109{
110 if (op->customdata) {
111 SequencerAddData *sad = reinterpret_cast<SequencerAddData *>(op->customdata);
112 MEM_delete(sad);
113 op->customdata = nullptr;
114 }
115}
116
118{
119 PropertyRNA *prop;
120
121 if (flag & SEQPROP_MOVE) {
122 prop = RNA_def_boolean(
123 ot->srna,
124 "move_strips",
125 true,
126 "Move Strips",
127 "Automatically begin translating strips with the mouse after adding them to the timeline");
129 }
130
131 if (flag & SEQPROP_STARTFRAME) {
132 RNA_def_int(ot->srna,
133 "frame_start",
134 0,
135 INT_MIN,
136 INT_MAX,
137 "Start Frame",
138 "Start frame of the strip",
139 -MAXFRAME,
140 MAXFRAME);
141 }
142
143 if (flag & SEQPROP_LENGTH) {
144 /* Not usual since most strips have a predefined length. */
145 RNA_def_int(ot->srna,
146 "length",
147 0,
148 INT_MIN,
149 INT_MAX,
150 "Length",
151 "Length of the strip in frames, or the length of each strip if multiple are added",
152 -MAXFRAME,
153 MAXFRAME);
154 }
155
156 RNA_def_int(ot->srna,
157 "channel",
158 1,
159 1,
161 "Channel",
162 "Channel to place this strip into",
163 1,
165
166 RNA_def_boolean(ot->srna,
167 "replace_sel",
168 true,
169 "Replace Selection",
170 "Deselect previously selected strips after add operation completes");
171
172 /* Only for python scripts which import strips and place them after. */
173 prop = RNA_def_boolean(
174 ot->srna, "overlap", false, "Allow Overlap", "Don't correct overlap on new strips");
176
177 prop = RNA_def_boolean(
178 ot->srna,
179 "overlap_shuffle_override",
180 false,
181 "Override Overlap Shuffle Behavior",
182 "Use the overlap_mode tool settings to determine how to shuffle overlapping strips");
184
185 prop = RNA_def_boolean(ot->srna,
186 "skip_locked_or_muted_channels",
187 true,
188 "Skip Locked or Muted Channels",
189 "Add strips to muted or locked channels when adding movie strips");
191
192 if (flag & SEQPROP_FIT_METHOD) {
193 ot->prop = RNA_def_enum(ot->srna,
194 "fit_method",
197 "Fit Method",
198 "Mode for fitting the image to the canvas");
199 }
200
202 ot->prop = RNA_def_boolean(ot->srna,
203 "set_view_transform",
204 true,
205 "Set View Transform",
206 "Set appropriate view transform based on media color space");
207 }
208
210 ot->prop = RNA_def_boolean(ot->srna,
211 "adjust_playback_rate",
212 true,
213 "Adjust Playback Rate",
214 "Play at normal speed regardless of scene FPS");
215 }
216}
217
219 wmOperator *op,
220 const char *identifier)
221{
222 if (RNA_struct_find_property(op->ptr, identifier)) {
224 Strip *last_strip = seq::select_active_get(scene);
225 if (last_strip && last_strip->data && STRIP_HAS_PATH(last_strip)) {
226 Main *bmain = CTX_data_main(C);
227 char dirpath[FILE_MAX];
228 STRNCPY(dirpath, last_strip->data->dirpath);
229 BLI_path_abs(dirpath, ID_BLEND_PATH(bmain, &scene->id));
230 RNA_string_set(op->ptr, identifier, dirpath);
231 }
232 }
233}
234
235static int find_unlocked_unmuted_channel(const Editing *ed, int channel_index)
236{
237 const ListBase *channels = seq::channels_displayed_get(ed);
238
239 while (channel_index < seq::MAX_CHANNELS) {
240 SeqTimelineChannel *channel = seq::channel_get_by_index(channels, channel_index);
241 if (!seq::channel_is_muted(channel) && !seq::channel_is_locked(channel)) {
242 break;
243 }
244 channel_index++;
245 }
246
247 return channel_index;
248}
249
251{
252 Strip *tgt = nullptr;
255 int timeline_frame = scene->r.cfra;
256 int proximity = INT_MAX;
257
258 if (!ed || !ed->current_strips()) {
259 return 1;
260 }
261
262 LISTBASE_FOREACH (Strip *, strip, ed->current_strips()) {
263 const int strip_end = seq::time_right_handle_frame_get(scene, strip);
264 if (ELEM(type, -1, strip->type) && (strip_end <= timeline_frame) &&
265 (timeline_frame - strip_end < proximity))
266 {
267 tgt = strip;
268 proximity = timeline_frame - strip_end;
269 }
270 }
271
272 int best_channel = 1;
273 if (tgt) {
274 best_channel = (type == STRIP_TYPE_MOVIE) ? tgt->channel - 1 : tgt->channel;
275 }
276
277 best_channel = find_unlocked_unmuted_channel(ed, best_channel);
278
279 return math::clamp(best_channel, 0, seq::MAX_CHANNELS);
280}
281
283 wmOperator *op,
284 int need_channels,
285 const char **r_error_msg)
286{
287 const int channel = RNA_int_get(op->ptr, "channel");
288 const int frame_start = RNA_int_get(op->ptr, "frame_start");
289
290 /* First check simple case - strip is added to very top of timeline. */
291 const int max_channel = seq::MAX_CHANNELS - need_channels + 1;
292 if (channel > max_channel) {
293 *r_error_msg = RPT_("No available channel for the current frame.");
294 return false;
295 }
296
297 /* When adding strip(s) to lower channels, we must count number of free channels. There can be
298 * gaps. */
299 Set<int> used_channels;
300 for (Strip *strip : all_strips_from_context(C)) {
302 used_channels.add(strip->channel);
303 }
304 }
305
306 int free_channels = 0;
307 for (int i : IndexRange(channel, seq::MAX_CHANNELS - channel + 1)) {
308 if (!used_channels.contains(i)) {
309 free_channels++;
310 }
311 if (free_channels == need_channels) {
312 return true;
313 }
314 }
315
316 *r_error_msg = RPT_("No available channel for the current frame.");
317 return false;
318}
319
320/* Sets `channel` and `frame_start` properties when the operator is likely to have been invoked
321 * with drag-and-drop data. */
323 wmOperator *op,
324 const wmEvent *event)
325{
327 !RNA_collection_is_empty(op->ptr, "files")) ||
328 RNA_struct_property_is_set(op->ptr, "filepath"));
329
330 if (RNA_struct_property_is_set(op->ptr, "channel") ||
331 RNA_struct_property_is_set(op->ptr, "frame_start"))
332 {
333 return;
334 }
335
336 ARegion *region = CTX_wm_region(C);
337 if (!region || region->regiontype != RGN_TYPE_WINDOW) {
338 return;
339 }
340
341 float frame_start, channel;
342 UI_view2d_region_to_view(&region->v2d, event->mval[0], event->mval[1], &frame_start, &channel);
343 RNA_int_set(op->ptr, "channel", int(channel));
344 RNA_int_set(op->ptr, "frame_start", int(frame_start));
345}
346
348{
349 SequencerAddData *sad = reinterpret_cast<SequencerAddData *>(op->customdata);
350 if (sad == nullptr) {
351 return false;
352 }
353 return sad->is_drop_event;
354}
355
356static bool can_move_strips(const wmOperator *op)
357{
358 PropertyRNA *prop = RNA_struct_find_property(op->ptr, "move_strips");
359
360 return prop != nullptr && RNA_property_boolean_get(op->ptr, prop) &&
361 (op->flag & OP_IS_REPEAT) == 0 && !op_invoked_by_drop_event(op);
362}
363
365 bContext *C, wmOperator *op, int flag, int type, const wmEvent *event)
366{
368
369 int timeline_frame = scene->r.cfra;
370 if (event && (flag & SEQPROP_NOPATHS)) {
371 SequencerAddData *sad = reinterpret_cast<SequencerAddData *>(op->customdata);
372 sad->is_drop_event = true;
374 }
375
376 /* Effect strips shouldn't have their channel guessed. Instead,
377 * it will be set to the first free channel above the input strips. */
378 if (!(flag & SEQPROP_NOCHAN) && !RNA_struct_property_is_set(op->ptr, "channel")) {
380 }
381
382 if (!RNA_struct_property_is_set(op->ptr, "frame_start")) {
383 RNA_int_set(op->ptr, "frame_start", timeline_frame);
384 }
385
386 if ((flag & SEQPROP_LENGTH) && !RNA_struct_property_is_set(op->ptr, "length")) {
388 }
389
390 if (!(flag & SEQPROP_NOPATHS)) {
393 }
394}
395
397{
398 if (!can_move_strips(op)) {
399 return;
400 }
401
402 wmOperatorType *ot = WM_operatortype_find("TRANSFORM_OT_seq_slide", true);
405 RNA_boolean_set(&ptr, "remove_on_cancel", true);
406 RNA_boolean_set(&ptr, "view2d_edge_pan", true);
407 RNA_boolean_set(&ptr, "release_confirm", false);
410}
411
413{
414 const Main *bmain = CTX_data_main(C);
415 const ARegion *region = CTX_wm_region(C);
416
417 memset(load_data, 0, sizeof(seq::LoadData));
418
419 load_data->start_frame = RNA_int_get(op->ptr, "frame_start");
420 load_data->channel = RNA_int_get(op->ptr, "channel");
421 load_data->image.length = 1;
422 load_data->image.count = 1;
423
424 PropertyRNA *prop;
425 if ((prop = RNA_struct_find_property(op->ptr, "fit_method"))) {
426 load_data->fit_method = eSeqImageFitMethod(RNA_enum_get(op->ptr, "fit_method"));
428 }
429
430 if ((prop = RNA_struct_find_property(op->ptr, "adjust_playback_rate"))) {
431 load_data->adjust_playback_rate = RNA_boolean_get(op->ptr, "adjust_playback_rate");
432 }
433
434 if ((prop = RNA_struct_find_property(op->ptr, "filepath"))) {
435 RNA_property_string_get(op->ptr, prop, load_data->path);
436 /* File basename might be too long, better report it now than silently
437 * truncating the basename later. */
438 const char *basename = BLI_path_basename(load_data->path);
439 if (strlen(basename) >= sizeof(StripElem::filename)) {
441 RPT_ERROR,
442 "Filename '%s' too long (max length %zu, was %zu)",
443 basename,
444 sizeof(StripElem::filename),
445 strlen(basename));
446 return false;
447 }
448 STRNCPY(load_data->name, basename);
449 }
450 else if ((prop = RNA_struct_find_property(op->ptr, "directory"))) {
451 std::string directory = RNA_string_get(op->ptr, "directory");
452
453 if ((prop = RNA_struct_find_property(op->ptr, "files"))) {
454 RNA_PROP_BEGIN (op->ptr, itemptr, prop) {
455 std::string filename = RNA_string_get(&itemptr, "name");
456 STRNCPY(load_data->name, filename.c_str());
458 load_data->path, sizeof(load_data->path), directory.c_str(), filename.c_str());
459 break;
460 }
462 }
463 }
464
465 const bool relative = (prop = RNA_struct_find_property(op->ptr, "relative_path")) &&
466 RNA_property_boolean_get(op->ptr, prop);
467 if (relative) {
469 }
470
471 if ((prop = RNA_struct_find_property(op->ptr, "length"))) {
472 load_data->image.length = RNA_property_int_get(op->ptr, prop);
473 load_data->effect.length = load_data->image.length;
474 }
475
476 if ((prop = RNA_struct_find_property(op->ptr, "cache")) &&
477 RNA_property_boolean_get(op->ptr, prop))
478 {
480 }
481
482 if ((prop = RNA_struct_find_property(op->ptr, "mono")) &&
483 RNA_property_boolean_get(op->ptr, prop))
484 {
486 }
487
488 if ((prop = RNA_struct_find_property(op->ptr, "use_framerate")) &&
489 RNA_property_boolean_get(op->ptr, prop))
490 {
492 }
493
494 if ((prop = RNA_struct_find_property(op->ptr, "set_view_transform")) &&
495 RNA_property_boolean_get(op->ptr, prop))
496 {
498 }
499
500 if ((prop = RNA_struct_find_property(op->ptr, "use_multiview")) &&
501 RNA_property_boolean_get(op->ptr, prop))
502 {
503 if (op->customdata) {
504 SequencerAddData *sad = reinterpret_cast<SequencerAddData *>(op->customdata);
505 ImageFormatData *imf = &sad->im_format;
506
507 load_data->use_multiview = true;
508 load_data->views_format = imf->views_format;
509 load_data->stereo3d_format = &imf->stereo3d_format;
510 }
511 }
512
513 if (region == nullptr) {
514 RNA_boolean_set(op->ptr, "move_strips", false);
515 }
516
517 /* Override strip position by current mouse position. */
518 if (can_move_strips(op) && region != nullptr) {
519 const wmWindow *win = CTX_wm_window(C);
520 int2 mouse_region(win->eventstate->xy[0] - region->winrct.xmin,
521 win->eventstate->xy[1] - region->winrct.ymin);
522
523 /* Clamp mouse cursor location (strip starting position) to the sequencer region bounds so that
524 * it is immediately visible even if the mouse cursor is out of bounds. For maximums, use 90%
525 * of the bounds instead of 1 frame away, which works well even if zoomed out. */
527 rcti clamp_bounds;
528 BLI_rcti_init(&clamp_bounds,
529 mask.xmin,
530 mask.xmin + 0.9 * BLI_rcti_size_x(&mask),
531 mask.ymin,
532 mask.ymin + 0.9 * BLI_rcti_size_y(&mask));
533 BLI_rcti_clamp_pt_v(&clamp_bounds, mouse_region);
534
535 float2 mouse_view;
537 &region->v2d, mouse_region.x, mouse_region.y, &mouse_view.x, &mouse_view.y);
538
539 load_data->start_frame = std::trunc(mouse_view.x);
540 load_data->channel = std::trunc(mouse_view.y);
541 load_data->image.length = DEFAULT_IMG_STRIP_LENGTH;
542 load_data->effect.length = load_data->image.length;
543 }
544 return true;
545}
546
548{
550 Editing *ed = seq::editing_get(scene);
551
552 if (strip == nullptr) {
553 return;
554 }
555
556 if (RNA_boolean_get(op->ptr, "replace_sel")) {
557 strip->flag |= SELECT;
558 seq::select_active_set(scene, strip);
559 }
560
561 if (RNA_boolean_get(op->ptr, "overlap") == true ||
562 !seq::transform_test_overlap(scene, ed->current_strips(), strip))
563 {
564 /* No overlap should be handled or the strip is not overlapping, exit early. */
565 return;
566 }
567
568 if (RNA_boolean_get(op->ptr, "overlap_shuffle_override")) {
569 /* Use set overlap_mode to fix overlaps. */
571 strip_col.add(strip);
572
573 ScrArea *area = CTX_wm_area(C);
574 const bool use_sync_markers = (((SpaceSeq *)area->spacedata.first)->flag & SEQ_MARKER_TRANS) !=
575 0;
576 seq::transform_handle_overlap(scene, ed->current_strips(), strip_col, use_sync_markers);
577 }
578 else {
579 /* Shuffle strip channel to fix overlaps. */
580 seq::transform_seqbase_shuffle(ed->current_strips(), strip, scene);
581 }
582}
583
584/* In this alternative version we only check for overlap, but do not do anything about them. */
586 wmOperator *op,
587 Strip *strip)
588{
590 Editing *ed = seq::editing_get(scene);
591
592 if (strip == nullptr) {
593 return false;
594 }
595
596 if (RNA_boolean_get(op->ptr, "replace_sel")) {
597 strip->flag |= SELECT;
598 seq::select_active_set(scene, strip);
599 }
600
601 return seq::transform_test_overlap(scene, ed->current_strips(), strip);
602}
603
605{
607 /* Disable following properties if there are any existing strips, unless overridden by user. */
608 if (ed && ed->current_strips() && ed->current_strips()->first) {
609 if (RNA_struct_find_property(op->ptr, "use_framerate")) {
610 RNA_boolean_set(op->ptr, "use_framerate", false);
611 }
612 if (RNA_struct_find_property(op->ptr, "set_view_transform")) {
613 RNA_boolean_set(op->ptr, "set_view_transform", false);
614 }
615 }
616}
617
619
620/* -------------------------------------------------------------------- */
623
625{
626 Main *bmain = CTX_data_main(C);
628 const Editing *ed = seq::editing_ensure(scene);
629 Scene *sce_seq = static_cast<Scene *>(
630 BLI_findlink(&bmain->scenes, RNA_enum_get(op->ptr, "scene")));
631
632 if (sce_seq == nullptr) {
633 BKE_report(op->reports, RPT_ERROR, "Scene not found");
634 return OPERATOR_CANCELLED;
635 }
636
637 const char *error_msg;
638 if (!have_free_channels(C, op, 1, &error_msg)) {
639 BKE_report(op->reports, RPT_ERROR, error_msg);
640 return OPERATOR_CANCELLED;
641 }
642
643 if (RNA_boolean_get(op->ptr, "replace_sel")) {
644 deselect_all_strips(scene);
645 }
646
649 load_data.scene = sce_seq;
650
651 Strip *strip = seq::add_scene_strip(scene, ed->current_strips(), &load_data);
653
657 move_strips(C, op);
658
659 return OPERATOR_FINISHED;
660}
661
663 wmOperator *op,
664 const wmEvent *event)
665{
667 if (!RNA_struct_property_is_set(op->ptr, "scene")) {
668 return WM_enum_search_invoke(C, op, event);
669 }
670
673}
674
676{
677 PropertyRNA *prop;
678
679 /* Identifiers. */
680 ot->name = "Add Scene Strip";
681 ot->idname = "SEQUENCER_OT_scene_strip_add";
682 ot->description = "Add a strip re-using this scene as the source";
683
684 /* API callbacks. */
688
689 /* Flags. */
691
693 prop = RNA_def_enum(ot->srna, "scene", rna_enum_dummy_NULL_items, 0, "Scene", "");
696 ot->prop = prop;
697}
698
700
701/* -------------------------------------------------------------------- */
704
706 {SCE_COPY_NEW, "NEW", 0, "New", "Add new Strip with a new empty Scene with default settings"},
708 "EMPTY",
709 0,
710 "Copy Settings",
711 "Add a new Strip, with an empty scene, and copy settings from the current scene"},
713 "LINK_COPY",
714 0,
715 "Linked Copy",
716 "Add a Strip and link in the collections from the current scene (shallow copy)"},
718 "FULL_COPY",
719 0,
720 "Full Copy",
721 "Add a Strip and make a full copy of the current scene"},
722 {0, nullptr, 0, nullptr, nullptr},
723};
724
726{
727 Main *bmain = CTX_data_main(C);
729 const Editing *ed = seq::editing_ensure(scene);
730
731 const char *error_msg;
732 if (!have_free_channels(C, op, 1, &error_msg)) {
733 BKE_report(op->reports, RPT_ERROR, error_msg);
734 return OPERATOR_CANCELLED;
735 }
736
737 if (RNA_boolean_get(op->ptr, "replace_sel")) {
738 deselect_all_strips(scene);
739 }
740
743
744 int type = RNA_enum_get(op->ptr, "type");
745 Scene *scene_new = ED_scene_sequencer_add(bmain, C, eSceneCopyMethod(type));
746 if (scene_new == nullptr) {
747 return OPERATOR_CANCELLED;
748 }
749 load_data.scene = scene_new;
750
751 Strip *strip = seq::add_scene_strip(scene, ed->current_strips(), &load_data);
753
757 move_strips(C, op);
758
759 return OPERATOR_FINISHED;
760}
761
770
772{
773 /* Identifiers. */
774 ot->name = "Add Strip with a new Scene";
775 ot->idname = "SEQUENCER_OT_scene_strip_add_new";
776 ot->description = "Add a strip using a new scene as the source";
777
778 /* API callbacks. */
782
783 /* Flags. */
785
787
788 ot->prop = RNA_def_enum(ot->srna, "type", strip_new_scene_items, SCE_COPY_NEW, "Type", "");
789}
790
792
793/* -------------------------------------------------------------------- */
796
803 ReportList & /*reports*/)
804{
805 Main &bmain = *CTX_data_main(&C);
806 Scene *scene_asset = reinterpret_cast<Scene *>(
808
809 if (asset.is_local_id()) {
810 /* Local scene that needs to be duplicated. */
811 Scene *scene_copy = BKE_scene_duplicate(
812 &bmain,
813 scene_asset,
815 static_cast<eDupli_ID_Flags>(U.dupflag | USER_DUP_OBJECT),
817 return scene_copy;
818 }
819 return scene_asset;
820}
821
823 wmOperator *op,
824 const wmEvent *event)
825{
826 Main *bmain = CTX_data_main(C);
828 if (!scene) {
829 return OPERATOR_CANCELLED;
830 }
832 BLI_assert(ed != nullptr);
833
835
839 if (!asset) {
840 return OPERATOR_CANCELLED;
841 }
842
843 Scene *scene_asset = sequencer_add_scene_asset(*C, *asset, *op->reports);
844 if (!scene_asset) {
845 return OPERATOR_CANCELLED;
846 }
847
848 const char *error_msg;
849 if (!have_free_channels(C, op, 1, &error_msg)) {
850 BKE_report(op->reports, RPT_ERROR, error_msg);
851 return OPERATOR_CANCELLED;
852 }
853
854 if (RNA_boolean_get(op->ptr, "replace_sel")) {
855 deselect_all_strips(scene);
856 }
857
860 load_data.scene = scene_asset;
861
862 Strip *strip = seq::add_scene_strip(scene, ed->current_strips(), &load_data);
864
868 move_strips(C, op);
869
870 return OPERATOR_FINISHED;
871}
872
874 wmOperatorType * /*ot*/,
876{
879 if (!asset) {
880 return "";
881 }
882 const AssetMetaData &asset_data = asset->get_metadata();
883 if (!asset_data.description) {
884 return "";
885 }
886 return TIP_(asset_data.description);
887}
888
890{
891 ot->name = "Add Scene Asset";
892 ot->description = "Add a strip using a duplicate of this scene asset as the source";
893 ot->idname = "SEQUENCER_OT_add_scene_strip_from_scene_asset";
894
898
900
902
904}
905
907
908/* -------------------------------------------------------------------- */
911
913{
914 Main *bmain = CTX_data_main(C);
916 const Editing *ed = seq::editing_ensure(scene);
917 MovieClip *clip = static_cast<MovieClip *>(
918 BLI_findlink(&bmain->movieclips, RNA_enum_get(op->ptr, "clip")));
919
920 if (clip == nullptr) {
921 BKE_report(op->reports, RPT_ERROR, "Movie clip not found");
922 return OPERATOR_CANCELLED;
923 }
924
925 const char *error_msg;
926 if (!have_free_channels(C, op, 1, &error_msg)) {
927 BKE_report(op->reports, RPT_ERROR, error_msg);
928 return OPERATOR_CANCELLED;
929 }
930
931 if (RNA_boolean_get(op->ptr, "replace_sel")) {
932 deselect_all_strips(scene);
933 }
934
937 return OPERATOR_CANCELLED;
938 }
939 load_data.clip = clip;
940
941 Strip *strip = seq::add_movieclip_strip(scene, ed->current_strips(), &load_data);
943
946 move_strips(C, op);
947
948 return OPERATOR_FINISHED;
949}
950
952 wmOperator *op,
953 const wmEvent *event)
954{
955 if (!RNA_struct_property_is_set(op->ptr, "clip")) {
956 return WM_enum_search_invoke(C, op, event);
957 }
958
961}
962
964{
965 PropertyRNA *prop;
966
967 /* Identifiers. */
968 ot->name = "Add MovieClip Strip";
969 ot->idname = "SEQUENCER_OT_movieclip_strip_add";
970 ot->description = "Add a movieclip strip to the sequencer";
971
972 /* API callbacks. */
976
977 /* Flags. */
979
981 prop = RNA_def_enum(ot->srna, "clip", rna_enum_dummy_NULL_items, 0, "Clip", "");
985 ot->prop = prop;
986}
987
989
990/* -------------------------------------------------------------------- */
993
995{
996 Main *bmain = CTX_data_main(C);
998 const Editing *ed = seq::editing_ensure(scene);
999 Mask *mask = static_cast<Mask *>(BLI_findlink(&bmain->masks, RNA_enum_get(op->ptr, "mask")));
1000
1001 if (mask == nullptr) {
1002 BKE_report(op->reports, RPT_ERROR, "Mask not found");
1003 return OPERATOR_CANCELLED;
1004 }
1005
1006 const char *error_msg;
1007 if (!have_free_channels(C, op, 1, &error_msg)) {
1008 BKE_report(op->reports, RPT_ERROR, error_msg);
1009 return OPERATOR_CANCELLED;
1010 }
1011
1012 if (RNA_boolean_get(op->ptr, "replace_sel")) {
1013 deselect_all_strips(scene);
1014 }
1015
1018 load_data.mask = mask;
1019
1020 Strip *strip = seq::add_mask_strip(scene, ed->current_strips(), &load_data);
1022
1025 move_strips(C, op);
1026
1027 return OPERATOR_FINISHED;
1028}
1029
1031 wmOperator *op,
1032 const wmEvent *event)
1033{
1034 if (!RNA_struct_property_is_set(op->ptr, "mask")) {
1035 return WM_enum_search_invoke(C, op, event);
1036 }
1037
1039 return sequencer_add_mask_strip_exec(C, op);
1040}
1041
1043{
1044 PropertyRNA *prop;
1045
1046 /* Identifiers. */
1047 ot->name = "Add Mask Strip";
1048 ot->idname = "SEQUENCER_OT_mask_strip_add";
1049 ot->description = "Add a mask strip to the sequencer";
1050
1051 /* API callbacks. */
1055
1056 /* Flags. */
1057 ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
1058
1060 prop = RNA_def_enum(ot->srna, "mask", rna_enum_dummy_NULL_items, 0, "Mask", "");
1063 ot->prop = prop;
1064}
1065
1067
1068/* -------------------------------------------------------------------- */
1071
1072/* Strips are added in context of timeline which has different preview size than actual preview. We
1073 * must search for preview area. In most cases there will be only one preview area, but there can
1074 * be more with different preview sizes. */
1076{
1077 bScreen *screen = CTX_wm_screen(C);
1079 LISTBASE_FOREACH (ScrArea *, area, &screen->areabase) {
1080 LISTBASE_FOREACH (SpaceLink *, sl, &area->spacedata) {
1081 switch (sl->spacetype) {
1082 case SPACE_SEQ: {
1083 SpaceSeq *sseq = (SpaceSeq *)sl;
1085 continue;
1086 }
1089 }
1090 }
1091 }
1092 }
1093 return proxy_sizes;
1094}
1095
1097{
1098 if (U.sequencer_proxy_setup != USER_SEQ_PROXY_SETUP_AUTOMATIC) {
1099 return;
1100 }
1101
1104
1105 for (Strip *strip : movie_strips) {
1106 /* Enable and set proxy size. */
1107 seq::proxy_set(strip, true);
1108 strip->data->proxy->build_size_flags = seq_get_proxy_size_flags(C);
1109 strip->data->proxy->build_flags |= SEQ_PROXY_SKIP_EXISTING;
1111 pj->main, pj->depsgraph, pj->scene, strip, nullptr, &pj->queue, true);
1112 }
1113
1114 if (!WM_jobs_is_running(wm_job)) {
1115 G.is_break = false;
1116 WM_jobs_start(CTX_wm_manager(C), wm_job);
1117 }
1119}
1120
1122 Main *bmain, Scene *scene, Strip *strip_movie, Strip *strip_sound, seq::LoadData *load_data)
1123{
1124 if (ELEM(nullptr, strip_movie, strip_sound)) {
1125 return;
1126 }
1127
1128 /* Make sure that the sound strip start time relative to the movie is taken into account. */
1129 seq::add_sound_av_sync(bmain, scene, strip_sound, load_data);
1130
1131 /* Expand missing sound data in the underlying container to fill the movie strip's length. To the
1132 * user, this missing data is the same as complete silence, so we pretend like it is. */
1133 strip_sound->len = std::max(strip_movie->len, strip_sound->len);
1134
1135 /* Ensure that length matches the movie strip even if the underlying sound data
1136 * doesn't match up (e.g. it is longer). */
1138 scene, strip_sound, seq::time_right_handle_frame_get(scene, strip_movie));
1140 scene, strip_sound, seq::time_left_handle_frame_get(scene, strip_movie));
1141}
1142
1144 wmOperator *op,
1146 blender::VectorSet<Strip *> &r_movie_strips)
1147{
1148 Main *bmain = CTX_data_main(C);
1150 const Editing *ed = seq::editing_ensure(scene);
1151 bool overlap_shuffle_override = RNA_boolean_get(op->ptr, "overlap") == false &&
1152 RNA_boolean_get(op->ptr, "overlap_shuffle_override");
1153 bool has_seq_overlap = false;
1154 blender::Vector<Strip *> added_strips;
1155
1156 RNA_BEGIN (op->ptr, itemptr, "files") {
1157 char dir_only[FILE_MAX];
1158 char file_only[FILE_MAX];
1159 RNA_string_get(op->ptr, "directory", dir_only);
1160 RNA_string_get(&itemptr, "name", file_only);
1161 BLI_path_join(load_data->path, sizeof(load_data->path), dir_only, file_only);
1162 STRNCPY(load_data->name, file_only);
1163 Strip *strip_movie = nullptr;
1164 Strip *strip_sound = nullptr;
1165
1166 strip_movie = seq::add_movie_strip(bmain, scene, ed->current_strips(), load_data);
1167
1168 if (strip_movie == nullptr) {
1169 BKE_reportf(op->reports, RPT_ERROR, "File '%s' could not be loaded", load_data->path);
1170 }
1171 else {
1172 if (RNA_boolean_get(op->ptr, "sound")) {
1173 strip_sound = seq::add_sound_strip(bmain, scene, ed->current_strips(), load_data);
1174 sequencer_add_movie_sync_sound_strip(bmain, scene, strip_movie, strip_sound, load_data);
1175 added_strips.append(strip_movie);
1176
1177 if (strip_sound) {
1178 /* The video has sound, shift the video strip up a channel to make room for the sound
1179 * strip. */
1180 added_strips.append(strip_sound);
1181 seq::strip_channel_set(strip_movie,
1182 find_unlocked_unmuted_channel(ed, strip_movie->channel + 1));
1183 }
1184 }
1185
1186 load_data->start_frame += seq::time_right_handle_frame_get(scene, strip_movie) -
1187 seq::time_left_handle_frame_get(scene, strip_movie);
1188 if (overlap_shuffle_override) {
1189 has_seq_overlap |= seq_load_apply_generic_options_only_test_overlap(C, op, strip_sound);
1190 has_seq_overlap |= seq_load_apply_generic_options_only_test_overlap(C, op, strip_movie);
1191 }
1192 else {
1193 seq_load_apply_generic_options(C, op, strip_sound);
1194 seq_load_apply_generic_options(C, op, strip_movie);
1195 }
1196
1197 if (U.sequencer_editor_flag & USER_SEQ_ED_CONNECT_STRIPS_BY_DEFAULT) {
1198 seq::connect(strip_movie, strip_sound);
1199 }
1200
1201 r_movie_strips.add(strip_movie);
1202 }
1203 }
1204 RNA_END;
1205
1206 if (overlap_shuffle_override) {
1207 if (has_seq_overlap) {
1208 ScrArea *area = CTX_wm_area(C);
1209 const bool use_sync_markers = (((SpaceSeq *)area->spacedata.first)->flag &
1210 SEQ_MARKER_TRANS) != 0;
1211 seq::transform_handle_overlap(scene, ed->current_strips(), added_strips, use_sync_markers);
1212 }
1213 }
1214}
1215
1217 wmOperator *op,
1219 blender::VectorSet<Strip *> &r_movie_strips)
1220{
1221 Main *bmain = CTX_data_main(C);
1223 const Editing *ed = seq::editing_ensure(scene);
1224
1225 Strip *strip_movie = nullptr;
1226 Strip *strip_sound = nullptr;
1227 blender::Vector<Strip *> added_strips;
1228
1229 strip_movie = seq::add_movie_strip(bmain, scene, ed->current_strips(), load_data);
1230
1231 if (strip_movie == nullptr) {
1232 BKE_reportf(op->reports, RPT_ERROR, "File '%s' could not be loaded", load_data->path);
1233 return false;
1234 }
1235 if (RNA_boolean_get(op->ptr, "sound")) {
1236 strip_sound = seq::add_sound_strip(bmain, scene, ed->current_strips(), load_data);
1237 sequencer_add_movie_sync_sound_strip(bmain, scene, strip_movie, strip_sound, load_data);
1238 added_strips.append(strip_movie);
1239
1240 if (strip_sound) {
1241 added_strips.append(strip_sound);
1242
1243 /* The video has sound, shift the video strip up a channel to make room for the sound
1244 * strip. */
1245 int movie_channel = strip_movie->channel + 1;
1246
1247 if (RNA_boolean_get(op->ptr, "skip_locked_or_muted_channels")) {
1248 movie_channel = find_unlocked_unmuted_channel(ed, strip_movie->channel + 1);
1249 }
1250
1251 seq::strip_channel_set(strip_movie, movie_channel);
1252 }
1253 }
1254
1255 bool overlap_shuffle_override = RNA_boolean_get(op->ptr, "overlap") == false &&
1256 RNA_boolean_get(op->ptr, "overlap_shuffle_override");
1257 if (overlap_shuffle_override) {
1258 bool has_seq_overlap = false;
1259
1260 has_seq_overlap |= seq_load_apply_generic_options_only_test_overlap(C, op, strip_sound);
1261 has_seq_overlap |= seq_load_apply_generic_options_only_test_overlap(C, op, strip_movie);
1262
1263 if (has_seq_overlap) {
1264 ScrArea *area = CTX_wm_area(C);
1265 const bool use_sync_markers = (((SpaceSeq *)area->spacedata.first)->flag &
1266 SEQ_MARKER_TRANS) != 0;
1267 seq::transform_handle_overlap(scene, ed->current_strips(), added_strips, use_sync_markers);
1268 }
1269 }
1270 else {
1271 seq_load_apply_generic_options(C, op, strip_sound);
1272 seq_load_apply_generic_options(C, op, strip_movie);
1273 }
1274
1275 if (U.sequencer_editor_flag & USER_SEQ_ED_CONNECT_STRIPS_BY_DEFAULT) {
1276 seq::connect(strip_movie, strip_sound);
1277 }
1278
1279 r_movie_strips.add(strip_movie);
1280
1281 return true;
1282}
1283
1285{
1286 Main *bmain = CTX_data_main(C);
1289
1291 return OPERATOR_CANCELLED;
1292 }
1293
1295
1296 const char *error_msg;
1297 if (!have_free_channels(C, op, 2, &error_msg)) {
1298 BKE_report(op->reports, RPT_ERROR, error_msg);
1299 return OPERATOR_CANCELLED;
1300 }
1301
1302 if (RNA_boolean_get(op->ptr, "replace_sel")) {
1303 deselect_all_strips(scene);
1304 }
1305
1306 blender::VectorSet<Strip *> movie_strips;
1307 const int tot_files = RNA_property_collection_length(op->ptr,
1308 RNA_struct_find_property(op->ptr, "files"));
1309
1310 char vt_old[64];
1312 float fps_old = scene->r.frs_sec / scene->r.frs_sec_base;
1313
1314 if (tot_files > 1) {
1315 sequencer_add_movie_multiple_strips(C, op, &load_data, movie_strips);
1316 }
1317 else {
1318 sequencer_add_movie_single_strip(C, op, &load_data, movie_strips);
1319 }
1320
1321 if (!STREQ(vt_old, scene->view_settings.view_transform)) {
1322 BKE_reportf(op->reports,
1324 "View transform set to %s (converted from %s)",
1326 vt_old);
1327 }
1328
1329 if (fps_old != scene->r.frs_sec / scene->r.frs_sec_base) {
1330 BKE_reportf(op->reports,
1332 "Scene frame rate set to %.4g (converted from %.4g)",
1333 scene->r.frs_sec / scene->r.frs_sec_base,
1334 fps_old);
1335 }
1336
1337 if (movie_strips.is_empty()) {
1338 sequencer_add_free(C, op);
1339 return OPERATOR_CANCELLED;
1340 }
1341
1342 seq_build_proxy(C, movie_strips);
1346 move_strips(C, op);
1347
1348 sequencer_add_free(C, op);
1349
1350 return OPERATOR_FINISHED;
1351}
1352
1354 wmOperator *op,
1355 const wmEvent *event)
1356{
1357 PropertyRNA *prop;
1359
1361 sequencer_add_init(C, op);
1362
1363 RNA_enum_set(op->ptr, "fit_method", seq::tool_settings_fit_method_get(scene));
1364 RNA_boolean_set(op->ptr, "adjust_playback_rate", true);
1365
1366 /* This is for drag and drop. */
1367 if ((RNA_struct_property_is_set(op->ptr, "files") &&
1368 !RNA_collection_is_empty(op->ptr, "files")) ||
1369 RNA_struct_property_is_set(op->ptr, "filepath"))
1370 {
1372
1373 const char *error_msg;
1374 if (!have_free_channels(C, op, 2, &error_msg)) {
1375 BKE_report(op->reports, RPT_ERROR, error_msg);
1376 return OPERATOR_CANCELLED;
1377 }
1378
1380 }
1381
1383
1384 /* Show multiview save options only if scene use multiview. */
1385 prop = RNA_struct_find_property(op->ptr, "show_multiview");
1386 RNA_property_boolean_set(op->ptr, prop, (scene->r.scemode & R_MULTIVIEW) != 0);
1387
1390}
1391
1392static bool sequencer_add_draw_check_fn(PointerRNA *ptr, PropertyRNA *prop, void * /*user_data*/)
1393{
1394 const char *prop_id = RNA_property_identifier(prop);
1395
1396 /* Only show placeholders option if sequence detection is enabled. */
1397 if (STREQ(prop_id, "use_placeholders")) {
1398 return RNA_boolean_get(ptr, "use_sequence_detection");
1399 }
1400
1401 return !STR_ELEM(prop_id,
1402 "filepath",
1403 "directory",
1404 "filename",
1405 "frame_start",
1406 "channel",
1407 "length",
1408 "move_strips",
1409 "replace_sel");
1410}
1411
1412static void sequencer_add_draw(bContext * /*C*/, wmOperator *op)
1413{
1414 uiLayout *layout = op->layout;
1415 SequencerAddData *sad = reinterpret_cast<SequencerAddData *>(op->customdata);
1416 ImageFormatData *imf = &sad->im_format;
1417
1418 bool is_redo_panel = sad == nullptr;
1419
1420 if (!is_redo_panel) {
1421 layout->prop(op->ptr, "move_strips", UI_ITEM_NONE, std::nullopt, ICON_NONE);
1422 }
1423 if (!RNA_boolean_get(op->ptr, "move_strips") || is_redo_panel) {
1424 uiLayout &col = layout->column(true);
1425 col.prop(op->ptr, "frame_start", UI_ITEM_NONE, std::nullopt, ICON_NONE);
1426 if (RNA_struct_find_property(op->ptr, "length")) {
1427 col.prop(op->ptr, "length", UI_ITEM_NONE, std::nullopt, ICON_NONE);
1428 }
1429 layout->prop(op->ptr, "channel", UI_ITEM_NONE, std::nullopt, ICON_NONE);
1430 layout->separator();
1431 layout->prop(op->ptr, "replace_sel", UI_ITEM_NONE, std::nullopt, ICON_NONE);
1432 }
1433
1434 /* Main draw call. */
1435 uiDefAutoButsRNA(layout,
1436 op->ptr,
1438 nullptr,
1439 nullptr,
1441 false);
1442
1443 layout->separator();
1444
1445 /* Image template. */
1446 PointerRNA imf_ptr = RNA_pointer_create_discrete(nullptr, &RNA_ImageFormatSettings, imf);
1447
1448 /* Multiview template. */
1449 if (RNA_boolean_get(op->ptr, "show_multiview")) {
1450 uiTemplateImageFormatViews(layout, &imf_ptr, op->ptr);
1451 }
1452}
1453
1455{
1456
1457 /* Identifiers. */
1458 ot->name = "Add Movie Strip";
1459 ot->idname = "SEQUENCER_OT_movie_strip_add";
1460 ot->description = "Add a movie strip to the sequencer";
1461
1462 /* API callbacks. */
1465 ot->cancel = sequencer_add_free;
1466 ot->ui = sequencer_add_draw;
1468
1469 /* Flags. */
1470 ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
1471
1483 SEQPROP_MOVE);
1484 RNA_def_boolean(ot->srna, "sound", true, "Sound", "Load sound with the movie");
1485 RNA_def_boolean(ot->srna,
1486 "use_framerate",
1487 true,
1488 "Set Scene Frame Rate",
1489 "Set frame rate of the current scene to the frame rate of the movie");
1490}
1491
1493
1494/* -------------------------------------------------------------------- */
1497
1499 wmOperator *op,
1501{
1502 Main *bmain = CTX_data_main(C);
1504 Editing *ed = seq::editing_ensure(scene);
1505
1506 RNA_BEGIN (op->ptr, itemptr, "files") {
1507 char dir_only[FILE_MAX];
1508 char file_only[FILE_MAX];
1509 RNA_string_get(op->ptr, "directory", dir_only);
1510 RNA_string_get(&itemptr, "name", file_only);
1511 BLI_path_join(load_data->path, sizeof(load_data->path), dir_only, file_only);
1512 STRNCPY(load_data->name, file_only);
1513 Strip *strip = seq::add_sound_strip(bmain, scene, ed->current_strips(), load_data);
1514 if (strip == nullptr) {
1515 BKE_reportf(op->reports, RPT_ERROR, "File '%s' could not be loaded", load_data->path);
1516 }
1517 else {
1519 load_data->start_frame += seq::time_right_handle_frame_get(scene, strip) -
1520 seq::time_left_handle_frame_get(scene, strip);
1521 }
1522 }
1523 RNA_END;
1524}
1525
1527{
1528 Main *bmain = CTX_data_main(C);
1530 Editing *ed = seq::editing_ensure(scene);
1531
1532 Strip *strip = seq::add_sound_strip(bmain, scene, ed->current_strips(), load_data);
1533 if (strip == nullptr) {
1534 BKE_reportf(op->reports, RPT_ERROR, "File '%s' could not be loaded", load_data->path);
1535 return false;
1536 }
1538
1539 return true;
1540}
1541
1543{
1544 Main *bmain = CTX_data_main(C);
1548
1549 const char *error_msg;
1550 if (!have_free_channels(C, op, 1, &error_msg)) {
1551 BKE_report(op->reports, RPT_ERROR, error_msg);
1552 return OPERATOR_CANCELLED;
1553 }
1554
1555 if (RNA_boolean_get(op->ptr, "replace_sel")) {
1556 deselect_all_strips(scene);
1557 }
1558
1559 const int tot_files = RNA_property_collection_length(op->ptr,
1560 RNA_struct_find_property(op->ptr, "files"));
1561 if (tot_files > 1) {
1563 }
1564 else {
1566 sequencer_add_free(C, op);
1567 return OPERATOR_CANCELLED;
1568 }
1569 }
1570
1574 move_strips(C, op);
1575
1576 sequencer_add_free(C, op);
1577
1578 return OPERATOR_FINISHED;
1579}
1580
1582 wmOperator *op,
1583 const wmEvent *event)
1584{
1585 sequencer_add_init(C, op);
1586
1587 /* This is for drag and drop. */
1588 if ((RNA_struct_property_is_set(op->ptr, "files") &&
1589 !RNA_collection_is_empty(op->ptr, "files")) ||
1590 RNA_struct_property_is_set(op->ptr, "filepath"))
1591 {
1593
1594 const char *error_msg;
1595 if (!have_free_channels(C, op, 1, &error_msg)) {
1596 BKE_report(op->reports, RPT_ERROR, error_msg);
1597 return OPERATOR_CANCELLED;
1598 }
1599
1601 }
1602
1604
1607}
1608
1610{
1611
1612 /* Identifiers. */
1613 ot->name = "Add Sound Strip";
1614 ot->idname = "SEQUENCER_OT_sound_strip_add";
1615 ot->description = "Add a sound strip to the sequencer";
1616
1617 /* API callbacks. */
1621
1622 /* Flags. */
1623 ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
1624
1634 RNA_def_boolean(ot->srna, "cache", false, "Cache", "Cache the sound in memory");
1635 RNA_def_boolean(ot->srna, "mono", false, "Mono", "Merge all the sound's channels into one");
1636}
1637
1639
1640/* -------------------------------------------------------------------- */
1643
1645 int sfra,
1646 int *r_minframe,
1647 int *r_numdigits)
1648{
1649 int minframe = INT32_MAX, maxframe = INT32_MIN;
1650 int numdigits = 0;
1651
1652 RNA_BEGIN (op->ptr, itemptr, "files") {
1653 int frame;
1654 std::string filename = RNA_string_get(&itemptr, "name");
1655
1656 if (!filename.empty()) {
1657 if (BLI_path_frame_get(filename.c_str(), &frame, &numdigits)) {
1658 minframe = min_ii(minframe, frame);
1659 maxframe = max_ii(maxframe, frame);
1660 }
1661 }
1662 }
1663 RNA_END;
1664
1665 if (minframe == INT32_MAX) {
1666 minframe = sfra;
1667 maxframe = minframe + 1;
1668 }
1669
1670 *r_minframe = minframe;
1671 *r_numdigits = numdigits;
1672
1673 return maxframe - minframe + 1;
1674}
1675
1677 wmOperator *op, StripElem *se, int len, int minframe, int numdigits)
1678{
1679 char *filename = nullptr;
1680 RNA_BEGIN (op->ptr, itemptr, "files") {
1681 filename = RNA_string_get_alloc(&itemptr, "name", nullptr, 0, nullptr);
1682 break;
1683 }
1684 RNA_END;
1685
1686 if (filename) {
1687 char ext[FILE_MAX];
1688 char filename_stripped[FILE_MAX];
1689 /* Strip the frame from filename and substitute with `#`. */
1690 BLI_path_frame_strip(filename, ext, sizeof(ext));
1691
1692 for (int i = 0; i < len; i++, se++) {
1693 STRNCPY(filename_stripped, filename);
1694 BLI_path_frame(filename_stripped, sizeof(filename_stripped), minframe + i, numdigits);
1695 SNPRINTF(se->filename, "%s%s", filename_stripped, ext);
1696 }
1697
1698 MEM_freeN(filename);
1699 }
1700}
1701
1702static void frame_filename_set(char *dst,
1703 size_t dst_len,
1704 const char *filename_stripped,
1705 const int frame,
1706 const int numdigits,
1707 const char *ext)
1708{
1709 BLI_strncpy(dst, filename_stripped, dst_len);
1710 BLI_path_frame(dst, dst_len, frame, numdigits);
1711 BLI_path_extension_ensure(dst, dst_len, ext);
1712}
1713
1715 Scene *scene,
1716 Strip *strip,
1718 const ImageFrameRange *range)
1719{
1720 int framenr, numdigits;
1721 BLI_path_frame_get(load_data->path, &framenr, &numdigits);
1722 char ext[FILE_MAX];
1723 char filename_stripped[FILE_MAX];
1724 BLI_path_split_file_part(load_data->path, filename_stripped, sizeof(filename_stripped));
1725 BLI_path_frame_strip(filename_stripped, ext, sizeof(ext));
1726
1727 StripElem *se = strip->data->stripdata;
1728 const bool use_placeholders = RNA_boolean_get(op->ptr, "use_placeholders");
1729 if (use_placeholders) {
1730 for (int i = range->offset; i < range->max_framenr + 1; i++, se++) {
1731 frame_filename_set(se->filename, sizeof(se->filename), filename_stripped, i, numdigits, ext);
1732 }
1733 }
1734 else {
1735 size_t strip_frame = 0;
1736 LISTBASE_FOREACH (ImageFrame *, frame, &range->frames) {
1737 char filename[FILE_MAX];
1739 filename, sizeof(filename), filename_stripped, frame->framenr, numdigits, ext);
1740 seq::add_image_load_file(scene, strip, strip_frame, filename);
1741 strip_frame++;
1742 }
1743 }
1744}
1745
1747{
1748 Main *bmain = CTX_data_main(C);
1750 Editing *ed = seq::editing_ensure(scene);
1751
1754 return OPERATOR_CANCELLED;
1755 }
1756
1757 const char *error_msg;
1758 if (!have_free_channels(C, op, 1, &error_msg)) {
1759 BKE_report(op->reports, RPT_ERROR, error_msg);
1760 return OPERATOR_CANCELLED;
1761 }
1762
1763 const char *blendfile_path = BKE_main_blendfile_path(bmain);
1764 ListBase ranges = ED_image_filesel_detect_sequences(blendfile_path, blendfile_path, op, false);
1765 if (BLI_listbase_is_empty(&ranges)) {
1766 sequencer_add_free(C, op);
1767 return OPERATOR_CANCELLED;
1768 }
1769
1770 if (RNA_boolean_get(op->ptr, "replace_sel")) {
1771 deselect_all_strips(scene);
1772 }
1773
1774 char vt_old[64];
1776
1777 const bool use_placeholders = RNA_boolean_get(op->ptr, "use_placeholders");
1778 LISTBASE_FOREACH (ImageFrameRange *, range, &ranges) {
1779 /* Populate `load_data` with data from `range`. */
1780 load_data.image.count = use_placeholders ? range->max_framenr - range->offset + 1 :
1781 BLI_listbase_count(&range->frames);
1782 STRNCPY(load_data.path, range->filepath);
1783 BLI_path_split_file_part(load_data.path, load_data.name, sizeof(load_data.name));
1784
1785 Strip *strip = seq::add_image_strip(bmain, scene, ed->current_strips(), &load_data);
1786 const bool is_sequence = !seq::transform_single_image_check(strip);
1787
1788 char dirpath[sizeof(strip->data->dirpath)];
1789 BLI_path_split_dir_part(load_data.path, dirpath, sizeof(dirpath));
1790 seq::add_image_set_directory(strip, dirpath);
1791
1792 /* Set `StripElem` filenames, one for each `ImageFrame` in this range, or if `use_placeholders`
1793 * is set, every frame between `offset` and `max_framenr` . */
1794 sequencer_add_image_strip_load_files(op, scene, strip, &load_data, range);
1795
1796 seq::add_image_init_alpha_mode(bmain, scene, strip);
1797
1798 /* Adjust starting length of strip.
1799 * Note that this length differs from `strip->len`, which is always 1 for single images. */
1800 if (!is_sequence) {
1802 scene, strip, load_data.start_frame + load_data.image.length);
1803 }
1804
1806 load_data.start_frame += is_sequence ? load_data.image.count : load_data.image.length;
1807 BLI_freelistN(&range->frames);
1808 }
1809 BLI_freelistN(&ranges);
1810
1811 if (!STREQ(vt_old, scene->view_settings.view_transform)) {
1812 BKE_reportf(op->reports,
1814 "View transform set to %s (converted from %s)",
1816 vt_old);
1817 }
1818
1821 move_strips(C, op);
1822
1823 sequencer_add_free(C, op);
1824
1825 return OPERATOR_FINISHED;
1826}
1827
1829 wmOperator *op,
1830 const wmEvent *event)
1831{
1832 PropertyRNA *prop;
1834
1836 sequencer_add_init(C, op);
1837
1838 RNA_enum_set(op->ptr, "fit_method", seq::tool_settings_fit_method_get(scene));
1839
1840 /* Name set already by drag and drop. */
1841 if (RNA_struct_property_is_set(op->ptr, "files") && !RNA_collection_is_empty(op->ptr, "files")) {
1844
1845 const char *error_msg;
1846 if (!have_free_channels(C, op, 1, &error_msg)) {
1847 BKE_report(op->reports, RPT_ERROR, error_msg);
1848 return OPERATOR_CANCELLED;
1849 }
1850
1852 }
1853
1855
1856 /* Show multiview save options only if the scene uses multiview. */
1857 prop = RNA_struct_find_property(op->ptr, "show_multiview");
1858 RNA_property_boolean_set(op->ptr, prop, (scene->r.scemode & R_MULTIVIEW) != 0);
1859
1862}
1863
1865{
1866
1867 /* Identifiers. */
1868 ot->name = "Add Image Strip";
1869 ot->idname = "SEQUENCER_OT_image_strip_add";
1870 ot->description = "Add an image or image sequence to the sequencer";
1871
1872 /* API callbacks. */
1875 ot->cancel = sequencer_add_free;
1876 ot->ui = sequencer_add_draw;
1878
1879 /* Flags. */
1880 ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
1881
1883 ot,
1893
1895 ot->srna,
1896 "use_sequence_detection",
1897 true,
1898 "Detect Sequences",
1899 "Automatically detect animated sequences in selected images (based on file names)");
1900
1901 RNA_def_boolean(ot->srna,
1902 "use_placeholders",
1903 false,
1904 "Use Placeholders",
1905 "Reserve placeholder frames for missing frames of the image sequence");
1906}
1907
1909
1910/* -------------------------------------------------------------------- */
1913
1915{
1917 Editing *ed = seq::editing_ensure(scene);
1918
1919 const char *error;
1920 if (!have_free_channels(C, op, 1, &error)) {
1922 return OPERATOR_CANCELLED;
1923 }
1924
1927 load_data.effect.type = RNA_enum_get(op->ptr, "type");
1928 const int num_inputs = seq::effect_get_num_inputs(load_data.effect.type);
1929
1931 StringRef error_msg = effect_inputs_validate(inputs, num_inputs);
1932
1933 if (!error_msg.is_empty()) {
1934 BKE_report(op->reports, RPT_ERROR, error_msg.data());
1935 return OPERATOR_CANCELLED;
1936 }
1937
1938 if (RNA_boolean_get(op->ptr, "replace_sel")) {
1939 deselect_all_strips(scene);
1940 }
1941
1942 Strip *input1 = inputs.size() > 0 ? inputs[0] : nullptr;
1943 Strip *input2 = inputs.size() == 2 ? inputs[1] : nullptr;
1944
1945 load_data.effect.input1 = input1;
1946 load_data.effect.input2 = input2;
1947
1948 /* Set channel. If unset, use lowest free one above strips. */
1949 if (!RNA_struct_property_is_set(op->ptr, "channel")) {
1950 if (input1 != nullptr) {
1951 int chan = max_ii(input1 ? input1->channel : 0, input2 ? input2->channel : 0);
1952 if (chan < seq::MAX_CHANNELS) {
1953 load_data.channel = chan;
1954 }
1955 }
1956 }
1957
1958 Strip *strip = seq::add_effect_strip(scene, ed->current_strips(), &load_data);
1960
1961 if (strip->type == STRIP_TYPE_COLOR) {
1962 SolidColorVars *colvars = (SolidColorVars *)strip->effectdata;
1963 RNA_float_get_array(op->ptr, "color", colvars->col);
1964 }
1965
1968
1969 /* It's reasonable to add effects with inputs directly above the input. */
1970 if (ELEM(load_data.effect.type,
1975 {
1976 move_strips(C, op);
1977 }
1978
1979 return OPERATOR_FINISHED;
1980}
1981
1983 wmOperator *op,
1984 const wmEvent *event)
1985{
1986 bool is_type_set = RNA_struct_property_is_set(op->ptr, "type");
1987 int type = -1;
1988 int prop_flag = SEQPROP_LENGTH;
1989
1990 if (!is_type_set) {
1991 BKE_report(op->reports, RPT_ERROR_INVALID_INPUT, "Strip type is not set.");
1992 return OPERATOR_CANCELLED;
1993 }
1994
1995 type = RNA_enum_get(op->ptr, "type");
1996
1997 /* When invoking an effect strip which uses inputs, skip guessing of the channel. */
1998 if (seq::effect_get_num_inputs(type) != 0) {
1999 prop_flag |= SEQPROP_NOCHAN;
2000 }
2001
2002 sequencer_generic_invoke_xy__internal(C, op, prop_flag, type, event);
2003
2005}
2006
2008 wmOperator *op,
2009 const PropertyRNA *prop)
2010{
2011 const char *prop_id = RNA_property_identifier(prop);
2012 int type = RNA_enum_get(op->ptr, "type");
2013
2014 /* Hide start frame and length for effect strips that are locked to their parents' location. */
2015 if (seq::effect_get_num_inputs(type) != 0) {
2016 if (STR_ELEM(prop_id, "frame_start", "length")) {
2017 return false;
2018 }
2019 }
2020 if ((type != STRIP_TYPE_COLOR) && STREQ(prop_id, "color")) {
2021 return false;
2022 }
2023
2024 return true;
2025}
2026
2028 wmOperatorType * /*ot*/,
2029 PointerRNA *ptr)
2030{
2031 const int type = RNA_enum_get(ptr, "type");
2032
2033 switch (type) {
2034 case STRIP_TYPE_CROSS:
2035 return TIP_("Add a crossfade transition strip for two selected strips with video content");
2036 case STRIP_TYPE_ADD:
2037 return TIP_("Add an add blend mode effect strip for two selected strips with video content");
2038 case STRIP_TYPE_SUB:
2039 return TIP_(
2040 "Add a subtract blend mode effect strip for two selected strips with video content");
2042 return TIP_(
2043 "Add an alpha over blend mode effect strip for two selected strips with video content");
2045 return TIP_(
2046 "Add an alpha under blend mode effect strip for two selected strips with video content");
2048 return TIP_(
2049 "Add a gamma crossfade transition strip for two selected strips with video content");
2050 case STRIP_TYPE_MUL:
2051 return TIP_(
2052 "Add a multiply blend mode effect strip for two selected strips with video content");
2053 case STRIP_TYPE_WIPE:
2054 return TIP_("Add a wipe transition strip for two selected strips with video content");
2055 case STRIP_TYPE_GLOW:
2056 return TIP_("Add a glow effect strip for a single selected strip with video content");
2057 case STRIP_TYPE_COLOR:
2058 return TIP_("Add a color strip to the sequencer");
2059 case STRIP_TYPE_SPEED:
2060 return TIP_("Add a video speed effect strip for a single selected strip with video content");
2062 return TIP_("Add a multicam selector effect strip to the sequencer");
2064 return TIP_("Add an adjustment layer effect strip to the sequencer");
2066 return TIP_(
2067 "Add a gaussian blur effect strip for a single selected strip with video content");
2068 case STRIP_TYPE_TEXT:
2069 return TIP_("Add a text strip to the sequencer");
2071 return TIP_("Add a color mix effect strip to the sequencer");
2072 default:
2073 break;
2074 }
2075
2076 /* Use default description. */
2077 return "";
2078}
2079
2081{
2082 PropertyRNA *prop;
2083
2084 /* Identifiers. */
2085 ot->name = "Add Effect Strip";
2086 ot->idname = "SEQUENCER_OT_effect_strip_add";
2087 ot->description = "Add an effect to the sequencer, most are applied on top of existing strips";
2088
2089 /* API callbacks. */
2095
2096 /* Flags. */
2097 ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
2098
2099 prop = RNA_def_enum(ot->srna,
2100 "type",
2103 "Type",
2104 "Sequencer effect type");
2107 /* Only used when strip is of the Color type. */
2108 prop = RNA_def_float_color(ot->srna,
2109 "color",
2110 3,
2111 nullptr,
2112 0.0f,
2113 1.0f,
2114 "Color",
2115 "Initialize the strip with this color",
2116 0.0f,
2117 1.0f);
2119}
2120
2122
2123} // namespace blender::ed::vse
Main runtime representation of an asset.
bScreen * CTX_wm_screen(const bContext *C)
ScrArea * CTX_wm_area(const bContext *C)
wmWindow * CTX_wm_window(const bContext *C)
Main * CTX_data_main(const bContext *C)
ARegion * CTX_wm_region(const bContext *C)
wmWindowManager * CTX_wm_manager(const bContext *C)
Scene * CTX_data_sequencer_scene(const bContext *C)
@ LIB_ID_DUPLICATE_IS_ROOT_ID
const char * BKE_main_blendfile_path(const Main *bmain) ATTR_NONNULL()
Definition main.cc:887
void BKE_reportf(ReportList *reports, eReportType type, const char *format,...) ATTR_PRINTF_FORMAT(3
@ RPT_ERROR_INVALID_INPUT
Definition BKE_report.hh:40
@ RPT_ERROR
Definition BKE_report.hh:39
@ RPT_WARNING
Definition BKE_report.hh:38
void BKE_report(ReportList *reports, eReportType type, const char *message)
Definition report.cc:153
eSceneCopyMethod
Definition BKE_scene.hh:32
@ SCE_COPY_EMPTY
Definition BKE_scene.hh:34
@ SCE_COPY_NEW
Definition BKE_scene.hh:33
@ SCE_COPY_FULL
Definition BKE_scene.hh:36
@ SCE_COPY_LINK_COLLECTION
Definition BKE_scene.hh:35
Scene * BKE_scene_duplicate(Main *bmain, Scene *sce, eSceneCopyMethod type, eDupli_ID_Flags duplicate_flags, uint duplicate_options)
Definition scene.cc:1783
#define BLI_assert(a)
Definition BLI_assert.h:46
void * BLI_findlink(const ListBase *listbase, int number) ATTR_WARN_UNUSED_RESULT ATTR_NONNULL(1)
Definition listbase.cc:534
#define LISTBASE_FOREACH(type, var, list)
BLI_INLINE bool BLI_listbase_is_empty(const ListBase *lb)
void void BLI_freelistN(ListBase *listbase) ATTR_NONNULL(1)
Definition listbase.cc:497
int BLI_listbase_count(const ListBase *listbase) ATTR_WARN_UNUSED_RESULT ATTR_NONNULL(1)
Definition listbase.cc:524
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(...)
void void void BLI_path_split_file_part(const char *filepath, char *file, size_t file_maxncpy) ATTR_NONNULL(1
bool BLI_path_frame_get(const char *path, int *r_frame, int *r_digits_len) ATTR_NONNULL(1
bool BLI_path_extension_ensure(char *path, size_t path_maxncpy, const char *ext) 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)
BLI_INLINE int BLI_rcti_size_y(const struct rcti *rct)
Definition BLI_rect.h:198
void BLI_rcti_init(struct rcti *rect, int xmin, int xmax, int ymin, int ymax)
Definition rct.cc:414
bool BLI_rcti_clamp_pt_v(const struct rcti *rect, int xy[2])
BLI_INLINE int BLI_rcti_size_x(const struct rcti *rct)
Definition BLI_rect.h:194
#define STR_ELEM(...)
Definition BLI_string.h:661
#define SNPRINTF(dst, format,...)
Definition BLI_string.h:604
char * STRNCPY(char(&dst)[N], const char *src)
Definition BLI_string.h:693
char * BLI_strncpy(char *__restrict dst, const char *__restrict src, size_t dst_maxncpy) ATTR_NONNULL(1
#define STRNCPY_UTF8(dst, src)
#define ELEM(...)
#define STREQ(a, b)
#define RPT_(msgid)
#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:1122
#define ID_BLEND_PATH(_bmain, _id)
Definition DNA_ID.h:685
@ ASSET_IMPORT_APPEND
eSeqImageFitMethod
@ SEQ_SCALE_TO_FIT
@ R_MULTIVIEW
#define MAXFRAME
@ RGN_TYPE_WINDOW
@ STRIP_TYPE_GAUSSIAN_BLUR
@ STRIP_TYPE_GAMCROSS
@ STRIP_TYPE_SCENE
@ STRIP_TYPE_MOVIECLIP
@ STRIP_TYPE_COLORMIX
@ STRIP_TYPE_WIPE
@ STRIP_TYPE_TEXT
@ STRIP_TYPE_SOUND_RAM
@ STRIP_TYPE_ADD
@ STRIP_TYPE_IMAGE
@ STRIP_TYPE_MOVIE
@ STRIP_TYPE_GLOW
@ STRIP_TYPE_SUB
@ STRIP_TYPE_MUL
@ STRIP_TYPE_SPEED
@ STRIP_TYPE_COLOR
@ STRIP_TYPE_ADJUSTMENT
@ STRIP_TYPE_MULTICAM
@ STRIP_TYPE_MASK
@ STRIP_TYPE_ALPHAUNDER
@ STRIP_TYPE_CROSS
@ STRIP_TYPE_ALPHAOVER
#define STRIP_HAS_PATH(_strip)
@ SEQ_PROXY_SKIP_EXISTING
@ FILE_SORT_DEFAULT
@ FILE_SPECIAL
eSpaceSeq_Proxy_RenderSize
@ 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
eDupli_ID_Flags
@ USER_DUP_OBJECT
@ USER_SEQ_PROXY_SETUP_AUTOMATIC
@ USER_SEQ_ED_CONNECT_STRIPS_BY_DEFAULT
@ OPERATOR_CANCELLED
@ OPERATOR_FINISHED
@ OPERATOR_RUNNING_MODAL
ListBase ED_image_filesel_detect_sequences(blender::StringRefNull blendfile_path, blender::StringRefNull root_path, wmOperator *op, bool detect_udim)
Scene * ED_scene_sequencer_add(Main *bmain, bContext *C, eSceneCopyMethod method)
Definition scene_edit.cc:73
void ED_area_tag_redraw(ScrArea *area)
Definition area.cc:693
bool ED_operator_sequencer_active_editable(bContext *C)
IMB_Proxy_Size
@ IMB_PROXY_NONE
Read Guarded memory(de)allocation.
#define RNA_PROP_END
#define RNA_BEGIN(sptr, itemptr, propname)
#define RNA_END
#define RNA_PROP_BEGIN(sptr, itemptr, prop)
const EnumPropertyItem * RNA_scene_without_sequencer_scene_itemf(bContext *C, PointerRNA *ptr, PropertyRNA *prop, bool *r_free)
const EnumPropertyItem * RNA_movieclip_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:432
@ PROP_SKIP_SAVE
Definition RNA_types.hh:344
@ PROP_HIDDEN
Definition RNA_types.hh:338
@ PROP_COLOR_GAMMA
Definition RNA_types.hh:272
#define C
Definition RandGen.cpp:29
@ 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)
#define UI_ITEM_NONE
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:1668
@ WM_FILESEL_FILES
Definition WM_api.hh:1125
@ WM_FILESEL_DIRECTORY
Definition WM_api.hh:1122
@ WM_FILESEL_RELPATH
Definition WM_api.hh:1121
@ WM_FILESEL_SHOW_PROPS
Definition WM_api.hh:1127
@ WM_FILESEL_FILEPATH
Definition WM_api.hh:1124
@ FILE_OPENFILE
Definition WM_api.hh:1133
@ OPTYPE_INTERNAL
Definition WM_types.hh:202
@ OPTYPE_UNDO
Definition WM_types.hh:182
@ OPTYPE_REGISTER
Definition WM_types.hh:180
#define U
bool contains(const Key &key) const
Definition BLI_set.hh:310
bool add(const Key &key)
Definition BLI_set.hh:248
constexpr bool is_empty() const
constexpr const char * data() const
bool add(const Key &key)
void append(const T &value)
#define SELECT
float4 load_data(StoredFloat4 data)
#define INT32_MAX
#define INT32_MIN
uint col
void MEM_freeN(void *vmemh)
Definition mallocn.cc:113
ccl_device_inline float2 mask(const MaskType mask, const float2 a)
#define G(x, y, z)
static void error(const char *str)
static const IMB_Proxy_Size proxy_sizes[]
void operator_asset_reference_props_register(StructRNA &srna)
const asset_system::AssetRepresentation * operator_asset_reference_props_get_asset_from_all_library(const bContext &C, PointerRNA &ptr, ReportList *reports)
ID * asset_local_id_ensure_imported(Main &bmain, const asset_system::AssetRepresentation &asset, const std::optional< eAssetImportMethod > import_method=std::nullopt)
void SEQUENCER_OT_mask_strip_add(wmOperatorType *ot)
static int find_unlocked_unmuted_channel(const Editing *ed, int channel_index)
static int sequencer_generic_invoke_xy_guess_channel(bContext *C, int type)
static void sequencer_disable_one_time_properties(bContext *C, wmOperator *op)
static void sequencer_add_free(bContext *, wmOperator *op)
static void seq_load_apply_generic_options(bContext *C, wmOperator *op, Strip *strip)
static void sequencer_generic_invoke_path__internal(bContext *C, wmOperator *op, const char *identifier)
static bool can_move_strips(const wmOperator *op)
static wmOperatorStatus sequencer_add_image_strip_exec(bContext *C, wmOperator *op)
static bool sequencer_add_draw_check_fn(PointerRNA *ptr, PropertyRNA *prop, void *)
static wmOperatorStatus sequencer_add_scene_asset_invoke(bContext *C, wmOperator *op, const wmEvent *event)
void sequencer_image_strip_reserve_frames(wmOperator *op, StripElem *se, int len, int minframe, int numdigits)
static wmOperatorStatus sequencer_add_movie_strip_exec(bContext *C, wmOperator *op)
void SEQUENCER_OT_movieclip_strip_add(wmOperatorType *ot)
static bool seq_load_apply_generic_options_only_test_overlap(bContext *C, wmOperator *op, Strip *strip)
static wmOperatorStatus sequencer_add_mask_strip_invoke(bContext *C, wmOperator *op, const wmEvent *event)
static wmOperatorStatus sequencer_add_mask_strip_exec(bContext *C, wmOperator *op)
static std::string sequencer_add_scene_asset_get_description(bContext *C, wmOperatorType *, PointerRNA *ptr)
blender::VectorSet< Strip * > all_strips_from_context(bContext *C)
void SEQUENCER_OT_add_scene_strip_from_scene_asset(wmOperatorType *ot)
void SEQUENCER_OT_effect_strip_add(wmOperatorType *ot)
static void sequencer_add_movie_sync_sound_strip(Main *bmain, Scene *scene, Strip *strip_movie, Strip *strip_sound, seq::LoadData *load_data)
const EnumPropertyItem sequencer_prop_effect_types[]
static void sequencer_generic_invoke_xy__internal(bContext *C, wmOperator *op, int flag, int type, const wmEvent *event)
static void sequencer_add_sound_multiple_strips(bContext *C, wmOperator *op, seq::LoadData *load_data)
static IMB_Proxy_Size seq_get_proxy_size_flags(bContext *C)
static wmOperatorStatus sequencer_add_scene_strip_invoke(bContext *C, wmOperator *op, const wmEvent *event)
static void sequencer_add_image_strip_load_files(wmOperator *op, Scene *scene, Strip *strip, seq::LoadData *load_data, const ImageFrameRange *range)
static wmOperatorStatus sequencer_add_movieclip_strip_invoke(bContext *C, wmOperator *op, const wmEvent *event)
static Scene * sequencer_add_scene_asset(const bContext &C, const asset_system::AssetRepresentation &asset, ReportList &)
static void move_strips(bContext *C, wmOperator *op)
StringRef effect_inputs_validate(const VectorSet< Strip * > &inputs, int num_inputs)
VectorSet< Strip * > strip_effect_get_new_inputs(const Scene *scene, int num_inputs, bool ignore_active)
static wmOperatorStatus sequencer_add_scene_strip_new_invoke(bContext *C, wmOperator *op, const wmEvent *event)
static std::string sequencer_add_effect_strip_get_description(bContext *, wmOperatorType *, PointerRNA *ptr)
void SEQUENCER_OT_movie_strip_add(wmOperatorType *ot)
void sequencer_select_do_updates(const bContext *C, Scene *scene)
static bool sequencer_add_movie_single_strip(bContext *C, wmOperator *op, seq::LoadData *load_data, blender::VectorSet< Strip * > &r_movie_strips)
static wmOperatorStatus sequencer_add_movie_strip_invoke(bContext *C, wmOperator *op, const wmEvent *event)
static EnumPropertyItem strip_new_scene_items[]
void SEQUENCER_OT_scene_strip_add(wmOperatorType *ot)
static void sequencer_generic_props__internal(wmOperatorType *ot, int flag)
static bool op_invoked_by_drop_event(const wmOperator *op)
static bool have_free_channels(bContext *C, wmOperator *op, int need_channels, const char **r_error_msg)
static bool sequencer_add_sound_single_strip(bContext *C, wmOperator *op, seq::LoadData *load_data)
bool deselect_all_strips(const Scene *scene)
static wmOperatorStatus sequencer_add_effect_strip_invoke(bContext *C, wmOperator *op, const wmEvent *event)
void SEQUENCER_OT_sound_strip_add(wmOperatorType *ot)
static void frame_filename_set(char *dst, size_t dst_len, const char *filename_stripped, const int frame, const int numdigits, const char *ext)
static wmOperatorStatus sequencer_add_effect_strip_exec(bContext *C, wmOperator *op)
static wmOperatorStatus sequencer_add_scene_strip_new_exec(bContext *C, wmOperator *op)
static void sequencer_add_draw(bContext *, wmOperator *op)
static void sequencer_add_init(bContext *, wmOperator *op)
static wmOperatorStatus sequencer_add_scene_strip_exec(bContext *C, wmOperator *op)
static wmOperatorStatus sequencer_add_sound_strip_exec(bContext *C, wmOperator *op)
static void seq_build_proxy(bContext *C, blender::Span< Strip * > movie_strips)
void SEQUENCER_OT_image_strip_add(wmOperatorType *ot)
static bool load_data_init_from_operator(seq::LoadData *load_data, bContext *C, wmOperator *op)
static void sequencer_file_drop_channel_frame_set(bContext *C, wmOperator *op, const wmEvent *event)
static wmOperatorStatus sequencer_add_image_strip_invoke(bContext *C, wmOperator *op, const wmEvent *event)
static wmOperatorStatus sequencer_add_movieclip_strip_exec(bContext *C, wmOperator *op)
static wmOperatorStatus sequencer_add_sound_strip_invoke(bContext *C, wmOperator *op, const wmEvent *event)
static void sequencer_add_movie_multiple_strips(bContext *C, wmOperator *op, seq::LoadData *load_data, blender::VectorSet< Strip * > &r_movie_strips)
static bool sequencer_add_effect_strip_poll_property(const bContext *, wmOperator *op, const PropertyRNA *prop)
int sequencer_image_strip_get_minmax_frame(wmOperator *op, int sfra, int *r_minframe, int *r_numdigits)
void SEQUENCER_OT_scene_strip_add_new(wmOperatorType *ot)
T clamp(const T &a, const T &min, const T &max)
int time_right_handle_frame_get(const Scene *scene, const Strip *strip)
SeqTimelineChannel * channel_get_by_index(const ListBase *channels, const int channel_index)
Definition channels.cc:60
ListBase * channels_displayed_get(const Editing *ed)
Definition channels.cc:28
eSeqImageFitMethod tool_settings_fit_method_get(Scene *scene)
Definition sequencer.cc:391
bool channel_is_locked(const SeqTimelineChannel *channel)
Definition channels.cc:76
IMB_Proxy_Size rendersize_to_proxysize(eSpaceSeq_Proxy_RenderSize render_size)
Definition proxy.cc:72
void strip_channel_set(Strip *strip, int channel)
bool transform_test_overlap(const Scene *scene, Strip *strip1, Strip *strip2)
Editing * editing_get(const Scene *scene)
Definition sequencer.cc:286
Strip * add_effect_strip(Scene *scene, ListBase *seqbase, LoadData *load_data)
Definition strip_add.cc:166
void add_image_load_file(Scene *scene, Strip *strip, size_t strip_frame, const char *filename)
Definition strip_add.cc:202
void add_image_set_directory(Strip *strip, const char *dirpath)
Definition strip_add.cc:197
int time_left_handle_frame_get(const Scene *, const Strip *strip)
Strip * add_sound_strip(Main *, Scene *, ListBase *, LoadData *)
Definition strip_add.cc:374
bool proxy_rebuild_context(Main *bmain, Depsgraph *depsgraph, Scene *scene, Strip *strip, blender::Set< std::string > *processed_paths, ListBase *queue, bool build_only_on_bad_performance)
Definition proxy.cc:431
void add_sound_av_sync(Main *, Scene *, Strip *, LoadData *)
Definition strip_add.cc:367
void connect(Strip *strip1, Strip *strip2)
bool transform_single_image_check(const Strip *strip)
Editing * editing_ensure(Scene *scene)
Definition sequencer.cc:291
void proxy_set(Strip *strip, bool value)
Definition proxy.cc:613
Strip * select_active_get(const Scene *scene)
constexpr int MAX_CHANNELS
ProxyJob * ED_seq_proxy_job_get(const bContext *C, wmJob *wm_job)
Definition proxy_job.cc:70
Strip * add_scene_strip(Scene *scene, ListBase *seqbase, LoadData *load_data)
Definition strip_add.cc:131
void add_image_init_alpha_mode(Main *bmain, Scene *scene, Strip *strip)
Definition strip_add.cc:208
bool time_strip_intersects_frame(const Scene *scene, const Strip *strip, const int timeline_frame)
Strip * add_image_strip(Main *bmain, Scene *scene, ListBase *seqbase, LoadData *load_data)
Definition strip_add.cc:239
Strip * add_movieclip_strip(Scene *scene, ListBase *seqbase, LoadData *load_data)
Definition strip_add.cc:143
void tool_settings_fit_method_set(Scene *scene, eSeqImageFitMethod fit_method)
Definition sequencer.cc:415
void select_active_set(Scene *scene, Strip *strip)
@ SEQ_LOAD_SOUND_MONO
Definition SEQ_add.hh:28
@ SEQ_LOAD_SET_VIEW_TRANSFORM
Definition SEQ_add.hh:30
@ SEQ_LOAD_SOUND_CACHE
Definition SEQ_add.hh:27
@ SEQ_LOAD_MOVIE_SYNC_FPS
Definition SEQ_add.hh:29
Strip * add_mask_strip(Scene *scene, ListBase *seqbase, LoadData *load_data)
Definition strip_add.cc:155
void time_left_handle_frame_set(const Scene *scene, Strip *strip, int timeline_frame)
bool channel_is_muted(const SeqTimelineChannel *channel)
Definition channels.cc:81
void transform_handle_overlap(Scene *scene, ListBase *seqbasep, blender::Span< Strip * > transformed_strips, bool use_sync_markers)
void time_right_handle_frame_set(const Scene *scene, Strip *strip, int timeline_frame)
Strip * add_movie_strip(Main *bmain, Scene *scene, ListBase *seqbase, LoadData *load_data)
Definition strip_add.cc:401
bool transform_seqbase_shuffle(ListBase *seqbasep, Strip *test, Scene *evil_scene)
wmJob * ED_seq_proxy_wm_job_get(const bContext *C)
Definition proxy_job.cc:87
int effect_get_num_inputs(int strip_type)
Definition effects.cc:327
VecBase< int32_t, 2 > int2
VecBase< float, 2 > float2
static blender::bke::bNodeSocketTemplate inputs[]
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)
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_string_get(PointerRNA *ptr, const char *name)
std::string RNA_property_string_get(PointerRNA *ptr, PropertyRNA *prop)
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_discrete(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)
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:26
const EnumPropertyItem rna_enum_strip_scale_method_items[]
#define SEQPROP_NOPATHS
#define SEQPROP_LENGTH
#define SEQPROP_MOVE
#define SEQPROP_VIEW_TRANSFORM
#define SEQPROP_STARTFRAME
#define SEQPROP_NOCHAN
#define SEQPROP_PLAYBACK_RATE
#define SEQPROP_FIT_METHOD
#define DEFAULT_IMG_STRIP_LENGTH
The meta-data of an asset. By creating and giving this for a data-block (ID.asset_data),...
Stereo3dFormat stereo3d_format
ListBase frames
Definition ED_image.hh:211
void * first
ListBase masks
Definition BKE_main.hh:312
ListBase scenes
Definition BKE_main.hh:278
ListBase movieclips
Definition BKE_main.hh:311
ColorManagedViewSettings view_settings
struct RenderData r
ListBase spacedata
short render_size
StripElem * stripdata
char dirpath[768]
char filename[256]
StripData * data
void * effectdata
ListBase areabase
Depsgraph * depsgraph
Definition SEQ_proxy.hh:48
int ymin
int xmin
uiLayout & column(bool align)
void separator(float factor=1.0f, LayoutSeparatorType type=LayoutSeparatorType::Auto)
void prop(PointerRNA *ptr, PropertyRNA *prop, int index, int value, eUI_Item_Flag flag, std::optional< blender::StringRef > name_opt, int icon, std::optional< blender::StringRef > placeholder=std::nullopt)
int xy[2]
Definition WM_types.hh:761
int mval[2]
Definition WM_types.hh:763
struct ReportList * reports
struct uiLayout * layout
struct PointerRNA * ptr
struct wmEvent * eventstate
i
Definition text_draw.cc:230
rcti ED_time_scrub_clamp_scroller_mask(const rcti &scroller_mask)
uint len
wmOperatorStatus WM_operator_name_call_ptr(bContext *C, wmOperatorType *ot, blender::wm::OpCallContext context, PointerRNA *properties, const wmEvent *event)
void WM_event_add_fileselect(bContext *C, wmOperator *op)
PointerRNA * ptr
Definition wm_files.cc:4238
wmOperatorType * ot
Definition wm_files.cc:4237
bool WM_jobs_is_running(const wmJob *wm_job)
Definition wm_jobs.cc:341
void WM_jobs_start(wmWindowManager *wm, wmJob *wm_job)
Definition wm_jobs.cc:479
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)
wmOperatorType * WM_operatortype_find(const char *idname, bool quiet)
void WM_operator_properties_create_ptr(PointerRNA *ptr, wmOperatorType *ot)
wmOperatorStatus WM_enum_search_invoke(bContext *C, wmOperator *op, const wmEvent *)
void WM_operator_properties_free(PointerRNA *ptr)
uint8_t flag
Definition wm_window.cc:145