Blender V4.3
iterator.cc
Go to the documentation of this file.
1/* SPDX-FileCopyrightText: 2001-2002 NaN Holding BV. All rights reserved.
2 * SPDX-FileCopyrightText: 2003-2024 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
11#include <cstring>
12
13#include "MEM_guardedalloc.h"
14
15#include "DNA_sequence_types.h"
16
17#include "BLI_listbase.h"
18
19#include "SEQ_effects.hh"
20#include "SEQ_iterator.hh"
21#include "SEQ_relations.hh"
22#include "SEQ_render.hh"
23#include "SEQ_time.hh"
24
26
27static bool seq_for_each_recursive(ListBase *seqbase, SeqForEachFunc callback, void *user_data)
28{
29 LISTBASE_FOREACH (Sequence *, seq, seqbase) {
30 if (!callback(seq, user_data)) {
31 /* Callback signaled stop, return. */
32 return false;
33 }
34 if (seq->type == SEQ_TYPE_META) {
35 if (!seq_for_each_recursive(&seq->seqbase, callback, user_data)) {
36 return false;
37 }
38 }
39 }
40 return true;
41}
42
43void SEQ_for_each_callback(ListBase *seqbase, SeqForEachFunc callback, void *user_data)
44{
45 seq_for_each_recursive(seqbase, callback, user_data);
46}
47
49 const Scene *scene,
50 ListBase *seqbase,
51 void seq_query_func(const Scene *scene,
52 Sequence *seq_reference,
53 ListBase *seqbase,
54 VectorSet<Sequence *> &strips))
55{
57 seq_query_func(scene, seq_reference, seqbase, strips);
58 return strips;
59}
60
62 ListBase *seqbase,
64 void seq_query_func(const Scene *scene,
65 Sequence *seq_reference,
66 ListBase *seqbase,
67 VectorSet<Sequence *> &strips))
68{
69 /* Collect expanded results for each sequence in provided VectorSet. */
70 VectorSet<Sequence *> query_matches;
71
72 for (Sequence *strip : strips) {
73 query_matches.add_multiple(SEQ_query_by_reference(strip, scene, seqbase, seq_query_func));
74 }
75
76 /* Merge all expanded results in provided VectorSet. */
77 strips.add_multiple(query_matches);
78}
79
80static void query_all_strips_recursive(const ListBase *seqbase, VectorSet<Sequence *> &strips)
81{
82 LISTBASE_FOREACH (Sequence *, seq, seqbase) {
83 if (seq->type == SEQ_TYPE_META) {
84 query_all_strips_recursive(&seq->seqbase, strips);
85 }
86 strips.add(seq);
87 }
88}
89
91{
93 query_all_strips_recursive(seqbase, strips);
94 return strips;
95}
96
98{
100 LISTBASE_FOREACH (Sequence *, strip, seqbase) {
101 strips.add(strip);
102 }
103 return strips;
104}
105
107{
109 LISTBASE_FOREACH (Sequence *, strip, seqbase) {
110 if ((strip->flag & SELECT) != 0) {
111 strips.add(strip);
112 }
113 }
114 return strips;
115}
116
118 ListBase *seqbase,
119 const int timeline_frame)
120{
122
123 LISTBASE_FOREACH (Sequence *, strip, seqbase) {
124 if (SEQ_time_strip_intersects_frame(scene, strip, timeline_frame)) {
125 strips.add(strip);
126 }
127 }
128 return strips;
129}
130
131static void collection_filter_channel_up_to_incl(VectorSet<Sequence *> &strips, const int channel)
132{
133 strips.remove_if([&](Sequence *strip) { return strip->machine > channel; });
134}
135
136/* Check if seq must be rendered. This depends on whole stack in some cases, not only seq itself.
137 * Order of applying these conditions is important. */
138static bool must_render_strip(const VectorSet<Sequence *> &strips, Sequence *strip)
139{
140 bool seq_have_effect_in_stack = false;
141 for (Sequence *strip_iter : strips) {
142 /* Strips is below another strip with replace blending are not rendered. */
143 if (strip_iter->blend_mode == SEQ_BLEND_REPLACE && strip->machine < strip_iter->machine) {
144 return false;
145 }
146
147 if ((strip_iter->type & SEQ_TYPE_EFFECT) != 0 &&
148 SEQ_relation_is_effect_of_strip(strip_iter, strip))
149 {
150 /* Strips in same channel or higher than its effect are rendered. */
151 if (strip->machine >= strip_iter->machine) {
152 return true;
153 }
154 /* Mark that this strip has effect in stack, that is above the strip. */
155 seq_have_effect_in_stack = true;
156 }
157 }
158
159 /* All non-generator effects are rendered (with respect to conditions above). */
160 if ((strip->type & SEQ_TYPE_EFFECT) != 0 && SEQ_effect_get_num_inputs(strip->type) != 0) {
161 return true;
162 }
163
164 /* If strip has effects in stack, and all effects are above this strip, it is not rendered. */
165 if (seq_have_effect_in_stack) {
166 return false;
167 }
168
169 return true;
170}
171
172/* Remove strips we don't want to render from VectorSet. */
174{
175 /* Remove sound strips and muted strips from VectorSet, because these are not rendered.
176 * Function #must_render_strip() don't have to check for these strips anymore. */
177 strips.remove_if([&](Sequence *strip) {
178 return strip->type == SEQ_TYPE_SOUND_RAM || SEQ_render_is_muted(channels, strip);
179 });
180
181 strips.remove_if([&](Sequence *strip) { return !must_render_strip(strips, strip); });
182}
183
185 ListBase *channels,
186 ListBase *seqbase,
187 const int timeline_frame,
188 const int displayed_channel)
189{
190 VectorSet strips = query_strips_at_frame(scene, seqbase, timeline_frame);
191 if (displayed_channel != 0) {
192 collection_filter_channel_up_to_incl(strips, displayed_channel);
193 }
194 collection_filter_rendered_strips(strips, channels);
195 return strips;
196}
197
199{
201 LISTBASE_FOREACH (Sequence *, seq, seqbase) {
202 if ((seq->flag & SELECT) != 0) {
203 continue;
204 }
205 strips.add(seq);
206 }
207 return strips;
208}
209
211 Sequence *reference_strip,
212 ListBase *seqbase,
213 VectorSet<Sequence *> &strips)
214{
215 if (strips.contains(reference_strip)) {
216 return; /* Strip is already in set, so all effects connected to it are as well. */
217 }
218
219 strips.add(reference_strip);
220
221 /* Find all strips that reference_strip is connected to. */
222 if (reference_strip->type & SEQ_TYPE_EFFECT) {
223 if (reference_strip->seq1) {
224 SEQ_query_strip_effect_chain(scene, reference_strip->seq1, seqbase, strips);
225 }
226 if (reference_strip->seq2) {
227 SEQ_query_strip_effect_chain(scene, reference_strip->seq2, seqbase, strips);
228 }
229 }
230
231 /* Find all strips connected to reference_strip. */
232 LISTBASE_FOREACH (Sequence *, seq_test, seqbase) {
233 if (seq_test->seq1 == reference_strip || seq_test->seq2 == reference_strip) {
234 SEQ_query_strip_effect_chain(scene, seq_test, seqbase, strips);
235 }
236 }
237}
#define LISTBASE_FOREACH(type, var, list)
@ SEQ_BLEND_REPLACE
@ SEQ_TYPE_SOUND_RAM
@ SEQ_TYPE_META
@ SEQ_TYPE_EFFECT
Read Guarded memory(de)allocation.
bool(*)(Sequence *seq, void *user_data) SeqForEachFunc
bool add(const Key &key)
bool contains(const Key &key) const
void add_multiple(Span< Key > keys)
int64_t remove_if(Predicate &&predicate)
#define SELECT
DEGForeachIDComponentCallback callback
int SEQ_effect_get_num_inputs(int seq_type)
Definition effects.cc:3467
VectorSet< Sequence * > SEQ_query_unselected_strips(ListBase *seqbase)
Definition iterator.cc:198
static bool seq_for_each_recursive(ListBase *seqbase, SeqForEachFunc callback, void *user_data)
Definition iterator.cc:27
static bool must_render_strip(const VectorSet< Sequence * > &strips, Sequence *strip)
Definition iterator.cc:138
VectorSet< Sequence * > SEQ_query_rendered_strips(const Scene *scene, ListBase *channels, ListBase *seqbase, const int timeline_frame, const int displayed_channel)
Definition iterator.cc:184
static VectorSet< Sequence * > query_strips_at_frame(const Scene *scene, ListBase *seqbase, const int timeline_frame)
Definition iterator.cc:117
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
VectorSet< Sequence * > SEQ_query_all_strips_recursive(const ListBase *seqbase)
Definition iterator.cc:90
static void collection_filter_channel_up_to_incl(VectorSet< Sequence * > &strips, const int channel)
Definition iterator.cc:131
static void collection_filter_rendered_strips(VectorSet< Sequence * > &strips, ListBase *channels)
Definition iterator.cc:173
static void query_all_strips_recursive(const ListBase *seqbase, VectorSet< Sequence * > &strips)
Definition iterator.cc:80
void SEQ_query_strip_effect_chain(const Scene *scene, Sequence *reference_strip, ListBase *seqbase, VectorSet< Sequence * > &strips)
Definition iterator.cc:210
VectorSet< Sequence * > SEQ_query_all_strips(ListBase *seqbase)
Definition iterator.cc:97
VectorSet< Sequence * > SEQ_query_selected_strips(ListBase *seqbase)
Definition iterator.cc:106
VectorSet< Sequence * > SEQ_query_by_reference(Sequence *seq_reference, const Scene *scene, ListBase *seqbase, void seq_query_func(const Scene *scene, Sequence *seq_reference, ListBase *seqbase, VectorSet< Sequence * > &strips))
Definition iterator.cc:48
void SEQ_for_each_callback(ListBase *seqbase, SeqForEachFunc callback, void *user_data)
Definition iterator.cc:43
bool SEQ_render_is_muted(const ListBase *channels, const Sequence *seq)
Definition render.cc:2154
bool SEQ_relation_is_effect_of_strip(const Sequence *effect, const Sequence *input)
bool SEQ_time_strip_intersects_frame(const Scene *scene, const Sequence *seq, const int timeline_frame)
struct Sequence * seq1
struct Sequence * seq2