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
10
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
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 }
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.
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
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
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