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