Blender  V3.3
depsgraph_query.cc
Go to the documentation of this file.
1 /* SPDX-License-Identifier: GPL-2.0-or-later
2  * Copyright 2013 Blender Foundation. All rights reserved. */
3 
10 #include "MEM_guardedalloc.h"
11 
12 #include <cstring> /* XXX: memcpy */
13 
14 #include "BLI_listbase.h"
15 #include "BLI_utildefines.h"
16 
17 #include "BKE_action.h" /* XXX: BKE_pose_channel_find_name */
18 #include "BKE_customdata.h"
19 #include "BKE_idtype.h"
20 #include "BKE_main.h"
21 
22 #include "DNA_object_types.h"
23 #include "DNA_scene_types.h"
24 
25 #include "RNA_access.h"
26 #include "RNA_path.h"
27 #include "RNA_prototypes.h"
28 
29 #include "DEG_depsgraph.h"
30 #include "DEG_depsgraph_query.h"
31 
32 #include "intern/depsgraph.h"
35 
36 namespace blender::deg {
37 
38 static const ID *get_original_id(const ID *id)
39 {
40  if (id == nullptr) {
41  return nullptr;
42  }
43  if (id->orig_id == nullptr) {
44  return id;
45  }
47  return (ID *)id->orig_id;
48 }
49 
50 static ID *get_original_id(ID *id)
51 {
52  const ID *const_id = id;
53  return const_cast<ID *>(get_original_id(const_id));
54 }
55 
56 static const ID *get_evaluated_id(const Depsgraph *deg_graph, const ID *id)
57 {
58  if (id == nullptr) {
59  return nullptr;
60  }
61  /* TODO(sergey): This is a duplicate of Depsgraph::get_cow_id(),
62  * but here we never do assert, since we don't know nature of the
63  * incoming ID data-block. */
64  const IDNode *id_node = deg_graph->find_id_node(id);
65  if (id_node == nullptr) {
66  return id;
67  }
68  return id_node->id_cow;
69 }
70 
71 static ID *get_evaluated_id(const Depsgraph *deg_graph, ID *id)
72 {
73  const ID *const_id = id;
74  return const_cast<ID *>(get_evaluated_id(deg_graph, const_id));
75 }
76 
77 } // namespace blender::deg
78 
79 namespace deg = blender::deg;
80 
82 {
83  const deg::Depsgraph *deg_graph = reinterpret_cast<const deg::Depsgraph *>(graph);
84  return deg_graph->scene;
85 }
86 
88 {
89  const deg::Depsgraph *deg_graph = reinterpret_cast<const deg::Depsgraph *>(graph);
90  return deg_graph->view_layer;
91 }
92 
94 {
95  const deg::Depsgraph *deg_graph = reinterpret_cast<const deg::Depsgraph *>(graph);
96  return deg_graph->bmain;
97 }
98 
100 {
101  const deg::Depsgraph *deg_graph = reinterpret_cast<const deg::Depsgraph *>(graph);
102  return deg_graph->mode;
103 }
104 
106 {
107  const deg::Depsgraph *deg_graph = reinterpret_cast<const deg::Depsgraph *>(graph);
108  return deg_graph->ctime;
109 }
110 
111 bool DEG_id_type_updated(const Depsgraph *graph, short id_type)
112 {
113  const deg::Depsgraph *deg_graph = reinterpret_cast<const deg::Depsgraph *>(graph);
114  return deg_graph->id_type_updated[BKE_idtype_idcode_to_index(id_type)] != 0;
115 }
116 
118 {
119  const deg::Depsgraph *deg_graph = reinterpret_cast<const deg::Depsgraph *>(graph);
120 
121  /* Loop over all ID types. */
122  for (char id_type_index : deg_graph->id_type_updated) {
123  if (id_type_index) {
124  return true;
125  }
126  }
127 
128  return false;
129 }
130 
131 bool DEG_id_type_any_exists(const Depsgraph *depsgraph, short id_type)
132 {
133  const deg::Depsgraph *deg_graph = reinterpret_cast<const deg::Depsgraph *>(depsgraph);
134  return deg_graph->id_type_exist[BKE_idtype_idcode_to_index(id_type)] != 0;
135 }
136 
138 {
139  if (graph == nullptr) {
140  /* Happens when converting objects to mesh from a python script
141  * after modifying scene graph.
142  *
143  * Currently harmless because it's only called for temporary
144  * objects which are out of the DAG anyway. */
145  return 0;
146  }
147 
148  const deg::Depsgraph *deg_graph = reinterpret_cast<const deg::Depsgraph *>(graph);
149  const deg::IDNode *id_node = deg_graph->find_id_node(deg::get_original_id(id));
150  if (id_node == nullptr) {
151  /* TODO(sergey): Does it mean we need to check set scene? */
152  return 0;
153  }
154 
155  return id_node->eval_flags;
156 }
157 
159  Object *ob,
160  CustomData_MeshMasks *r_mask)
161 {
162  if (graph == nullptr) {
163  /* Happens when converting objects to mesh from a python script
164  * after modifying scene graph.
165  *
166  * Currently harmless because it's only called for temporary
167  * objects which are out of the DAG anyway. */
168  return;
169  }
170 
171  const deg::Depsgraph *deg_graph = reinterpret_cast<const deg::Depsgraph *>(graph);
172  const deg::IDNode *id_node = deg_graph->find_id_node(DEG_get_original_id(&ob->id));
173  if (id_node == nullptr) {
174  /* TODO(sergey): Does it mean we need to check set scene? */
175  return;
176  }
177 
178  r_mask->vmask |= id_node->customdata_masks.vert_mask;
179  r_mask->emask |= id_node->customdata_masks.edge_mask;
180  r_mask->fmask |= id_node->customdata_masks.face_mask;
181  r_mask->lmask |= id_node->customdata_masks.loop_mask;
182  r_mask->pmask |= id_node->customdata_masks.poly_mask;
183 }
184 
186 {
187  const deg::Depsgraph *deg_graph = reinterpret_cast<const deg::Depsgraph *>(graph);
188  Scene *scene_cow = deg_graph->scene_cow;
189  /* TODO(sergey): Shall we expand data-block here? Or is it OK to assume
190  * that caller is OK with just a pointer in case scene is not updated yet? */
191  BLI_assert(scene_cow != nullptr && deg::deg_copy_on_write_is_expanded(&scene_cow->id));
192  return scene_cow;
193 }
194 
196 {
197  const deg::Depsgraph *deg_graph = reinterpret_cast<const deg::Depsgraph *>(graph);
198  Scene *scene_cow = DEG_get_evaluated_scene(graph);
199  if (scene_cow == nullptr) {
200  return nullptr; /* Happens with new, not-yet-built/evaluated graphs. */
201  }
202  /* Do name-based lookup. */
203  /* TODO(sergey): Can this be optimized? */
204  ViewLayer *view_layer_orig = deg_graph->view_layer;
205  ViewLayer *view_layer_cow = (ViewLayer *)BLI_findstring(
206  &scene_cow->view_layers, view_layer_orig->name, offsetof(ViewLayer, name));
207  BLI_assert(view_layer_cow != nullptr);
208  return view_layer_cow;
209 }
210 
212 {
213  return (Object *)DEG_get_evaluated_id(depsgraph, &object->id);
214 }
215 
217 {
218  return deg::get_evaluated_id(reinterpret_cast<const deg::Depsgraph *>(depsgraph), id);
219 }
220 
222  PointerRNA *ptr,
223  PointerRNA *r_ptr_eval)
224 {
225  if ((ptr == nullptr) || (r_ptr_eval == nullptr)) {
226  return;
227  }
228  ID *orig_id = ptr->owner_id;
229  ID *cow_id = DEG_get_evaluated_id(depsgraph, orig_id);
230  if (ptr->owner_id == ptr->data) {
231  /* For ID pointers, it's easy... */
232  r_ptr_eval->owner_id = cow_id;
233  r_ptr_eval->data = (void *)cow_id;
234  r_ptr_eval->type = ptr->type;
235  }
236  else if (ptr->type == &RNA_PoseBone) {
237  /* HACK: Since bone keyframing is quite commonly used,
238  * speed things up for this case by doing a special lookup
239  * for bones */
240  const Object *ob_eval = (Object *)cow_id;
241  bPoseChannel *pchan = (bPoseChannel *)ptr->data;
242  const bPoseChannel *pchan_eval = BKE_pose_channel_find_name(ob_eval->pose, pchan->name);
243  r_ptr_eval->owner_id = cow_id;
244  r_ptr_eval->data = (void *)pchan_eval;
245  r_ptr_eval->type = ptr->type;
246  }
247  else {
248  /* For everything else, try to get RNA Path of the BMain-pointer,
249  * then use that to look up what the COW-domain one should be
250  * given the COW ID pointer as the new lookup point */
251  /* TODO: Find a faster alternative, or implement support for other
252  * common types too above (e.g. modifiers) */
253  char *path = RNA_path_from_ID_to_struct(ptr);
254  if (path) {
255  PointerRNA cow_id_ptr;
256  RNA_id_pointer_create(cow_id, &cow_id_ptr);
257  if (!RNA_path_resolve(&cow_id_ptr, path, r_ptr_eval, nullptr)) {
258  /* Couldn't find COW copy of data */
259  fprintf(stderr,
260  "%s: Couldn't resolve RNA path ('%s') relative to COW ID (%p) for '%s'\n",
261  __func__,
262  path,
263  (void *)cow_id,
264  orig_id->name);
265  }
266  }
267  else {
268  /* Path resolution failed - XXX: Hide this behind a debug flag */
269  fprintf(stderr,
270  "%s: Couldn't get RNA path for %s relative to %s\n",
271  __func__,
273  orig_id->name);
274  }
275  }
276 }
277 
279 {
280  return (Object *)DEG_get_original_id(&object->id);
281 }
282 
284 {
285  return deg::get_original_id(id);
286 }
287 
288 bool DEG_is_original_id(const ID *id)
289 {
290  /* Some explanation of the logic.
291  *
292  * What we want here is to be able to tell whether given ID is a result of dependency graph
293  * evaluation or not.
294  *
295  * All the data-blocks which are created by copy-on-write mechanism will have will be tagged with
296  * LIB_TAG_COPIED_ON_WRITE tag. Those data-blocks can not be original.
297  *
298  * Modifier stack evaluation might create special data-blocks which have all the modifiers
299  * applied, and those will be tagged with LIB_TAG_COPIED_ON_WRITE_EVAL_RESULT. Such data-blocks
300  * can not be original as well.
301  *
302  * Localization is usually happening from evaluated data-block, or will have some special pointer
303  * magic which will make them to act as evaluated.
304  *
305  * NOTE: We consider ID evaluated if ANY of those flags is set. We do NOT require ALL of them. */
306  if (id->tag &
308  return false;
309  }
310  return true;
311 }
312 
313 bool DEG_is_original_object(const Object *object)
314 {
315  return DEG_is_original_id(&object->id);
316 }
317 
318 bool DEG_is_evaluated_id(const ID *id)
319 {
320  return !DEG_is_original_id(id);
321 }
322 
323 bool DEG_is_evaluated_object(const Object *object)
324 {
325  return !DEG_is_original_object(object);
326 }
327 
329 {
330  const deg::Depsgraph *deg_graph = (const deg::Depsgraph *)depsgraph;
331  /* Check whether relations are up to date. */
332  if (deg_graph->need_update_relations) {
333  return false;
334  }
335  /* Check whether IDs are up to date. */
336  if (!deg_graph->entry_tags.is_empty()) {
337  return false;
338  }
339  return true;
340 }
Blender kernel action and pose functionality.
struct bPoseChannel * BKE_pose_channel_find_name(const struct bPose *pose, const char *name)
CustomData interface, see also DNA_customdata_types.h.
int BKE_idtype_idcode_to_index(short idcode)
Definition: idtype.c:324
#define BLI_assert(a)
Definition: BLI_assert.h:46
void * BLI_findstring(const struct ListBase *listbase, const char *id, int offset) ATTR_WARN_UNUSED_RESULT ATTR_NONNULL(1)
struct Depsgraph Depsgraph
Definition: DEG_depsgraph.h:35
eEvaluationMode
Definition: DEG_depsgraph.h:44
@ LIB_TAG_COPIED_ON_WRITE_EVAL_RESULT
Definition: DNA_ID.h:730
@ LIB_TAG_COPIED_ON_WRITE
Definition: DNA_ID.h:720
@ LIB_TAG_LOCALIZED
Definition: DNA_ID.h:740
Object is a sort of wrapper for general info.
Read Guarded memory(de)allocation.
Depsgraph * graph
const IDNode * id_node
const Depsgraph * depsgraph
float DEG_get_ctime(const Depsgraph *graph)
Scene * DEG_get_evaluated_scene(const Depsgraph *graph)
struct Scene * DEG_get_input_scene(const Depsgraph *graph)
ID * DEG_get_evaluated_id(const Depsgraph *depsgraph, ID *id)
uint32_t DEG_get_eval_flags_for_id(const Depsgraph *graph, const ID *id)
bool DEG_is_fully_evaluated(const struct Depsgraph *depsgraph)
bool DEG_is_evaluated_id(const ID *id)
void DEG_get_customdata_mask_for_object(const Depsgraph *graph, Object *ob, CustomData_MeshMasks *r_mask)
eEvaluationMode DEG_get_mode(const Depsgraph *graph)
bool DEG_is_original_id(const ID *id)
ViewLayer * DEG_get_evaluated_view_layer(const Depsgraph *graph)
ID * DEG_get_original_id(ID *id)
struct Main * DEG_get_bmain(const Depsgraph *graph)
bool DEG_is_original_object(const Object *object)
struct ViewLayer * DEG_get_input_view_layer(const Depsgraph *graph)
bool DEG_id_type_any_exists(const Depsgraph *depsgraph, short id_type)
void DEG_get_evaluated_rna_pointer(const Depsgraph *depsgraph, PointerRNA *ptr, PointerRNA *r_ptr_eval)
Object * DEG_get_original_object(Object *object)
bool DEG_id_type_updated(const Depsgraph *graph, short id_type)
Object * DEG_get_evaluated_object(const Depsgraph *depsgraph, Object *object)
bool DEG_is_evaluated_object(const Object *object)
bool DEG_id_type_any_updated(const Depsgraph *graph)
static const ID * get_original_id(const ID *id)
static const ID * get_evaluated_id(const Depsgraph *deg_graph, const ID *id)
static ID * get_original_id(ID *id)
bool deg_copy_on_write_is_expanded(const ID *id_cow)
static ID * get_evaluated_id(const Depsgraph *deg_graph, ID *id)
const char * RNA_struct_identifier(const StructRNA *type)
Definition: rna_access.c:586
void RNA_id_pointer_create(ID *id, PointerRNA *r_ptr)
Definition: rna_access.c:112
char * RNA_path_from_ID_to_struct(const PointerRNA *ptr)
Definition: rna_path.cc:981
bool RNA_path_resolve(const PointerRNA *ptr, const char *path, PointerRNA *r_ptr, PropertyRNA **r_prop)
Definition: rna_path.cc:503
unsigned int uint32_t
Definition: stdint.h:80
Definition: DNA_ID.h:368
int tag
Definition: DNA_ID.h:387
struct ID * orig_id
Definition: DNA_ID.h:419
char name[66]
Definition: DNA_ID.h:378
Definition: BKE_main.h:121
struct bPose * pose
struct StructRNA * type
Definition: RNA_types.h:37
void * data
Definition: RNA_types.h:38
struct ID * owner_id
Definition: RNA_types.h:36
ListBase view_layers
char name[64]
IDNode * find_id_node(const ID *id) const
Definition: depsgraph.cc:101
char id_type_updated[INDEX_ID_MAX]
Definition: depsgraph.h:106
eEvaluationMode mode
Definition: depsgraph.h:130
ViewLayer * view_layer
Definition: depsgraph.h:129
char id_type_exist[INDEX_ID_MAX]
Definition: depsgraph.h:109
Set< OperationNode * > entry_tags
Definition: depsgraph.h:114
PointerRNA * ptr
Definition: wm_files.c:3480