Blender V4.3
deg_builder_relations.cc
Go to the documentation of this file.
1/* SPDX-FileCopyrightText: 2013 Blender Authors
2 *
3 * SPDX-License-Identifier: GPL-2.0-or-later */
4
12
13#include <cstdio>
14#include <cstdlib>
15#include <cstring> /* required for STREQ later on. */
16#include <optional>
17
18#include "DNA_modifier_types.h"
19#include "MEM_guardedalloc.h"
20
21#include "BLI_blenlib.h"
22#include "BLI_span.hh"
23#include "BLI_utildefines.h"
24
25#include "DNA_action_types.h"
26#include "DNA_anim_types.h"
27#include "DNA_armature_types.h"
28#include "DNA_cachefile_types.h"
29#include "DNA_camera_types.h"
30#include "DNA_cloth_types.h"
33#include "DNA_curve_types.h"
34#include "DNA_curves_types.h"
35#include "DNA_effect_types.h"
37#include "DNA_key_types.h"
38#include "DNA_light_types.h"
40#include "DNA_linestyle_types.h"
41#include "DNA_mask_types.h"
42#include "DNA_material_types.h"
43#include "DNA_mesh_types.h"
44#include "DNA_meta_types.h"
45#include "DNA_movieclip_types.h"
46#include "DNA_node_types.h"
48#include "DNA_object_types.h"
49#include "DNA_particle_types.h"
50#include "DNA_rigidbody_types.h"
51#include "DNA_scene_types.h"
52#include "DNA_sequence_types.h"
53#include "DNA_sound_types.h"
54#include "DNA_speaker_types.h"
55#include "DNA_texture_types.h"
56#include "DNA_vfont_types.h"
57#include "DNA_volume_types.h"
58#include "DNA_world_types.h"
59
60#include "BKE_action.hh"
61#include "BKE_anim_data.hh"
62#include "BKE_armature.hh"
63#include "BKE_collection.hh"
64#include "BKE_collision.h"
65#include "BKE_constraint.h"
66#include "BKE_curve.hh"
67#include "BKE_effect.h"
68#include "BKE_fcurve_driver.h"
70#include "BKE_grease_pencil.hh"
71#include "BKE_idprop.hh"
72#include "BKE_image.hh"
73#include "BKE_key.hh"
74#include "BKE_layer.hh"
75#include "BKE_lib_query.hh"
76#include "BKE_material.h"
77#include "BKE_mball.hh"
78#include "BKE_modifier.hh"
79#include "BKE_node.hh"
80#include "BKE_node_runtime.hh"
81#include "BKE_object.hh"
82#include "BKE_particle.h"
83#include "BKE_pointcache.h"
84#include "BKE_rigidbody.h"
85#include "BKE_shader_fx.h"
86#include "BKE_shrinkwrap.hh"
87#include "BKE_sound.h"
88#include "BKE_tracking.h"
89#include "BKE_world.h"
90
91#include "RNA_access.hh"
92#include "RNA_prototypes.hh"
93#include "RNA_types.hh"
94
95#include "ANIM_action.hh"
96#include "SEQ_iterator.hh"
97
98#include "DEG_depsgraph.hh"
100
108
114
115#include "intern/depsgraph.hh"
118
119namespace blender::deg {
120
121/* ***************** */
122/* Relations Builder */
123
124namespace {
125
126bool is_time_dependent_scene_driver_target(const DriverTarget *target)
127{
128 return target->rna_path != nullptr && STREQ(target->rna_path, "frame_current");
129}
130
131bool driver_target_depends_on_time(const DriverVar *variable, const DriverTarget *target)
132{
133 if (variable->type == DVAR_TYPE_CONTEXT_PROP &&
134 target->context_property == DTAR_CONTEXT_PROPERTY_ACTIVE_SCENE)
135 {
136 return is_time_dependent_scene_driver_target(target);
137 }
138
139 if (target->idtype == ID_SCE) {
140 return is_time_dependent_scene_driver_target(target);
141 }
142
143 return false;
144}
145
146bool driver_variable_depends_on_time(const DriverVar *variable)
147{
148 for (int i = 0; i < variable->num_targets; ++i) {
149 if (driver_target_depends_on_time(variable, &variable->targets[i])) {
150 return true;
151 }
152 }
153 return false;
154}
155
156bool driver_variables_depends_on_time(const ListBase *variables)
157{
158 LISTBASE_FOREACH (const DriverVar *, variable, variables) {
159 if (driver_variable_depends_on_time(variable)) {
160 return true;
161 }
162 }
163 return false;
164}
165
166bool driver_depends_on_time(ChannelDriver *driver)
167{
169 return true;
170 }
171 if (driver_variables_depends_on_time(&driver->variables)) {
172 return true;
173 }
174 return false;
175}
176
177bool particle_system_depends_on_time(ParticleSystem *psys)
178{
179 ParticleSettings *part = psys->part;
180 /* Non-hair particles we always consider dependent on time. */
181 if (part->type != PART_HAIR) {
182 return true;
183 }
184 /* Dynamics always depends on time. */
185 if (psys->flag & PSYS_HAIR_DYNAMICS) {
186 return true;
187 }
188 /* TODO(sergey): Check what else makes hair dependent on time. */
189 return false;
190}
191
192bool object_particles_depends_on_time(Object *object)
193{
194 if (object->type != OB_MESH) {
195 return false;
196 }
197 LISTBASE_FOREACH (ParticleSystem *, psys, &object->particlesystem) {
198 if (particle_system_depends_on_time(psys)) {
199 return true;
200 }
201 }
202 return false;
203}
204
205bool check_id_has_anim_component(ID *id)
206{
208 if (adt == nullptr) {
209 return false;
210 }
211 return (adt->action != nullptr) || !BLI_listbase_is_empty(&adt->nla_tracks);
212}
213
214bool check_id_has_driver_component(ID *id)
215{
217 if (adt == nullptr) {
218 return false;
219 }
220 return !BLI_listbase_is_empty(&adt->drivers);
221}
222
223OperationCode bone_target_opcode(ID *target,
224 const char *subtarget,
225 ID *id,
226 const char *component_subdata,
227 RootPChanMap *root_map)
228{
229 /* Same armature. root_map will be nullptr when building object-level constraints, and in that
230 * case we don't need to check for the common chains. */
231 if (target == id && root_map != nullptr) {
232 /* Using "done" here breaks in-chain deps, while using
233 * "ready" here breaks most production rigs instead.
234 * So, we do a compromise here, and only do this when an
235 * IK chain conflict may occur. */
236 if (root_map->has_common_root(component_subdata, subtarget)) {
238 }
239 }
241}
242
243bool object_have_geometry_component(const Object *object)
244{
245 return ELEM(object->type,
246 OB_MESH,
248 OB_FONT,
249 OB_SURF,
250 OB_MBALL,
253}
254
255} // namespace
256
257/* **** General purpose functions **** */
258
260 Depsgraph *graph,
262 : DepsgraphBuilder(bmain, graph, cache), scene_(nullptr), rna_node_query_(graph, this)
263{
264}
265
270
272{
274 if (!id_node) {
275 fprintf(stderr,
276 "find_node component: Could not find ID %s\n",
277 (key.id != nullptr) ? key.id->name : "<null>");
278 return nullptr;
279 }
280
281 ComponentNode *node = id_node->find_component(key.type, key.name);
282 return node;
283}
284
286{
287 OperationNode *op_node = find_node(key);
288 if (op_node == nullptr) {
289 fprintf(stderr,
290 "find_node_operation: Failed for (%s, '%s')\n",
292 key.name);
293 }
294 return op_node;
295}
296
298{
299 return rna_node_query_.find_node(&key.ptr, key.prop, key.source);
300}
301
303{
305 if (!id_node) {
306 return nullptr;
307 }
308 return id_node->find_component(key.type, key.name);
309}
310
312{
314 if (!id_node) {
315 return nullptr;
316 }
317 ComponentNode *comp_node = id_node->find_component(key.component_type, key.component_name);
318 if (!comp_node) {
319 return nullptr;
320 }
321 return comp_node->find_operation(key.opcode, key.name, key.name_tag);
322}
323
325{
326 return find_node(key) != nullptr;
327}
328
330{
331 return find_node(key) != nullptr;
332}
333
335 const char *description)
336{
337 IDNode *id_node = handle->node->owner->owner;
338 ID *id = id_node->id_orig;
339 const OperationKey geometry_key(
340 id, NodeType::GEOMETRY, OperationCode::MODIFIER, handle->node->name.c_str());
341 /* Wire up the actual relation. */
342 add_depends_on_transform_relation(id, geometry_key, description);
343}
344
346 const DEGCustomDataMeshMasks &customdata_masks)
347{
348 if (customdata_masks != DEGCustomDataMeshMasks() && object != nullptr && object->type == OB_MESH)
349 {
350 IDNode *id_node = graph_->find_id_node(&object->id);
351
352 if (id_node == nullptr) {
353 BLI_assert_msg(0, "ID should always be valid");
354 }
355 else {
356 id_node->customdata_masks |= customdata_masks;
357 }
358 }
359}
360
362{
364 if (id_node == nullptr) {
365 BLI_assert_msg(0, "ID should always be valid");
366 }
367 else {
368 id_node->eval_flags |= flag;
369 }
370}
371
373 Node *node_to,
374 const char *description,
375 int flags)
376{
377 if (timesrc && node_to) {
378 return graph_->add_new_relation(timesrc, node_to, description, flags);
379 }
380
381 DEG_DEBUG_PRINTF((::Depsgraph *)graph_,
382 BUILD,
383 "add_time_relation(%p = %s, %p = %s, %s) Failed\n",
384 timesrc,
385 (timesrc) ? timesrc->identifier().c_str() : "<None>",
386 node_to,
387 (node_to) ? node_to->identifier().c_str() : "<None>",
388 description);
389
390 return nullptr;
391}
392
394{
395 ComponentKey from_key(id_from, NodeType::VISIBILITY);
396 ComponentKey to_key(id_to, NodeType::VISIBILITY);
397 add_relation(from_key, to_key, "visibility");
398}
399
401 OperationNode *node_to,
402 const char *description,
403 int flags)
404{
405 if (node_from && node_to) {
406 return graph_->add_new_relation(node_from, node_to, description, flags);
407 }
408
409 DEG_DEBUG_PRINTF((::Depsgraph *)graph_,
410 BUILD,
411 "add_operation_relation(%p = %s, %p = %s, %s) Failed\n",
412 node_from,
413 (node_from) ? node_from->identifier().c_str() : "<None>",
414 node_to,
415 (node_to) ? node_to->identifier().c_str() : "<None>",
416 description);
417
418 return nullptr;
419}
420
422 Object *object,
423 Collection *collection,
424 const char *name)
425{
427
428 LISTBASE_FOREACH (CollisionRelation *, relation, relations) {
429 if (relation->ob != object) {
430 ComponentKey trf_key(&relation->ob->id, NodeType::TRANSFORM);
431 add_relation(trf_key, key, name);
432
433 ComponentKey coll_key(&relation->ob->id, NodeType::GEOMETRY);
434 add_relation(coll_key, key, name);
435 }
436 }
437}
438
440 Object *object,
441 ParticleSystem *psys,
442 EffectorWeights *eff,
443 bool add_absorption,
444 const char *name)
445{
446 ListBase *relations = build_effector_relations(graph_, eff->group);
447
448 /* Make sure physics effects like wind are properly re-evaluating the modifier stack. */
449 if (!BLI_listbase_is_empty(relations)) {
450 TimeSourceKey time_src_key;
451 ComponentKey geometry_key(&object->id, NodeType::GEOMETRY);
453 time_src_key, geometry_key, "Effector Time -> Particle", RELATION_CHECK_BEFORE_ADD);
454 }
455
456 LISTBASE_FOREACH (EffectorRelation *, relation, relations) {
457 if (relation->ob != object) {
458 /* Relation to forcefield object, optionally including geometry. */
459 ComponentKey eff_key(&relation->ob->id, NodeType::TRANSFORM);
460 add_relation(eff_key, key, name);
461
462 if (ELEM(relation->pd->shape, PFIELD_SHAPE_SURFACE, PFIELD_SHAPE_POINTS) ||
463 relation->pd->forcefield == PFIELD_GUIDE)
464 {
465 ComponentKey mod_key(&relation->ob->id, NodeType::GEOMETRY);
466 add_relation(mod_key, key, name);
467 }
468
469 /* Force field Texture. */
470 if ((relation->pd != nullptr) && (relation->pd->forcefield == PFIELD_TEXTURE) &&
471 (relation->pd->tex != nullptr))
472 {
473 ComponentKey tex_key(&relation->pd->tex->id, NodeType::GENERIC_DATABLOCK);
474 add_relation(tex_key, key, "Force field Texture");
475 }
476
477 /* Smoke flow relations. */
478 if (relation->pd->forcefield == PFIELD_FLUIDFLOW && relation->pd->f_source) {
479 ComponentKey trf_key(&relation->pd->f_source->id, NodeType::TRANSFORM);
480 add_relation(trf_key, key, "Smoke Force Domain");
481 ComponentKey eff_key(&relation->pd->f_source->id, NodeType::GEOMETRY);
482 add_relation(eff_key, key, "Smoke Force Domain");
483 }
484
485 /* Absorption forces need collision relation. */
486 if (add_absorption && (relation->pd->flag & PFIELD_VISIBILITY)) {
487 add_particle_collision_relations(key, object, nullptr, "Force Absorption");
488 }
489 }
490
491 if (relation->psys) {
492 if (relation->ob != object) {
493 ComponentKey eff_key(&relation->ob->id, NodeType::PARTICLE_SYSTEM);
494 add_relation(eff_key, key, name);
495 /* TODO: remove this when/if EVAL_PARTICLES is sufficient
496 * for up to date particles. */
497 ComponentKey mod_key(&relation->ob->id, NodeType::GEOMETRY);
498 add_relation(mod_key, key, name);
499 }
500 else if (relation->psys != psys) {
501 OperationKey eff_key(&relation->ob->id,
504 relation->psys->name);
505 add_relation(eff_key, key, name);
506 }
507 }
508 }
509}
510
515
516/* **** Functions to build relations between entities **** */
517
519
521{
522 if (id == nullptr) {
523 return;
524 }
525
526 const ID_Type id_type = GS(id->name);
527 switch (id_type) {
528 case ID_AC:
529 build_action((bAction *)id);
530 break;
531 case ID_AR:
533 break;
534 case ID_CA:
535 build_camera((Camera *)id);
536 break;
537 case ID_GR:
538 build_collection(nullptr, (Collection *)id);
539 break;
540 case ID_OB:
541 build_object((Object *)id);
542 break;
543 case ID_KE:
544 build_shapekeys((Key *)id);
545 break;
546 case ID_LA:
547 build_light((Light *)id);
548 break;
549 case ID_LP:
551 break;
552 case ID_NT:
554 break;
555 case ID_MA:
557 break;
558 case ID_TE:
559 build_texture((Tex *)id);
560 break;
561 case ID_IM:
562 build_image((Image *)id);
563 break;
564 case ID_WO:
565 build_world((World *)id);
566 break;
567 case ID_MSK:
568 build_mask((Mask *)id);
569 break;
570 case ID_LS:
572 break;
573 case ID_MC:
575 break;
576 case ID_ME:
577 case ID_MB:
578 case ID_CU_LEGACY:
579 case ID_LT:
580 case ID_CV:
581 case ID_PT:
582 case ID_VO:
583 case ID_GD_LEGACY:
584 case ID_GP:
586 break;
587 case ID_SPK:
588 build_speaker((Speaker *)id);
589 break;
590 case ID_SO:
591 build_sound((bSound *)id);
592 break;
593 case ID_TXT:
594 /* Not a part of dependency graph. */
595 break;
596 case ID_CF:
598 break;
599 case ID_SCE:
601 break;
602 case ID_PA:
604 break;
605
606 case ID_LI:
607 case ID_IP:
608 case ID_SCR:
609 case ID_VF:
610 case ID_BR:
611 case ID_WM:
612 case ID_PAL:
613 case ID_PC:
614 case ID_WS:
617 break;
618 }
619}
620
622{
623 if (built_map_.checkIsBuiltAndTag(id)) {
624 return;
625 }
626
627 const BuilderStack::ScopedEntry stack_entry = stack_.trace(*id);
628
629 build_idproperties(id->properties);
630 build_animdata(id);
632}
633
635{
636 IDP_foreach_property(id_property, IDP_TYPE_FILTER_ID, [&](IDProperty *id_property) {
637 this->build_id(static_cast<ID *>(id_property->data.pointer));
638 });
639}
640
642 Collection *collection)
643{
644 const ComponentKey collection_hierarchy_key{&collection->id, NodeType::HIERARCHY};
645
646 if (from_layer_collection != nullptr) {
647 /* If we came from layer collection we don't go deeper, view layer builder takes care of going
648 * deeper.
649 *
650 * NOTE: Do early output before tagging build as done, so possible subsequent builds from
651 * outside of the layer collection properly recurses into all the nested objects and
652 * collections. */
653
654 LISTBASE_FOREACH (CollectionObject *, cob, &collection->gobject) {
655 Object *object = cob->ob;
656
657 /* Ensure that the hierarchy relations always exists, even for the layer collection.
658 *
659 * Note that the view layer builder can skip bases if they are constantly excluded from the
660 * collections. In order to avoid noisy output check that the target node exists before
661 * adding the relation. */
662 const ComponentKey object_hierarchy_key{&object->id, NodeType::HIERARCHY};
663 if (has_node(object_hierarchy_key)) {
664 add_relation(collection_hierarchy_key,
665 object_hierarchy_key,
666 "Collection -> Object hierarchy",
668 }
669 }
670 return;
671 }
672
673 if (built_map_.checkIsBuiltAndTag(collection)) {
674 return;
675 }
676
677 build_idproperties(collection->id.properties);
678 build_parameters(&collection->id);
679
680 const BuilderStack::ScopedEntry stack_entry = stack_.trace(collection->id);
681
682 const OperationKey collection_geometry_key{
684
685 LISTBASE_FOREACH (CollectionObject *, cob, &collection->gobject) {
686 Object *object = cob->ob;
687
688 build_object(object);
689
690 const ComponentKey object_hierarchy_key{&object->id, NodeType::HIERARCHY};
691 add_relation(collection_hierarchy_key, object_hierarchy_key, "Collection -> Object hierarchy");
692
693 const OperationKey object_instance_geometry_key{
695 add_relation(object_instance_geometry_key, collection_geometry_key, "Collection Geometry");
696
697 /* An instance is part of the geometry of the collection. */
698 if (object->type == OB_EMPTY) {
699 Collection *collection_instance = cob->ob->instance_collection;
700 if (collection_instance != nullptr) {
701 const OperationKey collection_instance_key{
703 add_relation(collection_instance_key, collection_geometry_key, "Collection Geometry");
704 }
705 }
706 }
707
708 LISTBASE_FOREACH (CollectionChild *, child, &collection->children) {
709 build_collection(nullptr, child->collection);
710 const OperationKey child_collection_geometry_key{
712 add_relation(child_collection_geometry_key, collection_geometry_key, "Collection Geometry");
713 }
714}
715
717{
718 if (built_map_.checkIsBuiltAndTag(object)) {
719 return;
720 }
721
722 const BuilderStack::ScopedEntry stack_entry = stack_.trace(object->id);
723
724 /* Object Transforms. */
725 OperationCode base_op = (object->parent) ? OperationCode::TRANSFORM_PARENT :
727 OperationKey base_op_key(&object->id, NodeType::TRANSFORM, base_op);
728 OperationKey init_transform_key(&object->id, NodeType::TRANSFORM, OperationCode::TRANSFORM_INIT);
729 OperationKey local_transform_key(
731 OperationKey parent_transform_key(
733 OperationKey transform_eval_key(&object->id, NodeType::TRANSFORM, OperationCode::TRANSFORM_EVAL);
734 OperationKey final_transform_key(
737
738 add_relation(init_transform_key, local_transform_key, "Transform Init");
739
740 /* Various flags, flushing from bases/collections. */
742
743 /* Parenting. */
744 if (object->parent != nullptr) {
745 /* Make sure parent object's relations are built. */
746 build_object(object->parent);
747 /* Parent relationship. */
748 build_object_parent(object);
749 /* Local -> parent. */
750 add_relation(local_transform_key, parent_transform_key, "ObLocal -> ObParent");
751 }
752
755 "Instance Geometry -> Geometry");
756
758 OperationKey{&object->id, NodeType::INSTANCING, OperationCode::INSTANCE_GEOMETRY},
759 "Transform -> Instance Geometry");
760
761 /* Modifiers. */
763
764 /* Grease Pencil Modifiers. */
765 if (object->greasepencil_modifiers.first != nullptr) {
766 BuilderWalkUserData data;
767 data.builder = this;
768 BKE_gpencil_modifiers_foreach_ID_link(object, modifier_walk, &data);
769 }
770
771 /* Shader FX. */
772 if (object->shader_fx.first != nullptr) {
773 BuilderWalkUserData data;
774 data.builder = this;
775 BKE_shaderfx_foreach_ID_link(object, modifier_walk, &data);
776 }
777
778 /* Constraints. */
779 if (object->constraints.first != nullptr) {
780 BuilderWalkUserData data;
781 data.builder = this;
782 BKE_constraints_id_loop(&object->constraints, constraint_walk, IDWALK_NOP, &data);
783 }
784
785 /* Object constraints. */
786 OperationKey object_transform_simulation_init_key(
788 if (object->constraints.first != nullptr) {
789 OperationKey constraint_key(
791 /* Constraint relations. */
792 build_constraints(&object->id, NodeType::TRANSFORM, "", &object->constraints, nullptr);
793 /* operation order */
794 add_relation(base_op_key, constraint_key, "ObBase-> Constraint Stack");
795 add_relation(constraint_key, final_transform_key, "ObConstraints -> Done");
796 add_relation(constraint_key, ob_eval_key, "Constraint -> Transform Eval");
798 ob_eval_key, object_transform_simulation_init_key, "Transform Eval -> Simulation Init");
799 add_relation(object_transform_simulation_init_key,
800 final_transform_key,
801 "Simulation -> Final Transform");
802 }
803 else {
804 add_relation(base_op_key, ob_eval_key, "Eval");
806 ob_eval_key, object_transform_simulation_init_key, "Transform Eval -> Simulation Init");
807 add_relation(object_transform_simulation_init_key,
808 final_transform_key,
809 "Simulation -> Final Transform");
810 }
811
812 build_idproperties(object->id.properties);
813
814 /* Animation data */
815 build_animdata(&object->id);
816
817 /* Object data. */
818 build_object_data(object);
819
820 /* Particle systems. */
821 if (object->particlesystem.first != nullptr) {
823 }
824
825 /* Force field Texture. */
826 if ((object->pd != nullptr) && (object->pd->forcefield == PFIELD_TEXTURE) &&
827 (object->pd->tex != nullptr))
828 {
829 build_texture(object->pd->tex);
830 }
831
834
835 build_object_shading(object);
837
838 /* Synchronization back to original object. */
839 OperationKey synchronize_key(
841 add_relation(final_transform_key, synchronize_key, "Synchronize to Original");
842
843 /* Parameters. */
844 build_parameters(&object->id);
845
846 /* Visibility.
847 * Evaluate visibility node after the object's base_flags has been updated to the current state
848 * of collections restrict and object's restrict flags. */
849 const ComponentKey object_from_layer_entry_key(&object->id, NodeType::OBJECT_FROM_LAYER);
850 const ComponentKey visibility_key(&object->id, NodeType::VISIBILITY);
851 add_relation(object_from_layer_entry_key, visibility_key, "Object Visibility");
852}
853
854/* NOTE: Implies that the object has base in the current view layer. */
856{
857 /* It is possible to have situation when an object is pulled into the dependency graph in a
858 * few different ways:
859 *
860 * - Indirect driver dependency, which doesn't have a Base (or, Base is unknown).
861 * - Via a base from a view layer (view layer of the graph, or view layer of a set scene).
862 * - Possibly other ways, which are not important for decision making here.
863 *
864 * There needs to be a relation from view layer which has a base with the object so that the
865 * order of flags evaluation is correct (object-level base flags evaluation requires view layer
866 * to be evaluated first).
867 *
868 * This build call handles situation when object comes from a view layer, hence has a base, and
869 * needs a relation from the view layer. Do the relation prior to check of whether the object
870 * relations are built so that the relation is created from every view layer which has a base
871 * with this object. */
872
873 OperationKey view_layer_done_key(
875 OperationKey object_from_layer_entry_key(
877
878 add_relation(view_layer_done_key, object_from_layer_entry_key, "View Layer flags to Object");
879
880 /* Regular object building. */
881 build_object(object);
882}
883
885{
886 OperationKey object_from_layer_entry_key(
888 OperationKey object_from_layer_exit_key(
890 OperationKey object_flags_key(
892
893 if (!has_node(object_flags_key)) {
894 /* Just connect Entry -> Exit if there is no OBJECT_BASE_FLAGS node. */
895 add_relation(object_from_layer_entry_key, object_from_layer_exit_key, "Object from Layer");
896 return;
897 }
898
899 /* Entry -> OBJECT_BASE_FLAGS -> Exit */
900 add_relation(object_from_layer_entry_key, object_flags_key, "Base flags flush Entry");
901 add_relation(object_flags_key, object_from_layer_exit_key, "Base flags flush Exit");
902
903 /* Synchronization back to original object. */
904 OperationKey synchronize_key(
906 add_relation(object_from_layer_exit_key, synchronize_key, "Synchronize to Original");
907}
908
910{
911 if (BLI_listbase_is_empty(&object->modifiers)) {
912 return;
913 }
914
915 const OperationKey eval_init_key(
918
919 const ComponentKey object_visibility_key(&object->id, NodeType::VISIBILITY);
920 const OperationKey modifier_visibility_key(
922 add_relation(modifier_visibility_key,
923 object_visibility_key,
924 "modifier -> object visibility",
926
927 add_relation(modifier_visibility_key, eval_key, "modifier visibility -> geometry eval");
928
930 ctx.scene = scene_;
931 ctx.object = object;
932
933 OperationKey previous_key = eval_init_key;
934 LISTBASE_FOREACH (ModifierData *, modifier, &object->modifiers) {
935 const OperationKey modifier_key(
936 &object->id, NodeType::GEOMETRY, OperationCode::MODIFIER, modifier->name);
937
938 /* Relation for the modifier stack chain. */
939 add_relation(previous_key, modifier_key, "Modifier");
940
941 const ModifierTypeInfo *mti = BKE_modifier_get_info((ModifierType)modifier->type);
942 if (mti->update_depsgraph) {
943 const BuilderStack::ScopedEntry stack_entry = stack_.trace(*modifier);
944
945 DepsNodeHandle handle = create_node_handle(modifier_key);
946 ctx.node = reinterpret_cast<::DepsNodeHandle *>(&handle);
947 mti->update_depsgraph(modifier, &ctx);
948 }
949
950 /* Time dependency. */
951 if (BKE_modifier_depends_ontime(scene_, modifier)) {
952 const TimeSourceKey time_src_key;
953 add_relation(time_src_key, modifier_key, "Time Source -> Modifier");
954 }
955
956 previous_key = modifier_key;
957 }
958 add_relation(previous_key, eval_key, "modifier stack order");
959
960 /* Build IDs referenced by the modifiers. */
961 BuilderWalkUserData data;
962 data.builder = this;
963 BKE_modifiers_foreach_ID_link(object, modifier_walk, &data);
964}
965
967{
968 if (object->data == nullptr) {
969 return;
970 }
971 ID *obdata_id = (ID *)object->data;
972 /* Object data animation. */
973 if (!built_map_.checkIsBuilt(obdata_id)) {
974 build_animdata(obdata_id);
975 }
976 /* type-specific data. */
977 switch (object->type) {
978 case OB_MESH:
979 case OB_CURVES_LEGACY:
980 case OB_FONT:
981 case OB_SURF:
982 case OB_MBALL:
983 case OB_LATTICE:
985 case OB_CURVES:
986 case OB_POINTCLOUD:
987 case OB_VOLUME:
988 case OB_GREASE_PENCIL: {
990 /* TODO(sergey): Only for until we support granular
991 * update of curves. */
992 if (object->type == OB_FONT) {
993 Curve *curve = (Curve *)object->data;
994 if (curve->textoncurve) {
995 ComponentKey geometry_key((ID *)object->data, NodeType::GEOMETRY);
996 ComponentKey transform_key(&object->id, NodeType::TRANSFORM);
997 add_relation(transform_key, geometry_key, "Text on Curve own Transform");
998 add_special_eval_flag(&curve->textoncurve->id, DAG_EVAL_NEED_CURVE_PATH);
999 }
1000 }
1001 break;
1002 }
1003 case OB_ARMATURE:
1004 build_rig(object);
1005 break;
1006 case OB_LAMP:
1008 break;
1009 case OB_CAMERA:
1011 break;
1012 case OB_LIGHTPROBE:
1014 break;
1015 case OB_SPEAKER:
1017 break;
1018 }
1019 Key *key = BKE_key_from_object(object);
1020 if (key != nullptr) {
1021 ComponentKey geometry_key((ID *)object->data, NodeType::GEOMETRY);
1022 ComponentKey key_key(&key->id, NodeType::GEOMETRY);
1023 add_relation(key_key, geometry_key, "Shapekeys");
1024 build_nested_shapekey(&object->id, key);
1025 }
1026 /* Materials. */
1027 Material ***materials_ptr = BKE_object_material_array_p(object);
1028 if (materials_ptr != nullptr) {
1029 short *num_materials_ptr = BKE_object_material_len_p(object);
1030 ID *obdata = (ID *)object->data;
1031 build_materials(obdata, *materials_ptr, *num_materials_ptr);
1032 }
1033}
1034
1036{
1037 Camera *camera = (Camera *)object->data;
1038 build_camera(camera);
1039 ComponentKey object_parameters_key(&object->id, NodeType::PARAMETERS);
1040 ComponentKey camera_parameters_key(&camera->id, NodeType::PARAMETERS);
1041 add_relation(camera_parameters_key, object_parameters_key, "Camera -> Object");
1042}
1043
1045{
1046 Light *lamp = (Light *)object->data;
1048 ComponentKey lamp_parameters_key(&lamp->id, NodeType::PARAMETERS);
1049 ComponentKey object_parameters_key(&object->id, NodeType::PARAMETERS);
1050 add_relation(lamp_parameters_key, object_parameters_key, "Light -> Object");
1051 OperationKey object_shading_key(&object->id, NodeType::SHADING, OperationCode::SHADING);
1052 add_relation(lamp_parameters_key, object_shading_key, "Light -> Object Shading");
1053}
1054
1056{
1057 LightProbe *probe = (LightProbe *)object->data;
1058 build_lightprobe(probe);
1061 add_relation(probe_key, object_key, "LightProbe Update");
1062 OperationKey object_shading_key(&object->id, NodeType::SHADING, OperationCode::SHADING);
1063 add_relation(probe_key, object_shading_key, "LightProbe -> Object Shading");
1064}
1065
1067{
1068 Speaker *speaker = (Speaker *)object->data;
1069 build_speaker(speaker);
1070 ComponentKey speaker_key(&speaker->id, NodeType::AUDIO);
1071 ComponentKey object_key(&object->id, NodeType::AUDIO);
1072 add_relation(speaker_key, object_key, "Speaker Update");
1073}
1074
1076{
1077 Object *parent = object->parent;
1078 ID *parent_id = &object->parent->id;
1079 ComponentKey object_transform_key(&object->id, NodeType::TRANSFORM);
1080 /* Type-specific links. */
1081 switch (object->partype) {
1082 /* Armature Deform (Virtual Modifier) */
1083 case PARSKEL: {
1084 ComponentKey parent_transform_key(parent_id, NodeType::TRANSFORM);
1085 add_relation(parent_transform_key, object_transform_key, "Parent Armature Transform");
1086
1087 if (parent->type == OB_ARMATURE) {
1088 ComponentKey object_geometry_key(&object->id, NodeType::GEOMETRY);
1089 ComponentKey parent_pose_key(parent_id, NodeType::EVAL_POSE);
1091 parent_transform_key, object_geometry_key, "Parent Armature Transform -> Geometry");
1092 add_relation(parent_pose_key, object_geometry_key, "Parent Armature Pose -> Geometry");
1093
1095 &object->id, object_geometry_key, "Virtual Armature Modifier");
1096 }
1097
1098 break;
1099 }
1100
1101 /* Vertex Parent */
1102 case PARVERT1:
1103 case PARVERT3: {
1104 ComponentKey parent_key(parent_id, NodeType::GEOMETRY);
1105 add_relation(parent_key, object_transform_key, "Vertex Parent");
1106 /* Original index is used for optimizations of lookups for subdiv
1107 * only meshes.
1108 * TODO(sergey): This optimization got lost at 2.8, so either verify
1109 * we can get rid of this mask here, or bring the optimization
1110 * back. */
1111 add_customdata_mask(object->parent,
1116 ComponentKey transform_key(parent_id, NodeType::TRANSFORM);
1117 add_relation(transform_key, object_transform_key, "Vertex Parent TFM");
1118 break;
1119 }
1120
1121 /* Bone Parent */
1122 case PARBONE: {
1123 if (object->parsubstr[0] != '\0') {
1124 ComponentKey parent_bone_key(parent_id, NodeType::BONE, object->parsubstr);
1125 OperationKey parent_transform_key(
1127 add_relation(parent_bone_key, object_transform_key, "Bone Parent");
1128 add_relation(parent_transform_key, object_transform_key, "Armature Parent");
1129 }
1130 break;
1131 }
1132
1133 default: {
1134 if (object->parent->type == OB_LATTICE) {
1135 /* Lattice Deform Parent - Virtual Modifier. */
1136 ComponentKey parent_key(parent_id, NodeType::TRANSFORM);
1137 ComponentKey geom_key(parent_id, NodeType::GEOMETRY);
1138 add_relation(parent_key, object_transform_key, "Lattice Deform Parent");
1139 add_relation(geom_key, object_transform_key, "Lattice Deform Parent Geom");
1140 }
1141 else if (object->parent->type == OB_CURVES_LEGACY) {
1142 Curve *cu = (Curve *)object->parent->data;
1143
1144 if (cu->flag & CU_PATH) {
1145 /* Follow Path. */
1146 ComponentKey parent_key(parent_id, NodeType::GEOMETRY);
1147 add_relation(parent_key, object_transform_key, "Curve Follow Parent");
1148 ComponentKey transform_key(parent_id, NodeType::TRANSFORM);
1149 add_relation(transform_key, object_transform_key, "Curve Follow TFM");
1150 }
1151 else {
1152 /* Standard Parent. */
1153 ComponentKey parent_key(parent_id, NodeType::TRANSFORM);
1154 add_relation(parent_key, object_transform_key, "Curve Parent");
1155 }
1156 }
1157 else {
1158 /* Standard Parent. */
1159 ComponentKey parent_key(parent_id, NodeType::TRANSFORM);
1160 add_relation(parent_key, object_transform_key, "Parent");
1161 }
1162 break;
1163 }
1164 }
1165 /* Meta-balls are the odd balls here (no pun intended): they will request
1166 * instance-list (formerly known as dupli-list) during evaluation. This is
1167 * their way of interacting with all instanced surfaces, making a nice
1168 * effect when is used form particle system. */
1169 if (object->type == OB_MBALL && parent->transflag & OB_DUPLI) {
1170 ComponentKey parent_geometry_key(parent_id, NodeType::GEOMETRY);
1171 /* NOTE: Meta-balls are evaluating geometry only after their transform,
1172 * so we only hook up to transform channel here. */
1173 add_relation(parent_geometry_key, object_transform_key, "Parent");
1174 }
1175
1176 /* Dupliverts uses original vertex index. */
1177 if (parent->transflag & OB_DUPLIVERTS) {
1179 }
1180}
1181
1182/* Returns the modifier that is last in the modifier stack. */
1183static const ModifierData *get_latter_modifier(const ModifierData *md1, const ModifierData *md2)
1184{
1185 if (md1 == nullptr) {
1186 return md2;
1187 }
1188 if (md2 == nullptr) {
1189 return md1;
1190 }
1191
1192 for (const ModifierData *md = md2->prev; md; md = md->prev) {
1193 if (md == md1) {
1194 return md2;
1195 }
1196 }
1197 return md1;
1198}
1199
1201{
1202 std::optional<ComponentKey> point_cache_key;
1203 bool has_rigid_body_relation = false;
1204 bool has_geometry_eval_relation = false;
1205 const ModifierData *last_input_modifier = nullptr;
1207 *object, *scene_, false, [&](PTCacheID &ptcache_id, ModifierData *md) {
1208 if (!point_cache_key) {
1209 point_cache_key = ComponentKey(&object->id, NodeType::POINT_CACHE);
1210 }
1211
1212 /* Check which components needs the point cache. */
1213 if (!has_geometry_eval_relation) {
1214 has_geometry_eval_relation = true;
1215
1217 add_relation(*point_cache_key, geometry_key, "Point Cache -> Geometry");
1218 }
1219 if (!has_rigid_body_relation && ptcache_id.type == PTCACHE_TYPE_RIGIDBODY) {
1220 if (object->rigidbody_object->type == RBO_TYPE_PASSIVE) {
1221 return true;
1222 }
1223 has_rigid_body_relation = true;
1224
1225 OperationKey transform_key(
1227 add_relation(*point_cache_key, transform_key, "Point Cache -> Rigid Body");
1228 /* Manual changes to effectors need to invalidate simulation.
1229 *
1230 * Don't add this relation for the render pipeline dependency graph as it does not
1231 * contain rigid body simulation. Good thing is that there are no user edits in such
1232 * dependency graph, so the relation is not really needed in it. */
1234 OperationKey rigidbody_rebuild_key(
1236 add_relation(rigidbody_rebuild_key,
1237 *point_cache_key,
1238 "Rigid Body Rebuild -> Point Cache Reset",
1240 }
1241 }
1242
1243 if (md && md->prev) {
1244 last_input_modifier = get_latter_modifier(last_input_modifier, md->prev);
1245 }
1246
1247 return true;
1248 });
1249
1250 /* Manual edits to any dependency (or self) should reset the point cache. */
1251 if (point_cache_key) {
1252 OperationKey transform_eval_key(
1254 add_relation(transform_eval_key,
1255 *point_cache_key,
1256 "Transform Simulation -> Point Cache",
1258
1259 /* For caches in specific modifiers:
1260 * Input data changes from previous modifiers require a point cache reset. */
1261 if (last_input_modifier != nullptr) {
1262 const OperationKey input_modifier_key(
1263 &object->id, NodeType::GEOMETRY, OperationCode::MODIFIER, last_input_modifier->name);
1264 add_relation(input_modifier_key,
1265 *point_cache_key,
1266 "Previous Modifier -> Point Cache",
1268 }
1269 else {
1270 OperationKey geometry_init_key(
1272 add_relation(geometry_init_key,
1273 *point_cache_key,
1274 "Geometry Init -> Point Cache",
1276 }
1277 }
1278}
1279
1281{
1282 if (object->instance_collection == nullptr) {
1283 return;
1284 }
1285
1286 Collection *instance_collection = object->instance_collection;
1287
1288 build_collection(nullptr, instance_collection);
1289
1290 const OperationKey object_transform_final_key(
1292 const OperationKey instancer_key(&object->id, NodeType::INSTANCING, OperationCode::INSTANCER);
1293
1295 const ComponentKey dupli_transform_key(&ob->id, NodeType::TRANSFORM);
1296 add_relation(dupli_transform_key, object_transform_final_key, "Dupligroup");
1297
1298 /* Hook to special component, to ensure proper visibility/evaluation optimizations. */
1300 instancer_key,
1301 "Instance -> Instancer");
1302 }
1304}
1305
1307{
1308 const OperationKey shading_done_key(&object->id, NodeType::SHADING, OperationCode::SHADING_DONE);
1309
1310 const OperationKey shading_key(&object->id, NodeType::SHADING, OperationCode::SHADING);
1311 add_relation(shading_key, shading_done_key, "Shading -> Done");
1312
1313 /* Hook up shading component to the instance, so that if the object is instanced by a visible
1314 * object the shading component is ensured to be evaluated.
1315 * Don't to flushing to avoid re-evaluation of geometry when the object is used as part of a
1316 * collection used as a boolean modifier operand. */
1317 add_relation(shading_done_key,
1319 "Light Linking -> Instance",
1321}
1322
1324{
1325 const ComponentKey hierarchy_key(&emitter->id, NodeType::HIERARCHY);
1326 const OperationKey shading_done_key(
1328 const OperationKey light_linking_key(
1330
1331 add_relation(hierarchy_key, light_linking_key, "Light Linking From Layer");
1332 add_relation(light_linking_key, shading_done_key, "Light Linking -> Shading Done");
1333
1334 if (emitter->light_linking) {
1335 LightLinking &light_linking = *emitter->light_linking;
1336
1338 build_light_linking_collection(emitter, light_linking.blocker_collection);
1339 }
1340}
1341
1343 Collection *collection)
1344{
1345 if (collection == nullptr) {
1346 return;
1347 }
1348
1349 build_collection(nullptr, collection);
1350
1351 /* TODO(sergey): Avoid duplicate dependencies if multiple emitters are using the same collection.
1352 */
1353
1354 const OperationKey emitter_light_linking_key(
1356
1357 const OperationKey collection_parameters_entry_key(
1359 const OperationKey collection_parameters_exit_key(
1361 const OperationKey collection_hierarchy_key(
1363
1364 const OperationKey collection_light_linking_key(
1366
1367 /* Order of parameters evaluation within the receiver collection. */
1368 /* TODO(sergey): Can optimize this out by explicitly separating the different built tags. This
1369 * needs to be done in all places where the collection is built (is not something that can be
1370 * easily solved from just adding the light linking functionality). */
1371 add_relation(collection_parameters_entry_key,
1372 collection_light_linking_key,
1373 "Entry -> Collection Light Linking",
1375 add_relation(collection_light_linking_key,
1376 collection_parameters_exit_key,
1377 "Collection Light Linking -> Exit",
1379
1380 add_relation(collection_hierarchy_key,
1381 collection_light_linking_key,
1382 "Collection Hierarchy -> Light Linking",
1384
1385 /* Order to ensure the emitter's light linking is only evaluated after the receiver collection.
1386 * This is because light linking runtime data is "cached" om the emitter object for the
1387 * simplicity of access, but the mask is allocated per collection bases (so that if two emitters
1388 * share the same receiving collection they share the same runtime data). */
1389 add_relation(collection_light_linking_key,
1390 emitter_light_linking_key,
1391 "Collection -> Object Light Linking");
1392}
1393
1395 NodeType component_type,
1396 const char *component_subdata,
1398 RootPChanMap *root_map)
1399{
1400 OperationKey constraint_op_key(id,
1401 component_type,
1402 component_subdata,
1403 (component_type == NodeType::BONE) ?
1406 /* Add dependencies for each constraint in turn. */
1409 ListBase targets = {nullptr, nullptr};
1410 /* Invalid constraint type. */
1411 if (cti == nullptr) {
1412 continue;
1413 }
1414
1415 const BuilderStack::ScopedEntry stack_entry = stack_.trace(*con);
1416
1417 /* Special case for camera tracking -- it doesn't use targets to
1418 * define relations. */
1419 /* TODO: we can now represent dependencies in a much richer manner,
1420 * so review how this is done. */
1421 if (ELEM(cti->type,
1425 {
1426 bool depends_on_camera = false;
1427 if (cti->type == CONSTRAINT_TYPE_FOLLOWTRACK) {
1429 if (((data->clip) || (data->flag & FOLLOWTRACK_ACTIVECLIP)) && data->track[0]) {
1430 depends_on_camera = true;
1431 }
1432 if (data->depth_ob) {
1433 ComponentKey depth_transform_key(&data->depth_ob->id, NodeType::TRANSFORM);
1434 ComponentKey depth_geometry_key(&data->depth_ob->id, NodeType::GEOMETRY);
1435 add_relation(depth_transform_key, constraint_op_key, cti->name);
1436 add_relation(depth_geometry_key, constraint_op_key, cti->name);
1437 }
1438 }
1439 else if (cti->type == CONSTRAINT_TYPE_OBJECTSOLVER) {
1440 depends_on_camera = true;
1441 }
1442 if (depends_on_camera && scene_->camera != nullptr) {
1443 ComponentKey camera_key(&scene_->camera->id, NodeType::TRANSFORM);
1444 add_relation(camera_key, constraint_op_key, cti->name);
1445 }
1446 /* TODO(sergey): This is more a TimeSource -> MovieClip ->
1447 * Constraint dependency chain. */
1448 TimeSourceKey time_src_key;
1449 add_relation(time_src_key, constraint_op_key, "TimeSrc -> Animation");
1450 }
1451 else if (cti->type == CONSTRAINT_TYPE_TRANSFORM_CACHE) {
1452 /* TODO(kevin): This is more a TimeSource -> CacheFile -> Constraint
1453 * dependency chain. */
1454 TimeSourceKey time_src_key;
1455 add_relation(time_src_key, constraint_op_key, "TimeSrc -> Animation");
1457 if (data->cache_file) {
1458 ComponentKey cache_key(&data->cache_file->id, NodeType::CACHE);
1459 add_relation(cache_key, constraint_op_key, cti->name);
1460 }
1461 }
1462 else if (BKE_constraint_targets_get(con, &targets)) {
1463 LISTBASE_FOREACH (bConstraintTarget *, ct, &targets) {
1464 if (ct->tar == nullptr) {
1465 continue;
1466 }
1468 /* Ignore IK constraints - these are handled separately
1469 * (on pose level). */
1470 }
1472 /* These constraints require path geometry data. */
1473 ComponentKey target_key(&ct->tar->id, NodeType::GEOMETRY);
1474 add_relation(target_key, constraint_op_key, cti->name);
1475 ComponentKey target_transform_key(&ct->tar->id, NodeType::TRANSFORM);
1476 add_relation(target_transform_key, constraint_op_key, cti->name);
1477 }
1478 else if ((ct->tar->type == OB_ARMATURE) && (ct->subtarget[0])) {
1479 OperationCode opcode;
1480 /* relation to bone */
1481 opcode = bone_target_opcode(
1482 &ct->tar->id, ct->subtarget, id, component_subdata, root_map);
1483 /* Armature constraint always wants the final position and chan_mat. */
1484 if (ELEM(con->type, CONSTRAINT_TYPE_ARMATURE)) {
1485 opcode = OperationCode::BONE_DONE;
1486 }
1487 /* if needs bbone shape, reference the segment computation */
1488 if (BKE_constraint_target_uses_bbone(con, ct) &&
1489 check_pchan_has_bbone_segments(ct->tar, ct->subtarget))
1490 {
1492 }
1493 OperationKey target_key(&ct->tar->id, NodeType::BONE, ct->subtarget, opcode);
1494 add_relation(target_key, constraint_op_key, cti->name);
1495 }
1496 else if (ELEM(ct->tar->type, OB_MESH, OB_LATTICE) && (ct->subtarget[0])) {
1497 /* Vertex group. */
1498 /* NOTE: Vertex group is likely to be used to get vertices
1499 * in a world space. This requires to know both geometry
1500 * and transformation of the target object. */
1501 ComponentKey target_transform_key(&ct->tar->id, NodeType::TRANSFORM);
1502 ComponentKey target_geometry_key(&ct->tar->id, NodeType::GEOMETRY);
1503 add_relation(target_transform_key, constraint_op_key, cti->name);
1504 add_relation(target_geometry_key, constraint_op_key, cti->name);
1506 }
1507 else if (con->type == CONSTRAINT_TYPE_SHRINKWRAP) {
1508 bShrinkwrapConstraint *scon = (bShrinkwrapConstraint *)con->data;
1509
1510 /* Constraints which requires the target object surface. */
1511 ComponentKey target_key(&ct->tar->id, NodeType::GEOMETRY);
1512 add_relation(target_key, constraint_op_key, cti->name);
1513
1514 /* Add dependency on normal layers if necessary. */
1515 if (ct->tar->type == OB_MESH && scon->shrinkType != MOD_SHRINKWRAP_NEAREST_VERTEX) {
1516 bool track = (scon->flag & CON_SHRINKWRAP_TRACK_NORMAL) != 0;
1517 if (track || BKE_shrinkwrap_needs_normals(scon->shrinkType, scon->shrinkMode)) {
1518 add_customdata_mask(ct->tar,
1520 }
1523 }
1524 }
1525
1526 /* NOTE: obdata eval now doesn't necessarily depend on the
1527 * object's transform. */
1528 ComponentKey target_transform_key(&ct->tar->id, NodeType::TRANSFORM);
1529 add_relation(target_transform_key, constraint_op_key, cti->name);
1530 }
1531 else {
1532 /* Standard object relation. */
1533 /* TODO: loc vs rot vs scale? */
1534 if (&ct->tar->id == id) {
1535 /* Constraint targeting its own object:
1536 * - This case is fine IF we're dealing with a bone
1537 * constraint pointing to its own armature. In that
1538 * case, it's just transform -> bone.
1539 * - If however it is a real self targeting case, just
1540 * make it depend on the previous constraint (or the
1541 * pre-constraint state). */
1542 if ((ct->tar->type == OB_ARMATURE) && (component_type == NodeType::BONE)) {
1543 OperationKey target_key(
1545 add_relation(target_key, constraint_op_key, cti->name);
1546 }
1547 else {
1548 OperationKey target_key(
1550 add_relation(target_key, constraint_op_key, cti->name);
1551 }
1552 }
1553 else {
1554 /* Normal object dependency. */
1555 OperationKey target_key(
1557 add_relation(target_key, constraint_op_key, cti->name);
1558 }
1559 }
1560 /* Constraints which needs world's matrix for transform.
1561 * TODO(sergey): More constraints here? */
1562 if (ELEM(con->type,
1567 {
1568 /* TODO(sergey): Add used space check. */
1569 ComponentKey target_transform_key(&ct->tar->id, NodeType::TRANSFORM);
1570 add_relation(target_transform_key, constraint_op_key, cti->name);
1571 }
1572 }
1573 BKE_constraint_targets_flush(con, &targets, true);
1574 }
1575 }
1576}
1577
1579{
1580 /* Images. */
1582 /* Animation curves, NLA, and Animation datablock. */
1584 /* Drivers. */
1586
1587 if (check_id_has_anim_component(id)) {
1588 ComponentKey animation_key(id, NodeType::ANIMATION);
1589 ComponentKey parameters_key(id, NodeType::PARAMETERS);
1590 add_relation(animation_key, parameters_key, "Animation -> Parameters");
1592 }
1593}
1594
1596{
1597 AnimData *adt = BKE_animdata_from_id(id);
1598 if (adt == nullptr) {
1599 return;
1600 }
1601 if (adt->action != nullptr) {
1602 build_action(adt->action);
1603 }
1604 if (adt->action == nullptr && BLI_listbase_is_empty(&adt->nla_tracks)) {
1605 return;
1606 }
1607 /* Ensure evaluation order from entry to exit. */
1611 add_relation(animation_entry_key, animation_eval_key, "Init -> Eval");
1612 add_relation(animation_eval_key, animation_exit_key, "Eval -> Exit");
1613 /* Wire up dependency from Actions. */
1614 ComponentKey adt_key(id, NodeType::ANIMATION);
1615 /* Relation from action itself. */
1616 if (adt->action != nullptr) {
1617 ComponentKey action_key(&adt->action->id, NodeType::ANIMATION);
1618 add_relation(action_key, adt_key, "Action -> Animation");
1619 }
1620 /* Get source operations. */
1621 Node *node_from = get_node(adt_key);
1622 BLI_assert(node_from != nullptr);
1623 if (node_from == nullptr) {
1624 return;
1625 }
1626 OperationNode *operation_from = node_from->get_exit_operation();
1627 BLI_assert(operation_from != nullptr);
1628 /* Build relations from animation operation to properties it changes. */
1629 if (adt->action != nullptr) {
1630 build_animdata_action_targets(id, adt->slot_handle, adt_key, operation_from, adt->action);
1631 }
1632 LISTBASE_FOREACH (NlaTrack *, nlt, &adt->nla_tracks) {
1633 build_animdata_nlastrip_targets(id, adt_key, operation_from, &nlt->strips);
1634 }
1635}
1636
1638 ID *id, PointerRNA id_ptr, ComponentKey &adt_key, OperationNode *operation_from, FCurve *fcu)
1639{
1641 PropertyRNA *prop;
1642 int index;
1643 if (!RNA_path_resolve_full(&id_ptr, fcu->rna_path, &ptr, &prop, &index)) {
1644 return;
1645 }
1646 Node *node_to = rna_node_query_.find_node(&ptr, prop, RNAPointerSource::ENTRY);
1647 if (node_to == nullptr) {
1648 return;
1649 }
1650 OperationNode *operation_to = node_to->get_entry_operation();
1651 /* NOTE: Special case for bones, avoid relation from animation to
1652 * each of the bones. Bone evaluation could only start from pose
1653 * init anyway. */
1654 if (operation_to->opcode == OperationCode::BONE_LOCAL) {
1656 add_relation(adt_key, pose_init_key, "Animation -> Prop", RELATION_CHECK_BEFORE_ADD);
1657 return;
1658 }
1660 operation_from, operation_to, "Animation -> Prop", RELATION_CHECK_BEFORE_ADD);
1661 /* It is possible that animation is writing to a nested ID data-block,
1662 * need to make sure animation is evaluated after target ID is copied. */
1663 const IDNode *id_node_from = operation_from->owner->owner;
1664 const IDNode *id_node_to = operation_to->owner->owner;
1665 if (id_node_from != id_node_to) {
1666 ComponentKey cow_key(id_node_to->id_orig, NodeType::COPY_ON_EVAL);
1667 add_relation(cow_key,
1668 adt_key,
1669 "Animated Copy-on-Eval -> Animation",
1671 }
1672}
1673
1675 ComponentKey &adt_key,
1676 OperationNode *operation_from,
1677 ListBase *curves)
1678{
1679 /* Iterate over all curves and build relations. */
1680 PointerRNA id_ptr = RNA_id_pointer_create(id);
1681 LISTBASE_FOREACH (FCurve *, fcu, curves) {
1682 build_animdata_fcurve_target(id, id_ptr, adt_key, operation_from, fcu);
1683 }
1684}
1685
1687 const int32_t slot_handle,
1688 ComponentKey &adt_key,
1689 OperationNode *operation_from,
1690 bAction *dna_action)
1691{
1692 BLI_assert(id != nullptr);
1693 BLI_assert(operation_from != nullptr);
1694 BLI_assert(dna_action != nullptr);
1695 animrig::Action &action = dna_action->wrap();
1696
1697 if (action.is_empty()) {
1698 return;
1699 }
1700 if (action.is_action_legacy()) {
1701 build_animdata_curves_targets(id, adt_key, operation_from, &action.curves);
1702 return;
1703 }
1704
1705#ifdef WITH_ANIM_BAKLAVA
1706 const animrig::Slot *slot = action.slot_for_handle(slot_handle);
1707 if (slot == nullptr) {
1708 /* If there's no matching slot, there's no Action dependency. */
1709 return;
1710 }
1711
1712 PointerRNA id_ptr = RNA_id_pointer_create(id);
1713
1714 for (animrig::Layer *layer : action.layers()) {
1715 for (animrig::Strip *strip : layer->strips()) {
1716 switch (strip->type()) {
1717 case animrig::Strip::Type::Keyframe: {
1718 animrig::StripKeyframeData &strip_data = strip->data<animrig::StripKeyframeData>(action);
1719 animrig::ChannelBag *channels = strip_data.channelbag_for_slot(*slot);
1720 if (channels == nullptr) {
1721 /* Go to next strip. */
1722 break;
1723 }
1724 for (FCurve *fcu : channels->fcurves()) {
1725 build_animdata_fcurve_target(id, id_ptr, adt_key, operation_from, fcu);
1726 }
1727 break;
1728 }
1729 }
1730 }
1731 }
1732#else
1733 UNUSED_VARS(slot_handle);
1734#endif
1735}
1736
1738 ComponentKey &adt_key,
1739 OperationNode *operation_from,
1740 ListBase *strips)
1741{
1742 LISTBASE_FOREACH (NlaStrip *, strip, strips) {
1743 if (strip->act != nullptr) {
1744 build_action(strip->act);
1745
1746 ComponentKey action_key(&strip->act->id, NodeType::ANIMATION);
1747 add_relation(action_key, adt_key, "Action -> Animation");
1748
1750 id, strip->action_slot_handle, adt_key, operation_from, strip->act);
1751 }
1752 else if (strip->strips.first != nullptr) {
1753 build_animdata_nlastrip_targets(id, adt_key, operation_from, &strip->strips);
1754 }
1755 }
1756}
1757
1759{
1760 AnimData *adt = BKE_animdata_from_id(id);
1761 if (adt == nullptr) {
1762 return;
1763 }
1764 ComponentKey adt_key(id, NodeType::ANIMATION);
1765 LISTBASE_FOREACH (FCurve *, fcu, &adt->drivers) {
1766 OperationKey driver_key(id,
1769 fcu->rna_path ? fcu->rna_path : "",
1770 fcu->array_index);
1771
1772 /* create the driver's relations to targets */
1773 build_driver(id, fcu);
1774
1775 /* prevent driver from occurring before its own animation... */
1776 if (adt->action || adt->nla_tracks.first) {
1777 add_relation(adt_key, driver_key, "AnimData Before Drivers");
1778 }
1779 }
1780}
1781
1783{
1784 /* See #DepsgraphNodeBuilder::build_animation_images. */
1785 bool has_image_animation = false;
1786 if (ELEM(GS(id->name), ID_MA, ID_WO)) {
1788 if (ntree != nullptr && ntree->runtime->runtime_flag & NTREE_RUNTIME_FLAG_HAS_IMAGE_ANIMATION)
1789 {
1790 has_image_animation = true;
1791 }
1792 }
1793
1794 if (has_image_animation || BKE_image_user_id_has_animation(id)) {
1795 OperationKey image_animation_key(
1797 TimeSourceKey time_src_key;
1798 add_relation(time_src_key, image_animation_key, "TimeSrc -> Image Animation");
1799
1800 /* The image users of these ids may change during evaluation. Make sure that the image
1801 * animation update happens after evaluation. */
1802 if (GS(id->name) == ID_MA) {
1804 add_relation(material_update_key, image_animation_key, "Material Update -> Image Animation");
1805 }
1806 else if (GS(id->name) == ID_WO) {
1808 add_relation(world_update_key, image_animation_key, "World Update -> Image Animation");
1809 }
1810 else if (GS(id->name) == ID_NT) {
1812 add_relation(ntree_output_key, image_animation_key, "NTree Output -> Image Animation");
1813 }
1814 }
1815}
1816
1818{
1819 if (GS(id->name) != ID_OB) {
1820 return;
1821 }
1822
1823 const Object *object = (Object *)id;
1824 if (object->pd == nullptr || object->pd->forcefield == PFIELD_NULL) {
1825 return;
1826 }
1827
1828 /* Updates to animation data (in the UI, for example by altering FCurve Modifier parameters
1829 * animating force field strength) may need to rebuild the rigid body world. */
1830 ComponentKey animation_key(id, NodeType::ANIMATION);
1832 add_relation(animation_key, rigidbody_key, "Animation -> Rigid Body");
1833}
1834
1836{
1837 if (built_map_.checkIsBuiltAndTag(dna_action)) {
1838 return;
1839 }
1840
1841 const BuilderStack::ScopedEntry stack_entry = stack_.trace(dna_action->id);
1842
1843 build_idproperties(dna_action->id.properties);
1844
1845 blender::animrig::Action &action = dna_action->wrap();
1846#ifndef WITH_ANIM_BAKLAVA
1847 /* Prevent evaluation of data introduced by Project Baklava. */
1848 if (action.is_action_layered()) {
1849 return;
1850 }
1851#endif
1852
1853 if (!action.is_empty()) {
1854 TimeSourceKey time_src_key;
1855 ComponentKey animation_key(&dna_action->id, NodeType::ANIMATION);
1856 add_relation(time_src_key, animation_key, "TimeSrc -> Animation");
1857 }
1858}
1859
1861{
1862 ChannelDriver *driver = fcu->driver;
1863 OperationKey driver_key(id,
1866 fcu->rna_path ? fcu->rna_path : "",
1867 fcu->array_index);
1868 /* Driver -> data components (for interleaved evaluation
1869 * bones/constraints/modifiers). */
1870 build_driver_data(id, fcu);
1871 /* Loop over variables to get the target relationships. */
1872 build_driver_variables(id, fcu);
1873 /* It's quite tricky to detect if the driver actually depends on time or
1874 * not, so for now we'll be quite conservative here about optimization and
1875 * consider all python drivers to be depending on time. */
1876 if (driver_depends_on_time(driver)) {
1877 TimeSourceKey time_src_key;
1878 add_relation(time_src_key, driver_key, "TimeSrc -> Driver");
1879 }
1880}
1881
1883{
1884 /* Validate the RNA path pointer just in case. */
1885 const char *rna_path = fcu->rna_path;
1886 if (rna_path == nullptr || rna_path[0] == '\0') {
1887 return;
1888 }
1889 /* Parse the RNA path to find the target property pointer. */
1890 RNAPathKey property_entry_key(id, rna_path, RNAPointerSource::ENTRY);
1891 if (RNA_pointer_is_null(&property_entry_key.ptr)) {
1892 /* TODO(sergey): This would only mean that driver is broken.
1893 * so we can't create relation anyway. However, we need to avoid
1894 * adding drivers which are known to be buggy to a dependency
1895 * graph, in order to save computational power. */
1896 return;
1897 }
1898 OperationKey driver_key(
1900 /* If the target of the driver is a Bone property, find the Armature data,
1901 * and then link the driver to all pose bone evaluation components that use
1902 * it. This is necessary to provide more granular dependencies specifically for
1903 * Bone objects, because the armature data doesn't have per-bone components,
1904 * and generic add_relation can only add one link. */
1905 ID *id_ptr = property_entry_key.ptr.owner_id;
1906 bool is_bone = id_ptr && property_entry_key.ptr.type == &RNA_Bone;
1907 /* If the Bone property is referenced via obj.pose.bones[].bone,
1908 * the RNA pointer refers to the Object ID, so skip to data. */
1909 if (is_bone && GS(id_ptr->name) == ID_OB) {
1910 id_ptr = (ID *)((Object *)id_ptr)->data;
1911 }
1912 if (is_bone && GS(id_ptr->name) == ID_AR) {
1913 /* Drivers on armature-level bone settings (i.e. bbone stuff),
1914 * which will affect the evaluation of corresponding pose bones. */
1915 Bone *bone = (Bone *)property_entry_key.ptr.data;
1916 if (bone == nullptr) {
1917 fprintf(stderr, "Couldn't find armature bone name for driver path - '%s'\n", rna_path);
1918 return;
1919 }
1920
1921 const char *prop_identifier = RNA_property_identifier(property_entry_key.prop);
1922 const bool driver_targets_bbone = STRPREFIX(prop_identifier, "bbone_");
1923
1924 /* Find objects which use this, and make their eval callbacks depend on this. */
1925 for (IDNode *to_node : graph_->id_nodes) {
1926 if (GS(to_node->id_orig->name) != ID_OB) {
1927 continue;
1928 }
1929
1930 /* We only care about objects with pose data which use this. */
1931 Object *object = (Object *)to_node->id_orig;
1932 if (object->data != id_ptr || object->pose == nullptr) {
1933 continue;
1934 }
1935
1936 bPoseChannel *pchan = BKE_pose_channel_find_name(object->pose, bone->name);
1937 if (pchan == nullptr) {
1938 continue;
1939 }
1940
1942 if (driver_targets_bbone) {
1945 }
1946 OperationKey bone_key(&object->id, NodeType::BONE, pchan->name, target_op);
1947 add_relation(driver_key, bone_key, "Arm Bone -> Driver -> Bone");
1948 }
1949 /* Make the driver depend on copy-on-eval, similar to the generic case below. */
1950 if (id_ptr != id) {
1951 ComponentKey cow_key(id_ptr, NodeType::COPY_ON_EVAL);
1953 cow_key, driver_key, "Driven Copy-on-Eval -> Driver", RELATION_CHECK_BEFORE_ADD);
1954 }
1955 }
1956 else {
1957 /* If it's not a Bone, handle the generic single dependency case. */
1958 Node *node_to = get_node(property_entry_key);
1959 if (node_to != nullptr) {
1960 add_relation(driver_key, property_entry_key, "Driver -> Driven Property");
1961 }
1962
1963 /* Similar to the case with f-curves, driver might drive a nested
1964 * data-block, which means driver execution should wait for that
1965 * data-block to be copied. */
1966 {
1967 PointerRNA id_ptr = RNA_id_pointer_create(id);
1969 if (RNA_path_resolve_full(&id_ptr, fcu->rna_path, &ptr, nullptr, nullptr)) {
1970 if (id_ptr.owner_id != ptr.owner_id) {
1973 cow_key, driver_key, "Driven Copy-on-Eval -> Driver", RELATION_CHECK_BEFORE_ADD);
1974 }
1975 }
1976 }
1977 if (rna_prop_affects_parameters_node(&property_entry_key.ptr, property_entry_key.prop)) {
1978 RNAPathKey property_exit_key(property_entry_key.id,
1979 property_entry_key.ptr,
1980 property_entry_key.prop,
1983 add_relation(property_exit_key, parameters_key, "Driven Property -> Properties");
1984 }
1985 }
1986
1987 /* Assume drivers on a node tree affect the evaluated output of the node tree. In theory we could
1988 * check if the driven value actually affects the output, i.e. if it drives a node that is linked
1989 * to the output. */
1990 if (GS(id_ptr->name) == ID_NT) {
1991 ComponentKey ntree_output_key(id_ptr, NodeType::NTREE_OUTPUT);
1992 add_relation(driver_key, ntree_output_key, "Drivers -> NTree Output");
1993 if (reinterpret_cast<bNodeTree *>(id_ptr)->type == NTREE_GEOMETRY) {
1994 OperationKey ntree_geo_preprocess_key(
1996 add_relation(driver_key, ntree_geo_preprocess_key, "Drivers -> NTree Geo Preprocess");
1997 }
1998 }
1999}
2000
2002{
2003 ChannelDriver *driver = fcu->driver;
2004 OperationKey driver_key(id,
2007 fcu->rna_path ? fcu->rna_path : "",
2008 fcu->array_index);
2009 const char *rna_path = fcu->rna_path ? fcu->rna_path : "";
2010
2011 const RNAPathKey self_key(id, rna_path, RNAPointerSource::ENTRY);
2012
2013 DriverTargetContext driver_target_context;
2014 driver_target_context.scene = graph_->scene;
2015 driver_target_context.view_layer = graph_->view_layer;
2016
2017 LISTBASE_FOREACH (DriverVar *, dvar, &driver->variables) {
2018 /* Only used targets. */
2020 PointerRNA target_prop;
2021 if (!driver_get_target_property(&driver_target_context, dvar, dtar, &target_prop)) {
2022 continue;
2023 }
2024
2025 /* Property is always expected to be resolved to a non-null RNA property, which is always
2026 * relative to some ID. */
2027 BLI_assert(target_prop.owner_id);
2028
2029 ID *target_id = target_prop.owner_id;
2030
2031 build_id(target_id);
2032 build_driver_id_property(target_prop, dtar->rna_path);
2033
2034 Object *object = nullptr;
2035 if (GS(target_id->name) == ID_OB) {
2036 object = (Object *)target_id;
2037 }
2038 /* Special handling for directly-named bones. */
2039 if ((dtar->flag & DTAR_FLAG_STRUCT_REF) && (object && object->type == OB_ARMATURE) &&
2040 (dtar->pchan_name[0]))
2041 {
2042 bPoseChannel *target_pchan = BKE_pose_channel_find_name(object->pose, dtar->pchan_name);
2043 if (target_pchan == nullptr) {
2044 continue;
2045 }
2046 OperationKey variable_key(
2047 target_id, NodeType::BONE, target_pchan->name, OperationCode::BONE_DONE);
2048 if (is_same_bone_dependency(variable_key, self_key)) {
2049 continue;
2050 }
2051 add_relation(variable_key, driver_key, "Bone Target -> Driver");
2052 }
2053 else if (dtar->flag & DTAR_FLAG_STRUCT_REF) {
2054 /* Get node associated with the object's transforms. */
2055 if (target_id == id) {
2056 /* Ignore input dependency if we're driving properties of
2057 * the same ID, otherwise we'll be ending up in a cyclic
2058 * dependency here. */
2059 continue;
2060 }
2062 add_relation(target_key, driver_key, "Target -> Driver");
2063 }
2064 else if (dtar->rna_path != nullptr && dtar->rna_path[0] != '\0') {
2066 driver_key, self_key, target_id, target_prop, dtar->rna_path);
2067
2068 /* Add relations to all other cameras used by the scene timeline if applicable. */
2069 if (const char *camera_path = get_rna_path_relative_to_scene_camera(
2070 scene_, target_prop, dtar->rna_path))
2071 {
2072 build_driver_scene_camera_variable(driver_key, self_key, scene_, camera_path);
2073 }
2074
2075 /* The RNA getter for `object.data` can write to the mesh datablock due
2076 * to the call to `BKE_mesh_wrapper_ensure_subdivision()`. This relation
2077 * ensures it is safe to call when the driver is evaluated.
2078 *
2079 * For the sake of making the code more generic/defensive, the relation
2080 * is added for any geometry type.
2081 *
2082 * See #96289 for more info. */
2083 if (object != nullptr && OB_TYPE_IS_GEOMETRY(object->type)) {
2084 StringRef rna_path(dtar->rna_path);
2085 if (rna_path == "data" || rna_path.startswith("data.")) {
2086 ComponentKey ob_key(target_id, NodeType::GEOMETRY);
2087 add_relation(ob_key, driver_key, "ID -> Driver");
2088 }
2089 }
2090 }
2091 else {
2092 /* If rna_path is nullptr, and DTAR_FLAG_STRUCT_REF isn't set, this
2093 * is an incomplete target reference, so nothing to do here. */
2094 }
2095 }
2097 }
2098}
2099
2101 const RNAPathKey &self_key,
2102 Scene *scene,
2103 const char *rna_path)
2104{
2105 /* First, add relations to all cameras used in the timeline,
2106 * excluding scene->camera which was already handled by the caller. */
2107 bool animated = false;
2108
2109 LISTBASE_FOREACH (TimeMarker *, marker, &scene->markers) {
2110 if (!ELEM(marker->camera, nullptr, scene->camera)) {
2111 PointerRNA camera_ptr = RNA_id_pointer_create(&marker->camera->id);
2112 build_driver_id_property(camera_ptr, rna_path);
2113 build_driver_rna_path_variable(driver_key, self_key, &scene->id, camera_ptr, rna_path);
2114 animated = true;
2115 }
2116 }
2117
2118 /* If timeline indeed switches the camera, this variable also implicitly depends on time. */
2119 if (animated) {
2120 TimeSourceKey time_src_key;
2121 add_relation(time_src_key, driver_key, "TimeSrc -> Driver Camera Ref");
2122 }
2123}
2124
2126 const RNAPathKey &self_key,
2127 ID *target_id,
2128 const PointerRNA &target_prop,
2129 const char *rna_path)
2130{
2131 RNAPathKey variable_exit_key(target_prop, rna_path, RNAPointerSource::EXIT);
2132 if (RNA_pointer_is_null(&variable_exit_key.ptr)) {
2133 return;
2134 }
2135 if (is_same_bone_dependency(variable_exit_key, self_key) ||
2136 is_same_nodetree_node_dependency(variable_exit_key, self_key))
2137 {
2138 return;
2139 }
2140 add_relation(variable_exit_key, driver_key, "RNA Target -> Driver");
2141
2142 /* It is possible that RNA path points to a property of a different ID than the target_id:
2143 * for example, paths like "data" on Object, "camera" on Scene.
2144 *
2145 * For the demonstration purposes lets consider a driver variable uses Scene ID as target
2146 * and "camera.location.x" as its RNA path. If the scene has 2 different cameras at
2147 * 2 different locations changing the active scene camera is expected to immediately be
2148 * reflected in the variable value. In order to achieve this behavior we create a relation
2149 * from the target ID to the driver so that if the ID property of the target ID changes the
2150 * driver is re-evaluated.
2151 *
2152 * The most straightforward (at the moment of writing this comment) way of figuring out
2153 * such relation is to use copy-on-evaluation operation of the target ID. There are two down
2154 * sides of this approach which are considered a design limitation as there is a belief
2155 * that they are not common in practice or are not reliable due to other issues:
2156 *
2157 * - IDs which are not covered with the copy-on-evaluation mechanism.
2158 *
2159 * Such IDs are either do not have ID properties, or are not part of the dependency
2160 * graph.
2161 *
2162 * - Modifications of evaluated IDs from a Python handler.
2163 * Such modifications are not fully integrated in the dependency graph evaluation as it
2164 * has issues with copy-on-evaluation tagging and the fact that relations are defined by the
2165 * original main database status.
2166 *
2167 * The original report for this is #98618.
2168 *
2169 * The not-so-obvious part is that we don't do such relation for the context properties.
2170 * They are resolved at the graph build time and do not change at runtime (#107081).
2171 * Thus scene has to be excluded as a special case; this is OK because changes to
2172 * scene.camera not caused by animation should actually force a dependency graph rebuild.
2173 */
2174 if (target_id != variable_exit_key.ptr.owner_id && GS(target_id->name) != ID_SCE) {
2175 if (deg_eval_copy_is_needed(GS(target_id->name))) {
2176 ComponentKey target_id_key(target_id, NodeType::COPY_ON_EVAL);
2177 add_relation(target_id_key, driver_key, "Target ID -> Driver");
2178 }
2179 }
2180}
2181
2183 const char *rna_path_from_target_prop)
2184{
2185 if (rna_path_from_target_prop == nullptr || rna_path_from_target_prop[0] == '\0') {
2186 return;
2187 }
2188
2190 PropertyRNA *prop;
2191 int index;
2192 if (!RNA_path_resolve_full(&target_prop, rna_path_from_target_prop, &ptr, &prop, &index)) {
2193 return;
2194 }
2195 if (prop == nullptr) {
2196 return;
2197 }
2199 return;
2200 }
2201 if (ptr.owner_id) {
2203 }
2204 const char *prop_identifier = RNA_property_identifier((PropertyRNA *)prop);
2205 /* Custom properties of bones are placed in their components to improve granularity. */
2206 OperationKey id_property_key;
2207 if (RNA_struct_is_a(ptr.type, &RNA_PoseBone)) {
2208 const bPoseChannel *pchan = static_cast<const bPoseChannel *>(ptr.data);
2209 id_property_key = OperationKey(
2210 ptr.owner_id, NodeType::BONE, pchan->name, OperationCode::ID_PROPERTY, prop_identifier);
2211 /* Create relation from the parameters component so that tagging armature for parameters update
2212 * properly propagates updates to all properties on bones and deeper (if needed). */
2213 OperationKey parameters_init_key(
2216 parameters_init_key, id_property_key, "Init -> ID Property", RELATION_CHECK_BEFORE_ADD);
2217 }
2218 else {
2219 id_property_key = OperationKey(
2221 }
2222 OperationKey parameters_exit_key(
2225 id_property_key, parameters_exit_key, "ID Property -> Done", RELATION_CHECK_BEFORE_ADD);
2226}
2227
2229{
2233 add_relation(parameters_entry_key, parameters_eval_key, "Entry -> Eval");
2234 add_relation(parameters_eval_key, parameters_exit_key, "Entry -> Exit");
2235}
2236
2238{
2239 OperationKey dimensions_key(&object->id, NodeType::PARAMETERS, OperationCode::DIMENSIONS);
2240 ComponentKey geometry_key(&object->id, NodeType::GEOMETRY);
2241 ComponentKey transform_key(&object->id, NodeType::TRANSFORM);
2242 add_relation(geometry_key, dimensions_key, "Geometry -> Dimensions");
2243 add_relation(transform_key, dimensions_key, "Transform -> Dimensions");
2244}
2245
2247{
2248 if (built_map_.checkIsBuiltAndTag(world)) {
2249 return;
2250 }
2251
2252 const BuilderStack::ScopedEntry stack_entry = stack_.trace(world->id);
2253
2254 build_idproperties(world->id.properties);
2255 /* animation */
2256 build_animdata(&world->id);
2257 build_parameters(&world->id);
2258
2259 /* Animated / driven parameters (without nodetree). */
2261 ComponentKey parameters_key(&world->id, NodeType::PARAMETERS);
2262 add_relation(parameters_key, world_key, "World's parameters");
2263
2264 /* world's nodetree */
2265 if (world->nodetree != nullptr) {
2266 build_nodetree(world->nodetree);
2267 OperationKey ntree_key(
2269 add_relation(ntree_key, world_key, "World's NTree");
2270 build_nested_nodetree(&world->id, world->nodetree);
2271 }
2272}
2273
2275{
2276 RigidBodyWorld *rbw = scene->rigidbody_world;
2279 /* Simulation depends on time. */
2280 TimeSourceKey time_src_key;
2281 add_relation(time_src_key, rb_init_key, "TimeSrc -> Rigidbody Init");
2282 /* Simulation should always be run after initialization. */
2283 /* NOTE: It is possible in theory to have dependency cycle which involves
2284 * this relation. We never want it to be killed. */
2285 add_relation(rb_init_key, rb_simulate_key, "Rigidbody [Init -> SimStep]", RELATION_FLAG_GODMODE);
2286 /* Effectors should be evaluated at the time simulation is being
2287 * initialized.
2288 * TODO(sergey): Verify that it indeed goes to initialization and not to a
2289 * simulation. */
2290 ListBase *effector_relations = build_effector_relations(graph_, rbw->effector_weights->group);
2291 LISTBASE_FOREACH (EffectorRelation *, effector_relation, effector_relations) {
2292 ComponentKey effector_transform_key(&effector_relation->ob->id, NodeType::TRANSFORM);
2293 add_relation(effector_transform_key, rb_init_key, "RigidBody Field");
2294 if (effector_relation->pd != nullptr) {
2295 const short shape = effector_relation->pd->shape;
2297 ComponentKey effector_geometry_key(&effector_relation->ob->id, NodeType::GEOMETRY);
2298 add_relation(effector_geometry_key, rb_init_key, "RigidBody Field");
2299 }
2300 if ((effector_relation->pd->forcefield == PFIELD_TEXTURE) &&
2301 (effector_relation->pd->tex != nullptr))
2302 {
2303 ComponentKey tex_key(&effector_relation->pd->tex->id, NodeType::GENERIC_DATABLOCK);
2304 add_relation(tex_key, rb_init_key, "Force field Texture");
2305 }
2306 }
2307 }
2308 /* Objects. */
2309 if (rbw->group != nullptr) {
2310 build_collection(nullptr, rbw->group);
2312 if (object->type != OB_MESH) {
2313 continue;
2314 }
2315 if (object->rigidbody_object == nullptr) {
2316 continue;
2317 }
2318
2319 if (object->parent != nullptr && object->parent->rigidbody_object != nullptr &&
2320 object->parent->rigidbody_object->shape == RB_SHAPE_COMPOUND)
2321 {
2322 /* If we are a child of a compound shape object, the transforms and sim evaluation will be
2323 * handled by the parent compound shape object. Do not add any evaluation triggers
2324 * for the child objects.
2325 */
2326 continue;
2327 }
2328
2329 /* Simulation uses object transformation after parenting and solving constraints. */
2330 OperationKey object_transform_simulation_init_key(
2332 OperationKey object_transform_eval_key(
2334 add_relation(object_transform_simulation_init_key,
2335 rb_simulate_key,
2336 "Object Transform -> Rigidbody Sim Eval");
2337 /* Geometry must be known to create the rigid body. RBO_MESH_BASE
2338 * uses the non-evaluated mesh, so then the evaluation is
2339 * unnecessary. */
2340 if (rigidbody_object_depends_on_evaluated_geometry(object->rigidbody_object)) {
2341 /* NOTE: We prefer this relation to be never killed, to avoid
2342 * access partially evaluated mesh from solver. */
2343 ComponentKey object_geometry_key(&object->id, NodeType::GEOMETRY);
2344 add_relation(object_geometry_key,
2345 rb_simulate_key,
2346 "Object Geom Eval -> Rigidbody Sim Eval",
2348 }
2349
2350 /* Final transform is whatever the solver gave to us. */
2351 if (object->rigidbody_object->type == RBO_TYPE_ACTIVE) {
2352 /* We do not have to update the objects final transform after the simulation if it is
2353 * passive or controlled by the animation system in blender.
2354 * (Bullet doesn't move the object at all in these cases).
2355 * But we can't update the depsgraph when the animated property in changed during playback.
2356 * So always assume that active bodies needs updating. */
2357 OperationKey rb_transform_copy_key(
2359 /* Rigid body synchronization depends on the actual simulation. */
2360 add_relation(rb_simulate_key, rb_transform_copy_key, "Rigidbody Sim Eval -> RBO Sync");
2361
2362 OperationKey object_transform_final_key(
2364 add_relation(rb_transform_copy_key,
2365 object_transform_final_key,
2366 "Rigidbody Sync -> Transform Final");
2367 }
2368
2369 /* Relations between colliders and force fields, needed for force field absorption. */
2371 }
2373 }
2374}
2375
2377{
2378 OperationKey obdata_ubereval_key(&object->id, NodeType::GEOMETRY, OperationCode::GEOMETRY_EVAL);
2379 OperationKey eval_init_key(
2381 OperationKey eval_done_key(
2383 ComponentKey eval_key(&object->id, NodeType::PARTICLE_SYSTEM);
2384 if (BKE_ptcache_object_has(scene_, object, 0)) {
2385 ComponentKey point_cache_key(&object->id, NodeType::POINT_CACHE);
2387 eval_key, point_cache_key, "Particle Point Cache", RELATION_FLAG_FLUSH_USER_EDIT_ONLY);
2388 }
2389 /* Particle systems. */
2390 LISTBASE_FOREACH (ParticleSystem *, psys, &object->particlesystem) {
2391 ParticleSettings *part = psys->part;
2392 /* Build particle settings relations.
2393 * NOTE: The call itself ensures settings are only build once. */
2395 /* This particle system. */
2396 OperationKey psys_key(
2398 /* Update particle system when settings changes. */
2399 OperationKey particle_settings_key(
2401 add_relation(particle_settings_key, eval_init_key, "Particle Settings Change");
2402 add_relation(eval_init_key, psys_key, "Init -> PSys");
2403 add_relation(psys_key, eval_done_key, "PSys -> Done");
2404 /* TODO(sergey): Currently particle update is just a placeholder,
2405 * hook it to the ubereval node so particle system is getting updated
2406 * on playback. */
2407 add_relation(psys_key, obdata_ubereval_key, "PSys -> UberEval");
2408 /* Collisions. */
2409 if (part->type != PART_HAIR) {
2411 psys_key, object, part->collision_group, "Particle Collision");
2412 }
2413 else if ((psys->flag & PSYS_HAIR_DYNAMICS) && psys->clmd != nullptr &&
2414 psys->clmd->coll_parms != nullptr)
2415 {
2417 psys_key, object, psys->clmd->coll_parms->group, "Hair Collision");
2418 }
2419 /* Effectors. */
2421 psys_key, object, psys, part->effector_weights, part->type == PART_HAIR, "Particle Field");
2422 /* Boids. */
2423 if (part->boids != nullptr) {
2424 LISTBASE_FOREACH (BoidState *, state, &part->boids->states) {
2425 LISTBASE_FOREACH (BoidRule *, rule, &state->rules) {
2426 Object *ruleob = nullptr;
2427 if (rule->type == eBoidRuleType_Avoid) {
2428 ruleob = ((BoidRuleGoalAvoid *)rule)->ob;
2429 }
2430 else if (rule->type == eBoidRuleType_FollowLeader) {
2431 ruleob = ((BoidRuleFollowLeader *)rule)->ob;
2432 }
2433 if (ruleob != nullptr) {
2434 ComponentKey ruleob_key(&ruleob->id, NodeType::TRANSFORM);
2435 add_relation(ruleob_key, psys_key, "Boid Rule");
2436 }
2437 }
2438 }
2439 }
2440 /* Keyed particle targets. */
2441 if (ELEM(part->phystype, PART_PHYS_KEYED, PART_PHYS_BOIDS)) {
2442 LISTBASE_FOREACH (ParticleTarget *, particle_target, &psys->targets) {
2443 if (ELEM(particle_target->ob, nullptr, object)) {
2444 continue;
2445 }
2446 /* Make sure target object is pulled into the graph. */
2447 build_object(particle_target->ob);
2448 /* Use geometry component, since that's where particles are
2449 * actually evaluated. */
2450 ComponentKey target_key(&particle_target->ob->id, NodeType::GEOMETRY);
2451 add_relation(target_key, psys_key, "Keyed Target");
2452 }
2453 }
2454 /* Visualization. */
2455 switch (part->ren_as) {
2456 case PART_DRAW_OB:
2457 if (part->instance_object != nullptr) {
2458 /* Make sure object's relations are all built. */
2459 build_object(part->instance_object);
2460 /* Build relation for the particle visualization. */
2461 build_particle_system_visualization_object(object, psys, part->instance_object);
2462 }
2463 break;
2464 case PART_DRAW_GR:
2465 if (part->instance_collection != nullptr) {
2466 build_collection(nullptr, part->instance_collection);
2467 LISTBASE_FOREACH (CollectionObject *, go, &part->instance_collection->gobject) {
2468 build_particle_system_visualization_object(object, psys, go->ob);
2469 }
2470 }
2471 break;
2472 }
2473 }
2474 /* Particle depends on the object transform, so that channel is to be ready
2475 * first. */
2476 add_depends_on_transform_relation(&object->id, obdata_ubereval_key, "Particle Eval");
2477}
2478
2480{
2481 if (built_map_.checkIsBuiltAndTag(part)) {
2482 return;
2483 }
2484
2485 const BuilderStack::ScopedEntry stack_entry = stack_.trace(part->id);
2486
2487 /* Animation data relations. */
2488 build_animdata(&part->id);
2489 build_parameters(&part->id);
2490 OperationKey particle_settings_init_key(
2492 OperationKey particle_settings_eval_key(
2494 OperationKey particle_settings_reset_key(
2497 particle_settings_init_key, particle_settings_eval_key, "Particle Settings Init Order");
2498 add_relation(particle_settings_reset_key, particle_settings_eval_key, "Particle Settings Reset");
2499 /* Texture slots. */
2500 for (MTex *mtex : part->mtex) {
2501 if (mtex == nullptr || mtex->tex == nullptr) {
2502 continue;
2503 }
2504 build_texture(mtex->tex);
2505 ComponentKey texture_key(&mtex->tex->id, NodeType::GENERIC_DATABLOCK);
2506 add_relation(texture_key,
2507 particle_settings_reset_key,
2508 "Particle Texture -> Particle Reset",
2510 add_relation(texture_key, particle_settings_eval_key, "Particle Texture -> Particle Eval");
2511 /* TODO(sergey): Consider moving texture space handling to its own
2512 * function. */
2513 if (mtex->texco == TEXCO_OBJECT && mtex->object != nullptr) {
2514 ComponentKey object_key(&mtex->object->id, NodeType::TRANSFORM);
2515 add_relation(object_key, particle_settings_eval_key, "Particle Texture Space");
2516 }
2517 }
2518 if (check_id_has_anim_component(&part->id)) {
2519 ComponentKey animation_key(&part->id, NodeType::ANIMATION);
2520 add_relation(animation_key, particle_settings_eval_key, "Particle Settings Animation");
2521 }
2522}
2523
2525 ParticleSystem *psys,
2526 Object *draw_object)
2527{
2528 OperationKey psys_key(
2530 OperationKey obdata_ubereval_key(&object->id, NodeType::GEOMETRY, OperationCode::GEOMETRY_EVAL);
2531 ComponentKey dup_ob_key(&draw_object->id, NodeType::TRANSFORM);
2532 add_relation(dup_ob_key, psys_key, "Particle Object Visualization");
2533 if (draw_object->type == OB_MBALL) {
2534 ComponentKey dup_geometry_key(&draw_object->id, NodeType::GEOMETRY);
2535 add_relation(obdata_ubereval_key, dup_geometry_key, "Particle MBall Visualization");
2536 }
2537}
2538
2539/* Shapekeys */
2541{
2542 if (built_map_.checkIsBuiltAndTag(key)) {
2543 return;
2544 }
2545
2546 const BuilderStack::ScopedEntry stack_entry = stack_.trace(key->id);
2547
2549 /* Attach animdata to geometry. */
2550 build_animdata(&key->id);
2551 build_parameters(&key->id);
2552 /* Connect all blocks properties to the final result evaluation. */
2553 ComponentKey geometry_key(&key->id, NodeType::GEOMETRY);
2555 LISTBASE_FOREACH (KeyBlock *, key_block, &key->block) {
2556 OperationKey key_block_key(
2558 add_relation(key_block_key, geometry_key, "Key Block Properties");
2559 add_relation(key_block_key, parameters_eval_key, "Key Block Properties");
2560 }
2561}
2562
2584{
2585 ID *obdata = (ID *)object->data;
2586 /* Init operation of object-level geometry evaluation. */
2588 /* Get nodes for result of obdata's evaluation, and geometry evaluation
2589 * on object. */
2590 ComponentKey obdata_geom_key(obdata, NodeType::GEOMETRY);
2591 ComponentKey geom_key(&object->id, NodeType::GEOMETRY);
2592 /* Link components to each other. */
2593 add_relation(obdata_geom_key, geom_key, "Object Geometry Base Data");
2594 OperationKey obdata_ubereval_key(&object->id, NodeType::GEOMETRY, OperationCode::GEOMETRY_EVAL);
2595 /* Special case: modifiers evaluation queries scene for various things like
2596 * data mask to be used. We add relation here to ensure object is never
2597 * evaluated prior to Scene's evaluated copy is ready. */
2598 ComponentKey scene_key(&scene_->id, NodeType::SCENE);
2599 add_relation(scene_key, obdata_ubereval_key, "Copy-on-Eval Relation", RELATION_FLAG_NO_FLUSH);
2600 /* Relation to the instance, so that instancer can use geometry of this object. */
2603 "Transform -> Instance Geometry");
2604 /* Shader FX. */
2605 if (object->shader_fx.first != nullptr) {
2607 ctx.scene = scene_;
2608 ctx.object = object;
2609 LISTBASE_FOREACH (ShaderFxData *, fx, &object->shader_fx) {
2610 const ShaderFxTypeInfo *fxi = BKE_shaderfx_get_info((ShaderFxType)fx->type);
2611 if (fxi->update_depsgraph) {
2612 DepsNodeHandle handle = create_node_handle(obdata_ubereval_key);
2613 ctx.node = reinterpret_cast<::DepsNodeHandle *>(&handle);
2614 fxi->update_depsgraph(fx, &ctx);
2615 }
2617 TimeSourceKey time_src_key;
2618 add_relation(time_src_key, obdata_ubereval_key, "Time Source");
2619 }
2620 }
2621 }
2622 /* Materials. */
2623 build_materials(&object->id, object->mat, object->totcol);
2624 /* Geometry collision. */
2625 if (ELEM(object->type, OB_MESH, OB_CURVES_LEGACY, OB_LATTICE)) {
2626 // add geometry collider relations
2627 }
2628 /* Make sure uber update is the last in the dependencies.
2629 * Only do it here unless there are modifiers. This avoids transitive relations. */
2630 if (BLI_listbase_is_empty(&object->modifiers)) {
2631 OperationKey obdata_ubereval_key(
2633 add_relation(geom_init_key, obdata_ubereval_key, "Object Geometry UberEval");
2634 }
2635 if (object->type == OB_MBALL) {
2636 Object *mom = BKE_mball_basis_find(scene_, object);
2637 ComponentKey mom_geom_key(&mom->id, NodeType::GEOMETRY);
2638 /* motherball - mom depends on children! */
2639 if (mom == object) {
2640 ComponentKey mom_transform_key(&mom->id, NodeType::TRANSFORM);
2641 add_relation(mom_transform_key, mom_geom_key, "Metaball Motherball Transform -> Geometry");
2642 }
2643 else {
2644 ComponentKey transform_key(&object->id, NodeType::TRANSFORM);
2645 add_relation(geom_key, mom_geom_key, "Metaball Motherball");
2646 add_relation(transform_key, mom_geom_key, "Metaball Motherball");
2647 }
2648 }
2649 /* NOTE: This is compatibility code to support particle systems
2650 *
2651 * for viewport being properly rendered in final render mode.
2652 * This relation is similar to what dag_object_time_update_flags()
2653 * was doing for mesh objects with particle system.
2654 *
2655 * Ideally we need to get rid of this relation. */
2656 if (object_particles_depends_on_time(object)) {
2657 TimeSourceKey time_key;
2658 OperationKey obdata_ubereval_key(
2660 add_relation(time_key, obdata_ubereval_key, "Legacy particle time");
2661 }
2662 /* Object data data-block. */
2664 Key *key = BKE_key_from_object(object);
2665 if (key != nullptr) {
2666 if (key->adt != nullptr) {
2667 if (key->adt->action || key->adt->nla_tracks.first) {
2668 ComponentKey obdata_key((ID *)object->data, NodeType::GEOMETRY);
2669 ComponentKey adt_key(&key->id, NodeType::ANIMATION);
2670 add_relation(adt_key, obdata_key, "Animation");
2671 }
2672 }
2673 }
2674 build_dimensions(object);
2675 /* Synchronization back to original object. */
2676 ComponentKey final_geometry_key(&object->id, NodeType::GEOMETRY);
2677 OperationKey synchronize_key(
2679 add_relation(final_geometry_key, synchronize_key, "Synchronize to Original");
2680 /* Batch cache. */
2681 OperationKey object_data_select_key(
2683 OperationKey object_select_key(
2685 add_relation(object_data_select_key, object_select_key, "Data Selection -> Object Selection");
2687 geom_key, object_select_key, "Object Geometry -> Select Update", RELATION_FLAG_NO_FLUSH);
2688 /* Shading. */
2689 ComponentKey geometry_shading_key(obdata, NodeType::SHADING);
2690 OperationKey object_shading_key(&object->id, NodeType::SHADING, OperationCode::SHADING);
2691 add_relation(geometry_shading_key, object_shading_key, "Geometry Shading -> Object Shading");
2692}
2693
2695{
2696 if (built_map_.checkIsBuiltAndTag(obdata)) {
2697 return;
2698 }
2699
2700 const BuilderStack::ScopedEntry stack_entry = stack_.trace(*obdata);
2701
2703 /* Animation. */
2704 build_animdata(obdata);
2705 build_parameters(obdata);
2706 /* ShapeKeys. */
2707 Key *key = BKE_key_from_id(obdata);
2708 if (key != nullptr) {
2709 build_shapekeys(key);
2710 }
2711 /* Link object data evaluation node to exit operation. */
2712 OperationKey obdata_geom_eval_key(obdata, NodeType::GEOMETRY, OperationCode::GEOMETRY_EVAL);
2714 add_relation(obdata_geom_eval_key, obdata_geom_done_key, "ObData Geom Eval Done");
2715
2716 /* Link object data evaluation to parameter evaluation. */
2717 ComponentKey parameters_key(obdata, NodeType::PARAMETERS);
2718 add_relation(parameters_key, obdata_geom_eval_key, "ObData Geom Params");
2719
2720 /* Type-specific links. */
2721 const ID_Type id_type = GS(obdata->name);
2722 switch (id_type) {
2723 case ID_ME:
2724 break;
2725 case ID_MB:
2726 break;
2727 case ID_CU_LEGACY: {
2728 Curve *cu = (Curve *)obdata;
2729 if (cu->bevobj != nullptr) {
2730 ComponentKey bevob_geom_key(&cu->bevobj->id, NodeType::GEOMETRY);
2731 add_relation(bevob_geom_key, obdata_geom_eval_key, "Curve Bevel Geometry");
2732 ComponentKey bevob_key(&cu->bevobj->id, NodeType::TRANSFORM);
2733 add_relation(bevob_key, obdata_geom_eval_key, "Curve Bevel Transform");
2734 build_object(cu->bevobj);
2735 }
2736 if (cu->taperobj != nullptr) {
2737 ComponentKey taperob_key(&cu->taperobj->id, NodeType::GEOMETRY);
2738 add_relation(taperob_key, obdata_geom_eval_key, "Curve Taper");
2740 }
2741 if (cu->textoncurve != nullptr) {
2742 ComponentKey textoncurve_geom_key(&cu->textoncurve->id, NodeType::GEOMETRY);
2743 add_relation(textoncurve_geom_key, obdata_geom_eval_key, "Text on Curve Geometry");
2744 ComponentKey textoncurve_key(&cu->textoncurve->id, NodeType::TRANSFORM);
2745 add_relation(textoncurve_key, obdata_geom_eval_key, "Text on Curve Transform");
2747 }
2748 /* Special relation to ensure active spline index gets properly updated.
2749 *
2750 * The active spline index is stored on the Curve data-block, and the curve evaluation might
2751 * create a new curve data-block for the result, which does not intrinsically sharing the
2752 * active spline index. Hence a special relation is added to ensure the modifier stack is
2753 * evaluated when selection changes. */
2754 {
2755 const OperationKey object_data_select_key(
2757 add_relation(object_data_select_key, obdata_geom_eval_key, "Active Spline Update");
2758 }
2759 break;
2760 }
2761 case ID_LT:
2762 break;
2763 case ID_GD_LEGACY: /* Grease Pencil */
2764 {
2765 bGPdata *gpd = (bGPdata *)obdata;
2766
2767 /* Geometry cache needs to be recalculated on frame change
2768 * (e.g. to fix crashes after scrubbing the timeline when
2769 * onion skinning is enabled, since the ghosts need to be
2770 * re-added to the cache once scrubbing ends). */
2771 TimeSourceKey time_key;
2772 ComponentKey geometry_key(obdata, NodeType::GEOMETRY);
2773 add_relation(time_key, geometry_key, "GP Frame Change");
2774
2775 /* Geometry cache also needs to be recalculated when Material
2776 * settings change (e.g. when fill.opacity changes on/off,
2777 * we need to rebuild the bGPDstroke->triangles caches). */
2778 for (int i = 0; i < gpd->totcol; i++) {
2779 Material *ma = gpd->mat[i];
2780 if ((ma != nullptr) && (ma->gp_style != nullptr)) {
2782 add_relation(material_key, geometry_key, "Material -> GP Data");
2783 }
2784 }
2785
2786 /* Layer parenting need react to the parent object transformation. */
2787 LISTBASE_FOREACH (bGPDlayer *, gpl, &gpd->layers) {
2788 if (gpl->parent != nullptr) {
2789 ComponentKey gpd_geom_key(&gpd->id, NodeType::GEOMETRY);
2790
2791 if (gpl->partype == PARBONE) {
2792 ComponentKey bone_key(&gpl->parent->id, NodeType::BONE, gpl->parsubstr);
2793 OperationKey armature_key(
2795
2796 add_relation(bone_key, gpd_geom_key, "Bone Parent");
2797 add_relation(armature_key, gpd_geom_key, "Armature Parent");
2798 }
2799 else {
2800 ComponentKey transform_key(&gpl->parent->id, NodeType::TRANSFORM);
2801 add_relation(transform_key, gpd_geom_key, "GPencil Parent Layer");
2802 }
2803 }
2804 }
2805 break;
2806 }
2807 case ID_CV: {
2808 Curves *curves_id = reinterpret_cast<Curves *>(obdata);
2809 if (curves_id->surface != nullptr) {
2810 build_object(curves_id->surface);
2811
2812 /* The relations between the surface and the curves are handled as part of the modifier
2813 * stack building. */
2814 }
2815 break;
2816 }
2817 case ID_PT:
2818 break;
2819 case ID_VO: {
2820 Volume *volume = (Volume *)obdata;
2821 if (volume->is_sequence) {
2822 TimeSourceKey time_key;
2823 ComponentKey geometry_key(obdata, NodeType::GEOMETRY);
2824 add_relation(time_key, geometry_key, "Volume sequence time");
2825 }
2826 break;
2827 }
2828 case ID_GP: {
2829 GreasePencil &grease_pencil = *reinterpret_cast<GreasePencil *>(obdata);
2830
2831 /* Update geometry when time is changed. */
2832 TimeSourceKey time_key;
2833 ComponentKey geometry_key(&grease_pencil.id, NodeType::GEOMETRY);
2834 add_relation(time_key, geometry_key, "Grease Pencil Frame Change");
2835
2836 /* Add relations for layer parents. */
2837 for (const bke::greasepencil::Layer *layer : grease_pencil.layers()) {
2838 Object *parent = layer->parent;
2839 if (parent == nullptr) {
2840 continue;
2841 }
2842 if (parent->type == OB_ARMATURE && !layer->parent_bone_name().is_empty()) {
2843 ComponentKey bone_key(&parent->id, NodeType::BONE, layer->parent_bone_name().c_str());
2844 OperationKey armature_key(
2846
2847 add_relation(bone_key, geometry_key, "Grease Pencil Layer Bone Parent");
2848 add_relation(armature_key, geometry_key, "Grease Pencil Layer Armature Parent");
2849 }
2850 else {
2851 ComponentKey transform_key(&parent->id, NodeType::TRANSFORM);
2852 add_relation(transform_key, geometry_key, "Grease Pencil Layer Object Parent");
2853 }
2854 }
2855 break;
2856 }
2857 default:
2858 BLI_assert_msg(0, "Should not happen");
2859 break;
2860 }
2861}
2862
2864{
2865 if (built_map_.checkIsBuiltAndTag(armature)) {
2866 return;
2867 }
2868
2869 const BuilderStack::ScopedEntry stack_entry = stack_.trace(armature->id);
2870
2871 build_idproperties(armature->id.properties);
2872 build_animdata(&armature->id);
2873 build_parameters(&armature->id);
2874 build_armature_bones(&armature->bonebase);
2875 build_armature_bone_collections(armature->collections_span());
2876}
2877
2879{
2880 LISTBASE_FOREACH (Bone *, bone, bones) {
2881 build_idproperties(bone->prop);
2882 build_armature_bones(&bone->childbase);
2883 }
2884}
2885
2888{
2889 for (BoneCollection *bcoll : collections) {
2890 build_idproperties(bcoll->prop);
2891 }
2892}
2893
2895{
2896 if (built_map_.checkIsBuiltAndTag(camera)) {
2897 return;
2898 }
2899
2900 const BuilderStack::ScopedEntry stack_entry = stack_.trace(camera->id);
2901
2902 build_idproperties(camera->id.properties);
2903 build_animdata(&camera->id);
2904 build_parameters(&camera->id);
2905 if (camera->dof.focus_object != nullptr) {
2906 build_object(camera->dof.focus_object);
2907 ComponentKey camera_parameters_key(&camera->id, NodeType::PARAMETERS);
2908 ComponentKey dof_ob_key(&camera->dof.focus_object->id, NodeType::TRANSFORM);
2909 add_relation(dof_ob_key, camera_parameters_key, "Camera DOF");
2910 if (camera->dof.focus_subtarget[0]) {
2911 OperationKey target_key(&camera->dof.focus_object->id,
2913 camera->dof.focus_subtarget,
2915 add_relation(target_key, camera_parameters_key, "Camera DOF subtarget");
2916 }
2917 }
2918}
2919
2920/* Lights */
2922{
2923 if (built_map_.checkIsBuiltAndTag(lamp)) {
2924 return;
2925 }
2926
2927 const BuilderStack::ScopedEntry stack_entry = stack_.trace(lamp->id);
2928
2932
2933 ComponentKey lamp_parameters_key(&lamp->id, NodeType::PARAMETERS);
2934
2935 /* For allowing drivers on lamp properties. */
2936 ComponentKey shading_key(&lamp->id, NodeType::SHADING);
2937 add_relation(lamp_parameters_key, shading_key, "Light Shading Parameters");
2938
2939 /* light's nodetree */
2940 if (lamp->nodetree != nullptr) {
2942 OperationKey ntree_key(
2944 add_relation(ntree_key, shading_key, "NTree->Light Parameters");
2946 }
2947}
2948
2950{
2951 build_idproperties(socket->prop);
2952
2953 if (socket->type == SOCK_OBJECT) {
2954 Object *object = ((bNodeSocketValueObject *)socket->default_value)->value;
2955 if (object != nullptr) {
2956 build_object(object);
2957 }
2958 }
2959 else if (socket->type == SOCK_IMAGE) {
2960 Image *image = ((bNodeSocketValueImage *)socket->default_value)->value;
2961 if (image != nullptr) {
2962 build_image(image);
2963 }
2964 }
2965 else if (socket->type == SOCK_COLLECTION) {
2966 Collection *collection = ((bNodeSocketValueCollection *)socket->default_value)->value;
2967 if (collection != nullptr) {
2968 build_collection(nullptr, collection);
2969 }
2970 }
2971 else if (socket->type == SOCK_TEXTURE) {
2972 Tex *texture = ((bNodeSocketValueTexture *)socket->default_value)->value;
2973 if (texture != nullptr) {
2974 build_texture(texture);
2975 }
2976 }
2977 else if (socket->type == SOCK_MATERIAL) {
2978 Material *material = ((bNodeSocketValueMaterial *)socket->default_value)->value;
2979 if (material != nullptr) {
2980 build_material(material);
2981 }
2982 }
2983}
2984
2986{
2987 if (ntree == nullptr) {
2988 return;
2989 }
2990 if (built_map_.checkIsBuiltAndTag(ntree)) {
2991 return;
2992 }
2993
2994 const BuilderStack::ScopedEntry stack_entry = stack_.trace(ntree->id);
2995
2997 build_animdata(&ntree->id);
2998 build_parameters(&ntree->id);
3000 OperationKey ntree_geo_preprocess_key(
3002 if (ntree->type == NTREE_GEOMETRY) {
3004 add_relation(ntree_cow_key, ntree_geo_preprocess_key, "Copy-on-Eval -> Preprocess");
3005 add_relation(ntree_geo_preprocess_key,
3006 ntree_output_key,
3007 "Preprocess -> Output",
3009 }
3010 /* nodetree's nodes... */
3011 for (bNode *bnode : ntree->all_nodes()) {
3012 build_idproperties(bnode->prop);
3013 LISTBASE_FOREACH (bNodeSocket *, socket, &bnode->inputs) {
3014 build_nodetree_socket(socket);
3015 }
3016 LISTBASE_FOREACH (bNodeSocket *, socket, &bnode->outputs) {
3017 build_nodetree_socket(socket);
3018 }
3019
3020 ID *id = bnode->id;
3021 if (id == nullptr) {
3022 continue;
3023 }
3024 ID_Type id_type = GS(id->name);
3025 if (id_type == ID_MA) {
3026 build_material((Material *)bnode->id);
3027 ComponentKey material_key(id, NodeType::SHADING);
3028 add_relation(material_key, ntree_output_key, "Material -> Node");
3029 }
3030 else if (id_type == ID_TE) {
3031 build_texture((Tex *)bnode->id);
3033 add_relation(texture_key, ntree_output_key, "Texture -> Node");
3034 }
3035 else if (id_type == ID_IM) {
3036 build_image((Image *)bnode->id);
3038 add_relation(image_key, ntree_output_key, "Image -> Node");
3039 }
3040 else if (id_type == ID_OB) {
3041 build_object((Object *)id);
3042 ComponentKey object_transform_key(id, NodeType::TRANSFORM);
3043 add_relation(object_transform_key, ntree_output_key, "Object Transform -> Node");
3044 if (object_have_geometry_component(reinterpret_cast<Object *>(id))) {
3045 ComponentKey object_geometry_key(id, NodeType::GEOMETRY);
3046 add_relation(object_geometry_key, ntree_output_key, "Object Geometry -> Node");
3047 }
3048 }
3049 else if (id_type == ID_SCE) {
3050 Scene *node_scene = (Scene *)id;
3051 build_scene_parameters(node_scene);
3052 /* Camera is used by defocus node.
3053 *
3054 * On the one hand it's annoying to always pull it in, but on another hand it's also annoying
3055 * to have hardcoded node-type exception here. */
3056 if (node_scene->camera != nullptr) {
3057 build_object(node_scene->camera);
3058 }
3059 }
3060 else if (id_type == ID_TXT) {
3061 /* Ignore script nodes. */
3062 }
3063 else if (id_type == ID_MSK) {
3064 build_mask((Mask *)id);
3066 add_relation(mask_key, ntree_output_key, "Mask -> Node");
3067 }
3068 else if (id_type == ID_MC) {
3071 add_relation(clip_key, ntree_output_key, "Clip -> Node");
3072 }
3073 else if (id_type == ID_VF) {
3074 build_vfont((VFont *)id);
3076 add_relation(vfont_key, ntree_output_key, "VFont -> Node");
3077 }
3078 else if (ELEM(bnode->type, NODE_GROUP, NODE_CUSTOM_GROUP)) {
3079 bNodeTree *group_ntree = (bNodeTree *)id;
3080 build_nodetree(group_ntree);
3081 ComponentKey group_output_key(&group_ntree->id, NodeType::NTREE_OUTPUT);
3082 /* This relation is not necessary in all cases (e.g. when the group node is not connected to
3083 * the output). Currently, we lack the infrastructure to check for these cases efficiently.
3084 * That can be added later. */
3085 add_relation(group_output_key, ntree_output_key, "Group Node");
3086 if (group_ntree->type == NTREE_GEOMETRY) {
3087 OperationKey group_preprocess_key(&group_ntree->id,
3090 add_relation(group_preprocess_key, ntree_geo_preprocess_key, "Group Node Preprocess");
3091 }
3092 }
3093 else {
3094 /* Ignore this case. It can happen when the node type is not known currently. Either because
3095 * it belongs to an add-on or because it comes from a different Blender version that does
3096 * support the ID type here already. */
3097 }
3098 }
3099
3100 ntree->ensure_interface_cache();
3101 for (bNodeTreeInterfaceSocket *socket : ntree->interface_inputs()) {
3102 build_idproperties(socket->properties);
3103 }
3104 for (bNodeTreeInterfaceSocket *socket : ntree->interface_outputs()) {
3105 build_idproperties(socket->properties);
3106 }
3107
3108 if (check_id_has_anim_component(&ntree->id)) {
3109 ComponentKey animation_key(&ntree->id, NodeType::ANIMATION);
3110 add_relation(animation_key, ntree_output_key, "NTree Shading Parameters");
3111 if (ntree->type == NTREE_GEOMETRY) {
3112 add_relation(animation_key, ntree_geo_preprocess_key, "NTree Animation -> Preprocess");
3113 }
3114 }
3115}
3116
3117/* Recursively build graph for material */
3119{
3120 if (owner) {
3121 ComponentKey material_key(&material->id, NodeType::SHADING);
3122 OperationKey owner_shading_key(owner, NodeType::SHADING, OperationCode::SHADING);
3123 add_relation(material_key, owner_shading_key, "Material -> Owner Shading");
3124 }
3125
3126 if (built_map_.checkIsBuiltAndTag(material)) {
3127 return;
3128 }
3129
3130 const BuilderStack::ScopedEntry stack_entry = stack_.trace(material->id);
3131
3132 build_idproperties(material->id.properties);
3133 /* animation */
3134 build_animdata(&material->id);
3135 build_parameters(&material->id);
3136
3137 /* Animated / driven parameters (without nodetree). */
3139 ComponentKey parameters_key(&material->id, NodeType::PARAMETERS);
3140 add_relation(parameters_key, material_key, "Material's parameters");
3141
3142 /* material's nodetree */
3143 if (material->nodetree != nullptr) {
3144 build_nodetree(material->nodetree);
3145 OperationKey ntree_key(
3146 &material->nodetree->id, NodeType::NTREE_OUTPUT, OperationCode::NTREE_OUTPUT);
3147 add_relation(ntree_key, material_key, "Material's NTree");
3148 build_nested_nodetree(&material->id, material->nodetree);
3149 }
3150}
3151
3152void DepsgraphRelationBuilder::build_materials(ID *owner, Material **materials, int num_materials)
3153{
3154 for (int i = 0; i < num_materials; i++) {
3155 if (materials[i] == nullptr) {
3156 continue;
3157 }
3158 build_material(materials[i], owner);
3159 }
3160}
3161
3162/* Recursively build graph for texture */
3164{
3165 if (built_map_.checkIsBuiltAndTag(texture)) {
3166 return;
3167 }
3168
3169 const BuilderStack::ScopedEntry stack_entry = stack_.trace(texture->id);
3170
3171 /* texture itself */
3172 ComponentKey texture_key(&texture->id, NodeType::GENERIC_DATABLOCK);
3173 build_idproperties(texture->id.properties);
3174 build_animdata(&texture->id);
3175 build_parameters(&texture->id);
3176
3177 /* texture's nodetree */
3178 if (texture->nodetree) {
3179 build_nodetree(texture->nodetree);
3180 OperationKey ntree_key(
3181 &texture->nodetree->id, NodeType::NTREE_OUTPUT, OperationCode::NTREE_OUTPUT);
3182 add_relation(ntree_key, texture_key, "Texture's NTree");
3183 build_nested_nodetree(&texture->id, texture->nodetree);
3184 }
3185
3186 /* Special cases for different IDs which texture uses. */
3187 if (texture->type == TEX_IMAGE) {
3188 if (texture->ima != nullptr) {
3189 build_image(texture->ima);
3190
3191 ComponentKey image_key(&texture->ima->id, NodeType::GENERIC_DATABLOCK);
3192 add_relation(image_key, texture_key, "Texture Image");
3193 }
3194 }
3195
3196 if (check_id_has_anim_component(&texture->id)) {
3197 ComponentKey animation_key(&texture->id, NodeType::ANIMATION);
3198 add_relation(animation_key, texture_key, "Datablock Animation");
3199 }
3200
3201 if (BKE_image_user_id_has_animation(&texture->id)) {
3202 ComponentKey image_animation_key(&texture->id, NodeType::IMAGE_ANIMATION);
3203 add_relation(image_animation_key, texture_key, "Datablock Image Animation");
3204 }
3205}
3206
3208{
3209 if (built_map_.checkIsBuiltAndTag(image)) {
3210 return;
3211 }
3212
3213 const BuilderStack::ScopedEntry stack_entry = stack_.trace(image->id);
3214
3215 build_idproperties(image->id.properties);
3216 build_parameters(&image->id);
3217}
3218
3220{
3221 if (built_map_.checkIsBuiltAndTag(cache_file)) {
3222 return;
3223 }
3224
3225 const BuilderStack::ScopedEntry stack_entry = stack_.trace(cache_file->id);
3226
3227 build_idproperties(cache_file->id.properties);
3228 /* Animation. */
3229 build_animdata(&cache_file->id);
3230 build_parameters(&cache_file->id);
3231 if (check_id_has_anim_component(&cache_file->id)) {
3232 ComponentKey animation_key(&cache_file->id, NodeType::ANIMATION);
3233 ComponentKey datablock_key(&cache_file->id, NodeType::CACHE);
3234 add_relation(animation_key, datablock_key, "Datablock Animation");
3235 }
3236 if (check_id_has_driver_component(&cache_file->id)) {
3237 ComponentKey animation_key(&cache_file->id, NodeType::PARAMETERS);
3238 ComponentKey datablock_key(&cache_file->id, NodeType::CACHE);
3239 add_relation(animation_key, datablock_key, "Drivers -> Cache Eval");
3240 }
3241
3242 /* Cache file updates */
3243 if (cache_file->is_sequence) {
3244 OperationKey cache_update_key(
3246 TimeSourceKey time_src_key;
3247 add_relation(time_src_key, cache_update_key, "TimeSrc -> Cache File Eval");
3248 }
3249}
3250
3252{
3253 if (built_map_.checkIsBuiltAndTag(mask)) {
3254 return;
3255 }
3256
3257 const BuilderStack::ScopedEntry stack_entry = stack_.trace(mask->id);
3258
3259 ID *mask_id = &mask->id;
3261 /* F-Curve animation. */
3262 build_animdata(mask_id);
3263 build_parameters(mask_id);
3264 /* Own mask animation. */
3266 TimeSourceKey time_src_key;
3267 add_relation(time_src_key, mask_animation_key, "TimeSrc -> Mask Animation");
3268 /* Final mask evaluation. */
3270 add_relation(mask_animation_key, mask_eval_key, "Mask Animation -> Mask Eval");
3271 /* Build parents. */
3272 LISTBASE_FOREACH (MaskLayer *, mask_layer, &mask->masklayers) {
3273 LISTBASE_FOREACH (MaskSpline *, spline, &mask_layer->splines) {
3274 for (int i = 0; i < spline->tot_point; i++) {
3275 MaskSplinePoint *point = &spline->points[i];
3276 MaskParent *parent = &point->parent;
3277 if (parent == nullptr || parent->id == nullptr) {
3278 continue;
3279 }
3280 build_id(parent->id);
3281 if (parent->id_type == ID_MC) {
3282 OperationKey movieclip_eval_key(
3284 add_relation(movieclip_eval_key, mask_eval_key, "Movie Clip -> Mask Eval");
3285 }
3286 }
3287 }
3288 }
3289}
3290
3292{
3293 if (built_map_.checkIsBuiltAndTag(linestyle)) {
3294 return;
3295 }
3296
3297 const BuilderStack::ScopedEntry stack_entry = stack_.trace(linestyle->id);
3298
3299 ID *linestyle_id = &linestyle->id;
3300 build_parameters(linestyle_id);
3301 build_idproperties(linestyle_id->properties);
3302 build_animdata(linestyle_id);
3304}
3305
3307{
3308 if (built_map_.checkIsBuiltAndTag(clip)) {
3309 return;
3310 }
3311
3312 const BuilderStack::ScopedEntry stack_entry = stack_.trace(clip->id);
3313
3314 /* Animation. */
3315 build_idproperties(clip->id.properties);
3316 build_animdata(&clip->id);
3317 build_parameters(&clip->id);
3318}
3319
3321{
3322 if (built_map_.checkIsBuiltAndTag(probe)) {
3323 return;
3324 }
3325
3326 const BuilderStack::ScopedEntry stack_entry = stack_.trace(probe->id);
3327
3329 build_animdata(&probe->id);
3330 build_parameters(&probe->id);
3331}
3332
3334{
3335 if (built_map_.checkIsBuiltAndTag(speaker)) {
3336 return;
3337 }
3338
3339 const BuilderStack::ScopedEntry stack_entry = stack_.trace(speaker->id);
3340
3342 build_animdata(&speaker->id);
3343 build_parameters(&speaker->id);
3344 if (speaker->sound != nullptr) {
3345 build_sound(speaker->sound);
3346 ComponentKey speaker_key(&speaker->id, NodeType::AUDIO);
3347 ComponentKey sound_key(&speaker->sound->id, NodeType::AUDIO);
3348 add_relation(sound_key, speaker_key, "Sound -> Speaker");
3349 }
3350}
3351
3353{
3354 if (built_map_.checkIsBuiltAndTag(sound)) {
3355 return;
3356 }
3357
3358 const BuilderStack::ScopedEntry stack_entry = stack_.trace(sound->id);
3359
3361 build_animdata(&sound->id);
3362 build_parameters(&sound->id);
3363
3364 const ComponentKey parameters_key(&sound->id, NodeType::PARAMETERS);
3365 const ComponentKey audio_key(&sound->id, NodeType::AUDIO);
3366
3367 add_relation(parameters_key, audio_key, "Parameters -> Audio");
3368}
3369
3375
3376static bool seq_build_prop_cb(Sequence *seq, void *user_data)
3377{
3379
3380 cd->builder->build_idproperties(seq->prop);
3381 if (seq->sound != nullptr) {
3382 cd->builder->build_sound(seq->sound);
3383 ComponentKey sound_key(&seq->sound->id, NodeType::AUDIO);
3384 cd->builder->add_relation(sound_key, cd->sequencer_key, "Sound -> Sequencer");
3385 cd->has_audio_strips = true;
3386 }
3387 if (seq->scene != nullptr) {
3389 /* This is to support 3D audio. */
3390 cd->has_audio_strips = true;
3391 }
3392 if (seq->type == SEQ_TYPE_SCENE && seq->scene != nullptr) {
3393 if (seq->flag & SEQ_SCENE_STRIPS) {
3395 ComponentKey sequence_scene_audio_key(&seq->scene->id, NodeType::AUDIO);
3396 cd->builder->add_relation(
3397 sequence_scene_audio_key, cd->sequencer_key, "Sequence Scene Audio -> Sequencer");
3398 ComponentKey sequence_scene_key(&seq->scene->id, NodeType::SEQUENCER);
3399 cd->builder->add_relation(
3400 sequence_scene_key, cd->sequencer_key, "Sequence Scene -> Sequencer");
3401 }
3402 ViewLayer *sequence_view_layer = BKE_view_layer_default_render(seq->scene);
3403 cd->builder->build_scene_speakers(seq->scene, sequence_view_layer);
3404 }
3405 /* TODO(sergey): Movie clip, camera, mask. */
3406 return true;
3407}
3408
3410{
3411 if (scene->ed == nullptr) {
3412 return;
3413 }
3414 if (built_map_.checkIsBuiltAndTag(scene, BuilderMap::TAG_SCENE_SEQUENCER)) {
3415 return;
3416 }
3417
3418 /* TODO(sergey): Trace as a scene sequencer. */
3419
3420 build_scene_audio(scene);
3421 ComponentKey scene_audio_key(&scene->id, NodeType::AUDIO);
3422 /* Make sure dependencies from sequences data goes to the sequencer evaluation. */
3423 ComponentKey sequencer_key(&scene->id, NodeType::SEQUENCER);
3424
3425 Seq_build_prop_cb_data cb_data = {this, sequencer_key, false};
3426
3427 SEQ_for_each_callback(&scene->ed->seqbase, seq_build_prop_cb, &cb_data);
3428 if (cb_data.has_audio_strips) {
3429 add_relation(sequencer_key, scene_audio_key, "Sequencer -> Audio");
3430 }
3431}
3432
3434{
3435 OperationKey scene_audio_entry_key(&scene->id, NodeType::AUDIO, OperationCode::AUDIO_ENTRY);
3436 OperationKey scene_audio_volume_key(&scene->id, NodeType::AUDIO, OperationCode::AUDIO_VOLUME);
3437 OperationKey scene_sound_eval_key(&scene->id, NodeType::AUDIO, OperationCode::SOUND_EVAL);
3438 add_relation(scene_audio_entry_key, scene_audio_volume_key, "Audio Entry -> Volume");
3439 add_relation(scene_audio_volume_key, scene_sound_eval_key, "Audio Volume -> Sound");
3440
3441 if (scene->audio.flag & AUDIO_VOLUME_ANIMATED) {
3442 ComponentKey scene_anim_key(&scene->id, NodeType::ANIMATION);
3443 add_relation(scene_anim_key, scene_audio_volume_key, "Animation -> Audio Volume");
3444 }
3445}
3446
3448{
3449 BKE_view_layer_synced_ensure(scene, view_layer);
3451 Object *object = base->object;
3452 if (object->type != OB_SPEAKER || !need_pull_base_into_graph(base)) {
3453 continue;
3454 }
3455 build_object(base->object);
3456 }
3457}
3458
3460{
3461 if (built_map_.checkIsBuiltAndTag(vfont)) {
3462 return;
3463 }
3464
3465 const BuilderStack::ScopedEntry stack_entry = stack_.trace(vfont->id);
3466
3467 build_parameters(&vfont->id);
3469}
3470
3477
3484void DepsgraphRelationBuilder::build_nested_datablock(ID *owner, ID *id, bool flush_cow_changes)
3485{
3486 int relation_flag = 0;
3487 if (!flush_cow_changes) {
3488 relation_flag |= RELATION_FLAG_NO_FLUSH;
3489 }
3490 OperationKey owner_copy_on_write_key(owner, NodeType::COPY_ON_EVAL, OperationCode::COPY_ON_EVAL);
3492 add_relation(id_copy_on_write_key, owner_copy_on_write_key, "Eval Order", relation_flag);
3493}
3494
3496{
3497 if (ntree == nullptr) {
3498 return;
3499 }
3500 /* Don't flush cow changes, because the node tree may change in ways that do not affect the
3501 * owner data block (e.g. when a node is deleted that is not connected to any output).
3502 * Data blocks owning node trees should add a relation to the `NTREE_OUTPUT` node instead. */
3503 build_nested_datablock(owner, &ntree->id, false);
3504}
3505
3507{
3508 if (key == nullptr) {
3509 return;
3510 }
3511 build_nested_datablock(owner, &key->id, true);
3512}
3513
3515{
3516 ID *id_orig = id_node->id_orig;
3517
3518 const ID_Type id_type = GS(id_orig->name);
3519
3520 if (!deg_eval_copy_is_needed(id_type)) {
3521 return;
3522 }
3523
3525 /* XXX: This is a quick hack to make Alt-A to work. */
3526 // add_relation(time_source_key, copy_on_write_key, "Fluxgate capacitor hack");
3527 /* Resat of code is using rather low level trickery, so need to get some
3528 * explicit pointers. */
3529 Node *node_cow = find_node(copy_on_write_key);
3530 OperationNode *op_cow = node_cow->get_exit_operation();
3531 /* Plug any other components to this one. */
3532 for (ComponentNode *comp_node : id_node->components.values()) {
3533 if (comp_node->type == NodeType::COPY_ON_EVAL) {
3534 /* Copy-on-eval component never depends on itself. */
3535 continue;
3536 }
3537 if (!comp_node->depends_on_cow()) {
3538 /* Component explicitly requests to not add relation. */
3539 continue;
3540 }
3542 if ((ELEM(id_type, ID_ME, ID_CV, ID_PT, ID_VO) && comp_node->type == NodeType::GEOMETRY) ||
3543 (id_type == ID_CF && comp_node->type == NodeType::CACHE))
3544 {
3545 rel_flag &= ~RELATION_FLAG_NO_FLUSH;
3546 }
3547 /* TODO(sergey): Needs better solution for this. */
3548 if (id_type == ID_SO) {
3549 rel_flag &= ~RELATION_FLAG_NO_FLUSH;
3550 }
3551 /* Notes on exceptions:
3552 * - View layers have cached array of bases in them, which is not
3553 * copied by copy-on-evaluation, and not preserved. PROBABLY it is better
3554 * to preserve that cache in copy-on-evaluation, but for the time being
3555 * we allow flush to layer collections component which will ensure
3556 * that cached array of bases exists and is up-to-date. */
3557 if (ELEM(comp_node->type, NodeType::LAYER_COLLECTIONS)) {
3558 rel_flag &= ~RELATION_FLAG_NO_FLUSH;
3559 }
3560 /* Mask evaluation operation is part of parameters, and it needs to be re-evaluated when the
3561 * mask is tagged for copy-on-eval.
3562 *
3563 * TODO(@sergey): This needs to be moved out of here.
3564 * In order to do so, moving mask evaluation out of parameters would be helpful and
3565 * semantically correct. */
3566 if (comp_node->type == NodeType::PARAMETERS && id_type == ID_MSK) {
3567 rel_flag &= ~RELATION_FLAG_NO_FLUSH;
3568 }
3569 /* Compatibility with the legacy tagging: groups are only tagged for Copy-on-Write when their
3570 * hierarchy changes, and it needs to be flushed downstream. */
3571 if (id_type == ID_GR && comp_node->type == NodeType::HIERARCHY) {
3572 rel_flag &= ~RELATION_FLAG_NO_FLUSH;
3573 }
3574 /* All entry operations of each component should wait for a proper
3575 * copy of ID. */
3576 OperationNode *op_entry = comp_node->get_entry_operation();
3577 if (op_entry != nullptr) {
3578 Relation *rel = graph_->add_new_relation(op_cow, op_entry, "Copy-on-Eval Dependency");
3579 rel->flag |= rel_flag;
3580 }
3581 /* All dangling operations should also be executed after copy-on-evaluation. */
3582 for (OperationNode *op_node : comp_node->operations_map->values()) {
3583 if (op_node == op_entry) {
3584 continue;
3585 }
3586 if (op_node->inlinks.is_empty()) {
3587 Relation *rel = graph_->add_new_relation(op_cow, op_node, "Copy-on-Eval Dependency");
3588 rel->flag |= rel_flag;
3589 }
3590 else {
3591 bool has_same_comp_dependency = false;
3592 for (Relation *rel_current : op_node->inlinks) {
3593 if (rel_current->from->type != NodeType::OPERATION) {
3594 continue;
3595 }
3596 OperationNode *op_node_from = (OperationNode *)rel_current->from;
3597 if (op_node_from->owner == op_node->owner) {
3598 has_same_comp_dependency = true;
3599 break;
3600 }
3601 }
3602 if (!has_same_comp_dependency) {
3603 Relation *rel = graph_->add_new_relation(op_cow, op_node, "Copy-on-Eval Dependency");
3604 rel->flag |= rel_flag;
3605 }
3606 }
3607 }
3608 /* NOTE: We currently ignore implicit relations to an external
3609 * data-blocks for copy-on-evaluation operations. This means, for example,
3610 * copy-on-evaluation component of Object will not wait for copy-on-evaluation
3611 * component of its Mesh. This is because pointers are all known
3612 * already so remapping will happen all correct. And then If some object
3613 * evaluation step needs geometry, it will have transitive dependency
3614 * to Mesh copy-on-evaluation already. */
3615 }
3616 /* TODO(sergey): This solves crash for now, but causes too many
3617 * updates potentially. */
3618 if (GS(id_orig->name) == ID_OB) {
3619 Object *object = (Object *)id_orig;
3620 ID *object_data_id = (ID *)object->data;
3621 if (object_data_id != nullptr) {
3622 if (deg_eval_copy_is_needed(object_data_id)) {
3623 OperationKey data_copy_on_write_key(
3626 data_copy_on_write_key, copy_on_write_key, "Eval Order", RELATION_FLAG_GODMODE);
3627 }
3628 }
3629 else {
3630 BLI_assert(object->type == OB_EMPTY);
3631 }
3632 }
3633
3634#if 0
3635 /* NOTE: Relation is disabled since AnimationBackup() is disabled.
3636 * See comment in AnimationBackup:init_from_id(). */
3637
3638 /* Copy-on-eval of write will iterate over f-curves to store current values corresponding
3639 * to their RNA path. This means that action must be copied prior to the ID's copy-on-evaluation,
3640 * otherwise depsgraph might try to access freed data. */
3641 AnimData *animation_data = BKE_animdata_from_id(id_orig);
3642 if (animation_data != nullptr) {
3643 if (animation_data->action != nullptr) {
3644 OperationKey action_copy_on_write_key(
3646 add_relation(action_copy_on_write_key,
3647 copy_on_write_key,
3648 "Eval Order",
3650 }
3651 }
3652#endif
3653}
3654
3655/* **** ID traversal callbacks functions **** */
3656
3657void DepsgraphRelationBuilder::modifier_walk(void *user_data,
3658 Object * /*object*/,
3659 ID **idpoin,
3660 int /*cb_flag*/)
3661{
3662 BuilderWalkUserData *data = (BuilderWalkUserData *)user_data;
3663 ID *id = *idpoin;
3664 if (id == nullptr) {
3665 return;
3666 }
3667 data->builder->build_id(id);
3668}
3669
3670void DepsgraphRelationBuilder::constraint_walk(bConstraint * /*con*/,
3671 ID **idpoin,
3672 bool /*is_reference*/,
3673 void *user_data)
3674{
3675 BuilderWalkUserData *data = (BuilderWalkUserData *)user_data;
3676 ID *id = *idpoin;
3677 if (id == nullptr) {
3678 return;
3679 }
3680 data->builder->build_id(id);
3681}
3682
3683} // namespace blender::deg
Functions and classes to work with Actions.
Blender kernel action and pose functionality.
bPoseChannel * BKE_pose_channel_find_name(const bPose *pose, const char *name)
AnimData * BKE_animdata_from_id(const ID *id)
Definition anim_data.cc:89
#define FOREACH_COLLECTION_OBJECT_RECURSIVE_END
#define FOREACH_COLLECTION_VISIBLE_OBJECT_RECURSIVE_BEGIN(_collection, _object, _mode)
#define FOREACH_COLLECTION_OBJECT_RECURSIVE_BEGIN(_collection, _object)
#define FOREACH_COLLECTION_VISIBLE_OBJECT_RECURSIVE_END
void BKE_constraint_targets_flush(struct bConstraint *con, struct ListBase *targets, bool no_copy)
int BKE_constraint_targets_get(struct bConstraint *con, struct ListBase *r_targets)
bool BKE_constraint_target_uses_bbone(struct bConstraint *con, struct bConstraintTarget *ct)
const bConstraintTypeInfo * BKE_constraint_typeinfo_get(struct bConstraint *con)
void BKE_constraints_id_loop(struct ListBase *list, ConstraintIDFunc func, const int flag, void *userdata)
bool BKE_driver_expression_depends_on_time(struct ChannelDriver *driver)
bool driver_get_target_property(const DriverTargetContext *driver_target_context, struct DriverVar *dvar, struct DriverTarget *dtar, struct PointerRNA *r_prop)
#define DRIVER_TARGETS_USED_LOOPER_BEGIN(dvar)
#define DRIVER_TARGETS_LOOPER_END
void BKE_gpencil_modifiers_foreach_ID_link(struct Object *ob, GreasePencilIDWalkFunc walk, void *user_data)
Low-level operations for grease pencil.
void IDP_foreach_property(IDProperty *id_property_root, int type_filter, blender::FunctionRef< void(IDProperty *id_property)> callback)
bool BKE_image_user_id_has_animation(ID *id)
Key * BKE_key_from_id(ID *id)
Definition key.cc:1800
Key * BKE_key_from_object(Object *ob)
Definition key.cc:1820
void BKE_view_layer_synced_ensure(const Scene *scene, ViewLayer *view_layer)
ViewLayer * BKE_view_layer_default_render(const Scene *scene)
ListBase * BKE_view_layer_object_bases_get(ViewLayer *view_layer)
@ IDWALK_NOP
General operations, lookup, etc. for materials.
short * BKE_object_material_len_p(struct Object *ob)
struct Material *** BKE_object_material_array_p(struct Object *ob)
Object * BKE_mball_basis_find(Scene *scene, Object *ob)
Definition mball.cc:394
bool BKE_modifier_depends_ontime(Scene *scene, ModifierData *md)
const ModifierTypeInfo * BKE_modifier_get_info(ModifierType type)
void void void BKE_modifiers_foreach_ID_link(Object *ob, IDWalkFunc walk, void *user_data)
#define NODE_CUSTOM_GROUP
Definition BKE_node.hh:807
#define NODE_GROUP
Definition BKE_node.hh:800
General operations, lookup, etc. for blender objects.
bool BKE_ptcache_object_has(struct Scene *scene, struct Object *ob, int duplis)
void BKE_ptcache_foreach_object_cache(struct Object &ob, struct Scene &scene, bool duplis, PointCacheIdFn fn)
#define PTCACHE_TYPE_RIGIDBODY
API for Blender-side Rigid Body stuff.
void BKE_shaderfx_foreach_ID_link(struct Object *ob, ShaderFxIDWalkFunc walk, void *user_data)
Definition shader_fx.cc:240
bool BKE_shaderfx_depends_ontime(struct ShaderFxData *fx)
Definition shader_fx.cc:124
const ShaderFxTypeInfo * BKE_shaderfx_get_info(ShaderFxType type)
Definition shader_fx.cc:131
bool BKE_shrinkwrap_needs_normals(int shrinkType, int shrinkMode)
Definition shrinkwrap.cc:89
#define BLI_assert(a)
Definition BLI_assert.h:50
#define BLI_assert_msg(a, msg)
Definition BLI_assert.h:57
BLI_INLINE bool BLI_listbase_is_empty(const struct ListBase *lb)
#define LISTBASE_FOREACH(type, var, list)
#define STRPREFIX(a, b)
#define UNUSED_VARS(...)
#define ELEM(...)
#define STREQ(a, b)
@ DAG_EVAL_NEED_SHRINKWRAP_BOUNDARY
@ DAG_EVAL_NEED_CURVE_PATH
ID_Type
@ ID_WM
@ ID_CA
@ ID_AR
@ ID_MC
@ ID_CF
@ ID_LI
@ ID_TE
@ ID_IM
@ ID_VO
@ ID_WS
@ ID_NT
@ ID_LA
@ ID_KE
@ ID_TXT
@ ID_SO
@ ID_SCE
@ ID_LS
@ ID_MSK
@ ID_CV
@ ID_PAL
@ ID_BR
@ ID_LP
@ ID_WO
@ ID_MA
@ ID_AC
@ ID_SCR
@ ID_CU_LEGACY
@ ID_GD_LEGACY
@ ID_VF
@ ID_ME
@ ID_IP
@ ID_GR
@ ID_SPK
@ ID_MB
@ ID_LT
@ ID_OB
@ ID_GP
@ ID_PA
@ ID_PT
@ ID_PC
@ IDP_TYPE_FILTER_ID
@ DVAR_TYPE_CONTEXT_PROP
@ DTAR_FLAG_STRUCT_REF
@ DTAR_CONTEXT_PROPERTY_ACTIVE_SCENE
@ eBoidRuleType_Avoid
@ eBoidRuleType_FollowLeader
Object groups, one object can be in many groups at once.
@ CONSTRAINT_TYPE_FOLLOWTRACK
@ CONSTRAINT_TYPE_OBJECTSOLVER
@ CONSTRAINT_TYPE_ARMATURE
@ CONSTRAINT_TYPE_LOCLIKE
@ CONSTRAINT_TYPE_SHRINKWRAP
@ CONSTRAINT_TYPE_CAMERASOLVER
@ CONSTRAINT_TYPE_ROTLIKE
@ CONSTRAINT_TYPE_SPLINEIK
@ CONSTRAINT_TYPE_KINEMATIC
@ CONSTRAINT_TYPE_TRANSLIKE
@ CONSTRAINT_TYPE_CLAMPTO
@ CONSTRAINT_TYPE_FOLLOWPATH
@ CONSTRAINT_TYPE_SIZELIKE
@ CONSTRAINT_TYPE_TRANSFORM_CACHE
@ FOLLOWTRACK_ACTIVECLIP
@ CON_SHRINKWRAP_TRACK_NORMAL
@ CU_PATH
#define CD_MASK_ORIGINDEX
#define CD_MASK_MDEFORMVERT
#define CD_MASK_CUSTOMLOOPNORMAL
@ TEXCO_OBJECT
@ MOD_SHRINKWRAP_TARGET_PROJECT
@ MOD_SHRINKWRAP_NEAREST_VERTEX
@ eModifierType_Collision
@ NTREE_GEOMETRY
@ NTREE_RUNTIME_FLAG_HAS_IMAGE_ANIMATION
@ SOCK_TEXTURE
@ SOCK_MATERIAL
@ SOCK_IMAGE
@ SOCK_COLLECTION
@ SOCK_OBJECT
@ PFIELD_VISIBILITY
@ PFIELD_FLUIDFLOW
@ PFIELD_SHAPE_SURFACE
@ PFIELD_SHAPE_POINTS
Object is a sort of wrapper for general info.
#define OB_TYPE_IS_GEOMETRY(_type)
@ PARVERT1
@ PARSKEL
@ PARVERT3
@ PARBONE
@ OB_SPEAKER
@ OB_LATTICE
@ OB_MBALL
@ OB_EMPTY
@ OB_SURF
@ OB_CAMERA
@ OB_FONT
@ OB_GREASE_PENCIL
@ OB_ARMATURE
@ OB_LAMP
@ OB_MESH
@ OB_POINTCLOUD
@ OB_VOLUME
@ OB_CURVES_LEGACY
@ OB_GPENCIL_LEGACY
@ OB_CURVES
@ OB_LIGHTPROBE
@ OB_DUPLI
@ OB_DUPLIVERTS
@ PART_DRAW_GR
@ PART_DRAW_OB
@ PART_HAIR
@ PART_PHYS_KEYED
@ PART_PHYS_BOIDS
@ PSYS_HAIR_DYNAMICS
Types and defines for representing Rigid Body entities.
@ RBO_TYPE_ACTIVE
@ RBO_TYPE_PASSIVE
@ RB_SHAPE_COMPOUND
@ AUDIO_VOLUME_ANIMATED
@ SEQ_TYPE_SCENE
@ SEQ_SCENE_STRIPS
@ TEX_IMAGE
Read Guarded memory(de)allocation.
btSequentialImpulseConstraintSolverMt int btPersistentManifold int btTypedConstraint ** constraints
constexpr bool startswith(StringRef prefix) const
blender::Span< const Layer * > layers() const
Slot * slot_for_handle(slot_handle_t handle)
const ChannelBag * channelbag_for_slot(const Slot &slot) const
bool checkIsBuiltAndTag(ID *id, int tag=TAG_COMPLETE)
bool checkIsBuilt(ID *id, int tag=TAG_COMPLETE) const
ScopedEntry trace(const Args &...args)
virtual bool check_pchan_has_bbone_segments(const Object *object, const bPoseChannel *pchan)
virtual bool need_pull_base_into_graph(const Base *base)
static const char * get_rna_path_relative_to_scene_camera(const Scene *scene, const PointerRNA &target_prop, const char *rna_path)
virtual void build_driver_rna_path_variable(const OperationKey &driver_key, const RNAPathKey &self_key, ID *target_id, const PointerRNA &target_prop, const char *rna_path)
void add_particle_collision_relations(const OperationKey &key, Object *object, Collection *collection, const char *name)
virtual void build_animdata_action_targets(ID *id, int32_t slot_handle, ComponentKey &adt_key, OperationNode *operation_from, bAction *action)
Relation * add_depends_on_transform_relation(ID *id, const KeyTo &key_to, const char *description, int flags=0)
virtual void build_freestyle_linestyle(FreestyleLineStyle *linestyle)
virtual void build_collection(LayerCollection *from_layer_collection, Collection *collection)
virtual void build_driver_id_property(const PointerRNA &target_prop, const char *rna_path_from_target_prop)
virtual void build_object_layer_component_relations(Object *object)
virtual void build_object_from_view_layer_base(Object *object)
virtual void build_driver(ID *id, FCurve *fcurve)
virtual void build_driver_data(ID *id, FCurve *fcurve)
virtual void build_nested_nodetree(ID *owner, bNodeTree *ntree)
virtual void build_nodetree_socket(bNodeSocket *socket)
virtual void build_material(Material *ma, ID *owner=nullptr)
virtual void build_speaker(Speaker *speaker)
TimeSourceNode * get_node(const TimeSourceKey &key) const
bool is_same_nodetree_node_dependency(const KeyFrom &key_from, const KeyTo &key_to)
virtual void build_scene_speakers(Scene *scene, ViewLayer *view_layer)
OperationNode * find_node(const OperationKey &key) const
virtual void build_armature(bArmature *armature)
virtual void build_armature_bone_collections(blender::Span< BoneCollection * > collections)
virtual void build_armature_bones(ListBase *bones)
virtual void build_object_pointcache(Object *object)
virtual void build_constraints(ID *id, NodeType component_type, const char *component_subdata, ListBase *constraints, RootPChanMap *root_map)
virtual void build_object_modifiers(Object *object)
virtual void build_animdata_curves_targets(ID *id, ComponentKey &adt_key, OperationNode *operation_from, ListBase *curves)
virtual void build_object_data_light(Object *object)
void add_customdata_mask(Object *object, const DEGCustomDataMeshMasks &customdata_masks)
bool is_same_bone_dependency(const KeyFrom &key_from, const KeyTo &key_to)
virtual void build_object_data_camera(Object *object)
virtual void build_object_data_geometry(Object *object)
DepsgraphRelationBuilder(Main *bmain, Depsgraph *graph, DepsgraphBuilderCache *cache)
virtual void build_object_data_lightprobe(Object *object)
virtual void build_particle_settings(ParticleSettings *part)
virtual void build_object_light_linking(Object *emitter)
void add_special_eval_flag(ID *id, uint32_t flag)
virtual void build_driver_scene_camera_variable(const OperationKey &driver_key, const RNAPathKey &self_key, Scene *scene, const char *rna_path)
virtual void build_movieclip(MovieClip *clip)
virtual void build_nodetree(bNodeTree *ntree)
Relation * add_relation(const KeyFrom &key_from, const KeyTo &key_to, const char *description, int flags=0)
virtual void build_object_data_geometry_datablock(ID *obdata)
virtual void build_animdata_fcurve_target(ID *id, PointerRNA id_ptr, ComponentKey &adt_key, OperationNode *operation_from, FCurve *fcu)
void add_particle_forcefield_relations(const OperationKey &key, Object *object, ParticleSystem *psys, EffectorWeights *eff, bool add_absorption, const char *name)
virtual void build_nested_datablock(ID *owner, ID *id, bool flush_cow_changes)
virtual void build_particle_system_visualization_object(Object *object, ParticleSystem *psys, Object *draw_object)
virtual void build_lightprobe(LightProbe *probe)
void add_visibility_relation(ID *id_from, ID *id_to)
virtual void build_driver_variables(ID *id, FCurve *fcurve)
virtual void build_object_instance_collection(Object *object)
virtual void build_nested_shapekey(ID *owner, Key *key)
virtual void build_object_parent(Object *object)
bool has_node(const ComponentKey &key) const
virtual void build_object_data_speaker(Object *object)
virtual void build_light_linking_collection(Object *emitter, Collection *collection)
Relation * add_operation_relation(OperationNode *node_from, OperationNode *node_to, const char *description, int flags=0)
virtual void build_object_data(Object *object)
virtual void build_idproperties(IDProperty *id_property)
virtual void build_materials(ID *owner, Material **materials, int num_materials)
virtual void build_cachefile(CacheFile *cache_file)
virtual void build_object_shading(Object *object)
DepsNodeHandle create_node_handle(const KeyType &key, const char *default_name="")
virtual void build_animdata_nlastrip_targets(ID *id, ComponentKey &adt_key, OperationNode *operation_from, ListBase *strips)
Relation * add_time_relation(TimeSourceNode *timesrc, Node *node_to, const char *description, int flags=0)
virtual void build_particle_systems(Object *object)
Node * find_node(const PointerRNA *ptr, const PropertyRNA *prop, RNAPointerSource source)
OperationNode * node
#define DEG_DEBUG_PRINTF(depsgraph, type,...)
Definition deg_debug.h:45
const IDNode * id_node
FreestyleLineStyle linestyle
#define GS(x)
Definition iris.cc:202
void SEQ_for_each_callback(ListBase *seqbase, SeqForEachFunc callback, void *user_data)
Definition iterator.cc:43
static ulong state[N]
bNodeTree ** node_tree_ptr_from_id(ID *id)
Definition node.cc:3712
static bool seq_build_prop_cb(Sequence *seq, void *user_data)
bool rna_prop_affects_parameters_node(const PointerRNA *ptr, const PropertyRNA *prop)
static const ModifierData * get_latter_modifier(const ModifierData *md1, const ModifierData *md2)
ListBase * build_collision_relations(Depsgraph *graph, Collection *collection, uint modifier_type)
static bool rigidbody_object_depends_on_evaluated_geometry(const RigidBodyOb *rbo)
ListBase * build_effector_relations(Depsgraph *graph, Collection *collection)
const char * operationCodeAsString(OperationCode opcode)
bool deg_eval_copy_is_needed(const ID *id_orig)
bool RNA_struct_is_a(const StructRNA *type, const StructRNA *srna)
bool RNA_pointer_is_null(const PointerRNA *ptr)
const char * RNA_property_identifier(const PropertyRNA *prop)
PointerRNA RNA_id_pointer_create(ID *id)
bool RNA_path_resolve_full(const PointerRNA *ptr, const char *path, PointerRNA *r_ptr, PropertyRNA **r_prop, int *r_index)
Definition rna_path.cc:537
unsigned int uint32_t
Definition stdint.h:80
signed int int32_t
Definition stdint.h:77
bAction * action
int32_t slot_handle
ListBase drivers
ListBase nla_tracks
char name[64]
struct Collection * group
struct ClothCollSettings * coll_parms
struct Object * bevobj
struct Object * textoncurve
struct Object * taperobj
struct Object * surface
struct ViewLayer * view_layer
struct Collection * group
char * rna_path
ChannelDriver * driver
int array_index
struct bNodeTree * nodetree
void * pointer
Definition DNA_ID.h:145
IDPropertyData data
Definition DNA_ID.h:168
Definition DNA_ID.h:413
IDProperty * properties
Definition DNA_ID.h:456
char name[66]
Definition DNA_ID.h:425
struct AnimData * adt
ListBase block
struct Collection * blocker_collection
struct Collection * receiver_collection
struct bNodeTree * nodetree
void * first
char parent[64]
struct MaterialGPencilStyle * gp_style
struct ModifierData * prev
void(* update_depsgraph)(ModifierData *md, const ModifierUpdateDepsgraphContext *ctx)
const NodeType * type
Definition graph/node.h:178
short transflag
LightLinking * light_linking
struct Object * parent
unsigned int type
struct ListBase targets
ParticleSettings * part
struct ClothModifierData * clmd
ID * owner_id
Definition RNA_types.hh:40
StructRNA * type
Definition RNA_types.hh:41
void * data
Definition RNA_types.hh:42
struct Collection * group
struct EffectorWeights * effector_weights
struct Object * camera
struct Scene * scene
struct bSound * sound
struct IDProperty * prop
void(* update_depsgraph)(struct ShaderFxData *fx, const struct ModifierUpdateDepsgraphContext *ctx)
struct bSound * sound
ListBase curves
struct Material ** mat
IDProperty * prop
void * default_value
bNodeTreeRuntimeHandle * runtime
OperationNode * find_operation(OperationIDKey key) const
static DEGCustomDataMeshMasks MaskVert(const uint64_t vert_mask)
static DEGCustomDataMeshMasks MaskFace(const uint64_t face_mask)
static DEGCustomDataMeshMasks MaskLoop(const uint64_t loop_mask)
static DEGCustomDataMeshMasks MaskEdge(const uint64_t edge_mask)
static DEGCustomDataMeshMasks MaskPoly(const uint64_t poly_mask)
IDNode * find_id_node(const ID *id) const
Definition depsgraph.cc:105
eEvaluationMode mode
Definition depsgraph.hh:136
Relation * add_new_relation(Node *from, Node *to, const char *description, int flags=0)
Definition depsgraph.cc:177
TimeSourceNode * time_source
Definition depsgraph.hh:93
ComponentNode * find_component(NodeType type, const char *name="") const
virtual OperationNode * get_entry_operation()
Definition deg_node.hh:201
virtual string identifier() const
Definition deg_node.cc:304
virtual OperationNode * get_exit_operation()
Definition deg_node.hh:205
virtual OperationNode * get_entry_operation() override
virtual string identifier() const override
PointerRNA * ptr
Definition wm_files.cc:4126
uint8_t flag
Definition wm_window.cc:138