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