Blender  V3.3
depsgraph_query_iter.cc
Go to the documentation of this file.
1 /* SPDX-License-Identifier: GPL-2.0-or-later
2  * Copyright 2017 Blender Foundation. All rights reserved. */
3 
10 /* Silence warnings from copying deprecated fields. */
11 #define DNA_DEPRECATED_ALLOW
12 
13 #include "MEM_guardedalloc.h"
14 
15 #include "BKE_duplilist.h"
16 #include "BKE_geometry_set.hh"
17 #include "BKE_idprop.h"
18 #include "BKE_layer.h"
19 #include "BKE_node.h"
20 #include "BKE_object.h"
21 
22 #include "BLI_math.h"
23 #include "BLI_utildefines.h"
24 
25 #include "DNA_object_types.h"
26 #include "DNA_scene_types.h"
27 
28 #include "DEG_depsgraph.h"
29 #include "DEG_depsgraph_query.h"
30 
31 #include "intern/depsgraph.h"
33 
34 #ifndef NDEBUG
36 #endif
37 
38 /* If defined, all working data will be set to an invalid state, helping
39  * to catch issues when areas accessing data which is considered to be no
40  * longer available. */
41 #undef INVALIDATE_WORK_DATA
42 
43 #ifndef NDEBUG
44 # define INVALIDATE_WORK_DATA
45 #endif
46 
47 namespace deg = blender::deg;
48 
49 /* ************************ DEG ITERATORS ********************* */
50 
51 namespace {
52 
53 void deg_invalidate_iterator_work_data(DEGObjectIterData *data)
54 {
55 #ifdef INVALIDATE_WORK_DATA
56  BLI_assert(data != nullptr);
57  memset((void *)&data->temp_dupli_object, 0xff, sizeof(data->temp_dupli_object));
58 #else
59  (void)data;
60 #endif
61 }
62 
63 void ensure_id_properties_freed(const Object *dupli_object, Object *temp_dupli_object)
64 {
65  if (temp_dupli_object->id.properties == nullptr) {
66  /* No ID properties in temp data-block -- no leak is possible. */
67  return;
68  }
69  if (temp_dupli_object->id.properties == dupli_object->id.properties) {
70  /* Temp copy of object did not modify ID properties. */
71  return;
72  }
73  /* Free memory which is owned by temporary storage which is about to get overwritten. */
74  IDP_FreeProperty(temp_dupli_object->id.properties);
75  temp_dupli_object->id.properties = nullptr;
76 }
77 
78 void ensure_boundbox_freed(const Object *dupli_object, Object *temp_dupli_object)
79 {
80  if (temp_dupli_object->runtime.bb == nullptr) {
81  /* No Bounding Box in temp data-block -- no leak is possible. */
82  return;
83  }
84  if (temp_dupli_object->runtime.bb == dupli_object->runtime.bb) {
85  /* Temp copy of object did not modify Bounding Box. */
86  return;
87  }
88  /* Free memory which is owned by temporary storage which is about to get overwritten. */
89  MEM_freeN(temp_dupli_object->runtime.bb);
90  temp_dupli_object->runtime.bb = nullptr;
91 }
92 
93 void free_owned_memory(DEGObjectIterData *data)
94 {
95  if (data->dupli_object_current == nullptr) {
96  /* We didn't enter duplication yet, so we can't have any dangling pointers. */
97  return;
98  }
99 
100  const Object *dupli_object = data->dupli_object_current->ob;
101  Object *temp_dupli_object = &data->temp_dupli_object;
102 
103  ensure_id_properties_freed(dupli_object, temp_dupli_object);
104  ensure_boundbox_freed(dupli_object, temp_dupli_object);
105 }
106 
107 bool deg_object_hide_original(eEvaluationMode eval_mode, Object *ob, DupliObject *dob)
108 {
109  /* Automatic hiding if this object is being instanced on verts/faces/frames
110  * by its parent. Ideally this should not be needed, but due to the wrong
111  * dependency direction in the data design there is no way to keep the object
112  * visible otherwise. The better solution eventually would be for objects
113  * to specify which object they instance, instead of through parenting.
114  *
115  * This function should not be used for meta-balls. They have custom visibility rules, as hiding
116  * the base meta-ball will also hide all the other balls in the group. */
117  if (eval_mode == DAG_EVAL_RENDER || dob) {
118  const int hide_original_types = OB_DUPLIVERTS | OB_DUPLIFACES;
119 
120  if (!dob || !(dob->type & hide_original_types)) {
121  if (ob->parent && (ob->parent->transflag & hide_original_types)) {
122  return true;
123  }
124  }
125  }
126 
127  return false;
128 }
129 
130 void deg_iterator_duplis_init(DEGObjectIterData *data, Object *object)
131 {
132  if ((data->flag & DEG_ITER_OBJECT_FLAG_DUPLI) &&
133  ((object->transflag & OB_DUPLI) || object->runtime.geometry_set_eval != nullptr)) {
134  data->dupli_parent = object;
135  data->dupli_list = object_duplilist(data->graph, data->scene, object);
136  data->dupli_object_next = (DupliObject *)data->dupli_list->first;
137  }
138 }
139 
140 /* Returns false when iterator is exhausted. */
141 bool deg_iterator_duplis_step(DEGObjectIterData *data)
142 {
143  if (data->dupli_list == nullptr) {
144  return false;
145  }
146 
147  while (data->dupli_object_next != nullptr) {
148  DupliObject *dob = data->dupli_object_next;
149  Object *obd = dob->ob;
150 
151  data->dupli_object_next = data->dupli_object_next->next;
152 
153  if (dob->no_draw) {
154  continue;
155  }
156  if (obd->type == OB_MBALL) {
157  continue;
158  }
159  if (deg_object_hide_original(data->eval_mode, dob->ob, dob)) {
160  continue;
161  }
162 
163  free_owned_memory(data);
164 
165  data->dupli_object_current = dob;
166 
167  /* Temporary object to evaluate. */
168  Object *dupli_parent = data->dupli_parent;
169  Object *temp_dupli_object = &data->temp_dupli_object;
170  *temp_dupli_object = blender::dna::shallow_copy(*dob->ob);
171  temp_dupli_object->base_flag = dupli_parent->base_flag | BASE_FROM_DUPLI;
172  temp_dupli_object->base_local_view_bits = dupli_parent->base_local_view_bits;
173  temp_dupli_object->runtime.local_collections_bits =
174  dupli_parent->runtime.local_collections_bits;
175  temp_dupli_object->dt = MIN2(temp_dupli_object->dt, dupli_parent->dt);
176  copy_v4_v4(temp_dupli_object->color, dupli_parent->color);
177  temp_dupli_object->runtime.select_id = dupli_parent->runtime.select_id;
178  if (dob->ob->data != dob->ob_data) {
179  /* Do not modify the original boundbox. */
180  temp_dupli_object->runtime.bb = nullptr;
181  BKE_object_replace_data_on_shallow_copy(temp_dupli_object, dob->ob_data);
182  }
183 
184  /* Duplicated elements shouldn't care whether their original collection is visible or not. */
185  temp_dupli_object->base_flag |= BASE_VISIBLE_DEPSGRAPH;
186 
187  int ob_visibility = BKE_object_visibility(temp_dupli_object, data->eval_mode);
188  if ((ob_visibility & (OB_VISIBLE_SELF | OB_VISIBLE_PARTICLES)) == 0) {
189  continue;
190  }
191 
192  /* This could be avoided by refactoring make_dupli() in order to track all negative scaling
193  * recursively. */
194  bool is_neg_scale = is_negative_m4(dob->mat);
195  SET_FLAG_FROM_TEST(data->temp_dupli_object.transflag, is_neg_scale, OB_NEG_SCALE);
196 
197  copy_m4_m4(data->temp_dupli_object.obmat, dob->mat);
198  invert_m4_m4(data->temp_dupli_object.imat, data->temp_dupli_object.obmat);
199  data->next_object = &data->temp_dupli_object;
201  return true;
202  }
203 
204  free_owned_memory(data);
205  free_object_duplilist(data->dupli_list);
206  data->dupli_parent = nullptr;
207  data->dupli_list = nullptr;
208  data->dupli_object_next = nullptr;
209  data->dupli_object_current = nullptr;
210  deg_invalidate_iterator_work_data(data);
211  return false;
212 }
213 
214 /* Returns false when iterator is exhausted. */
215 bool deg_iterator_objects_step(DEGObjectIterData *data)
216 {
217  deg::Depsgraph *deg_graph = reinterpret_cast<deg::Depsgraph *>(data->graph);
218 
219  for (; data->id_node_index < data->num_id_nodes; data->id_node_index++) {
220  deg::IDNode *id_node = deg_graph->id_nodes[data->id_node_index];
221 
222  /* Use the build time visibility so that the ID is not appearing/disappearing throughout
223  * animation export. */
225  continue;
226  }
227 
228  const ID_Type id_type = GS(id_node->id_orig->name);
229 
230  if (id_type != ID_OB) {
231  continue;
232  }
233 
234  switch (id_node->linked_state) {
236  if ((data->flag & DEG_ITER_OBJECT_FLAG_LINKED_DIRECTLY) == 0) {
237  continue;
238  }
239  break;
241  if ((data->flag & DEG_ITER_OBJECT_FLAG_LINKED_VIA_SET) == 0) {
242  continue;
243  }
244  break;
246  if ((data->flag & DEG_ITER_OBJECT_FLAG_LINKED_INDIRECTLY) == 0) {
247  continue;
248  }
249  break;
250  }
251 
252  Object *object = (Object *)id_node->id_cow;
254 
255  int ob_visibility = OB_VISIBLE_ALL;
256  if (data->flag & DEG_ITER_OBJECT_FLAG_VISIBLE) {
257  ob_visibility = BKE_object_visibility(object, data->eval_mode);
258 
259  if (object->type != OB_MBALL && deg_object_hide_original(data->eval_mode, object, nullptr)) {
260  continue;
261  }
262  }
263 
264  object->runtime.select_id = DEG_get_original_object(object)->runtime.select_id;
265  if (ob_visibility & OB_VISIBLE_INSTANCES) {
266  deg_iterator_duplis_init(data, object);
267  }
268 
269  if (ob_visibility & (OB_VISIBLE_SELF | OB_VISIBLE_PARTICLES)) {
270  data->next_object = object;
271  }
272  data->id_node_index++;
273  return true;
274  }
275  return false;
276 }
277 
278 } // namespace
279 
281 {
282  Depsgraph *depsgraph = data->graph;
283  deg::Depsgraph *deg_graph = reinterpret_cast<deg::Depsgraph *>(depsgraph);
284  const size_t num_id_nodes = deg_graph->id_nodes.size();
285 
286  iter->data = data;
287 
288  if (num_id_nodes == 0) {
289  iter->valid = false;
290  return;
291  }
292 
293  data->next_object = nullptr;
294  data->dupli_parent = nullptr;
295  data->dupli_list = nullptr;
296  data->dupli_object_next = nullptr;
297  data->dupli_object_current = nullptr;
299  data->id_node_index = 0;
300  data->num_id_nodes = num_id_nodes;
301  data->eval_mode = DEG_get_mode(depsgraph);
302  deg_invalidate_iterator_work_data(data);
303 
305 }
306 
308 {
310  while (true) {
311  if (data->next_object != nullptr) {
312  iter->current = data->next_object;
313  data->next_object = nullptr;
314  return;
315  }
316  if (deg_iterator_duplis_step(data)) {
317  continue;
318  }
319  if (deg_iterator_objects_step(data)) {
320  continue;
321  }
322  iter->valid = false;
323  break;
324  }
325 }
326 
328 {
330  if (data != nullptr) {
331  /* Force crash in case the iterator data is referenced and accessed down
332  * the line. (T51718) */
333  deg_invalidate_iterator_work_data(data);
334  }
335 }
336 
337 /* ************************ DEG ID ITERATOR ********************* */
338 
339 static void DEG_iterator_ids_step(BLI_Iterator *iter, deg::IDNode *id_node, bool only_updated)
340 {
341  ID *id_cow = id_node->id_cow;
342 
343  /* Use the build time visibility so that the ID is not appearing/disappearing throughout
344  * animation export. */
345  if (!id_node->is_visible_on_build) {
346  iter->skip = true;
347  return;
348  }
349 
350  if (only_updated && !(id_cow->recalc & ID_RECALC_ALL)) {
351  /* Node-tree is considered part of the data-block. */
352  bNodeTree *ntree = ntreeFromID(id_cow);
353  if (ntree == nullptr) {
354  iter->skip = true;
355  return;
356  }
357  if ((ntree->id.recalc & ID_RECALC_NTREE_OUTPUT) == 0) {
358  iter->skip = true;
359  return;
360  }
361  }
362 
363  iter->current = id_cow;
364  iter->skip = false;
365 }
366 
368 {
369  Depsgraph *depsgraph = data->graph;
370  deg::Depsgraph *deg_graph = reinterpret_cast<deg::Depsgraph *>(depsgraph);
371  const size_t num_id_nodes = deg_graph->id_nodes.size();
372 
373  iter->data = data;
374 
375  if ((num_id_nodes == 0) || (data->only_updated && !DEG_id_type_any_updated(depsgraph))) {
376  iter->valid = false;
377  return;
378  }
379 
380  data->id_node_index = 0;
381  data->num_id_nodes = num_id_nodes;
382 
383  deg::IDNode *id_node = deg_graph->id_nodes[data->id_node_index];
384  DEG_iterator_ids_step(iter, id_node, data->only_updated);
385 
386  if (iter->skip) {
387  DEG_iterator_ids_next(iter);
388  }
389 }
390 
392 {
393  DEGIDIterData *data = (DEGIDIterData *)iter->data;
394  Depsgraph *depsgraph = data->graph;
395  deg::Depsgraph *deg_graph = reinterpret_cast<deg::Depsgraph *>(depsgraph);
396 
397  do {
398  iter->skip = false;
399 
400  ++data->id_node_index;
401  if (data->id_node_index == data->num_id_nodes) {
402  iter->valid = false;
403  return;
404  }
405 
406  deg::IDNode *id_node = deg_graph->id_nodes[data->id_node_index];
407  DEG_iterator_ids_step(iter, id_node, data->only_updated);
408  } while (iter->skip);
409 }
410 
412 {
413 }
struct ListBase * object_duplilist(struct Depsgraph *depsgraph, struct Scene *sce, struct Object *ob)
void free_object_duplilist(struct ListBase *lb)
void IDP_FreeProperty(struct IDProperty *prop)
Definition: idprop.c:1093
struct bNodeTree * ntreeFromID(struct ID *id)
Definition: node.cc:3231
General operations, lookup, etc. for blender objects.
@ OB_VISIBLE_INSTANCES
Definition: BKE_object.h:152
@ OB_VISIBLE_SELF
Definition: BKE_object.h:150
@ OB_VISIBLE_PARTICLES
Definition: BKE_object.h:151
@ OB_VISIBLE_ALL
Definition: BKE_object.h:153
void BKE_object_replace_data_on_shallow_copy(struct Object *ob, struct ID *new_data)
Definition: object.cc:5590
int BKE_object_visibility(const struct Object *ob, int dag_eval_mode)
#define BLI_assert(a)
Definition: BLI_assert.h:46
bool invert_m4_m4(float R[4][4], const float A[4][4])
Definition: math_matrix.c:1287
void copy_m4_m4(float m1[4][4], const float m2[4][4])
Definition: math_matrix.c:77
bool is_negative_m4(const float mat[4][4])
Definition: math_matrix.c:2509
MINLINE void copy_v4_v4(float r[4], const float a[4])
#define UNUSED(x)
#define SET_FLAG_FROM_TEST(value, test, flag)
#define MIN2(a, b)
struct Depsgraph Depsgraph
Definition: DEG_depsgraph.h:35
eEvaluationMode
Definition: DEG_depsgraph.h:44
@ DAG_EVAL_RENDER
Definition: DEG_depsgraph.h:46
eEvaluationMode DEG_get_mode(const Depsgraph *graph)
bool DEG_id_type_any_updated(const struct Depsgraph *depsgraph)
struct Object * DEG_get_original_object(struct Object *object)
@ DEG_ITER_OBJECT_FLAG_LINKED_DIRECTLY
@ DEG_ITER_OBJECT_FLAG_VISIBLE
@ DEG_ITER_OBJECT_FLAG_DUPLI
@ DEG_ITER_OBJECT_FLAG_LINKED_INDIRECTLY
@ DEG_ITER_OBJECT_FLAG_LINKED_VIA_SET
struct Scene * DEG_get_evaluated_scene(const struct Depsgraph *graph)
@ ID_RECALC_NTREE_OUTPUT
Definition: DNA_ID.h:871
@ ID_RECALC_ALL
Definition: DNA_ID.h:891
ID_Type
Definition: DNA_ID_enums.h:44
@ ID_OB
Definition: DNA_ID_enums.h:47
@ BASE_FROM_DUPLI
@ BASE_VISIBLE_DEPSGRAPH
Object is a sort of wrapper for general info.
@ OB_MBALL
@ OB_DUPLIFACES
@ OB_DUPLI
@ OB_NEG_SCALE
@ OB_DUPLIVERTS
Read Guarded memory(de)allocation.
int64_t size() const
Definition: BLI_vector.hh:694
const IDNode * id_node
const Depsgraph * depsgraph
void DEG_iterator_ids_begin(BLI_Iterator *iter, DEGIDIterData *data)
void DEG_iterator_objects_begin(BLI_Iterator *iter, DEGObjectIterData *data)
void DEG_iterator_objects_end(BLI_Iterator *iter)
void DEG_iterator_objects_next(BLI_Iterator *iter)
void DEG_iterator_ids_next(BLI_Iterator *iter)
void DEG_iterator_ids_end(BLI_Iterator *UNUSED(iter))
static void DEG_iterator_ids_step(BLI_Iterator *iter, deg::IDNode *id_node, bool only_updated)
SyclQueue void void size_t num_bytes void
bNodeTree * ntree
#define GS(x)
Definition: iris.c:225
void(* MEM_freeN)(void *vmemh)
Definition: mallocn.c:27
bool deg_validate_copy_on_write_datablock(ID *id_cow)
@ DEG_ID_LINKED_INDIRECTLY
Definition: deg_node_id.h:25
@ DEG_ID_LINKED_VIA_SET
Definition: deg_node_id.h:27
@ DEG_ID_LINKED_DIRECTLY
Definition: deg_node_id.h:29
void * current
Definition: BLI_iterator.h:14
float mat[4][4]
Definition: BKE_duplilist.h:37
struct ID * ob_data
Definition: BKE_duplilist.h:36
struct Object * ob
Definition: BKE_duplilist.h:34
Definition: DNA_ID.h:368
int recalc
Definition: DNA_ID.h:390
IDProperty * properties
Definition: DNA_ID.h:409
char name[66]
Definition: DNA_ID.h:378
unsigned short local_collections_bits
struct GeometrySet * geometry_set_eval
struct BoundBox * bb
short transflag
short base_flag
Object_Runtime runtime
float color[4]
struct Object * parent
unsigned short base_local_view_bits
void * data
IDDepsNodes id_nodes
Definition: depsgraph.h:86
eDepsNode_LinkedState_Type linked_state
Definition: deg_node_id.h:92