Blender V4.3
strip_edit.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#include "DNA_scene_types.h"
12#include "DNA_sequence_types.h"
13
14#include "BLI_listbase.h"
15#include "BLI_math_base.h"
16#include "BLI_string.h"
17#include "BLI_string_utf8.h"
18
19#include "BLT_translation.hh"
20
21#include "BKE_sound.h"
22
23#include "strip_time.hh"
24
25#include "SEQ_add.hh"
26#include "SEQ_animation.hh"
27#include "SEQ_channels.hh"
28#include "SEQ_connect.hh"
29
30#include "SEQ_edit.hh"
31#include "SEQ_effects.hh"
32#include "SEQ_iterator.hh"
33#include "SEQ_relations.hh"
34#include "SEQ_render.hh"
35#include "SEQ_sequencer.hh"
36#include "SEQ_time.hh"
37#include "SEQ_transform.hh"
38#include "SEQ_utils.hh"
39
40#include <cstring>
41
43 Sequence *seq_a,
44 Sequence *seq_b,
45 const char **r_error_str)
46{
47 char name[sizeof(seq_a->name)];
48
49 if (SEQ_time_strip_length_get(scene, seq_a) != SEQ_time_strip_length_get(scene, seq_b)) {
50 *r_error_str = N_("Strips must be the same length");
51 return false;
52 }
53
54 /* type checking, could be more advanced but disallow sound vs non-sound copy */
55 if (seq_a->type != seq_b->type) {
56 if (seq_a->type == SEQ_TYPE_SOUND_RAM || seq_b->type == SEQ_TYPE_SOUND_RAM) {
57 *r_error_str = N_("Strips were not compatible");
58 return false;
59 }
60
61 /* disallow effects to swap with non-effects strips */
62 if ((seq_a->type & SEQ_TYPE_EFFECT) != (seq_b->type & SEQ_TYPE_EFFECT)) {
63 *r_error_str = N_("Strips were not compatible");
64 return false;
65 }
66
67 if ((seq_a->type & SEQ_TYPE_EFFECT) && (seq_b->type & SEQ_TYPE_EFFECT)) {
69 *r_error_str = N_("Strips must have the same number of inputs");
70 return false;
71 }
72 }
73 }
74
75 blender::dna::shallow_swap(*seq_a, *seq_b);
76
77 /* swap back names so animation fcurves don't get swapped */
78 STRNCPY(name, seq_a->name + 2);
79 BLI_strncpy(seq_a->name + 2, seq_b->name + 2, sizeof(seq_b->name) - 2);
80 BLI_strncpy(seq_b->name + 2, name, sizeof(seq_b->name) - 2);
81
82 /* swap back opacity, and overlay mode */
83 std::swap(seq_a->blend_mode, seq_b->blend_mode);
84 std::swap(seq_a->blend_opacity, seq_b->blend_opacity);
85
86 std::swap(seq_a->prev, seq_b->prev);
87 std::swap(seq_a->next, seq_b->next);
88 std::swap(seq_a->start, seq_b->start);
89 std::swap(seq_a->startofs, seq_b->startofs);
90 std::swap(seq_a->endofs, seq_b->endofs);
91 std::swap(seq_a->machine, seq_b->machine);
92 seq_time_effect_range_set(scene, seq_a);
93 seq_time_effect_range_set(scene, seq_b);
94
95 return true;
96}
97
99 ListBase *seqbasep,
100 Sequence *metaseq,
101 const bool mute)
102{
103 /* For sound we go over full meta tree to update muted state,
104 * since sound is played outside of evaluating the imbufs. */
105 LISTBASE_FOREACH (Sequence *, seq, seqbasep) {
106 bool seqmute = (mute || SEQ_render_is_muted(channels, seq));
107
108 if (seq->type == SEQ_TYPE_META) {
109 /* if this is the current meta sequence, unmute because
110 * all sequences above this were set to mute */
111 if (seq == metaseq) {
112 seqmute = false;
113 }
114
115 seq_update_muting_recursive(&seq->channels, &seq->seqbase, metaseq, seqmute);
116 }
117 else if (ELEM(seq->type, SEQ_TYPE_SOUND_RAM, SEQ_TYPE_SCENE)) {
118 if (seq->scene_sound) {
119 BKE_sound_mute_scene_sound(seq->scene_sound, seqmute);
120 }
121 }
122 }
123}
124
126{
127 if (ed) {
128 /* mute all sounds up to current metastack list */
129 MetaStack *ms = static_cast<MetaStack *>(ed->metastack.last);
130
131 if (ms) {
132 seq_update_muting_recursive(&ed->channels, &ed->seqbase, ms->parseq, true);
133 }
134 else {
135 seq_update_muting_recursive(&ed->channels, &ed->seqbase, nullptr, false);
136 }
137 }
138}
139
140static void sequencer_flag_users_for_removal(Scene *scene, ListBase *seqbase, Sequence *seq)
141{
142 LISTBASE_FOREACH (Sequence *, user_seq, seqbase) {
143 /* Look in meta-strips for usage of seq. */
144 if (user_seq->type == SEQ_TYPE_META) {
145 sequencer_flag_users_for_removal(scene, &user_seq->seqbase, seq);
146 }
147
148 /* Clear seq from modifiers. */
149 LISTBASE_FOREACH (SequenceModifierData *, smd, &user_seq->modifiers) {
150 if (smd->mask_sequence == seq) {
151 smd->mask_sequence = nullptr;
152 }
153 }
154
155 /* Remove effects, that use seq. */
156 if (SEQ_relation_is_effect_of_strip(user_seq, seq)) {
157 user_seq->flag |= SEQ_FLAG_DELETE;
158 /* Strips can be used as mask even if not in same seqbase. */
159 sequencer_flag_users_for_removal(scene, &scene->ed->seqbase, user_seq);
160 }
161 }
162}
163
165{
166 if (seq == nullptr || (seq->flag & SEQ_FLAG_DELETE) != 0) {
167 return;
168 }
169
170 /* Flag and remove meta children. */
171 if (seq->type == SEQ_TYPE_META) {
172 LISTBASE_FOREACH (Sequence *, meta_child, &seq->seqbase) {
173 SEQ_edit_flag_for_removal(scene, &seq->seqbase, meta_child);
174 }
175 }
176
177 seq->flag |= SEQ_FLAG_DELETE;
178 sequencer_flag_users_for_removal(scene, seqbase, seq);
179}
180
182{
183 LISTBASE_FOREACH_MUTABLE (Sequence *, seq, seqbase) {
184 if (seq->flag & SEQ_FLAG_DELETE) {
185 if (seq->type == SEQ_TYPE_META) {
186 SEQ_edit_remove_flagged_sequences(scene, &seq->seqbase);
187 }
188 SEQ_free_animdata(scene, seq);
189 BLI_remlink(seqbase, seq);
190 SEQ_sequence_free(scene, seq);
192 }
193 }
194}
195
197 ListBase *seqbase,
198 Sequence *seq,
199 ListBase *dst_seqbase)
200{
201 /* Move to meta. */
202 BLI_remlink(seqbase, seq);
203 BLI_addtail(dst_seqbase, seq);
205
206 /* Update meta. */
207 if (SEQ_transform_test_overlap(scene, dst_seqbase, seq)) {
208 SEQ_transform_seqbase_shuffle(dst_seqbase, seq, scene);
209 }
210
211 return true;
212}
213
215 Sequence *src_seq,
216 Sequence *dst_seqm,
217 const char **r_error_str)
218{
219 /* Find the appropriate seqbase */
220 Editing *ed = SEQ_editing_get(scene);
221 ListBase *seqbase = SEQ_get_seqbase_by_seq(scene, src_seq);
222
223 if (dst_seqm->type != SEQ_TYPE_META) {
224 *r_error_str = N_("Cannot move strip to non-meta strip");
225 return false;
226 }
227
228 if (src_seq == dst_seqm) {
229 *r_error_str = N_("Strip cannot be moved into itself");
230 return false;
231 }
232
233 if (seqbase == &dst_seqm->seqbase) {
234 *r_error_str = N_("Moved strip is already inside provided meta strip");
235 return false;
236 }
237
238 if (src_seq->type == SEQ_TYPE_META && SEQ_exists_in_seqbase(dst_seqm, &src_seq->seqbase)) {
239 *r_error_str = N_("Moved strip is parent of provided meta strip");
240 return false;
241 }
242
243 if (!SEQ_exists_in_seqbase(dst_seqm, &ed->seqbase)) {
244 *r_error_str = N_("Cannot move strip to different scene");
245 return false;
246 }
247
249 strips.add(src_seq);
251
252 for (Sequence *seq : strips) {
253 /* Move to meta. */
254 SEQ_edit_move_strip_to_seqbase(scene, seqbase, seq, &dst_seqm->seqbase);
255 }
256
257 return true;
258}
259
261 Scene *scene,
262 Sequence *seq,
263 int timeline_frame)
264{
265 const float content_start = SEQ_time_start_frame_get(seq);
266 const float content_end = SEQ_time_content_end_frame_get(scene, seq);
267
268 /* Adjust within range of extended still-frames before strip. */
269 if (timeline_frame < content_start) {
270 const float offset = content_start + 1 - timeline_frame;
271 seq->start -= offset;
272 seq->startofs += offset;
273 }
274 /* Adjust within range of strip contents. */
275 else if ((timeline_frame >= content_start) && (timeline_frame <= content_end)) {
276 seq->endofs = 0;
277 float speed_factor = SEQ_time_media_playback_rate_factor_get(scene, seq);
278 seq->anim_endofs += round_fl_to_int((content_end - timeline_frame) * speed_factor);
279 }
280
281 /* Needed only to set `seq->len`. */
282 SEQ_add_reload_new_file(bmain, scene, seq, false);
283 SEQ_time_right_handle_frame_set(scene, seq, timeline_frame);
284}
285
287 Scene *scene,
288 Sequence *seq,
289 int timeline_frame)
290{
291 const float content_start = SEQ_time_start_frame_get(seq);
292 const float content_end = SEQ_time_content_end_frame_get(scene, seq);
293
294 /* Adjust within range of strip contents. */
295 if ((timeline_frame >= content_start) && (timeline_frame <= content_end)) {
296 float speed_factor = SEQ_time_media_playback_rate_factor_get(scene, seq);
297 seq->anim_startofs += round_fl_to_int((timeline_frame - content_start) * speed_factor);
298 seq->start = timeline_frame;
299 seq->startofs = 0;
300 }
301 /* Adjust within range of extended still-frames after strip. */
302 else if (timeline_frame > content_end) {
303 const float offset = timeline_frame - content_end + 1;
304 seq->start += offset;
305 seq->endofs += offset;
306 }
307
308 /* Needed only to set `seq->len`. */
309 SEQ_add_reload_new_file(bmain, scene, seq, false);
310 SEQ_time_left_handle_frame_set(scene, seq, timeline_frame);
311}
312
313static bool seq_edit_split_intersect_check(const Scene *scene,
314 const Sequence *seq,
315 const int timeline_frame)
316{
317 return timeline_frame > SEQ_time_left_handle_frame_get(scene, seq) &&
318 timeline_frame < SEQ_time_right_handle_frame_get(scene, seq);
319}
320
322 Scene *scene,
323 Sequence *left_seq,
324 Sequence *right_seq,
325 const int timeline_frame,
326 const eSeqSplitMethod method)
327{
328 if (seq_edit_split_intersect_check(scene, right_seq, timeline_frame)) {
329 switch (method) {
330 case SEQ_SPLIT_SOFT:
331 SEQ_time_left_handle_frame_set(scene, right_seq, timeline_frame);
332 break;
333 case SEQ_SPLIT_HARD:
334 seq_split_set_left_hold_offset(bmain, scene, right_seq, timeline_frame);
335 break;
336 }
337 }
338
339 if (seq_edit_split_intersect_check(scene, left_seq, timeline_frame)) {
340 switch (method) {
341 case SEQ_SPLIT_SOFT:
342 SEQ_time_right_handle_frame_set(scene, left_seq, timeline_frame);
343 break;
344 case SEQ_SPLIT_HARD:
345 seq_split_set_right_hold_offset(bmain, scene, left_seq, timeline_frame);
346 break;
347 }
348 }
349}
350
352 const Sequence *seq,
353 const int timeline_frame)
354{
355 bool input_does_intersect = false;
356 if (seq->seq1) {
357 input_does_intersect |= seq_edit_split_intersect_check(scene, seq->seq1, timeline_frame);
358 if ((seq->seq1->type & SEQ_TYPE_EFFECT) != 0) {
359 input_does_intersect |= seq_edit_split_effect_inputs_intersect(
360 scene, seq->seq1, timeline_frame);
361 }
362 }
363 if (seq->seq2) {
364 input_does_intersect |= seq_edit_split_intersect_check(scene, seq->seq2, timeline_frame);
365 if ((seq->seq1->type & SEQ_TYPE_EFFECT) != 0) {
366 input_does_intersect |= seq_edit_split_effect_inputs_intersect(
367 scene, seq->seq2, timeline_frame);
368 }
369 }
370 return input_does_intersect;
371}
372
375 const int timeline_frame,
376 const char **r_error)
377{
378 for (Sequence *seq : strips) {
381 *r_error = "Strip is locked.";
382 return false;
383 }
384 if ((seq->type & SEQ_TYPE_EFFECT) == 0) {
385 continue;
386 }
387 if (!seq_edit_split_intersect_check(scene, seq, timeline_frame)) {
388 continue;
389 }
390 if (SEQ_effect_get_num_inputs(seq->type) <= 1) {
391 continue;
392 }
394 *r_error = "Splitting transition effect is not permitted.";
395 return false;
396 }
397 if (!seq_edit_split_effect_inputs_intersect(scene, seq, timeline_frame)) {
398 *r_error = "Effect inputs don't overlap. Can not split such effect.";
399 return false;
400 }
401 }
402 return true;
403}
404
406 Scene *scene,
407 ListBase *seqbase,
408 Sequence *seq,
409 const int timeline_frame,
410 const eSeqSplitMethod method,
411 const char **r_error)
412{
413 if (!seq_edit_split_intersect_check(scene, seq, timeline_frame)) {
414 return nullptr;
415 }
416
417 /* Whole strip effect chain must be duplicated in order to preserve relationships. */
419 strips.add(seq);
421
422 /* All connected strips (that are selected and at the cut frame) must also be duplicated. */
423 blender::VectorSet<Sequence *> strips_old(strips);
424 for (Sequence *strip : strips_old) {
426 connections.remove_if([&](Sequence *connection) {
427 return !(connection->flag & SELECT) ||
428 !seq_edit_split_intersect_check(scene, connection, timeline_frame);
429 });
430 strips.add_multiple(connections.as_span());
431 }
432
433 /* In case connected strips had effects, duplicate those too: */
435
436 if (!seq_edit_split_operation_permitted_check(scene, strips, timeline_frame, r_error)) {
437 return nullptr;
438 }
439
440 /* Store `F-Curves`, so original ones aren't renamed. */
441 SeqAnimationBackup animation_backup{};
442 SEQ_animation_backup_original(scene, &animation_backup);
443
444 ListBase left_strips = {nullptr, nullptr};
445 for (Sequence *seq_iter : strips) {
446 /* Move strips in collection from seqbase to new ListBase. */
447 BLI_remlink(seqbase, seq_iter);
448 BLI_addtail(&left_strips, seq_iter);
449
450 /* Duplicate curves from backup, so they can be renamed along with split strips. */
451 SEQ_animation_duplicate_backup_to_scene(scene, seq_iter, &animation_backup);
452 }
453
454 /* Duplicate ListBase. */
455 ListBase right_strips = {nullptr, nullptr};
456 SEQ_sequence_base_dupli_recursive(scene, scene, &right_strips, &left_strips, SEQ_DUPE_ALL, 0);
457
458 Sequence *left_seq = static_cast<Sequence *>(left_strips.first);
459 Sequence *right_seq = static_cast<Sequence *>(right_strips.first);
460 Sequence *return_seq = nullptr;
461
462 /* Move strips from detached `ListBase`, otherwise they can't be flagged for removal. */
463 BLI_movelisttolist(seqbase, &left_strips);
464 BLI_movelisttolist(seqbase, &right_strips);
465
466 /* Rename duplicated strips. This has to be done immediately after adding
467 * strips to seqbase, for lookup cache to work correctly. */
468 Sequence *seq_rename = right_seq;
469 for (; seq_rename; seq_rename = seq_rename->next) {
470 SEQ_ensure_unique_name(seq_rename, scene);
471 }
472
473 /* Split strips. */
474 while (left_seq && right_seq) {
475 if (SEQ_time_left_handle_frame_get(scene, left_seq) >= timeline_frame) {
476 SEQ_edit_flag_for_removal(scene, seqbase, left_seq);
477 }
478 else if (SEQ_time_right_handle_frame_get(scene, right_seq) <= timeline_frame) {
479 SEQ_edit_flag_for_removal(scene, seqbase, right_seq);
480 }
481 else if (return_seq == nullptr) {
482 /* Store return value - pointer to strip that will not be removed. */
483 return_seq = right_seq;
484 }
485
486 seq_edit_split_handle_strip_offsets(bmain, scene, left_seq, right_seq, timeline_frame, method);
487 left_seq = left_seq->next;
488 right_seq = right_seq->next;
489 }
490
491 SEQ_edit_remove_flagged_sequences(scene, seqbase);
492 SEQ_animation_restore_original(scene, &animation_backup);
493
494 return return_seq;
495}
496
498 ListBase *seqbase,
499 const int initial_frame,
500 const bool remove_all_gaps)
501{
502 GapInfo gap_info = {0};
503 seq_time_gap_info_get(scene, seqbase, initial_frame, &gap_info);
504
505 if (!gap_info.gap_exists) {
506 return false;
507 }
508
509 if (remove_all_gaps) {
510 while (gap_info.gap_exists) {
512 scene, seqbase, -gap_info.gap_length, gap_info.gap_start_frame);
513 seq_time_gap_info_get(scene, seqbase, initial_frame, &gap_info);
514 }
515 }
516 else {
518 scene, seqbase, -gap_info.gap_length, gap_info.gap_start_frame);
519 }
520 return true;
521}
522
523void SEQ_edit_sequence_name_set(Scene *scene, Sequence *seq, const char *new_name)
524{
525 BLI_strncpy_utf8(seq->name + 2, new_name, MAX_NAME - 2);
526 BLI_str_utf8_invalid_strip(seq->name + 2, strlen(seq->name + 2));
528}
void BKE_sound_mute_scene_sound(void *handle, bool mute)
#define LISTBASE_FOREACH(type, var, list)
#define LISTBASE_FOREACH_MUTABLE(type, var, list)
void void void BLI_movelisttolist(struct ListBase *dst, struct ListBase *src) ATTR_NONNULL(1
void BLI_addtail(struct ListBase *listbase, void *vlink) ATTR_NONNULL(1)
Definition listbase.cc:110
void BLI_remlink(struct ListBase *listbase, void *vlink) ATTR_NONNULL(1)
Definition listbase.cc:130
MINLINE int round_fl_to_int(float a)
#define STRNCPY(dst, src)
Definition BLI_string.h:593
char * BLI_strncpy(char *__restrict dst, const char *__restrict src, size_t dst_maxncpy) ATTR_NONNULL(1
char * BLI_strncpy_utf8(char *__restrict dst, const char *__restrict src, size_t dst_maxncpy) ATTR_NONNULL(1
int BLI_str_utf8_invalid_strip(char *str, size_t length) ATTR_NONNULL(1)
#define ELEM(...)
#define MAX_NAME
Definition DNA_defs.h:50
@ SEQ_TYPE_SOUND_RAM
@ SEQ_TYPE_CROSS
@ SEQ_TYPE_WIPE
@ SEQ_TYPE_META
@ SEQ_TYPE_SCENE
@ SEQ_TYPE_GAMCROSS
@ SEQ_TYPE_EFFECT
@ SEQ_FLAG_DELETE
Group Output data from inside of a node group A color picker Mix two input colors RGB to Convert a color s luminance to a grayscale value Generate a normal vector and a dot product Brightness Control the brightness and contrast of the input color Vector Map input vector components with curves Camera Retrieve information about the camera and how it relates to the current shading point s position Clamp a value between a minimum and a maximum Vector Perform vector math operation Invert Invert a producing a negative Combine Generate a color from its and blue channels(Deprecated)") DefNode(ShaderNode
eSeqSplitMethod
Definition SEQ_edit.hh:54
@ SEQ_SPLIT_SOFT
Definition SEQ_edit.hh:55
@ SEQ_SPLIT_HARD
Definition SEQ_edit.hh:56
#define SEQ_DUPE_ALL
void SEQ_animation_backup_original(Scene *scene, SeqAnimationBackup *backup)
Definition animation.cc:120
void SEQ_free_animdata(Scene *scene, Sequence *seq)
Definition animation.cc:102
void SEQ_animation_duplicate_backup_to_scene(Scene *scene, Sequence *seq, SeqAnimationBackup *backup)
Definition animation.cc:161
void SEQ_animation_restore_original(Scene *scene, SeqAnimationBackup *backup)
Definition animation.cc:130
ListBase * SEQ_channels_displayed_get(Editing *ed)
Definition channels.cc:23
bool add(const Key &key)
Span< Key > as_span() const
void add_multiple(Span< Key > keys)
int64_t remove_if(Predicate &&predicate)
#define SELECT
int SEQ_effect_get_num_inputs(int seq_type)
Definition effects.cc:3467
void SEQ_iterator_set_expand(const Scene *scene, ListBase *seqbase, VectorSet< Sequence * > &strips, void seq_query_func(const Scene *scene, Sequence *seq_reference, ListBase *seqbase, VectorSet< Sequence * > &strips))
Definition iterator.cc:61
void SEQ_query_strip_effect_chain(const Scene *scene, Sequence *reference_strip, ListBase *seqbase, VectorSet< Sequence * > &strips)
Definition iterator.cc:210
bool SEQ_render_is_muted(const ListBase *channels, const Sequence *seq)
Definition render.cc:2154
void SEQ_sequence_lookup_invalidate(const Scene *scene)
ListBase * SEQ_get_seqbase_by_seq(const Scene *scene, Sequence *seq)
void SEQ_ensure_unique_name(Sequence *seq, Scene *scene)
void SEQ_sequence_base_dupli_recursive(const Scene *scene_src, Scene *scene_dst, ListBase *nseqbase, const ListBase *seqbase, int dupe_flag, const int flag)
Definition sequencer.cc:653
void SEQ_sequence_free(Scene *scene, Sequence *seq)
Definition sequencer.cc:245
Editing * SEQ_editing_get(const Scene *scene)
Definition sequencer.cc:262
void SEQ_add_reload_new_file(Main *bmain, Scene *scene, Sequence *seq, const bool lock_range)
Definition strip_add.cc:525
blender::VectorSet< Sequence * > SEQ_get_connected_strips(const Sequence *seq)
bool SEQ_edit_remove_gaps(Scene *scene, ListBase *seqbase, const int initial_frame, const bool remove_all_gaps)
static bool seq_edit_split_operation_permitted_check(const Scene *scene, blender::Span< Sequence * > strips, const int timeline_frame, const char **r_error)
static void seq_split_set_left_hold_offset(Main *bmain, Scene *scene, Sequence *seq, int timeline_frame)
void SEQ_edit_flag_for_removal(Scene *scene, ListBase *seqbase, Sequence *seq)
bool SEQ_edit_move_strip_to_seqbase(Scene *scene, ListBase *seqbase, Sequence *seq, ListBase *dst_seqbase)
static void seq_edit_split_handle_strip_offsets(Main *bmain, Scene *scene, Sequence *left_seq, Sequence *right_seq, const int timeline_frame, const eSeqSplitMethod method)
Sequence * SEQ_edit_strip_split(Main *bmain, Scene *scene, ListBase *seqbase, Sequence *seq, const int timeline_frame, const eSeqSplitMethod method, const char **r_error)
static bool seq_edit_split_effect_inputs_intersect(const Scene *scene, const Sequence *seq, const int timeline_frame)
static bool seq_edit_split_intersect_check(const Scene *scene, const Sequence *seq, const int timeline_frame)
bool SEQ_edit_sequence_swap(Scene *scene, Sequence *seq_a, Sequence *seq_b, const char **r_error_str)
Definition strip_edit.cc:42
static void seq_split_set_right_hold_offset(Main *bmain, Scene *scene, Sequence *seq, int timeline_frame)
void SEQ_edit_sequence_name_set(Scene *scene, Sequence *seq, const char *new_name)
void SEQ_edit_remove_flagged_sequences(Scene *scene, ListBase *seqbase)
bool SEQ_edit_move_strip_to_meta(Scene *scene, Sequence *src_seq, Sequence *dst_seqm, const char **r_error_str)
static void seq_update_muting_recursive(ListBase *channels, ListBase *seqbasep, Sequence *metaseq, const bool mute)
Definition strip_edit.cc:98
void SEQ_edit_update_muting(Editing *ed)
static void sequencer_flag_users_for_removal(Scene *scene, ListBase *seqbase, Sequence *seq)
bool SEQ_exists_in_seqbase(const Sequence *seq, const ListBase *seqbase)
bool SEQ_relation_is_effect_of_strip(const Sequence *effect, const Sequence *input)
void SEQ_relations_invalidate_cache_preprocessed(Scene *scene, Sequence *seq)
int SEQ_time_strip_length_get(const Scene *scene, const Sequence *seq)
void SEQ_time_right_handle_frame_set(const Scene *scene, Sequence *seq, int timeline_frame)
void SEQ_time_left_handle_frame_set(const Scene *scene, Sequence *seq, int timeline_frame)
int SEQ_time_left_handle_frame_get(const Scene *, const Sequence *seq)
float SEQ_time_content_end_frame_get(const Scene *scene, const Sequence *seq)
void seq_time_gap_info_get(const Scene *scene, ListBase *seqbase, const int initial_frame, GapInfo *r_gap_info)
void seq_time_effect_range_set(const Scene *scene, Sequence *seq)
float SEQ_time_start_frame_get(const Sequence *seq)
float SEQ_time_media_playback_rate_factor_get(const Scene *scene, const Sequence *seq)
Definition strip_time.cc:38
int SEQ_time_right_handle_frame_get(const Scene *scene, const Sequence *seq)
bool SEQ_transform_seqbase_shuffle(ListBase *seqbasep, Sequence *test, Scene *evil_scene)
bool SEQ_transform_test_overlap(const Scene *scene, ListBase *seqbasep, Sequence *test)
bool SEQ_transform_is_locked(ListBase *channels, const Sequence *seq)
void SEQ_transform_offset_after_frame(Scene *scene, ListBase *seqbase, const int delta, const int timeline_frame)
ListBase seqbase
ListBase channels
ListBase metastack
int gap_length
Definition strip_time.hh:22
int gap_start_frame
Definition strip_time.hh:21
bool gap_exists
Definition strip_time.hh:23
void * last
void * first
Sequence * parseq
struct Editing * ed
struct Sequence * prev
struct Sequence * seq1
struct Sequence * seq2
struct Sequence * next
#define N_(msgid)