Blender  V2.93
deg_eval_copy_on_write.cc
Go to the documentation of this file.
1 /*
2  * This program is free software; you can redistribute it and/or
3  * modify it under the terms of the GNU General Public License
4  * as published by the Free Software Foundation; either version 2
5  * of the License, or (at your option) any later version.
6  *
7  * This program is distributed in the hope that it will be useful,
8  * but WITHOUT ANY WARRANTY; without even the implied warranty of
9  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
10  * GNU General Public License for more details.
11  *
12  * You should have received a copy of the GNU General Public License
13  * along with this program; if not, write to the Free Software Foundation,
14  * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
15  *
16  * The Original Code is Copyright (C) 2017 Blender Foundation.
17  * All rights reserved.
18  */
19 
24 /* Enable special trickery to treat nested owned IDs (such as nodetree of
25  * material) to be handled in same way as "real" data-blocks, even tho some
26  * internal BKE routines doesn't treat them like that.
27  *
28  * TODO(sergey): Re-evaluate that after new ID handling is in place. */
29 #define NESTED_ID_NASTY_WORKAROUND
30 
31 /* Silence warnings from copying deprecated fields. */
32 #define DNA_DEPRECATED_ALLOW
33 
35 
36 #include <cstring>
37 
38 #include "BLI_listbase.h"
39 #include "BLI_string.h"
40 #include "BLI_threads.h"
41 #include "BLI_utildefines.h"
42 
43 #include "BKE_curve.h"
44 #include "BKE_global.h"
45 #include "BKE_gpencil.h"
46 #include "BKE_idprop.h"
47 #include "BKE_layer.h"
48 #include "BKE_lib_id.h"
49 #include "BKE_scene.h"
50 
51 #include "DEG_depsgraph.h"
52 #include "DEG_depsgraph_query.h"
53 
54 #include "MEM_guardedalloc.h"
55 
56 #include "DNA_ID.h"
57 #include "DNA_anim_types.h"
58 #include "DNA_armature_types.h"
59 #include "DNA_mesh_types.h"
60 #include "DNA_modifier_types.h"
61 #include "DNA_object_types.h"
62 #include "DNA_particle_types.h"
63 #include "DNA_rigidbody_types.h"
64 #include "DNA_scene_types.h"
65 #include "DNA_sequence_types.h"
66 #include "DNA_simulation_types.h"
67 #include "DNA_sound_types.h"
68 
69 #include "DRW_engine.h"
70 
71 #ifdef NESTED_ID_NASTY_WORKAROUND
72 # include "DNA_curve_types.h"
73 # include "DNA_key_types.h"
74 # include "DNA_lattice_types.h"
75 # include "DNA_light_types.h"
76 # include "DNA_linestyle_types.h"
77 # include "DNA_material_types.h"
78 # include "DNA_meta_types.h"
79 # include "DNA_node_types.h"
80 # include "DNA_texture_types.h"
81 # include "DNA_world_types.h"
82 #endif
83 
84 #include "BKE_action.h"
85 #include "BKE_anim_data.h"
86 #include "BKE_animsys.h"
87 #include "BKE_armature.h"
88 #include "BKE_editmesh.h"
89 #include "BKE_lib_query.h"
90 #include "BKE_modifier.h"
91 #include "BKE_object.h"
92 #include "BKE_pointcache.h"
93 #include "BKE_sound.h"
94 
95 #include "SEQ_relations.h"
96 
99 #include "intern/depsgraph.h"
101 #include "intern/node/deg_node.h"
102 #include "intern/node/deg_node_id.h"
103 
104 namespace blender::deg {
105 
106 #define DEBUG_PRINT \
107  if (G.debug & G_DEBUG_DEPSGRAPH_EVAL) \
108  printf
109 
110 namespace {
111 
112 #ifdef NESTED_ID_NASTY_WORKAROUND
113 union NestedIDHackTempStorage {
124 };
125 
126 /* Set nested owned ID pointers to nullptr. */
127 void nested_id_hack_discard_pointers(ID *id_cow)
128 {
129  switch (GS(id_cow->name)) {
130 # define SPECIAL_CASE(id_type, dna_type, field) \
131  case id_type: { \
132  ((dna_type *)id_cow)->field = nullptr; \
133  break; \
134  }
135 
137  SPECIAL_CASE(ID_LA, Light, nodetree)
138  SPECIAL_CASE(ID_MA, Material, nodetree)
139  SPECIAL_CASE(ID_TE, Tex, nodetree)
140  SPECIAL_CASE(ID_WO, World, nodetree)
141  SPECIAL_CASE(ID_SIM, Simulation, nodetree)
142 
143  SPECIAL_CASE(ID_CU, Curve, key)
144  SPECIAL_CASE(ID_LT, Lattice, key)
145  SPECIAL_CASE(ID_ME, Mesh, key)
146 
147  case ID_SCE: {
148  Scene *scene_cow = (Scene *)id_cow;
149  /* Node trees always have their own ID node in the graph, and are
150  * being copied as part of their copy-on-write process. */
151  scene_cow->nodetree = nullptr;
152  /* Tool settings pointer is shared with the original scene. */
153  scene_cow->toolsettings = nullptr;
154  break;
155  }
156 
157  case ID_OB: {
158  /* Clear the ParticleSettings pointer to prevent doubly-freeing it. */
159  Object *ob = (Object *)id_cow;
161  psys->part = nullptr;
162  }
163  break;
164  }
165 # undef SPECIAL_CASE
166 
167  default:
168  break;
169  }
170 }
171 
172 /* Set ID pointer of nested owned IDs (nodetree, key) to nullptr.
173  *
174  * Return pointer to a new ID to be used. */
175 const ID *nested_id_hack_get_discarded_pointers(NestedIDHackTempStorage *storage, const ID *id)
176 {
177  switch (GS(id->name)) {
178 # define SPECIAL_CASE(id_type, dna_type, field, variable) \
179  case id_type: { \
180  storage->variable = *(dna_type *)id; \
181  storage->variable.field = nullptr; \
182  return &storage->variable.id; \
183  }
184 
186  SPECIAL_CASE(ID_LA, Light, nodetree, lamp)
187  SPECIAL_CASE(ID_MA, Material, nodetree, material)
188  SPECIAL_CASE(ID_TE, Tex, nodetree, tex)
189  SPECIAL_CASE(ID_WO, World, nodetree, world)
191 
192  SPECIAL_CASE(ID_CU, Curve, key, curve)
194  SPECIAL_CASE(ID_ME, Mesh, key, mesh)
195 
196  case ID_SCE: {
197  storage->scene = *(Scene *)id;
198  storage->scene.toolsettings = nullptr;
199  storage->scene.nodetree = nullptr;
200  return &storage->scene.id;
201  }
202 
203 # undef SPECIAL_CASE
204 
205  default:
206  break;
207  }
208  return id;
209 }
210 
211 /* Set ID pointer of nested owned IDs (nodetree, key) to the original value. */
212 void nested_id_hack_restore_pointers(const ID *old_id, ID *new_id)
213 {
214  if (new_id == nullptr) {
215  return;
216  }
217  switch (GS(old_id->name)) {
218 # define SPECIAL_CASE(id_type, dna_type, field) \
219  case id_type: { \
220  ((dna_type *)(new_id))->field = ((dna_type *)(old_id))->field; \
221  break; \
222  }
223 
225  SPECIAL_CASE(ID_LA, Light, nodetree)
226  SPECIAL_CASE(ID_MA, Material, nodetree)
227  SPECIAL_CASE(ID_SCE, Scene, nodetree)
228  SPECIAL_CASE(ID_TE, Tex, nodetree)
229  SPECIAL_CASE(ID_WO, World, nodetree)
230  SPECIAL_CASE(ID_SIM, Simulation, nodetree)
231 
232  SPECIAL_CASE(ID_CU, Curve, key)
233  SPECIAL_CASE(ID_LT, Lattice, key)
234  SPECIAL_CASE(ID_ME, Mesh, key)
235 
236 # undef SPECIAL_CASE
237  default:
238  break;
239  }
240 }
241 
242 /* Remap pointer of nested owned IDs (nodetree. key) to the new ID values. */
243 void ntree_hack_remap_pointers(const Depsgraph *depsgraph, ID *id_cow)
244 {
245  switch (GS(id_cow->name)) {
246 # define SPECIAL_CASE(id_type, dna_type, field, field_type) \
247  case id_type: { \
248  dna_type *data = (dna_type *)id_cow; \
249  if (data->field != nullptr) { \
250  ID *ntree_id_cow = depsgraph->get_cow_id(&data->field->id); \
251  if (ntree_id_cow != nullptr) { \
252  DEG_COW_PRINT(" Remapping datablock for %s: id_orig=%p id_cow=%p\n", \
253  data->field->id.name, \
254  data->field, \
255  ntree_id_cow); \
256  data->field = (field_type *)ntree_id_cow; \
257  } \
258  } \
259  break; \
260  }
261 
263  SPECIAL_CASE(ID_LA, Light, nodetree, bNodeTree)
264  SPECIAL_CASE(ID_MA, Material, nodetree, bNodeTree)
265  SPECIAL_CASE(ID_SCE, Scene, nodetree, bNodeTree)
266  SPECIAL_CASE(ID_TE, Tex, nodetree, bNodeTree)
267  SPECIAL_CASE(ID_WO, World, nodetree, bNodeTree)
269 
270  SPECIAL_CASE(ID_CU, Curve, key, Key)
271  SPECIAL_CASE(ID_LT, Lattice, key, Key)
272  SPECIAL_CASE(ID_ME, Mesh, key, Key)
273 
274 # undef SPECIAL_CASE
275  default:
276  break;
277  }
278 }
279 #endif /* NODETREE_NASTY_WORKAROUND */
280 
281 struct ValidateData {
282  bool is_valid;
283 };
284 
285 /* Similar to generic BKE_id_copy() but does not require main and assumes pointer
286  * is already allocated. */
287 bool id_copy_inplace_no_main(const ID *id, ID *newid)
288 {
289  const ID *id_for_copy = id;
290 
291  if (G.debug & G_DEBUG_DEPSGRAPH_UUID) {
292  const ID_Type id_type = GS(id_for_copy->name);
293  if (id_type == ID_OB) {
294  const Object *object = reinterpret_cast<const Object *>(id_for_copy);
296  }
297  }
298 
299 #ifdef NESTED_ID_NASTY_WORKAROUND
300  NestedIDHackTempStorage id_hack_storage;
301  id_for_copy = nested_id_hack_get_discarded_pointers(&id_hack_storage, id);
302 #endif
303 
304  bool result = (BKE_id_copy_ex(nullptr,
305  (ID *)id_for_copy,
306  &newid,
308  LIB_ID_COPY_SET_COPIED_ON_WRITE)) != nullptr);
309 
310 #ifdef NESTED_ID_NASTY_WORKAROUND
311  if (result) {
312  nested_id_hack_restore_pointers(id, newid);
313  }
314 #endif
315 
316  return result;
317 }
318 
319 /* Similar to BKE_scene_copy() but does not require main and assumes pointer
320  * is already allocated. */
321 bool scene_copy_inplace_no_main(const Scene *scene, Scene *new_scene)
322 {
323  const ID *id_for_copy = &scene->id;
324 
325  if (G.debug & G_DEBUG_DEPSGRAPH_UUID) {
327  }
328 
329 #ifdef NESTED_ID_NASTY_WORKAROUND
330  NestedIDHackTempStorage id_hack_storage;
331  id_for_copy = nested_id_hack_get_discarded_pointers(&id_hack_storage, &scene->id);
332 #endif
333 
334  bool result = (BKE_id_copy_ex(nullptr,
335  id_for_copy,
336  (ID **)&new_scene,
338  LIB_ID_COPY_SET_COPIED_ON_WRITE)) != nullptr);
339 
340 #ifdef NESTED_ID_NASTY_WORKAROUND
341  if (result) {
342  nested_id_hack_restore_pointers(&scene->id, &new_scene->id);
343  }
344 #endif
345 
346  return result;
347 }
348 
349 /* For the given scene get view layer which corresponds to an original for the
350  * scene's evaluated one. This depends on how the scene is pulled into the
351  * dependency graph. */
352 ViewLayer *get_original_view_layer(const Depsgraph *depsgraph, const IDNode *id_node)
353 {
355  return depsgraph->view_layer;
356  }
358  Scene *scene_orig = reinterpret_cast<Scene *>(id_node->id_orig);
359  return BKE_view_layer_default_render(scene_orig);
360  }
361  /* Is possible to have scene linked indirectly (i.e. via the driver) which
362  * we need to support. Currently there are issues somewhere else, which
363  * makes testing hard. This is a reported problem, so will eventually be
364  * properly fixed.
365  *
366  * TODO(sergey): Support indirectly linked scene. */
367  return nullptr;
368 }
369 
370 /* Remove all view layers but the one which corresponds to an input one. */
371 void scene_remove_unused_view_layers(const Depsgraph *depsgraph,
372  const IDNode *id_node,
373  Scene *scene_cow)
374 {
375  const ViewLayer *view_layer_input;
377  /* If the dependency graph is used for post-processing (such as compositor) we do need to
378  * have access to its view layer names so can not remove any view layers.
379  * On a more positive side we can remove all the bases from all the view layers.
380  *
381  * NOTE: Need to clear pointers which might be pointing to original on freed (due to being
382  * unused) data.
383  *
384  * NOTE: Need to keep view layers for all scenes, even indirect ones. This is because of
385  * render layer node possibly pointing to another scene. */
386  LISTBASE_FOREACH (ViewLayer *, view_layer, &scene_cow->view_layers) {
387  view_layer->basact = nullptr;
388  }
389  return;
390  }
392  /* Indirectly linked scenes means it's not an input scene and not a set scene, and is pulled
393  * via some driver. Such scenes should not have view layers after copy. */
394  view_layer_input = nullptr;
395  }
396  else {
397  view_layer_input = get_original_view_layer(depsgraph, id_node);
398  }
399  ViewLayer *view_layer_eval = nullptr;
400  /* Find evaluated view layer. At the same time we free memory used by
401  * all other of the view layers. */
402  for (ViewLayer *view_layer_cow = reinterpret_cast<ViewLayer *>(scene_cow->view_layers.first),
403  *view_layer_next;
404  view_layer_cow != nullptr;
405  view_layer_cow = view_layer_next) {
406  view_layer_next = view_layer_cow->next;
407  if (view_layer_input != nullptr && STREQ(view_layer_input->name, view_layer_cow->name)) {
408  view_layer_eval = view_layer_cow;
409  }
410  else {
411  BKE_view_layer_free_ex(view_layer_cow, false);
412  }
413  }
414  /* Make evaluated view layer the only one in the evaluated scene (if it exists). */
415  if (view_layer_eval != nullptr) {
416  view_layer_eval->prev = view_layer_eval->next = nullptr;
417  }
418  scene_cow->view_layers.first = view_layer_eval;
419  scene_cow->view_layers.last = view_layer_eval;
420 }
421 
422 void scene_remove_all_bases(Scene *scene_cow)
423 {
424  LISTBASE_FOREACH (ViewLayer *, view_layer, &scene_cow->view_layers) {
425  BLI_freelistN(&view_layer->object_bases);
426  }
427 }
428 
429 /* Makes it so given view layer only has bases corresponding to enabled
430  * objects. */
431 void view_layer_remove_disabled_bases(const Depsgraph *depsgraph, ViewLayer *view_layer)
432 {
433  if (view_layer == nullptr) {
434  return;
435  }
436  ListBase enabled_bases = {nullptr, nullptr};
437  LISTBASE_FOREACH_MUTABLE (Base *, base, &view_layer->object_bases) {
438  /* TODO(sergey): Would be cool to optimize this somehow, or make it so
439  * builder tags bases.
440  *
441  * NOTE: The idea of using id's tag and check whether its copied ot not
442  * is not reliable, since object might be indirectly linked into the
443  * graph.
444  *
445  * NOTE: We are using original base since the object which evaluated base
446  * points to is not yet copied. This is dangerous access from evaluated
447  * domain to original one, but this is how the entire copy-on-write works:
448  * it does need to access original for an initial copy. */
449  const bool is_object_enabled = deg_check_base_in_depsgraph(depsgraph, base);
450  if (is_object_enabled) {
451  BLI_addtail(&enabled_bases, base);
452  }
453  else {
454  if (base == view_layer->basact) {
455  view_layer->basact = nullptr;
456  }
457  MEM_freeN(base);
458  }
459  }
460  view_layer->object_bases = enabled_bases;
461 }
462 
463 void view_layer_update_orig_base_pointers(const ViewLayer *view_layer_orig,
464  ViewLayer *view_layer_eval)
465 {
466  if (view_layer_orig == nullptr || view_layer_eval == nullptr) {
467  /* Happens when scene is only used for parameters or compositor/sequencer. */
468  return;
469  }
470  Base *base_orig = reinterpret_cast<Base *>(view_layer_orig->object_bases.first);
471  LISTBASE_FOREACH (Base *, base_eval, &view_layer_eval->object_bases) {
472  base_eval->base_orig = base_orig;
473  base_orig = base_orig->next;
474  }
475 }
476 
477 void scene_setup_view_layers_before_remap(const Depsgraph *depsgraph,
478  const IDNode *id_node,
479  Scene *scene_cow)
480 {
481  scene_remove_unused_view_layers(depsgraph, id_node, scene_cow);
482  /* If dependency graph is used for post-processing we don't need any bases and can free of them.
483  * Do it before re-mapping to make that process faster. */
485  scene_remove_all_bases(scene_cow);
486  }
487 }
488 
489 void scene_setup_view_layers_after_remap(const Depsgraph *depsgraph,
490  const IDNode *id_node,
491  Scene *scene_cow)
492 {
493  const ViewLayer *view_layer_orig = get_original_view_layer(depsgraph, id_node);
494  ViewLayer *view_layer_eval = reinterpret_cast<ViewLayer *>(scene_cow->view_layers.first);
495  view_layer_update_orig_base_pointers(view_layer_orig, view_layer_eval);
496  view_layer_remove_disabled_bases(depsgraph, view_layer_eval);
497  /* TODO(sergey): Remove objects from collections as well.
498  * Not a HUGE deal for now, nobody is looking into those CURRENTLY.
499  * Still not an excuse to have those. */
500 }
501 
502 /* Check whether given ID is expanded or still a shallow copy. */
503 inline bool check_datablock_expanded(const ID *id_cow)
504 {
505  return (id_cow->name[0] != '\0');
506 }
507 
508 /* Callback for BKE_library_foreach_ID_link which remaps original ID pointer
509  * with the one created by CoW system. */
510 
511 struct RemapCallbackUserData {
512  /* Dependency graph for which remapping is happening. */
514  /* Create placeholder for ID nodes for cases when we need to remap original
515  * ID to it[s CoW version but we don't have required ID node yet.
516  *
517  * This happens when expansion happens a ta construction time. */
518  DepsgraphNodeBuilder *node_builder;
520 };
521 
523 {
524  ID **id_p = cb_data->id_pointer;
525  if (*id_p == nullptr) {
526  return IDWALK_RET_NOP;
527  }
528 
529  ID *id_self = cb_data->id_self;
530  RemapCallbackUserData *user_data = (RemapCallbackUserData *)cb_data->user_data;
531  const Depsgraph *depsgraph = user_data->depsgraph;
532  ID *id_orig = *id_p;
533  if (deg_copy_on_write_is_needed(id_orig)) {
534  ID *id_cow;
535  if (user_data->create_placeholders) {
536  /* Special workaround to stop creating temp datablocks for
537  * objects which are coming from scene's collection and which
538  * are never linked to any of layers.
539  *
540  * TODO(sergey): Ideally we need to tell ID looper to ignore
541  * those or at least make it more reliable check where the
542  * pointer is coming from. */
543  const ID_Type id_type = GS(id_orig->name);
544  const ID_Type id_type_self = GS(id_self->name);
545  if (id_type == ID_OB && id_type_self == ID_SCE) {
546  IDNode *id_node = depsgraph->find_id_node(id_orig);
547  if (id_node == nullptr) {
548  id_cow = id_orig;
549  }
550  else {
551  id_cow = id_node->id_cow;
552  }
553  }
554  else {
555  id_cow = user_data->node_builder->ensure_cow_id(id_orig);
556  }
557  }
558  else {
559  id_cow = depsgraph->get_cow_id(id_orig);
560  }
561  BLI_assert(id_cow != nullptr);
563  " Remapping datablock for %s: id_orig=%p id_cow=%p\n", id_orig->name, id_orig, id_cow);
564  *id_p = id_cow;
565  }
566  return IDWALK_RET_NOP;
567 }
568 
569 void update_armature_edit_mode_pointers(const Depsgraph * /*depsgraph*/,
570  const ID *id_orig,
571  ID *id_cow)
572 {
573  const bArmature *armature_orig = (const bArmature *)id_orig;
574  bArmature *armature_cow = (bArmature *)id_cow;
575  armature_cow->edbo = armature_orig->edbo;
576  armature_cow->act_edbone = armature_orig->act_edbone;
577 }
578 
579 void update_curve_edit_mode_pointers(const Depsgraph * /*depsgraph*/,
580  const ID *id_orig,
581  ID *id_cow)
582 {
583  const Curve *curve_orig = (const Curve *)id_orig;
584  Curve *curve_cow = (Curve *)id_cow;
585  curve_cow->editnurb = curve_orig->editnurb;
586  curve_cow->editfont = curve_orig->editfont;
587 }
588 
589 void update_mball_edit_mode_pointers(const Depsgraph * /*depsgraph*/,
590  const ID *id_orig,
591  ID *id_cow)
592 {
593  const MetaBall *mball_orig = (const MetaBall *)id_orig;
594  MetaBall *mball_cow = (MetaBall *)id_cow;
595  mball_cow->editelems = mball_orig->editelems;
596 }
597 
598 void update_lattice_edit_mode_pointers(const Depsgraph * /*depsgraph*/,
599  const ID *id_orig,
600  ID *id_cow)
601 {
602  const Lattice *lt_orig = (const Lattice *)id_orig;
603  Lattice *lt_cow = (Lattice *)id_cow;
604  lt_cow->editlatt = lt_orig->editlatt;
605 }
606 
607 void update_mesh_edit_mode_pointers(const ID *id_orig, ID *id_cow)
608 {
609  /* For meshes we need to update edit_mesh to make it to point
610  * to the CoW version of object.
611  *
612  * This is kind of confusing, because actual bmesh is not owned by
613  * the CoW object, so need to be accurate about using link from
614  * edit_mesh to object. */
615  const Mesh *mesh_orig = (const Mesh *)id_orig;
616  Mesh *mesh_cow = (Mesh *)id_cow;
617  if (mesh_orig->edit_mesh == nullptr) {
618  return;
619  }
620  mesh_cow->edit_mesh = (BMEditMesh *)MEM_dupallocN(mesh_orig->edit_mesh);
621  mesh_cow->edit_mesh->mesh_eval_cage = nullptr;
622  mesh_cow->edit_mesh->mesh_eval_final = nullptr;
623 }
624 
625 /* Edit data is stored and owned by original datablocks, copied ones
626  * are simply referencing to them. */
627 void update_edit_mode_pointers(const Depsgraph *depsgraph, const ID *id_orig, ID *id_cow)
628 {
629  const ID_Type type = GS(id_orig->name);
630  switch (type) {
631  case ID_AR:
632  update_armature_edit_mode_pointers(depsgraph, id_orig, id_cow);
633  break;
634  case ID_ME:
635  update_mesh_edit_mode_pointers(id_orig, id_cow);
636  break;
637  case ID_CU:
638  update_curve_edit_mode_pointers(depsgraph, id_orig, id_cow);
639  break;
640  case ID_MB:
641  update_mball_edit_mode_pointers(depsgraph, id_orig, id_cow);
642  break;
643  case ID_LT:
644  update_lattice_edit_mode_pointers(depsgraph, id_orig, id_cow);
645  break;
646  default:
647  break;
648  }
649 }
650 
651 template<typename T>
652 void update_list_orig_pointers(const ListBase *listbase_orig,
653  ListBase *listbase,
654  T *T::*orig_field)
655 {
656  T *element_orig = reinterpret_cast<T *>(listbase_orig->first);
657  T *element_cow = reinterpret_cast<T *>(listbase->first);
658 
659  /* Both lists should have the same number of elements, so the check on
660  * `element_cow` is just to prevent a crash if this is not the case. */
661  while (element_orig != nullptr && element_cow != nullptr) {
662  element_cow->*orig_field = element_orig;
663  element_cow = element_cow->next;
664  element_orig = element_orig->next;
665  }
666 
667  BLI_assert((element_orig == nullptr && element_cow == nullptr) ||
668  !"list of pointers of different sizes, unable to reliably set orig pointer");
669 }
670 
671 void update_particle_system_orig_pointers(const Object *object_orig, Object *object_cow)
672 {
673  update_list_orig_pointers(
674  &object_orig->particlesystem, &object_cow->particlesystem, &ParticleSystem::orig_psys);
675 }
676 
677 void set_particle_system_modifiers_loaded(Object *object_cow)
678 {
679  LISTBASE_FOREACH (ModifierData *, md, &object_cow->modifiers) {
680  if (md->type != eModifierType_ParticleSystem) {
681  continue;
682  }
683  ParticleSystemModifierData *psmd = reinterpret_cast<ParticleSystemModifierData *>(md);
685  }
686 }
687 
688 void reset_particle_system_edit_eval(const Depsgraph *depsgraph, Object *object_cow)
689 {
690  /* Inactive (and render) dependency graphs are living in own little bubble, should not care about
691  * edit mode at all. */
692  if (!DEG_is_active(reinterpret_cast<const ::Depsgraph *>(depsgraph))) {
693  return;
694  }
695  LISTBASE_FOREACH (ParticleSystem *, psys, &object_cow->particlesystem) {
696  ParticleSystem *orig_psys = psys->orig_psys;
697  if (orig_psys->edit != nullptr) {
698  orig_psys->edit->psys_eval = nullptr;
699  orig_psys->edit->psmd_eval = nullptr;
700  }
701  }
702 }
703 
704 void update_particles_after_copy(const Depsgraph *depsgraph,
705  const Object *object_orig,
706  Object *object_cow)
707 {
708  update_particle_system_orig_pointers(object_orig, object_cow);
709  set_particle_system_modifiers_loaded(object_cow);
710  reset_particle_system_edit_eval(depsgraph, object_cow);
711 }
712 
713 void update_pose_orig_pointers(const bPose *pose_orig, bPose *pose_cow)
714 {
715  update_list_orig_pointers(&pose_orig->chanbase, &pose_cow->chanbase, &bPoseChannel::orig_pchan);
716 }
717 
718 void update_modifiers_orig_pointers(const Object *object_orig, Object *object_cow)
719 {
720  update_list_orig_pointers(
721  &object_orig->modifiers, &object_cow->modifiers, &ModifierData::orig_modifier_data);
722 }
723 
724 void update_nla_strips_orig_pointers(const ListBase *strips_orig, ListBase *strips_cow)
725 {
726  NlaStrip *strip_orig = reinterpret_cast<NlaStrip *>(strips_orig->first);
727  NlaStrip *strip_cow = reinterpret_cast<NlaStrip *>(strips_cow->first);
728  while (strip_orig != nullptr) {
729  strip_cow->orig_strip = strip_orig;
730  update_nla_strips_orig_pointers(&strip_orig->strips, &strip_cow->strips);
731  strip_cow = strip_cow->next;
732  strip_orig = strip_orig->next;
733  }
734 }
735 
736 void update_nla_tracks_orig_pointers(const ListBase *tracks_orig, ListBase *tracks_cow)
737 {
738  NlaTrack *track_orig = reinterpret_cast<NlaTrack *>(tracks_orig->first);
739  NlaTrack *track_cow = reinterpret_cast<NlaTrack *>(tracks_cow->first);
740  while (track_orig != nullptr) {
741  update_nla_strips_orig_pointers(&track_orig->strips, &track_cow->strips);
742  track_cow = track_cow->next;
743  track_orig = track_orig->next;
744  }
745 }
746 
747 void update_animation_data_after_copy(const ID *id_orig, ID *id_cow)
748 {
749  const AnimData *anim_data_orig = BKE_animdata_from_id(const_cast<ID *>(id_orig));
750  if (anim_data_orig == nullptr) {
751  return;
752  }
753  AnimData *anim_data_cow = BKE_animdata_from_id(id_cow);
754  BLI_assert(anim_data_cow != nullptr);
755  update_nla_tracks_orig_pointers(&anim_data_orig->nla_tracks, &anim_data_cow->nla_tracks);
756 }
757 
758 /* Some builders (like motion path one) will ignore proxies from being built. This code makes it so
759  * proxy and proxy_group pointers never point to an original objects, preventing evaluation code
760  * from assign evaluated pointer to an original proxy->proxy_from. */
761 void update_proxy_pointers_after_copy(const Depsgraph *depsgraph,
762  const Object *object_orig,
763  Object *object_cow)
764 {
765  if (object_cow->proxy != nullptr) {
766  if (!deg_check_id_in_depsgraph(depsgraph, &object_orig->proxy->id)) {
767  object_cow->proxy = nullptr;
768  }
769  }
770  if (object_cow->proxy_group != nullptr) {
771  if (!deg_check_id_in_depsgraph(depsgraph, &object_orig->proxy_group->id)) {
772  object_cow->proxy_group = nullptr;
773  }
774  }
775 }
776 
777 /* Do some special treatment of data transfer from original ID to its
778  * CoW complementary part.
779  *
780  * Only use for the newly created CoW data-blocks. */
781 void update_id_after_copy(const Depsgraph *depsgraph,
782  const IDNode *id_node,
783  const ID *id_orig,
784  ID *id_cow)
785 {
786  const ID_Type type = GS(id_orig->name);
787  update_animation_data_after_copy(id_orig, id_cow);
788  switch (type) {
789  case ID_OB: {
790  /* Ensure we don't drag someone's else derived mesh to the
791  * new copy of the object. */
792  Object *object_cow = (Object *)id_cow;
793  const Object *object_orig = (const Object *)id_orig;
794  object_cow->mode = object_orig->mode;
795  object_cow->sculpt = object_orig->sculpt;
796  object_cow->runtime.data_orig = (ID *)object_cow->data;
797  if (object_cow->type == OB_ARMATURE) {
798  const bArmature *armature_orig = (bArmature *)object_orig->data;
799  bArmature *armature_cow = (bArmature *)object_cow->data;
800  BKE_pose_remap_bone_pointers(armature_cow, object_cow->pose);
801  if (armature_orig->edbo == nullptr) {
802  update_pose_orig_pointers(object_orig->pose, object_cow->pose);
803  }
804  BKE_pose_pchan_index_rebuild(object_cow->pose);
805  }
806  if (object_cow->type == OB_GPENCIL) {
807  BKE_gpencil_update_orig_pointers(object_orig, object_cow);
808  }
809  update_particles_after_copy(depsgraph, object_orig, object_cow);
810  update_modifiers_orig_pointers(object_orig, object_cow);
811  update_proxy_pointers_after_copy(depsgraph, object_orig, object_cow);
812  break;
813  }
814  case ID_SCE: {
815  Scene *scene_cow = (Scene *)id_cow;
816  const Scene *scene_orig = (const Scene *)id_orig;
817  scene_cow->toolsettings = scene_orig->toolsettings;
818  scene_cow->eevee.light_cache_data = scene_orig->eevee.light_cache_data;
819  scene_setup_view_layers_after_remap(depsgraph, id_node, reinterpret_cast<Scene *>(id_cow));
820  break;
821  }
822  default:
823  break;
824  }
825  update_edit_mode_pointers(depsgraph, id_orig, id_cow);
827 }
828 
829 /* This callback is used to validate that all nested ID data-blocks are
830  * properly expanded. */
831 int foreach_libblock_validate_callback(LibraryIDLinkCallbackData *cb_data)
832 {
833  ValidateData *data = (ValidateData *)cb_data->user_data;
834  ID **id_p = cb_data->id_pointer;
835 
836  if (*id_p != nullptr) {
837  if (!check_datablock_expanded(*id_p)) {
838  data->is_valid = false;
839  /* TODO(sergey): Store which is not valid? */
840  }
841  }
842  return IDWALK_RET_NOP;
843 }
844 
845 } // namespace
846 
847 /* Actual implementation of logic which "expands" all the data which was not
848  * yet copied-on-write.
849  *
850  * NOTE: Expects that CoW datablock is empty. */
852  const IDNode *id_node,
854  bool create_placeholders)
855 {
856  const ID *id_orig = id_node->id_orig;
857  ID *id_cow = id_node->id_cow;
858  const int id_cow_recalc = id_cow->recalc;
859  /* No need to expand such datablocks, their copied ID is same as original
860  * one already. */
861  if (!deg_copy_on_write_is_needed(id_orig)) {
862  return id_cow;
863  }
865  "Expanding datablock for %s: id_orig=%p id_cow=%p\n", id_orig->name, id_orig, id_cow);
866  /* Sanity checks. */
867  /* NOTE: Disabled for now, conflicts when re-using evaluated datablock when
868  * rebuilding dependencies. */
869  if (check_datablock_expanded(id_cow) && create_placeholders) {
871  }
872  // BLI_assert(check_datablock_expanded(id_cow) == false);
873  /* Copy data from original ID to a copied version. */
874  /* TODO(sergey): Avoid doing full ID copy somehow, make Mesh to reference
875  * original geometry arrays for until those are modified. */
876  /* TODO(sergey): We do some trickery with temp bmain and extra ID pointer
877  * just to be able to use existing API. Ideally we need to replace this with
878  * in-place copy from existing datablock to a prepared memory.
879  *
880  * NOTE: We don't use BKE_main_{new,free} because:
881  * - We don't want heap-allocations here.
882  * - We don't want bmain's content to be freed when main is freed. */
883  bool done = false;
884  /* First we handle special cases which are not covered by BKE_id_copy() yet.
885  * or cases where we want to do something smarter than simple datablock
886  * copy. */
887  const ID_Type id_type = GS(id_orig->name);
888  switch (id_type) {
889  case ID_SCE: {
890  done = scene_copy_inplace_no_main((Scene *)id_orig, (Scene *)id_cow);
891  if (done) {
892  /* NOTE: This is important to do before remap, because this
893  * function will make it so less IDs are to be remapped. */
894  scene_setup_view_layers_before_remap(depsgraph, id_node, (Scene *)id_cow);
895  }
896  break;
897  }
898  case ID_ME: {
899  /* TODO(sergey): Ideally we want to handle meshes in a special
900  * manner here to avoid initial copy of all the geometry arrays. */
901  break;
902  }
903  default:
904  break;
905  }
906  if (!done) {
907  done = id_copy_inplace_no_main(id_orig, id_cow);
908  }
909  if (!done) {
910  BLI_assert(!"No idea how to perform CoW on datablock");
911  }
912  /* Update pointers to nested ID datablocks. */
914  " Remapping ID links for %s: id_orig=%p id_cow=%p\n", id_orig->name, id_orig, id_cow);
915 
916 #ifdef NESTED_ID_NASTY_WORKAROUND
917  ntree_hack_remap_pointers(depsgraph, id_cow);
918 #endif
919  /* Do it now, so remapping will understand that possibly remapped self ID
920  * is not to be remapped again. */
921  deg_tag_copy_on_write_id(id_cow, id_orig);
922  /* Perform remapping of the nodes. */
923  RemapCallbackUserData user_data = {nullptr};
924  user_data.depsgraph = depsgraph;
925  user_data.node_builder = node_builder;
926  user_data.create_placeholders = create_placeholders;
928  id_cow,
930  (void *)&user_data,
932  /* Correct or tweak some pointers which are not taken care by foreach
933  * from above. */
934  update_id_after_copy(depsgraph, id_node, id_orig, id_cow);
935  id_cow->recalc = id_cow_recalc;
936  return id_cow;
937 }
938 
939 /* NOTE: Depsgraph is supposed to have ID node already. */
941  ID *id_orig,
943  bool create_placeholders)
944 {
945  IDNode *id_node = depsgraph->find_id_node(id_orig);
946  BLI_assert(id_node != nullptr);
948 }
949 
951 {
952  const ID *id_orig = id_node->id_orig;
953  ID *id_cow = id_node->id_cow;
954  /* Similar to expansion, no need to do anything here. */
955  if (!deg_copy_on_write_is_needed(id_orig)) {
956  return id_cow;
957  }
959  backup.init_from_id(id_cow);
962  backup.restore_to_id(id_cow);
963  return id_cow;
964 }
965 
966 /* NOTE: Depsgraph is supposed to have ID node already. */
968 {
969  IDNode *id_node = depsgraph->find_id_node(id_orig);
970  BLI_assert(id_node != nullptr);
972 }
973 
974 namespace {
975 
976 void discard_armature_edit_mode_pointers(ID *id_cow)
977 {
978  bArmature *armature_cow = (bArmature *)id_cow;
979  armature_cow->edbo = nullptr;
980 }
981 
982 void discard_curve_edit_mode_pointers(ID *id_cow)
983 {
984  Curve *curve_cow = (Curve *)id_cow;
985  curve_cow->editnurb = nullptr;
986  curve_cow->editfont = nullptr;
987 }
988 
989 void discard_mball_edit_mode_pointers(ID *id_cow)
990 {
991  MetaBall *mball_cow = (MetaBall *)id_cow;
992  mball_cow->editelems = nullptr;
993 }
994 
995 void discard_lattice_edit_mode_pointers(ID *id_cow)
996 {
997  Lattice *lt_cow = (Lattice *)id_cow;
998  lt_cow->editlatt = nullptr;
999 }
1000 
1001 void discard_mesh_edit_mode_pointers(ID *id_cow)
1002 {
1003  Mesh *mesh_cow = (Mesh *)id_cow;
1004  if (mesh_cow->edit_mesh == nullptr) {
1005  return;
1006  }
1008  MEM_freeN(mesh_cow->edit_mesh);
1009  mesh_cow->edit_mesh = nullptr;
1010 }
1011 
1012 void discard_scene_pointers(ID *id_cow)
1013 {
1014  Scene *scene_cow = (Scene *)id_cow;
1015  scene_cow->toolsettings = nullptr;
1016  scene_cow->eevee.light_cache_data = nullptr;
1017 }
1018 
1019 /* nullptr-ify all edit mode pointers which points to data from
1020  * original object. */
1021 void discard_edit_mode_pointers(ID *id_cow)
1022 {
1023  const ID_Type type = GS(id_cow->name);
1024  switch (type) {
1025  case ID_AR:
1026  discard_armature_edit_mode_pointers(id_cow);
1027  break;
1028  case ID_ME:
1029  discard_mesh_edit_mode_pointers(id_cow);
1030  break;
1031  case ID_CU:
1032  discard_curve_edit_mode_pointers(id_cow);
1033  break;
1034  case ID_MB:
1035  discard_mball_edit_mode_pointers(id_cow);
1036  break;
1037  case ID_LT:
1038  discard_lattice_edit_mode_pointers(id_cow);
1039  break;
1040  case ID_SCE:
1041  /* Not really edit mode but still needs to run before
1042  * BKE_libblock_free_datablock() */
1043  discard_scene_pointers(id_cow);
1044  break;
1045  default:
1046  break;
1047  }
1048 }
1049 
1050 } // namespace
1051 
1052 /* Free content of the CoW data-block
1053  * Notes:
1054  * - Does not recurse into nested ID data-blocks.
1055  * - Does not free data-block itself. */
1057 {
1058  if (!check_datablock_expanded(id_cow)) {
1059  /* Actual content was never copied on top of CoW block, we have
1060  * nothing to free. */
1061  return;
1062  }
1063  const ID_Type type = GS(id_cow->name);
1064 #ifdef NESTED_ID_NASTY_WORKAROUND
1065  nested_id_hack_discard_pointers(id_cow);
1066 #endif
1067  switch (type) {
1068  case ID_OB: {
1069  /* TODO(sergey): This workaround is only to prevent free derived
1070  * caches from modifying object->data. This is currently happening
1071  * due to mesh/curve datablock boundbox tagging dirty. */
1072  Object *ob_cow = (Object *)id_cow;
1073  ob_cow->data = nullptr;
1074  ob_cow->sculpt = nullptr;
1075  break;
1076  }
1077  default:
1078  break;
1079  }
1080  discard_edit_mode_pointers(id_cow);
1081  BKE_libblock_free_datablock(id_cow, 0);
1082  BKE_libblock_free_data(id_cow, false);
1083  /* Signal datablock as not being expanded. */
1084  id_cow->name[0] = '\0';
1085 }
1086 
1088 {
1089  const Depsgraph *depsgraph = reinterpret_cast<const Depsgraph *>(graph);
1091  if (id_node->id_orig == &depsgraph->scene->id) {
1092  /* NOTE: This is handled by eval_ctx setup routines, which
1093  * ensures scene and view layer pointers are valid. */
1094  return;
1095  }
1097 }
1098 
1100 {
1101  if (id_cow == nullptr) {
1102  return false;
1103  }
1104  ValidateData data;
1105  data.is_valid = true;
1107  nullptr, id_cow, foreach_libblock_validate_callback, &data, IDWALK_NOP);
1108  return data.is_valid;
1109 }
1110 
1111 void deg_tag_copy_on_write_id(ID *id_cow, const ID *id_orig)
1112 {
1113  BLI_assert(id_cow != id_orig);
1114  BLI_assert((id_orig->tag & LIB_TAG_COPIED_ON_WRITE) == 0);
1115  id_cow->tag |= LIB_TAG_COPIED_ON_WRITE;
1116  /* This ID is no longer localized, is a self-sustaining copy now. */
1117  id_cow->tag &= ~LIB_TAG_LOCALIZED;
1118  id_cow->orig_id = (ID *)id_orig;
1119 }
1120 
1122 {
1123  return check_datablock_expanded(id_cow);
1124 }
1125 
1126 bool deg_copy_on_write_is_needed(const ID *id_orig)
1127 {
1128  const ID_Type id_type = GS(id_orig->name);
1129  return deg_copy_on_write_is_needed(id_type);
1130 }
1131 
1133 {
1134  return ID_TYPE_IS_COW(id_type);
1135 }
1136 
1137 } // namespace blender::deg
Blender kernel action and pose functionality.
struct AnimData * BKE_animdata_from_id(struct ID *id)
Definition: anim_data.c:96
void BKE_animsys_update_driver_array(struct ID *id)
Definition: anim_sys.c:3052
void BKE_pose_remap_bone_pointers(struct bArmature *armature, struct bPose *pose)
Definition: armature.c:2498
void BKE_pose_pchan_index_rebuild(struct bPose *pose)
void BKE_editmesh_free_derivedmesh(BMEditMesh *em)
Definition: editmesh.c:151
@ G_DEBUG_DEPSGRAPH_UUID
Definition: BKE_global.h:147
void BKE_gpencil_update_orig_pointers(const struct Object *ob_orig, const struct Object *ob_eval)
void BKE_view_layer_free_ex(struct ViewLayer *view_layer, const bool do_id_user)
Definition: layer.c:262
struct ViewLayer * BKE_view_layer_default_render(const struct Scene *scene)
void BKE_libblock_free_data(struct ID *id, const bool do_id_user) ATTR_NONNULL()
Definition: lib_id_delete.c:55
@ LIB_ID_CREATE_NO_ALLOCATE
Definition: BKE_lib_id.h:96
@ LIB_ID_COPY_SET_COPIED_ON_WRITE
Definition: BKE_lib_id.h:109
@ LIB_ID_COPY_LOCALIZE
Definition: BKE_lib_id.h:145
struct ID * BKE_id_copy_ex(struct Main *bmain, const struct ID *id, struct ID **r_newid, const int flag)
void BKE_libblock_free_datablock(struct ID *id, const int flag) ATTR_NONNULL()
@ IDWALK_NOP
@ IDWALK_IGNORE_EMBEDDED_ID
void BKE_library_foreach_ID_link(struct Main *bmain, struct ID *id, LibraryIDLinkCallback callback, void *user_data, int flag)
Definition: lib_query.c:322
@ IDWALK_RET_NOP
Definition: BKE_lib_query.h:97
General operations, lookup, etc. for blender objects.
void BKE_object_check_uuids_unique_and_report(const struct Object *object)
#define BLI_assert(a)
Definition: BLI_assert.h:58
#define LISTBASE_FOREACH(type, var, list)
Definition: BLI_listbase.h:172
#define LISTBASE_FOREACH_MUTABLE(type, var, list)
Definition: BLI_listbase.h:188
void void BLI_freelistN(struct ListBase *listbase) ATTR_NONNULL(1)
Definition: listbase.c:547
void BLI_addtail(struct ListBase *listbase, void *vlink) ATTR_NONNULL(1)
Definition: listbase.c:110
#define STREQ(a, b)
struct Depsgraph Depsgraph
Definition: DEG_depsgraph.h:51
bool DEG_is_active(const struct Depsgraph *depsgraph)
Definition: depsgraph.cc:331
void DEG_debug_print_eval(struct Depsgraph *depsgraph, const char *function_name, const char *object_name, const void *object_address)
ID and Library types, which are fundamental for sdna.
#define ID_TYPE_IS_COW(_id_type)
Definition: DNA_ID.h:454
@ LIB_TAG_COPIED_ON_WRITE
Definition: DNA_ID.h:565
@ LIB_TAG_LOCALIZED
Definition: DNA_ID.h:568
ID_Type
Definition: DNA_ID_enums.h:56
@ ID_AR
Definition: DNA_ID_enums.h:78
@ ID_TE
Definition: DNA_ID_enums.h:64
@ ID_LA
Definition: DNA_ID_enums.h:67
@ ID_SCE
Definition: DNA_ID_enums.h:57
@ ID_LS
Definition: DNA_ID_enums.h:87
@ ID_WO
Definition: DNA_ID_enums.h:71
@ ID_SIM
Definition: DNA_ID_enums.h:96
@ ID_MA
Definition: DNA_ID_enums.h:63
@ ID_ME
Definition: DNA_ID_enums.h:60
@ ID_MB
Definition: DNA_ID_enums.h:62
@ ID_LT
Definition: DNA_ID_enums.h:66
@ ID_OB
Definition: DNA_ID_enums.h:59
@ ID_CU
Definition: DNA_ID_enums.h:61
@ eParticleSystemFlag_file_loaded
@ eModifierType_ParticleSystem
Object is a sort of wrapper for general info.
@ OB_ARMATURE
@ OB_GPENCIL
Types and defines for representing Rigid Body entities.
_GL_VOID GLfloat value _GL_VOID_RET _GL_VOID const GLuint GLboolean *residences _GL_BOOL_RET _GL_VOID GLsizei GLfloat GLfloat GLfloat GLfloat const GLubyte *bitmap _GL_VOID_RET _GL_VOID GLenum type
Read Guarded memory(de)allocation.
Depsgraph * graph
const IDNode * id_node
Scene scene
Curve curve
bool create_placeholders
FreestyleLineStyle linestyle
bool is_valid
World world
#define SPECIAL_CASE(id_type, dna_type, field)
Material material
Simulation simulation
DepsgraphNodeBuilder * node_builder
Light lamp
const Depsgraph * depsgraph
Lattice lattice
#define DEG_COW_PRINT(format,...)
AnimationBackup * backup
void * user_data
#define GS(x)
Definition: iris.c:241
static int foreach_libblock_remap_callback(LibraryIDLinkCallbackData *cb_data)
Definition: lib_remap.c:94
void(* MEM_freeN)(void *vmemh)
Definition: mallocn.c:41
void *(* MEM_dupallocN)(const void *vmemh)
Definition: mallocn.c:42
#define T
bool deg_check_base_in_depsgraph(const Depsgraph *graph, Base *base)
Definition: deg_builder.cc:61
ID * deg_update_copy_on_write_datablock(const Depsgraph *depsgraph, const IDNode *id_node)
bool deg_copy_on_write_is_needed(const ID *id_orig)
ID * deg_expand_copy_on_write_datablock(const Depsgraph *depsgraph, const IDNode *id_node, DepsgraphNodeBuilder *node_builder, bool create_placeholders)
void deg_tag_copy_on_write_id(ID *id_cow, const ID *id_orig)
bool deg_validate_copy_on_write_datablock(ID *id_cow)
@ DEG_ID_LINKED_INDIRECTLY
Definition: deg_node_id.h:42
@ DEG_ID_LINKED_VIA_SET
Definition: deg_node_id.h:44
@ DEG_ID_LINKED_DIRECTLY
Definition: deg_node_id.h:46
bool deg_copy_on_write_is_expanded(const ID *id_cow)
void deg_evaluate_copy_on_write(struct ::Depsgraph *graph, const IDNode *id_node)
bool deg_check_id_in_depsgraph(const Depsgraph *graph, ID *id_orig)
Definition: deg_builder.cc:55
void deg_free_copy_on_write_datablock(ID *id_cow)
void SEQ_relations_check_uuids_unique_and_report(const Scene *scene)
ListBase nla_tracks
struct Mesh * mesh_eval_final
Definition: BKE_editmesh.h:63
struct Mesh * mesh_eval_cage
Definition: BKE_editmesh.h:63
struct Base * next
struct EditFont * editfont
EditNurb * editnurb
Definition: DNA_ID.h:273
int tag
Definition: DNA_ID.h:292
int recalc
Definition: DNA_ID.h:295
struct ID * orig_id
Definition: DNA_ID.h:324
char name[66]
Definition: DNA_ID.h:283
struct EditLatt * editlatt
void * last
Definition: DNA_listBase.h:47
void * first
Definition: DNA_listBase.h:47
struct BMEditMesh * edit_mesh
ListBase * editelems
struct ModifierData * orig_modifier_data
struct NlaStrip * next
ListBase strips
struct NlaStrip * orig_strip
ListBase strips
struct NlaTrack * next
struct ID * data_orig
struct Object * proxy_group
ListBase particlesystem
struct bPose * pose
ListBase modifiers
struct Object * proxy
Object_Runtime runtime
struct SculptSession * sculpt
void * data
struct ParticleSystemModifierData * psmd_eval
struct ParticleSystem * psys_eval
struct PTCacheEdit * edit
struct ParticleSystem * orig_psys
struct LightCache * light_cache_data
struct bNodeTree * nodetree
struct ToolSettings * toolsettings
ListBase view_layers
struct SceneEEVEE eevee
struct ViewLayer * prev
struct ViewLayer * next
struct Base * basact
ListBase object_bases
char name[64]
struct EditBone * act_edbone
ListBase * edbo
struct bPoseChannel * orig_pchan
ListBase chanbase
ID * get_cow_id(const ID *id_orig) const
Definition: depsgraph.cc:249
IDNode * find_id_node(const ID *id) const
Definition: depsgraph.cc:112
ViewLayer * view_layer
Definition: depsgraph.h:135
eDepsNode_LinkedState_Type linked_state
Definition: deg_node_id.h:108
#define G(x, y, z)