Blender V5.0
depsgraph_query_foreach.cc
Go to the documentation of this file.
1/* SPDX-FileCopyrightText: 2017 Blender Authors
2 *
3 * SPDX-License-Identifier: GPL-2.0-or-later */
4
10
11#include <deque>
12
13#include "DEG_depsgraph.hh"
15
16#include "intern/depsgraph.hh"
22
23namespace deg = blender::deg;
24
25/* ************************ DEG TRAVERSAL ********************* */
26
27namespace blender::deg {
28namespace {
29
30using TraversalQueue = std::deque<OperationNode *>;
31
32using DEGForeachOperation = void (*)(OperationNode *, void *);
33
34bool deg_foreach_needs_visit(const OperationNode *op_node, const int flags)
35{
37 if (op_node->opcode == OperationCode::RIGIDBODY_SIM) {
38 return false;
39 }
40 }
41 return true;
42}
43
44void deg_foreach_dependent_operation(const Depsgraph * /*graph*/,
45 const IDNode *target_id_node,
46 eDepsObjectComponentType source_component_type,
47 int flags,
48 DEGForeachOperation callback,
49 void *user_data)
50{
51 if (target_id_node == nullptr) {
52 /* TODO(sergey): Shall we inform or assert here about attempt to start
53 * iterating over non-existing ID? */
54 return;
55 }
56 /* Start with scheduling all operations from ID node. */
57 TraversalQueue queue;
58 Set<OperationNode *> scheduled;
59 for (ComponentNode *comp_node : target_id_node->components.values()) {
60 if (comp_node->type == NodeType::VISIBILITY) {
61 /* Visibility component is only used internally. It is not to be reporting dependencies to
62 * the outer world. */
63 continue;
64 }
65
66 if (source_component_type != DEG_OB_COMP_ANY &&
67 nodeTypeToObjectComponent(comp_node->type) != source_component_type)
68 {
69 continue;
70 }
71 for (OperationNode *op_node : comp_node->operations) {
72 if (!deg_foreach_needs_visit(op_node, flags)) {
73 continue;
74 }
75 queue.push_back(op_node);
76 scheduled.add(op_node);
77 }
78 }
79 /* Process the queue. */
80 while (!queue.empty()) {
81 /* get next operation node to process. */
82 OperationNode *op_node = queue.front();
83 queue.pop_front();
84 for (;;) {
85 callback(op_node, user_data);
86 /* Schedule outgoing operation nodes. */
87 if (op_node->outlinks.size() == 1) {
88 OperationNode *to_node = (OperationNode *)op_node->outlinks[0]->to;
89 if (!scheduled.contains(to_node) && deg_foreach_needs_visit(to_node, flags)) {
90 scheduled.add_new(to_node);
91 op_node = to_node;
92 }
93 else {
94 break;
95 }
96 }
97 else {
98 for (Relation *rel : op_node->outlinks) {
99 OperationNode *to_node = (OperationNode *)rel->to;
100 if (!scheduled.contains(to_node) && deg_foreach_needs_visit(to_node, flags)) {
101 queue.push_front(to_node);
102 scheduled.add_new(to_node);
103 }
104 }
105 break;
106 }
107 }
108 }
109}
110
111struct ForeachIDComponentData {
113 IDNode *target_id_node;
114 Set<ComponentNode *> visited;
115};
116
117void deg_foreach_dependent_component_callback(OperationNode *op_node, void *user_data_v)
118{
119 ForeachIDComponentData *user_data = reinterpret_cast<ForeachIDComponentData *>(user_data_v);
120 ComponentNode *comp_node = op_node->owner;
121 IDNode *id_node = comp_node->owner;
122 if (id_node != user_data->target_id_node && !user_data->visited.contains(comp_node)) {
123 user_data->callback(id_node->id_orig, nodeTypeToObjectComponent(comp_node->type));
124 user_data->visited.add_new(comp_node);
125 }
126}
127
128void deg_foreach_dependent_ID_component(const Depsgraph *graph,
129 const ID *id,
130 eDepsObjectComponentType source_component_type,
131 int flags,
133{
134 ForeachIDComponentData data;
135 data.callback = callback;
136 data.target_id_node = graph->find_id_node(id);
137 deg_foreach_dependent_operation(graph,
138 data.target_id_node,
139 source_component_type,
140 flags,
141 deg_foreach_dependent_component_callback,
142 &data);
143}
144
145struct ForeachIDData {
146 DEGForeachIDCallback callback;
147 IDNode *target_id_node;
148 Set<IDNode *> visited;
149};
150
151void deg_foreach_dependent_ID_callback(OperationNode *op_node, void *user_data_v)
152{
153 ForeachIDData *user_data = reinterpret_cast<ForeachIDData *>(user_data_v);
154 ComponentNode *comp_node = op_node->owner;
155 IDNode *id_node = comp_node->owner;
156 if (id_node != user_data->target_id_node && !user_data->visited.contains(id_node)) {
157 user_data->callback(id_node->id_orig);
158 user_data->visited.add_new(id_node);
159 }
160}
161
162void deg_foreach_dependent_ID(const Depsgraph *graph, const ID *id, DEGForeachIDCallback callback)
163{
164 ForeachIDData data;
165 data.callback = callback;
166 data.target_id_node = graph->find_id_node(id);
167 deg_foreach_dependent_operation(
168 graph, data.target_id_node, DEG_OB_COMP_ANY, 0, deg_foreach_dependent_ID_callback, &data);
169}
170
171void deg_foreach_ancestor_ID(const Depsgraph *graph, const ID *id, DEGForeachIDCallback callback)
172{
173 /* Start with getting ID node from the graph. */
174 IDNode *target_id_node = graph->find_id_node(id);
175 if (target_id_node == nullptr) {
176 /* TODO(sergey): Shall we inform or assert here about attempt to start
177 * iterating over non-existing ID? */
178 return;
179 }
180 /* Start with scheduling all operations from ID node. */
181 TraversalQueue queue;
182 Set<OperationNode *> scheduled;
183 for (ComponentNode *comp_node : target_id_node->components.values()) {
184 for (OperationNode *op_node : comp_node->operations) {
185 queue.push_back(op_node);
186 scheduled.add(op_node);
187 }
188 }
189 Set<IDNode *> visited;
190 visited.add_new(target_id_node);
191 /* Process the queue. */
192 while (!queue.empty()) {
193 /* get next operation node to process. */
194 OperationNode *op_node = queue.front();
195 queue.pop_front();
196 for (;;) {
197 /* Check whether we need to inform callee about corresponding ID node. */
198 ComponentNode *comp_node = op_node->owner;
199 IDNode *id_node = comp_node->owner;
200 if (!visited.contains(id_node)) {
201 /* TODO(sergey): Is it orig or evaluated? */
202 callback(id_node->id_orig);
203 visited.add_new(id_node);
204 }
205 /* Schedule incoming operation nodes. */
206 if (op_node->inlinks.size() == 1) {
207 Node *from = op_node->inlinks[0]->from;
208 if (from->get_class() == NodeClass::OPERATION) {
209 OperationNode *from_node = (OperationNode *)from;
210 if (scheduled.add(from_node)) {
211 op_node = from_node;
212 }
213 else {
214 break;
215 }
216 }
217 }
218 else {
219 for (Relation *rel : op_node->inlinks) {
220 Node *from = rel->from;
221 if (from->get_class() == NodeClass::OPERATION) {
222 OperationNode *from_node = (OperationNode *)from;
223 if (scheduled.add(from_node)) {
224 queue.push_front(from_node);
225 }
226 }
227 }
228 break;
229 }
230 }
231 }
232}
233
234void deg_foreach_id(const Depsgraph *depsgraph, DEGForeachIDCallback callback)
235{
236 for (const IDNode *id_node : depsgraph->id_nodes) {
237 callback(id_node->id_orig);
238 }
239}
240
241} // namespace
242} // namespace blender::deg
243
245 const ID *id,
246 DEGForeachIDCallback callback)
247{
248 deg::deg_foreach_dependent_ID((const deg::Depsgraph *)depsgraph, id, callback);
249}
250
252 const ID *id,
253 eDepsObjectComponentType source_component_type,
254 int flags,
256{
257 deg::deg_foreach_dependent_ID_component(
258 (const deg::Depsgraph *)depsgraph, id, source_component_type, flags, callback);
259}
260
261void DEG_foreach_ancestor_ID(const Depsgraph *depsgraph,
262 const ID *id,
263 DEGForeachIDCallback callback)
264{
265 deg::deg_foreach_ancestor_ID((const deg::Depsgraph *)depsgraph, id, callback);
266}
267
268void DEG_foreach_ID(const Depsgraph *depsgraph, DEGForeachIDCallback callback)
269{
270 deg::deg_foreach_id((const deg::Depsgraph *)depsgraph, callback);
271}
eDepsObjectComponentType
@ DEG_OB_COMP_ANY
blender::FunctionRef< void(ID *id, eDepsObjectComponentType component)> DEGForeachIDComponentCallback
@ DEG_FOREACH_COMPONENT_IGNORE_TRANSFORM_SOLVERS
blender::FunctionRef< void(ID *id)> DEGForeachIDCallback
struct ID ID
BMesh const char void * data
BPy_StructRNA * depsgraph
bool contains(const Key &key) const
Definition BLI_set.hh:310
bool add(const Key &key)
Definition BLI_set.hh:248
void add_new(const Key &key)
Definition BLI_set.hh:233
void DEG_foreach_ID(const Depsgraph *depsgraph, DEGForeachIDCallback callback)
void DEG_foreach_dependent_ID_component(const Depsgraph *depsgraph, const ID *id, eDepsObjectComponentType source_component_type, int flags, DEGForeachIDComponentCallback callback)
void DEG_foreach_dependent_ID(const Depsgraph *depsgraph, const ID *id, DEGForeachIDCallback callback)
void DEG_foreach_ancestor_ID(const Depsgraph *depsgraph, const ID *id, DEGForeachIDCallback callback)
eDepsObjectComponentType nodeTypeToObjectComponent(NodeType type)
Definition deg_node.cc:198
Definition DNA_ID.h:414
Relations inlinks
Definition deg_node.hh:182
Relations outlinks
Definition deg_node.hh:183