Blender V5.0
sequencer.cc
Go to the documentation of this file.
1/* SPDX-FileCopyrightText: 2001-2002 NaN Holding BV. All rights reserved.
2 * SPDX-FileCopyrightText: 2003-2009 Blender Authors
3 * SPDX-FileCopyrightText: 2005-2006 Peter Schlaile <peter [at] schlaile [dot] de>
4 *
5 * SPDX-License-Identifier: GPL-2.0-or-later */
6
10
11#define DNA_DEPRECATED_ALLOW
12
13#include <cstddef>
14
15#include "MEM_guardedalloc.h"
16
17#include "DNA_listBase.h"
18#include "DNA_mask_types.h"
19#include "DNA_scene_types.h"
20#include "DNA_sequence_types.h"
21#include "DNA_sound_types.h"
22
23#include "BLI_assert.h"
24#include "BLI_listbase.h"
25#include "BLI_map.hh"
26#include "BLI_path_utils.hh"
27#include "BLI_string_utf8.h"
28
29#include "BKE_duplilist.hh"
30#include "BKE_fcurve.hh"
31#include "BKE_idprop.hh"
32#include "BKE_layer.hh"
33#include "BKE_lib_id.hh"
34#include "BKE_lib_remap.hh"
35#include "BKE_main.hh"
36#include "BKE_scene.hh"
37#include "BKE_sound.h"
38
39#include "DEG_depsgraph.hh"
40
41#include "MOV_read.hh"
42
43#include "SEQ_channels.hh"
44#include "SEQ_connect.hh"
45#include "SEQ_edit.hh"
46#include "SEQ_effects.hh"
47#include "SEQ_iterator.hh"
48#include "SEQ_modifier.hh"
49#include "SEQ_preview_cache.hh"
50#include "SEQ_proxy.hh"
51#include "SEQ_relations.hh"
52#include "SEQ_retiming.hh"
53#include "SEQ_select.hh"
54#include "SEQ_sequencer.hh"
55#include "SEQ_sound.hh"
57#include "SEQ_time.hh"
58#include "SEQ_transform.hh"
59#include "SEQ_utils.hh"
60
61#include "BLO_read_write.hh"
62
66#include "modifiers/modifier.hh"
67#include "prefetch.hh"
68#include "sequencer.hh"
69#include "utils.hh"
70
71namespace blender::seq {
72
73/* -------------------------------------------------------------------- */
76
78{
79 StripProxy *strip_proxy = MEM_callocN<StripProxy>("StripProxy");
80 strip_proxy->quality = 50;
82 strip_proxy->tc = SEQ_PROXY_TC_RECORD_RUN;
83 return strip_proxy;
84}
85
86static StripData *seq_strip_alloc(int type)
87{
89
90 if (type != STRIP_TYPE_SOUND_RAM) {
91 data->transform = MEM_callocN<StripTransform>("StripTransform");
92 data->transform->scale_x = 1;
93 data->transform->scale_y = 1;
94 data->transform->origin[0] = 0.5f;
95 data->transform->origin[1] = 0.5f;
96 data->transform->filter = SEQ_TRANSFORM_FILTER_AUTO;
97 data->crop = MEM_callocN<StripCrop>("StripCrop");
98 }
99
100 data->us = 1;
101 return data;
102}
103
105{
106 data->us--;
107 if (data->us > 0) {
108 return;
109 }
110 if (data->us < 0) {
111 printf("error: negative users in strip\n");
112 return;
113 }
114
115 if (data->stripdata) {
116 MEM_freeN(data->stripdata);
117 }
118
119 if (data->proxy) {
120 if (data->proxy->anim) {
121 MOV_close(data->proxy->anim);
122 }
123
124 MEM_freeN(data->proxy);
125 }
126 if (data->crop) {
127 MEM_freeN(data->crop);
128 }
129 if (data->transform) {
130 MEM_freeN(data->transform);
131 }
132
134}
135
136Strip *strip_alloc(ListBase *lb, int timeline_frame, int channel, int type)
137{
138 Strip *strip;
139
140 strip = MEM_callocN<Strip>("addseq");
141 BLI_addtail(lb, strip);
142
143 *((short *)strip->name) = ID_SEQ;
144 strip->name[2] = 0;
145
146 strip->flag = SELECT;
147 strip->start = timeline_frame;
148 strip_channel_set(strip, channel);
149 strip->sat = 1.0;
150 strip->mul = 1.0;
151 strip->blend_opacity = 100.0;
152 strip->volume = 1.0f;
153 strip->scene_sound = nullptr;
154 strip->type = type;
155 strip->media_playback_rate = 0.0f;
156 strip->speed_factor = 1.0f;
157
158 if (strip->type == STRIP_TYPE_ADJUSTMENT) {
160 }
161 else {
163 }
164
165 strip->data = seq_strip_alloc(type);
166 strip->stereo3d_format = MEM_callocN<Stereo3dFormat>("Sequence Stereo Format");
167
169
170 if (strip->type == STRIP_TYPE_META) {
171 channels_ensure(&strip->channels);
172 }
173
175
176 return strip;
177}
178
179/* only give option to skip cache locally (static func) */
180static void seq_strip_free_ex(Scene *scene,
181 Strip *strip,
182 const bool do_cache,
183 const bool do_id_user)
184{
185 if (strip->data) {
186 seq_free_strip(strip->data);
187 }
188
190
191 if (strip->is_effect()) {
193 sh.free(strip, do_id_user);
194 }
195
196 if (strip->sound && do_id_user) {
197 id_us_min((ID *)strip->sound);
198 }
199
200 if (strip->clip && do_id_user) {
201 id_us_min(&strip->clip->id);
202 }
203
204 if (strip->mask && do_id_user) {
205 id_us_min(&strip->mask->id);
206 }
207
208 if (strip->stereo3d_format) {
210 }
211
212 /* clipboard has no scene and will never have a sound handle or be active
213 * same goes to sequences copy for proxy rebuild job
214 */
215 if (scene) {
216 Editing *ed = scene->ed;
217
218 if (ed->act_strip == strip) {
219 ed->act_strip = nullptr;
220 }
221
224 }
225 }
226
227 if (strip->prop) {
228 IDP_FreePropertyContent_ex(strip->prop, do_id_user);
229 MEM_freeN(strip->prop);
230 }
231 if (strip->system_properties) {
234 }
235
236 /* free modifiers */
237 modifier_clear(strip);
238
239 if (is_strip_connected(strip)) {
240 disconnect(strip);
241 }
242
243 /* free cached data used by this strip,
244 * also invalidate cache for all dependent sequences
245 *
246 * be _very_ careful here, invalidating cache loops over the scene sequences and
247 * assumes the listbase is valid for all strips,
248 * this may not be the case if lists are being freed.
249 * this is optional SEQ_relations_invalidate_cache
250 */
251 if (do_cache) {
252 if (scene) {
253 relations_invalidate_cache_raw(scene, strip);
254 }
255 }
256 if (strip->type == STRIP_TYPE_META) {
257 channels_free(&strip->channels);
258 }
259
260 if (strip->retiming_keys != nullptr) {
261 MEM_freeN(strip->retiming_keys);
262 strip->retiming_keys = nullptr;
263 strip->retiming_keys_num = 0;
264 }
265
266 MEM_freeN(strip);
267}
268
269void strip_free(Scene *scene, Strip *strip)
270{
271 seq_strip_free_ex(scene, strip, true, true);
272}
273
274void seq_free_strip_recurse(Scene *scene, Strip *strip, const bool do_id_user)
275{
276 Strip *istrip, *istrip_next;
277
278 for (istrip = static_cast<Strip *>(strip->seqbase.first); istrip; istrip = istrip_next) {
279 istrip_next = istrip->next;
280 seq_free_strip_recurse(scene, istrip, do_id_user);
281 }
282
283 seq_strip_free_ex(scene, strip, false, do_id_user);
284}
285
287{
288 return scene ? scene->ed : nullptr;
289}
290
292{
293 if (scene->ed == nullptr) {
294 Editing *ed;
295
296 ed = scene->ed = MEM_callocN<Editing>("addseq");
298 ed->show_missing_media_flag = SEQ_EDIT_SHOW_MISSING_MEDIA;
299 channels_ensure(&ed->channels);
300 }
301
302 return scene->ed;
303}
304
305void editing_free(Scene *scene, const bool do_id_user)
306{
307 Editing *ed = scene->ed;
308
309 if (ed == nullptr) {
310 return;
311 }
312
313 seq_prefetch_free(scene);
314
315 /* handle cache freeing above */
316 LISTBASE_FOREACH_MUTABLE (Strip *, strip, &ed->seqbase) {
317 seq_free_strip_recurse(scene, strip, do_id_user);
318 }
319
320 BLI_freelistN(&ed->metastack);
328 channels_free(&ed->channels);
329
330 MEM_freeN(ed);
331
332 scene->ed = nullptr;
333}
334
336{
337 if (strip->is_effect()) {
338 strip->input1 = strip_map.lookup_default(strip->input1, strip->input1);
339 strip->input2 = strip_map.lookup_default(strip->input2, strip->input2);
340 }
341
343 smd->mask_strip = strip_map.lookup_default(smd->mask_strip, smd->mask_strip);
344 }
345
346 if (is_strip_connected(strip)) {
348 con->strip_ref = strip_map.lookup_default(con->strip_ref, con->strip_ref);
349 }
350 }
351
352 if (strip->type == STRIP_TYPE_META) {
353 LISTBASE_FOREACH (Strip *, strip_n, &strip->seqbase) {
354 seq_new_fix_links_recursive(strip_n, strip_map);
355 }
356 }
357}
358
374
376{
378 if (tool_settings == nullptr) {
380 tool_settings = scene->toolsettings->sequencer_tool_settings;
381 }
382
383 return tool_settings;
384}
385
387{
388 MEM_freeN(tool_settings);
389}
390
392{
393 const SequencerToolSettings *tool_settings = tool_settings_ensure(scene);
394 return eSeqImageFitMethod(tool_settings->fit_method);
395}
396
398{
399 const SequencerToolSettings *tool_settings = tool_settings_ensure(scene);
400 return tool_settings->snap_mode;
401}
402
404{
405 const SequencerToolSettings *tool_settings = tool_settings_ensure(scene);
406 return tool_settings->snap_flag;
407}
408
410{
411 const SequencerToolSettings *tool_settings = tool_settings_ensure(scene);
412 return tool_settings->snap_distance;
413}
414
416{
417 SequencerToolSettings *tool_settings = tool_settings_ensure(scene);
418 tool_settings->fit_method = fit_method;
419}
420
422{
423 const SequencerToolSettings *tool_settings = tool_settings_ensure(scene);
424 return eSeqOverlapMode(tool_settings->overlap_mode);
425}
426
428{
429 const SequencerToolSettings *tool_settings = tool_settings_ensure(scene);
430 return tool_settings->pivot_point;
431}
432
434{
435 return ed ? ed->current_strips() : nullptr;
436}
437
438static MetaStack *seq_meta_stack_alloc(const Scene *scene, Strip *strip_meta)
439{
440 Editing *ed = editing_get(scene);
441
442 MetaStack *ms = MEM_mallocN<MetaStack>("metastack");
443 BLI_addhead(&ed->metastack, ms);
444 ms->parent_strip = strip_meta;
445
446 /* Reference to previously displayed timeline data. */
447 ms->old_strip = lookup_meta_by_strip(ed, strip_meta);
448
451 return ms;
452}
453
455{
456 if (ed == nullptr) {
457 return nullptr;
458 }
459
460 return static_cast<MetaStack *>(ed->metastack.last);
461}
462
463void meta_stack_set(const Scene *scene, Strip *dst)
464{
465 Editing *ed = editing_get(scene);
466 /* Clear metastack */
467 BLI_freelistN(&ed->metastack);
468
469 if (dst != nullptr) {
470 /* Allocate meta stack in a way, that represents meta hierarchy in timeline. */
471 seq_meta_stack_alloc(scene, dst);
472 Strip *meta_parent = dst;
473 while ((meta_parent = lookup_meta_by_strip(ed, meta_parent))) {
474 seq_meta_stack_alloc(scene, meta_parent);
475 }
476
477 ed->current_meta_strip = dst;
478 }
479 else {
480 ed->current_meta_strip = nullptr;
481 }
482}
483
485{
487 Strip *meta_parent = ms->parent_strip;
488 ed->current_meta_strip = ms->old_strip;
489 BLI_remlink(&ed->metastack, ms);
490 MEM_freeN(ms);
491 return meta_parent;
492}
493
495
496/* -------------------------------------------------------------------- */
499
501 /* TODO(john): Cleanup dupe code by adding bmain, dupe_flag, copy_flag, etc to this context. */
502
503 /* Sources of newly created datablocks when duplicating strips.
504 * Processed with `seq_duplicate_postprocess`. */
508};
509
513 const StripDuplicate dupe_flag)
514{
516
517 if (int(dupe_flag & StripDuplicate::Data) != 0) {
518 /* Remapping newids in Scenes will usually trigger a view_layers/collections resync after each
519 * scene. Besides performances considerations, this is also bad because it means some
520 * not-yet-remapped scenes will get their viewlayer updated while still referencing old
521 * (source) collections, objects etc. This can e.g. lead to losing the active object in the
522 * duplicated scenes.
523 *
524 * So instead, prevent any resync untill all new IDs have been remapped. */
526
527 /* Newly created datablocks may reference IDs that themselves have also been duplicated in the
528 * "current duplication". E.g. a scene may have a custom property that refers to itself; when
529 * it is duplicated, we should ensure that these references are properly remapped.
530 *
531 * NOTE: Some of these IDs may be processed as part of dependencies when relinking another ID,
532 * so they may have already been remapped, and their `newid` pointer, reset to nullptr. */
533 for (Scene *scene_src : ctx.scenes) {
534 BLI_assert(scene_src);
535 if (scene_src->id.newid) {
536 BKE_libblock_relink_to_newid(bmain, scene_src->id.newid, remap_flag);
537 }
538 }
539 for (MovieClip *movieclip_src : ctx.movieclips) {
540 BLI_assert(movieclip_src);
541 if (movieclip_src->id.newid) {
542 BKE_libblock_relink_to_newid(bmain, movieclip_src->id.newid, remap_flag);
543 }
544 }
545 for (Mask *mask_src : ctx.masks) {
546 BLI_assert(mask_src);
547 if (mask_src->id.newid) {
548 BKE_libblock_relink_to_newid(bmain, mask_src->id.newid, remap_flag);
549 }
550 }
551
553
554 if (bmain != nullptr) {
555#ifndef NDEBUG
556 /* Calls to `BKE_libblock_relink_to_newid` above are supposed to have cleared all these
557 * flags.
558 */
559 ID *id_iter;
560 FOREACH_MAIN_ID_BEGIN (bmain, id_iter) {
561 BLI_assert((id_iter->tag & ID_TAG_NEW) == 0);
562 }
564#endif
565
566 /* Clear temporary `newid` for potentially copied datablocks (scene, mask, and movieclip)
567 * to indicate that we have finished processing them. */
569
571 }
572 }
573 else {
577 }
578
579 /* Fix effect, modifier, and connected strip links. */
580 for (Strip *strip_new : strip_map.values()) {
581 seq_new_fix_links_recursive(strip_new, strip_map);
582 }
583
584 /* One-way connections must be cut after all connections are remapped above. */
585 for (Strip *strip_new : strip_map.values()) {
586 if (is_strip_connected(strip_new)) {
587 cut_one_way_connections(strip_new);
588 }
589 }
590}
591
593 const Scene *scene_src,
594 Scene *scene_dst,
595 ListBase *new_seq_list,
596 Strip *strip,
597 const StripDuplicate dupe_flag,
598 const int flag,
601{
602 Strip *strip_new = static_cast<Strip *>(MEM_dupallocN(strip));
603 strip_map.add(strip, strip_new);
604
605 if ((flag & LIB_ID_CREATE_NO_MAIN) == 0) {
607 }
608
609 strip_new->data = static_cast<StripData *>(MEM_dupallocN(strip->data));
610
611 strip_new->stereo3d_format = static_cast<Stereo3dFormat *>(
613
614 /* XXX: add F-Curve duplication stuff? */
615
616 if (strip->data->crop) {
617 strip_new->data->crop = static_cast<StripCrop *>(MEM_dupallocN(strip->data->crop));
618 }
619
620 if (strip->data->transform) {
621 strip_new->data->transform = static_cast<StripTransform *>(
622 MEM_dupallocN(strip->data->transform));
623 }
624
625 if (strip->data->proxy) {
626 strip_new->data->proxy = static_cast<StripProxy *>(MEM_dupallocN(strip->data->proxy));
627 strip_new->data->proxy->anim = nullptr;
628 }
629
630 if (strip->prop) {
631 strip_new->prop = IDP_CopyProperty_ex(strip->prop, flag);
632 }
633 if (strip->system_properties) {
635 }
636
637 if (strip_new->modifiers.first) {
638 BLI_listbase_clear(&strip_new->modifiers);
639
640 modifier_list_copy(strip_new, strip);
641 }
643
644 if (is_strip_connected(strip)) {
645 BLI_listbase_clear(&strip_new->connections);
646 connections_duplicate(&strip_new->connections, &strip->connections);
647 }
648
649 if (strip->type == STRIP_TYPE_META) {
650 strip_new->data->stripdata = nullptr;
651
652 BLI_listbase_clear(&strip_new->seqbase);
653 BLI_listbase_clear(&strip_new->channels);
654 channels_duplicate(&strip_new->channels, &strip->channels);
655 }
656 else if (strip->type == STRIP_TYPE_SCENE) {
657 if (int(dupe_flag & StripDuplicate::Data) != 0 && strip_new->scene != nullptr) {
658 Scene *scene_old = strip_new->scene;
659 ctx.scenes.add(scene_old);
660 strip_new->scene = BKE_scene_duplicate(bmain,
661 scene_old,
666 }
667 strip_new->data->stripdata = nullptr;
668 if (strip->scene_sound) {
669 strip_new->scene_sound = BKE_sound_scene_add_scene_sound_defaults(scene_dst, strip_new);
670 }
671 }
672 else if (strip->type == STRIP_TYPE_MOVIECLIP) {
673 if (int(dupe_flag & StripDuplicate::Data) != 0 && strip_new->clip != nullptr) {
674 MovieClip *clip_old = strip_new->clip;
675 ctx.movieclips.add(clip_old);
676 strip_new->clip = reinterpret_cast<MovieClip *>(BKE_id_copy_for_duplicate(
677 bmain, reinterpret_cast<ID *>(clip_old), USER_DUP_LINKED_ID, LIB_ID_COPY_DEFAULT));
678 }
680 id_us_plus(&strip_new->clip->id);
681 }
682 }
683 else if (strip->type == STRIP_TYPE_MASK) {
684 if (int(dupe_flag & StripDuplicate::Data) != 0 && strip_new->mask != nullptr) {
685 Mask *mask_old = strip_new->mask;
686 ctx.masks.add(mask_old);
687 strip_new->mask = reinterpret_cast<Mask *>(BKE_id_copy_for_duplicate(
688 bmain, reinterpret_cast<ID *>(mask_old), USER_DUP_LINKED_ID, LIB_ID_COPY_DEFAULT));
689 }
691 id_us_plus(&strip_new->mask->id);
692 }
693 }
694 else if (strip->type == STRIP_TYPE_MOVIE) {
695 strip_new->data->stripdata = static_cast<StripElem *>(MEM_dupallocN(strip->data->stripdata));
696 BLI_listbase_clear(&strip_new->anims);
697 }
698 else if (strip->type == STRIP_TYPE_SOUND_RAM) {
699 strip_new->data->stripdata = static_cast<StripElem *>(MEM_dupallocN(strip->data->stripdata));
700 strip_new->scene_sound = nullptr;
702 id_us_plus((ID *)strip_new->sound);
703 }
704 }
705 else if (strip->type == STRIP_TYPE_IMAGE) {
706 strip_new->data->stripdata = static_cast<StripElem *>(MEM_dupallocN(strip->data->stripdata));
707 }
708 else if (strip->is_effect()) {
709 EffectHandle sh;
710 sh = strip_effect_handle_get(strip);
711 if (sh.copy) {
712 sh.copy(strip_new, strip, flag);
713 }
714
715 strip_new->data->stripdata = nullptr;
716 }
717 else {
718 /* sequence type not handled in duplicate! Expect a crash now... */
720 }
721
722 /* When using StripDuplicate::UniqueName, it is mandatory to add new strips in relevant container
723 * (scene or meta's one), *before* checking for unique names. Otherwise the meta's list is empty
724 * and hence we miss all sequencer strips in that meta that have already been duplicated,
725 * (see #55668). Note that unique name check itself could be done at a later step in calling
726 * code, once all sequencer strips have been duplicated (that was first, simpler solution),
727 * but then handling of animation data will be broken (see #60194). */
728 if (new_seq_list != nullptr) {
729 BLI_addtail(new_seq_list, strip_new);
730 }
731
732 if (scene_src == scene_dst) {
733 if (int(dupe_flag & StripDuplicate::UniqueName) != 0) {
734 strip_unique_name_set(scene_dst, &scene_dst->ed->seqbase, strip_new);
735 }
736 }
737
738 if (strip->retiming_keys != nullptr) {
739 strip_new->retiming_keys = static_cast<SeqRetimingKey *>(MEM_dupallocN(strip->retiming_keys));
740 strip_new->retiming_keys_num = strip->retiming_keys_num;
741 }
742
743 return strip_new;
744}
745
747 const Scene *scene_src,
748 Scene *scene_dst,
749 ListBase *new_seq_list,
750 Strip *strip,
751 const StripDuplicate dupe_flag,
754{
755 Strip *strip_new = strip_duplicate(
756 bmain, scene_src, scene_dst, new_seq_list, strip, dupe_flag, 0, strip_map, ctx);
757 if (strip->type == STRIP_TYPE_META) {
758 LISTBASE_FOREACH (Strip *, s, &strip->seqbase) {
760 bmain, scene_src, scene_dst, &strip_new->seqbase, s, dupe_flag, strip_map, ctx);
761 }
762 }
763 return strip_new;
764}
765
767 const Scene *scene_src,
768 Scene *scene_dst,
769 ListBase *new_seq_list,
770 Strip *strip,
771 const StripDuplicate dupe_flag)
772{
775
777 bmain, scene_src, scene_dst, new_seq_list, strip, dupe_flag, strip_map, ctx);
778
779 seq_duplicate_postprocess(bmain, ctx, strip_map, dupe_flag);
780
781 return strip_new;
782}
783
784static void seqbase_dupli_recursive(Main *bmain,
785 const Scene *scene_src,
786 Scene *scene_dst,
787 ListBase *nseqbase,
788 const ListBase *seqbase,
789 const StripDuplicate dupe_flag,
790 const int flag,
793{
794 LISTBASE_FOREACH (Strip *, strip, seqbase) {
795 if ((strip->flag & SELECT) == 0 && int(dupe_flag & StripDuplicate::All) == 0) {
796 continue;
797 }
798
799 Strip *strip_new = strip_duplicate(
800 bmain, scene_src, scene_dst, nseqbase, strip, dupe_flag, flag, strip_map, ctx);
801 BLI_assert(strip_new != nullptr);
802
803 if (strip->type == STRIP_TYPE_META) {
804 /* Always include meta all strip children. */
805 const StripDuplicate dupe_flag_recursive = dupe_flag | StripDuplicate::All;
807 scene_src,
808 scene_dst,
809 &strip_new->seqbase,
810 &strip->seqbase,
811 dupe_flag_recursive,
812 flag,
813 strip_map,
814 ctx);
815 }
816 }
817}
818
820 const Scene *scene_src,
821 Scene *scene_dst,
822 ListBase *nseqbase,
823 const ListBase *seqbase,
824 const StripDuplicate dupe_flag,
825 const int flag)
826{
829
831 bmain, scene_src, scene_dst, nseqbase, seqbase, dupe_flag, flag, strip_map, ctx);
832
833 seq_duplicate_postprocess(bmain, ctx, strip_map, dupe_flag);
834}
835
837{
838 return strip->channel >= 1 && strip->channel <= MAX_CHANNELS;
839}
840
847
849
850static bool seq_set_strip_done_cb(Strip *strip, void * /*userdata*/)
851{
852 if (strip->data) {
853 strip->data->done = false;
854 }
855 return true;
856}
857
858static bool strip_write_data_cb(Strip *strip, void *userdata)
859{
860 BlendWriter *writer = (BlendWriter *)userdata;
861 BLO_write_struct(writer, Strip, strip);
862 if (strip->data && strip->data->done == 0) {
863 /* Write strip with 'done' at 0 because read-file. */
864
865 /* TODO this doesn't depend on the `Strip` data to be present? */
866 if (strip->effectdata) {
867 switch (strip->type) {
868 case STRIP_TYPE_COLOR:
870 break;
871 case STRIP_TYPE_SPEED:
873 break;
874 case STRIP_TYPE_WIPE:
875 BLO_write_struct(writer, WipeVars, strip->effectdata);
876 break;
877 case STRIP_TYPE_GLOW:
878 BLO_write_struct(writer, GlowVars, strip->effectdata);
879 break;
882 break;
883 case STRIP_TYPE_TEXT: {
884 TextVars *text = static_cast<TextVars *>(strip->effectdata);
885 if (!BLO_write_is_undo(writer)) {
886 /* Copy current text into legacy buffer. */
887 STRNCPY_UTF8(text->text_legacy, text->text_ptr);
888 }
889 BLO_write_struct(writer, TextVars, text);
890 BLO_write_string(writer, text->text_ptr);
891 } break;
894 break;
895 }
896 }
897
899
900 StripData *data = strip->data;
902 if (data->crop) {
903 BLO_write_struct(writer, StripCrop, data->crop);
904 }
905 if (data->transform) {
906 BLO_write_struct(writer, StripTransform, data->transform);
907 }
908 if (data->proxy) {
909 BLO_write_struct(writer, StripProxy, data->proxy);
910 }
911 if (strip->type == STRIP_TYPE_IMAGE) {
913 writer, StripElem, MEM_allocN_len(data->stripdata) / sizeof(StripElem), data->stripdata);
914 }
915 else if (ELEM(strip->type, STRIP_TYPE_MOVIE, STRIP_TYPE_SOUND_RAM)) {
916 BLO_write_struct(writer, StripElem, data->stripdata);
917 }
918
919 data->done = true;
920 }
921
922 if (strip->prop) {
923 IDP_BlendWrite(writer, strip->prop);
924 }
925 if (strip->system_properties) {
926 IDP_BlendWrite(writer, strip->system_properties);
927 }
928
929 modifier_blend_write(writer, &strip->modifiers);
930
931 LISTBASE_FOREACH (SeqTimelineChannel *, channel, &strip->channels) {
932 BLO_write_struct(writer, SeqTimelineChannel, channel);
933 }
934
936 BLO_write_struct(writer, StripConnection, con);
937 }
938
939 if (strip->retiming_keys != nullptr) {
940 int size = retiming_keys_count(strip);
942 }
943
944 return true;
945}
946
947void blend_write(BlendWriter *writer, ListBase *seqbase)
948{
949 /* reset write flags */
950 foreach_strip(seqbase, seq_set_strip_done_cb, nullptr);
951
952 foreach_strip(seqbase, strip_write_data_cb, writer);
953}
954
955static bool strip_read_data_cb(Strip *strip, void *user_data)
956{
957 BlendDataReader *reader = (BlendDataReader *)user_data;
958
959 /* Runtime data cleanup. */
960 strip->scene_sound = nullptr;
961 BLI_listbase_clear(&strip->anims);
962
963 /* Do as early as possible, so that other parts of reading can rely on valid session UID. */
965
966 BLO_read_struct(reader, Strip, &strip->input1);
967 BLO_read_struct(reader, Strip, &strip->input2);
968
969 if (strip->effectdata) {
970 switch (strip->type) {
971 case STRIP_TYPE_COLOR:
972 BLO_read_struct(reader, SolidColorVars, &strip->effectdata);
973 break;
974 case STRIP_TYPE_SPEED:
976 break;
977 case STRIP_TYPE_WIPE:
978 BLO_read_struct(reader, WipeVars, &strip->effectdata);
979 break;
980 case STRIP_TYPE_GLOW:
981 BLO_read_struct(reader, GlowVars, &strip->effectdata);
982 break;
985 break;
988 break;
989 case STRIP_TYPE_TEXT: {
990 BLO_read_struct(reader, TextVars, &strip->effectdata);
991 TextVars *text = static_cast<TextVars *>(strip->effectdata);
992 BLO_read_string(reader, &text->text_ptr);
993 text->text_len_bytes = text->text_ptr ? strlen(text->text_ptr) : 0;
994 } break;
996 BLO_read_struct(reader, ColorMixVars, &strip->effectdata);
997 break;
998 default:
1000 strip->effectdata = nullptr;
1001 break;
1002 }
1003 }
1004
1006
1007 if (strip->is_effect()) {
1009 }
1010
1011 if (strip->type == STRIP_TYPE_TEXT) {
1012 TextVars *t = static_cast<TextVars *>(strip->effectdata);
1014 t->runtime = nullptr;
1015 }
1016
1017 BLO_read_struct(reader, IDProperty, &strip->prop);
1018 IDP_BlendDataRead(reader, &strip->prop);
1020 IDP_BlendDataRead(reader, &strip->system_properties);
1021
1022 BLO_read_struct(reader, StripData, &strip->data);
1023 if (strip->data && strip->data->done == 0) {
1024 strip->data->done = true;
1025
1026 /* `STRIP_TYPE_SOUND_HD` case needs to be kept here, for backward compatibility. */
1027 if (ELEM(strip->type,
1032 {
1033 /* FIXME In #STRIP_TYPE_IMAGE case, there is currently no available information about the
1034 * length of the stored array of #StripElem.
1035 *
1036 * This is 'not a problem' because the reading code only checks that the loaded buffer is at
1037 * least large enough for the requested data (here a single #StripElem item), and always
1038 * assign the whole read memory (without any truncating). But relying on this behavior is
1039 * weak and should be addressed. */
1040 BLO_read_struct(reader, StripElem, &strip->data->stripdata);
1041 }
1042 else {
1043 strip->data->stripdata = nullptr;
1044 }
1045 BLO_read_struct(reader, StripCrop, &strip->data->crop);
1046 BLO_read_struct(reader, StripTransform, &strip->data->transform);
1047 BLO_read_struct(reader, StripProxy, &strip->data->proxy);
1048 if (strip->data->proxy) {
1049 strip->data->proxy->anim = nullptr;
1050 }
1051 else if (strip->flag & SEQ_USE_PROXY) {
1052 proxy_set(strip, true);
1053 }
1054
1055 /* need to load color balance to it could be converted to modifier */
1056 BLO_read_struct(reader, StripColorBalance, &strip->data->color_balance_legacy);
1057 }
1058
1059 modifier_blend_read_data(reader, &strip->modifiers);
1060
1062 LISTBASE_FOREACH (StripConnection *, con, &strip->connections) {
1063 if (con->strip_ref) {
1064 BLO_read_struct(reader, Strip, &con->strip_ref);
1065 }
1066 }
1067
1069
1070 if (strip->retiming_keys != nullptr) {
1071 const int size = retiming_keys_count(strip);
1073 }
1074
1075 return true;
1076}
1077void blend_read(BlendDataReader *reader, ListBase *seqbase)
1078{
1079 foreach_strip(seqbase, strip_read_data_cb, reader);
1080}
1081
1082static bool strip_doversion_250_sound_proxy_update_cb(Strip *strip, void *user_data)
1083{
1084 Main *bmain = static_cast<Main *>(user_data);
1085 if (strip->type == STRIP_TYPE_SOUND_HD) {
1086 char filepath_abs[FILE_MAX];
1087 BLI_path_join(filepath_abs,
1088 sizeof(filepath_abs),
1089 strip->data->dirpath,
1090 strip->data->stripdata->filename);
1091 BLI_path_abs(filepath_abs, BKE_main_blendfile_path(bmain));
1092 strip->sound = BKE_sound_new_file(bmain, filepath_abs);
1093 strip->type = STRIP_TYPE_SOUND_RAM;
1094 }
1095 return true;
1096}
1097
1102
1103/* Depsgraph update functions. */
1104
1105static bool seq_mute_sound_strips_cb(Strip *strip, void *user_data)
1106{
1107 Scene *scene = (Scene *)user_data;
1108 if (strip->scene_sound != nullptr) {
1110 strip->scene_sound = nullptr;
1111 }
1112 return true;
1113}
1114
1115/* Adds sound of strip to the `scene->sound_scene` - "sound timeline". */
1116static void strip_update_mix_sounds(Scene *scene, Strip *strip)
1117{
1118 if (strip->scene_sound != nullptr) {
1119 return;
1120 }
1121
1122 if (strip->sound != nullptr) {
1123 /* Adds `strip->sound->playback_handle` to `scene->sound_scene` */
1124 strip->scene_sound = BKE_sound_add_scene_sound_defaults(scene, strip);
1125 }
1126 else if (strip->type == STRIP_TYPE_SCENE && strip->scene != nullptr) {
1127 /* Adds `strip->scene->sound_scene` to `scene->sound_scene`. */
1130 }
1131}
1132
1133static void strip_update_sound_properties(const Scene *scene, const Strip *strip)
1134{
1135 const int frame = BKE_scene_frame_get(scene);
1137 strip->scene_sound, frame, strip->volume, (strip->flag & SEQ_AUDIO_VOLUME_ANIMATED) != 0);
1140 strip->scene_sound, frame, strip->pan, (strip->flag & SEQ_AUDIO_PAN_ANIMATED) != 0);
1141}
1142
1144{
1145 void *sound_handle = strip->sound->playback_handle;
1146 bool needs_update = false;
1147
1148 LISTBASE_FOREACH (StripModifierData *, smd, &strip->modifiers) {
1149 sound_handle = sound_modifier_recreator(strip, smd, sound_handle, needs_update);
1150 }
1151
1152 if (needs_update) {
1153 /* Assign modified sound back to `strip`. */
1154 BKE_sound_update_sequence_handle(strip->scene_sound, sound_handle);
1155 }
1156}
1157
1158static bool must_update_strip_sound(Scene *scene, Strip *strip)
1159{
1160 return (scene->id.recalc & (ID_RECALC_AUDIO | ID_RECALC_SYNC_TO_EVAL)) != 0 ||
1162}
1163
1164static void seq_update_sound_strips(Scene *scene, Strip *strip)
1165{
1166 if (strip->sound == nullptr || !must_update_strip_sound(scene, strip)) {
1167 return;
1168 }
1169
1170 /* Ensure strip is playing correct sound. */
1171 if (BLI_listbase_is_empty(&strip->modifiers)) {
1172 /* Just use playback handle from sound ID. */
1174 }
1175 else {
1176 /* Use Playback handle from sound ID as input for modifier stack. */
1178 }
1179}
1180
1181static bool scene_sequencer_is_used(const Scene *scene, ListBase *seqbase)
1182{
1183 bool sequencer_is_used = false;
1184 LISTBASE_FOREACH (Strip *, strip_iter, seqbase) {
1185 if (strip_iter->scene == scene && (strip_iter->flag & SEQ_SCENE_STRIPS) != 0) {
1186 sequencer_is_used = true;
1187 }
1188 if (strip_iter->type == STRIP_TYPE_META) {
1189 sequencer_is_used |= scene_sequencer_is_used(scene, &strip_iter->seqbase);
1190 }
1191 }
1192
1193 return sequencer_is_used;
1194}
1195
1196static void seq_update_scene_strip_sound(const Scene *scene, Strip *strip)
1197{
1198 if (strip->type != STRIP_TYPE_SCENE || strip->scene == nullptr) {
1199 return;
1200 }
1201
1202 /* Set `strip->scene` volume.
1203 * NOTE: Currently this doesn't work well, when this property is animated. Scene strip volume is
1204 * also controlled by `strip_update_sound_properties()` via `strip->volume` which works if
1205 * animated.
1206 *
1207 * Ideally, the entire `BKE_scene_update_sound()` will happen from a dependency graph, so
1208 * then it is no longer needed to do such manual forced updates. */
1210
1211 /* Mute sound when all scene strips using particular scene are not rendering sequencer strips. */
1212 bool sequencer_is_used = scene_sequencer_is_used(strip->scene, &scene->ed->seqbase);
1213
1214 if (!sequencer_is_used && strip->scene->sound_scene != nullptr && strip->scene->ed != nullptr) {
1216 }
1217}
1218
1219static bool strip_sound_update_cb(Strip *strip, void *user_data)
1220{
1221 Scene *scene = (Scene *)user_data;
1222
1223 strip_update_mix_sounds(scene, strip);
1224
1225 if (strip->scene_sound == nullptr) {
1226 return true;
1227 }
1228
1229 seq_update_sound_strips(scene, strip);
1230 seq_update_scene_strip_sound(scene, strip);
1231 strip_update_sound_properties(scene, strip);
1232 return true;
1233}
1234
1235void eval_strips(Depsgraph *depsgraph, Scene *scene, ListBase *seqbase)
1236{
1237 DEG_debug_print_eval(depsgraph, __func__, scene->id.name, scene);
1239
1240 foreach_strip(seqbase, strip_sound_update_cb, scene);
1241
1242 edit_update_muting(scene->ed);
1244}
1245
1246} // namespace blender::seq
1247
1248ListBase *Editing::current_strips()
1249{
1250 if (this->current_meta_strip) {
1251 return &this->current_meta_strip->seqbase;
1252 }
1253 return &this->seqbase;
1254}
1255
1256ListBase *Editing::current_strips() const
1257{
1258 if (this->current_meta_strip) {
1259 return &this->current_meta_strip->seqbase;
1260 }
1261 /* NOTE: Const correctness is non-existent with ListBase anyway. */
1262 return &const_cast<ListBase &>(this->seqbase);
1263}
1264
1265ListBase *Editing::current_channels()
1266{
1267 if (this->current_meta_strip) {
1268 return &this->current_meta_strip->channels;
1269 }
1270 return &this->channels;
1271}
1272
1273ListBase *Editing::current_channels() const
1274{
1275 if (this->current_meta_strip) {
1276 return &this->current_meta_strip->channels;
1277 }
1278 /* NOTE: Const correctness is non-existent with ListBase anyway. */
1279 return &const_cast<ListBase &>(this->channels);
1280}
1281
1282bool Strip::is_effect() const
1283{
1284 return (this->type >= STRIP_TYPE_CROSS && this->type <= STRIP_TYPE_OVERDROP_REMOVED) ||
1285 (this->type >= STRIP_TYPE_WIPE && this->type <= STRIP_TYPE_ADJUSTMENT) ||
1287}
#define IDP_BlendDataRead(reader, prop)
void IDP_FreePropertyContent_ex(IDProperty *prop, bool do_id_user)
Definition idprop.cc:1213
IDProperty * IDP_CopyProperty_ex(const IDProperty *prop, int flag) ATTR_WARN_UNUSED_RESULT ATTR_NONNULL()
Definition idprop.cc:845
void IDP_BlendWrite(BlendWriter *writer, const IDProperty *prop)
Definition idprop.cc:1461
void BKE_layer_collection_resync_forbid()
void BKE_layer_collection_resync_allow()
void BKE_main_collection_sync(const Main *bmain)
ID * BKE_id_copy_for_duplicate(Main *bmain, ID *id, eDupli_ID_Flags duplicate_flags, int copy_flags)
Definition lib_id.cc:787
void id_us_plus(ID *id)
Definition lib_id.cc:358
void BKE_main_id_newptr_and_tag_clear(Main *bmain)
Definition lib_id.cc:2001
@ LIB_ID_CREATE_NO_USER_REFCOUNT
@ LIB_ID_CREATE_NO_MAIN
@ LIB_ID_COPY_DEFAULT
void id_us_min(ID *id)
Definition lib_id.cc:366
@ LIB_ID_DUPLICATE_IS_ROOT_ID
@ LIB_ID_DUPLICATE_IS_SUBPROCESS
void BKE_libblock_relink_to_newid(Main *bmain, ID *id, int remap_flag) ATTR_NONNULL()
Definition lib_remap.cc:931
@ ID_REMAP_SKIP_USER_CLEAR
@ ID_REMAP_FORCE_OBDATA_IN_EDITMODE
#define FOREACH_MAIN_ID_END
Definition BKE_main.hh:583
#define FOREACH_MAIN_ID_BEGIN(_bmain, _id)
Definition BKE_main.hh:577
const char * BKE_main_blendfile_path(const Main *bmain) ATTR_NONNULL()
Definition main.cc:887
@ SCE_COPY_FULL
Definition BKE_scene.hh:36
float BKE_scene_frame_get(const Scene *scene)
Definition scene.cc:2384
Scene * BKE_scene_duplicate(Main *bmain, Scene *sce, eSceneCopyMethod type, eDupli_ID_Flags duplicate_flags, uint duplicate_options)
Definition scene.cc:1783
void BKE_sound_set_scene_sound_pan_at_frame(void *handle, int frame, float pan, char animated)
void BKE_sound_set_scene_volume(struct Scene *scene, float volume)
struct bSound * BKE_sound_new_file(struct Main *bmain, const char *filepath)
void BKE_sound_ensure_scene(struct Scene *scene)
void * BKE_sound_scene_add_scene_sound_defaults(struct Scene *scene, struct Strip *sequence)
void * BKE_sound_add_scene_sound_defaults(struct Scene *scene, struct Strip *sequence)
void BKE_sound_set_scene_sound_volume_at_frame(void *handle, int frame, float volume, char animated)
void BKE_sound_update_scene_sound(void *handle, struct bSound *sound)
void BKE_sound_update_sequence_handle(void *handle, void *sound_handle)
void BKE_sound_remove_scene_sound(struct Scene *scene, void *handle)
#define BLI_assert_unreachable()
Definition BLI_assert.h:93
#define BLI_assert(a)
Definition BLI_assert.h:46
#define LISTBASE_FOREACH(type, var, list)
BLI_INLINE void BLI_listbase_clear(ListBase *lb)
BLI_INLINE bool BLI_listbase_is_empty(const ListBase *lb)
#define LISTBASE_FOREACH_MUTABLE(type, var, list)
void void BLI_freelistN(ListBase *listbase) ATTR_NONNULL(1)
Definition listbase.cc:497
void BLI_addtail(ListBase *listbase, void *vlink) ATTR_NONNULL(1)
Definition listbase.cc:111
void BLI_remlink(ListBase *listbase, void *vlink) ATTR_NONNULL(1)
Definition listbase.cc:131
void BLI_addhead(ListBase *listbase, void *vlink) ATTR_NONNULL(1)
Definition listbase.cc:91
bool BLI_path_abs(char path[FILE_MAX], const char *basepath) ATTR_NONNULL(1
#define FILE_MAX
#define BLI_path_join(...)
#define STRNCPY_UTF8(dst, src)
#define ELEM(...)
#define BLO_write_struct(writer, struct_name, data_ptr)
void BLO_read_string(BlendDataReader *reader, char **ptr_p)
Definition readfile.cc:5828
void BLO_write_string(BlendWriter *writer, const char *data_ptr)
#define BLO_write_struct_array(writer, struct_name, array_size, data_ptr)
#define BLO_read_struct_list(reader, struct_name, list)
#define BLO_read_struct_array(reader, struct_name, array_size, ptr_p)
#define BLO_read_struct(reader, struct_name, ptr_p)
bool BLO_write_is_undo(BlendWriter *writer)
void DEG_debug_print_eval(Depsgraph *depsgraph, const char *function_name, const char *object_name, const void *object_address)
@ ID_TAG_NEW
Definition DNA_ID.h:919
@ ID_RECALC_AUDIO
Definition DNA_ID.h:1132
@ ID_RECALC_SYNC_TO_EVAL
Definition DNA_ID.h:1118
#define ID_SEQ
These structs are the foundation for all linked lists in the library system.
struct ListBase ListBase
eSeqImageFitMethod
@ SEQ_SCALE_TO_FIT
eSeqOverlapMode
@ SEQ_OVERLAP_SHUFFLE
@ SEQ_SNAP_TO_STRIPS
@ SEQ_SNAP_TO_MARKERS
@ SEQ_SNAP_TO_FRAME_RANGE
@ SEQ_SNAP_TO_PREVIEW_CENTER
@ SEQ_SNAP_TO_STRIPS_PREVIEW
@ SEQ_SNAP_TO_PREVIEW_BORDERS
@ SEQ_SNAP_TO_STRIP_HOLD
@ SEQ_SNAP_TO_RETIMING
@ SEQ_SNAP_TO_CURRENT_FRAME
@ SEQ_PROXY_TC_RECORD_RUN_NO_GAPS
@ SEQ_PROXY_TC_RECORD_RUN
@ STRIP_EFFECT_NOT_LOADED
@ SEQ_CACHE_STORE_RAW
@ SEQ_CACHE_STORE_FINAL_OUT
@ SEQ_CACHE_PREFETCH_ENABLE
@ STRIP_TYPE_GAUSSIAN_BLUR
@ STRIP_TYPE_SCENE
@ STRIP_TYPE_MOVIECLIP
@ STRIP_TYPE_COLORMIX
@ STRIP_TYPE_WIPE
@ STRIP_TYPE_TRANSFORM_LEGACY
@ STRIP_TYPE_TEXT
@ STRIP_TYPE_SOUND_HD
@ STRIP_TYPE_SOUND_RAM
@ STRIP_TYPE_IMAGE
@ STRIP_TYPE_MOVIE
@ STRIP_TYPE_GLOW
@ STRIP_TYPE_SPEED
@ STRIP_TYPE_COLOR
@ STRIP_TYPE_ADJUSTMENT
@ STRIP_TYPE_META
@ STRIP_TYPE_MASK
@ STRIP_TYPE_OVERDROP_REMOVED
@ STRIP_TYPE_CROSS
@ STRIP_COLOR_NONE
@ STRIP_BLEND_CROSS
@ STRIP_BLEND_ALPHAOVER
@ SEQ_TRANSFORM_FILTER_AUTO
@ SEQ_SCENE_STRIPS
@ SEQ_USE_PROXY
@ SEQ_AUDIO_VOLUME_ANIMATED
@ SEQ_AUDIO_PAN_ANIMATED
#define STRIP_FONT_NOT_LOADED
@ SEQ_EDIT_SHOW_MISSING_MEDIA
eDupli_ID_Flags
@ USER_DUP_LINKED_ID
@ USER_DUP_OBJECT
@ V3D_AROUND_LOCAL_ORIGINS
Read Guarded memory(de)allocation.
#define U
BMesh const char void * data
BPy_StructRNA * depsgraph
static DBVT_INLINE btScalar size(const btDbvtVolume &a)
Definition btDbvt.cpp:52
bool add(const Key &key)
Definition BLI_set.hh:248
bool is_empty() const
Definition BLI_set.hh:595
ValueIterator values() const &
Definition BLI_map.hh:884
bool add(const Key &key, const Value &value)
Definition BLI_map.hh:295
Value lookup_default(const Key &key, const Value &default_value) const
Definition BLI_map.hh:570
#define SELECT
#define printf(...)
void * MEM_mallocN(size_t len, const char *str)
Definition mallocn.cc:128
void * MEM_callocN(size_t len, const char *str)
Definition mallocn.cc:118
void * MEM_dupallocN(const void *vmemh)
Definition mallocn.cc:143
size_t(* MEM_allocN_len)(const void *vmemh)
Definition mallocn.cc:36
void MEM_freeN(void *vmemh)
Definition mallocn.cc:113
void MOV_close(MovieReader *anim)
Definition movie_read.cc:66
static StripData * seq_strip_alloc(int type)
Definition sequencer.cc:86
void relations_strip_free_anim(Strip *strip)
static void seq_update_sound_strips(Scene *scene, Strip *strip)
Strip * lookup_meta_by_strip(Editing *ed, const Strip *key)
int time_right_handle_frame_get(const Scene *scene, const Strip *strip)
void foreach_strip(ListBase *seqbase, ForEachFunc callback, void *user_data)
Definition iterator.cc:59
static void seqbase_dupli_recursive(Main *bmain, const Scene *scene_src, Scene *scene_dst, ListBase *nseqbase, const ListBase *seqbase, const StripDuplicate dupe_flag, const int flag, blender::Map< Strip *, Strip * > &strip_map, StripDuplicateContext &ctx)
Definition sequencer.cc:784
SequencerToolSettings * tool_settings_init()
Definition sequencer.cc:359
bool disconnect(Strip *strip)
EffectHandle strip_effect_handle_get(Strip *strip)
Definition effects.cc:290
void eval_strips(Depsgraph *depsgraph, Scene *scene, ListBase *seqbase)
void sound_update_bounds_all(Scene *scene)
static void strip_update_mix_sounds(Scene *scene, Strip *strip)
eSeqImageFitMethod tool_settings_fit_method_get(Scene *scene)
Definition sequencer.cc:391
int retiming_keys_count(const Strip *strip)
static bool scene_sequencer_is_used(const Scene *scene, ListBase *seqbase)
static void seq_duplicate_postprocess(Main *bmain, StripDuplicateContext &ctx, blender::Map< Strip *, Strip * > &strip_map, const StripDuplicate dupe_flag)
Definition sequencer.cc:510
static void seq_update_scene_strip_sound(const Scene *scene, Strip *strip)
void doversion_250_sound_proxy_update(Main *bmain, Editing *ed)
void channels_ensure(ListBase *channels)
Definition channels.cc:33
void strip_channel_set(Strip *strip, int channel)
void media_presence_free(Scene *scene)
SequencerToolSettings * tool_settings_copy(SequencerToolSettings *tool_settings)
Definition sequencer.cc:841
static bool must_update_strip_sound(Scene *scene, Strip *strip)
void blend_write(BlendWriter *writer, ListBase *seqbase)
Definition sequencer.cc:947
void tool_settings_free(SequencerToolSettings *tool_settings)
Definition sequencer.cc:386
Editing * editing_get(const Scene *scene)
Definition sequencer.cc:286
void meta_stack_set(const Scene *scene, Strip *dst)
Definition sequencer.cc:463
StripProxy * seq_strip_proxy_alloc()
Definition sequencer.cc:77
void seq_prefetch_free(Scene *scene)
Definition prefetch.cc:395
static bool strip_sound_update_cb(Strip *strip, void *user_data)
int time_left_handle_frame_get(const Scene *, const Strip *strip)
static void seq_free_strip(StripData *data)
Definition sequencer.cc:104
void seq_free_strip_recurse(Scene *scene, Strip *strip, const bool do_id_user)
Definition sequencer.cc:274
static void strip_update_sound_modifiers(Strip *strip)
void relations_invalidate_cache_raw(Scene *scene, Strip *strip)
static Strip * strip_duplicate_recursive_impl(Main *bmain, const Scene *scene_src, Scene *scene_dst, ListBase *new_seq_list, Strip *strip, const StripDuplicate dupe_flag, blender::Map< Strip *, Strip * > &strip_map, StripDuplicateContext &ctx)
Definition sequencer.cc:746
static bool seq_set_strip_done_cb(Strip *strip, void *)
Definition sequencer.cc:850
void strip_free(Scene *scene, Strip *strip)
Definition sequencer.cc:269
void cut_one_way_connections(Strip *strip)
static void seq_strip_free_ex(Scene *scene, Strip *strip, const bool do_cache, const bool do_id_user)
Definition sequencer.cc:180
MetaStack * meta_stack_active_get(const Editing *ed)
Definition sequencer.cc:454
Editing * editing_ensure(Scene *scene)
Definition sequencer.cc:291
void proxy_set(Strip *strip, bool value)
Definition proxy.cc:613
static bool seq_mute_sound_strips_cb(Strip *strip, void *user_data)
static MetaStack * seq_meta_stack_alloc(const Scene *scene, Strip *strip_meta)
Definition sequencer.cc:438
static bool strip_doversion_250_sound_proxy_update_cb(Strip *strip, void *user_data)
void final_image_cache_destroy(Scene *scene)
void editing_free(Scene *scene, const bool do_id_user)
Definition sequencer.cc:305
constexpr int MAX_CHANNELS
static void strip_update_sound_properties(const Scene *scene, const Strip *strip)
static bool strip_write_data_cb(Strip *strip, void *userdata)
Definition sequencer.cc:858
bool is_strip_connected(const Strip *strip)
void modifier_blend_read_data(BlendDataReader *reader, ListBase *lb)
void preview_cache_destroy(Scene *scene)
bool modifier_persistent_uids_are_valid(const Strip &strip)
int tool_settings_pivot_point_get(Scene *scene)
Definition sequencer.cc:427
void edit_update_muting(Editing *ed)
void retiming_sound_animation_data_set(const Scene *scene, const Strip *strip)
void * sound_modifier_recreator(Strip *strip, StripModifierData *smd, void *sound, bool &needs_update)
void tool_settings_fit_method_set(Scene *scene, eSeqImageFitMethod fit_method)
Definition sequencer.cc:415
void channels_duplicate(ListBase *channels_dst, ListBase *channels_src)
Definition channels.cc:44
bool is_valid_strip_channel(const Strip *strip)
Definition sequencer.cc:836
short tool_settings_snap_flag_get(Scene *scene)
Definition sequencer.cc:403
SequencerToolSettings * tool_settings_ensure(Scene *scene)
Definition sequencer.cc:375
static bool strip_read_data_cb(Strip *strip, void *user_data)
Definition sequencer.cc:955
int tool_settings_snap_distance_get(Scene *scene)
Definition sequencer.cc:409
void intra_frame_cache_destroy(Scene *scene)
void source_image_cache_destroy(Scene *scene)
static void strip_lookup_free(StripLookup **lookup)
void strip_unique_name_set(Scene *scene, ListBase *seqbasep, Strip *strip)
void relations_session_uid_generate(Strip *strip)
void modifier_list_copy(Strip *strip_new, Strip *strip)
static Strip * strip_duplicate(Main *bmain, const Scene *scene_src, Scene *scene_dst, ListBase *new_seq_list, Strip *strip, const StripDuplicate dupe_flag, const int flag, blender::Map< Strip *, Strip * > &strip_map, StripDuplicateContext &ctx)
Definition sequencer.cc:592
void channels_free(ListBase *channels)
Definition channels.cc:53
Strip * strip_duplicate_recursive(Main *bmain, const Scene *scene_src, Scene *scene_dst, ListBase *new_seq_list, Strip *strip, const StripDuplicate dupe_flag)
Definition sequencer.cc:766
static void seq_new_fix_links_recursive(Strip *strip, blender::Map< Strip *, Strip * > strip_map)
Definition sequencer.cc:335
ListBase * active_seqbase_get(const Editing *ed)
Definition sequencer.cc:433
short tool_settings_snap_mode_get(Scene *scene)
Definition sequencer.cc:397
void connections_duplicate(ListBase *connections_dst, ListBase *connections_src)
Strip * meta_stack_pop(Editing *ed)
Definition sequencer.cc:484
void blend_read(BlendDataReader *reader, ListBase *seqbase)
Strip * strip_alloc(ListBase *lb, int timeline_frame, int channel, int type)
Definition sequencer.cc:136
void thumbnail_cache_destroy(Scene *scene)
eSeqOverlapMode tool_settings_overlap_mode_get(Scene *scene)
Definition sequencer.cc:421
void modifier_blend_write(BlendWriter *writer, ListBase *modbase)
void seqbase_duplicate_recursive(Main *bmain, const Scene *scene_src, Scene *scene_dst, ListBase *nseqbase, const ListBase *seqbase, const StripDuplicate dupe_flag, const int flag)
Definition sequencer.cc:819
ListBase seqbase
ListBase channels
Strip * current_meta_strip
Definition DNA_ID.h:414
unsigned int recalc
Definition DNA_ID.h:445
int tag
Definition DNA_ID.h:442
char name[258]
Definition DNA_ID.h:432
struct ID * newid
Definition DNA_ID.h:418
void * first
void * sound_scene
struct ToolSettings * toolsettings
struct Editing * ed
struct AudioData audio
StripProxy * proxy
StripCrop * crop
StripTransform * transform
StripElem * stripdata
char dirpath[768]
char filename[256]
struct MovieReader * anim
struct Stereo3dFormat * stereo3d_format
void * scene_sound
struct Strip * input1
int8_t color_tag
int retiming_keys_num
struct Mask * mask
ListBase connections
StripData * data
struct IDProperty * prop
struct Scene * scene
struct MovieClip * clip
void * effectdata
float pitch_legacy pan
struct bSound * sound
ListBase seqbase
float speed_factor
StripRuntime runtime
float media_playback_rate
struct SeqRetimingKey * retiming_keys
struct IDProperty * system_properties
struct Strip * next
float blend_opacity
char name[64]
ListBase modifiers
struct Strip * input2
ListBase channels
ListBase anims
TextVarsRuntime * runtime
char text_legacy[512]
struct SequencerToolSettings * sequencer_tool_settings
void * playback_handle
void(* copy)(Strip *dst, const Strip *src, int flag)
void(* free)(Strip *strip, bool do_id_user)
blender::Set< Scene * > scenes
Definition sequencer.cc:505
blender::Set< Mask * > masks
Definition sequencer.cc:507
blender::Set< MovieClip * > movieclips
Definition sequencer.cc:506
uint8_t flag
Definition wm_window.cc:145