Blender V4.5
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_IP:
603 case ID_SCR:
604 case ID_VF:
605 case ID_BR:
606 case ID_WM:
607 case ID_PAL:
608 case ID_PC:
609 case ID_WS:
612 break;
613 }
614}
615
617{
618 if (built_map_.check_is_built_and_tag(id)) {
619 return;
620 }
621
622 const BuilderStack::ScopedEntry stack_entry = stack_.trace(*id);
623
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 (!built_map_.check_is_built_and_tag(collection, BuilderMap::TAG_COLLECTION_PROPERTIES)) {
640 build_idproperties(collection->id.properties);
641 build_parameters(&collection->id);
642 }
643
644 if (from_layer_collection != nullptr) {
645 /* If we came from layer collection we don't go deeper, view layer builder takes care of going
646 * deeper.
647 *
648 * NOTE: Do early output before tagging build as done, so possible subsequent builds from
649 * outside of the layer collection properly recurses into all the nested objects and
650 * collections. */
651
652 if (!built_map_.check_is_built_and_tag(collection,
654 {
655 const ComponentKey collection_hierarchy_key{&collection->id, NodeType::HIERARCHY};
656 OperationNode *collection_hierarchy_exit =
657 this->find_node(collection_hierarchy_key)->get_exit_operation();
658 LISTBASE_FOREACH (CollectionObject *, cob, &collection->gobject) {
659 Object *object = cob->ob;
660 const ComponentKey object_hierarchy_key{&object->id, NodeType::HIERARCHY};
661 /* Check whether the object hierarchy node exists, because the view layer builder can skip
662 * bases if they are constantly excluded from the collections. */
663 if (Node *object_hierarchy_node = this->find_node(object_hierarchy_key)) {
664 /* Note that while view layer builder ensures objects are built first and only then layer
665 * collections are built, it is not possible to assert() here: the object might be pulled
666 * into the dependency graph via different indirections, and it might not have been
667 * traversed into at this point.
668 * This build_object() is more of a safety measure, which follows the common rule in the
669 * dependency graph builder: ensure the entity is built when you encounter it. */
670 build_object(object);
671 this->add_operation_relation(collection_hierarchy_exit,
672 object_hierarchy_node->get_entry_operation(),
673 "Collection -> Object hierarchy");
674 }
675 }
676 }
677
678 return;
679 }
680
681 if (built_map_.check_is_built_and_tag(collection)) {
682 return;
683 }
684
685 const BuilderStack::ScopedEntry stack_entry = stack_.trace(collection->id);
686
687 const OperationKey collection_geometry_key{
689
690 const ComponentKey collection_hierarchy_key{&collection->id, NodeType::HIERARCHY};
691 OperationNode *collection_hierarchy_exit =
692 this->find_node(collection_hierarchy_key)->get_exit_operation();
693
694 LISTBASE_FOREACH (CollectionObject *, cob, &collection->gobject) {
695 Object *object = cob->ob;
696
697 build_object(object);
698
699 /* Unfortunately this may add duplicates with the hierarchy relations added below above. This
700 * is necessary though, for collections that are built as layer collections and otherwise,
701 * where an object may not be built yet in the layer collection case. */
702 const ComponentKey object_hierarchy_key{&object->id, NodeType::HIERARCHY};
703 Node *object_hierarchy_node = this->find_node(object_hierarchy_key);
704 this->add_operation_relation(collection_hierarchy_exit,
705 object_hierarchy_node->get_entry_operation(),
706 "Collection -> Object hierarchy");
707
708 const OperationKey object_instance_geometry_key{
710 add_relation(object_instance_geometry_key, collection_geometry_key, "Collection Geometry");
711
712 /* An instance is part of the geometry of the collection. */
713 if (object->type == OB_EMPTY) {
714 Collection *collection_instance = cob->ob->instance_collection;
715 if (collection_instance != nullptr) {
716 const OperationKey collection_instance_key{
718 add_relation(collection_instance_key, collection_geometry_key, "Collection Geometry");
719 }
720 }
721 }
722
723 LISTBASE_FOREACH (CollectionChild *, child, &collection->children) {
724 build_collection(nullptr, child->collection);
725 const OperationKey child_collection_geometry_key{
727 add_relation(child_collection_geometry_key, collection_geometry_key, "Collection Geometry");
728 }
729}
730
732{
733 if (built_map_.check_is_built_and_tag(object)) {
734 return;
735 }
736
737 const BuilderStack::ScopedEntry stack_entry = stack_.trace(object->id);
738
739 /* Object Transforms. */
740 OperationCode base_op = (object->parent) ? OperationCode::TRANSFORM_PARENT :
742 OperationKey base_op_key(&object->id, NodeType::TRANSFORM, base_op);
744 OperationKey local_transform_key(
746 OperationKey parent_transform_key(
749 OperationKey final_transform_key(
752
753 add_relation(init_transform_key, local_transform_key, "Transform Init");
754
755 /* Various flags, flushing from bases/collections. */
757
758 /* Parenting. */
759 if (object->parent != nullptr) {
760 /* Make sure parent object's relations are built. */
761 build_object(object->parent);
762 /* Parent relationship. */
763 build_object_parent(object);
764 /* Local -> parent. */
765 add_relation(local_transform_key, parent_transform_key, "ObLocal -> ObParent");
766 }
767
770 "Instance Geometry -> Geometry");
771
773 OperationKey{&object->id, NodeType::INSTANCING, OperationCode::INSTANCE_GEOMETRY},
774 "Transform -> Instance Geometry");
775
776 /* Modifiers. */
778
779 /* Grease Pencil Modifiers. */
780 if (object->greasepencil_modifiers.first != nullptr) {
781 BuilderWalkUserData data;
782 data.builder = this;
783 BKE_gpencil_modifiers_foreach_ID_link(object, modifier_walk, &data);
784 }
785
786 /* Shader FX. */
787 if (object->shader_fx.first != nullptr) {
788 BuilderWalkUserData data;
789 data.builder = this;
790 BKE_shaderfx_foreach_ID_link(object, modifier_walk, &data);
791 }
792
793 /* Constraints. */
794 if (object->constraints.first != nullptr) {
795 BuilderWalkUserData data;
796 data.builder = this;
797 BKE_constraints_id_loop(&object->constraints, constraint_walk, IDWALK_NOP, &data);
798 }
799
800 /* Object constraints. */
801 OperationKey object_transform_simulation_init_key(
803 if (object->constraints.first != nullptr) {
804 OperationKey constraint_key(
806 /* Constraint relations. */
807 build_constraints(&object->id, NodeType::TRANSFORM, "", &object->constraints, nullptr);
808 /* operation order */
809 add_relation(base_op_key, constraint_key, "ObBase-> Constraint Stack");
810 add_relation(constraint_key, final_transform_key, "ObConstraints -> Done");
811 add_relation(constraint_key, ob_eval_key, "Constraint -> Transform 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 else {
819 add_relation(base_op_key, ob_eval_key, "Eval");
821 ob_eval_key, object_transform_simulation_init_key, "Transform Eval -> Simulation Init");
822 add_relation(object_transform_simulation_init_key,
823 final_transform_key,
824 "Simulation -> Final Transform");
825 }
826
828
829 /* Animation data */
830 build_animdata(&object->id);
831
832 /* Object data. */
833 build_object_data(object);
834
835 /* Particle systems. */
836 if (object->particlesystem.first != nullptr) {
838 }
839
840 /* Force field Texture. */
841 if ((object->pd != nullptr) && (object->pd->forcefield == PFIELD_TEXTURE) &&
842 (object->pd->tex != nullptr))
843 {
844 build_texture(object->pd->tex);
845 }
846
849
850 build_object_shading(object);
852
853 /* Synchronization back to original object. */
854 OperationKey synchronize_key(
856 add_relation(final_transform_key, synchronize_key, "Synchronize to Original");
857
858 /* Parameters. */
859 build_parameters(&object->id);
860
861 /* Visibility.
862 * Evaluate visibility node after the object's base_flags has been updated to the current state
863 * of collections restrict and object's restrict flags. */
864 const ComponentKey object_from_layer_entry_key(&object->id, NodeType::OBJECT_FROM_LAYER);
865 const ComponentKey visibility_key(&object->id, NodeType::VISIBILITY);
866 add_relation(object_from_layer_entry_key, visibility_key, "Object Visibility");
867}
868
869/* NOTE: Implies that the object has base in the current view layer. */
871{
872 /* It is possible to have situation when an object is pulled into the dependency graph in a
873 * few different ways:
874 *
875 * - Indirect driver dependency, which doesn't have a Base (or, Base is unknown).
876 * - Via a base from a view layer (view layer of the graph, or view layer of a set scene).
877 * - Possibly other ways, which are not important for decision making here.
878 *
879 * There needs to be a relation from view layer which has a base with the object so that the
880 * order of flags evaluation is correct (object-level base flags evaluation requires view layer
881 * to be evaluated first).
882 *
883 * This build call handles situation when object comes from a view layer, hence has a base, and
884 * needs a relation from the view layer. Do the relation prior to check of whether the object
885 * relations are built so that the relation is created from every view layer which has a base
886 * with this object. */
887
888 OperationKey view_layer_done_key(
890 OperationKey object_from_layer_entry_key(
892
893 add_relation(view_layer_done_key, object_from_layer_entry_key, "View Layer flags to Object");
894
895 /* Regular object building. */
896 build_object(object);
897}
898
900{
901 OperationKey object_from_layer_entry_key(
903 OperationKey object_from_layer_exit_key(
905 OperationKey object_flags_key(
907
908 if (!has_node(object_flags_key)) {
909 /* Just connect Entry -> Exit if there is no OBJECT_BASE_FLAGS node. */
910 add_relation(object_from_layer_entry_key, object_from_layer_exit_key, "Object from Layer");
911 return;
912 }
913
914 /* Entry -> OBJECT_BASE_FLAGS -> Exit */
915 add_relation(object_from_layer_entry_key, object_flags_key, "Base flags flush Entry");
916 add_relation(object_flags_key, object_from_layer_exit_key, "Base flags flush Exit");
917
918 /* Synchronization back to original object. */
919 OperationKey synchronize_key(
921 add_relation(object_from_layer_exit_key, synchronize_key, "Synchronize to Original");
922}
923
925{
926 if (BLI_listbase_is_empty(&object->modifiers)) {
927 return;
928 }
929
930 const OperationKey eval_init_key(
933
934 const ComponentKey object_visibility_key(&object->id, NodeType::VISIBILITY);
935 const OperationKey modifier_visibility_key(
937 add_relation(modifier_visibility_key,
938 object_visibility_key,
939 "modifier -> object visibility",
941
942 add_relation(modifier_visibility_key, eval_key, "modifier visibility -> geometry eval");
943
945 ctx.scene = scene_;
946 ctx.object = object;
947
948 OperationKey previous_key = eval_init_key;
950 const OperationKey modifier_key(
952
953 /* Relation for the modifier stack chain. */
954 add_relation(previous_key, modifier_key, "Modifier");
955
957 if (mti->update_depsgraph) {
958 const BuilderStack::ScopedEntry stack_entry = stack_.trace(*modifier);
959
960 DepsNodeHandle handle = create_node_handle(modifier_key);
961 ctx.node = reinterpret_cast<::DepsNodeHandle *>(&handle);
962 mti->update_depsgraph(modifier, &ctx);
963 }
964
965 /* Time dependency. */
967 const TimeSourceKey time_src_key;
968 add_relation(time_src_key, modifier_key, "Time Source -> Modifier");
969 }
970
971 previous_key = modifier_key;
972 }
973 add_relation(previous_key, eval_key, "modifier stack order");
974
975 /* Build IDs referenced by the modifiers. */
976 BuilderWalkUserData data;
977 data.builder = this;
978 BKE_modifiers_foreach_ID_link(object, modifier_walk, &data);
979}
980
982{
983 if (object->data == nullptr) {
984 return;
985 }
986 ID *obdata_id = (ID *)object->data;
987 /* Object data animation. */
988 if (!built_map_.check_is_built(obdata_id)) {
989 build_animdata(obdata_id);
990 }
991 /* type-specific data. */
992 switch (object->type) {
993 case OB_MESH:
994 case OB_CURVES_LEGACY:
995 case OB_FONT:
996 case OB_SURF:
997 case OB_MBALL:
998 case OB_LATTICE:
999 case OB_CURVES:
1000 case OB_POINTCLOUD:
1001 case OB_VOLUME:
1002 case OB_GREASE_PENCIL: {
1004 /* TODO(sergey): Only for until we support granular
1005 * update of curves. */
1006 if (object->type == OB_FONT) {
1007 Curve *curve = (Curve *)object->data;
1008 if (curve->textoncurve) {
1009 ComponentKey geometry_key((ID *)object->data, NodeType::GEOMETRY);
1010 ComponentKey transform_key(&object->id, NodeType::TRANSFORM);
1011 add_relation(transform_key, geometry_key, "Text on Curve own Transform");
1013 }
1014 }
1015 break;
1016 }
1017 case OB_ARMATURE:
1018 build_rig(object);
1019 break;
1020 case OB_LAMP:
1022 break;
1023 case OB_CAMERA:
1025 break;
1026 case OB_LIGHTPROBE:
1028 break;
1029 case OB_SPEAKER:
1031 break;
1032 }
1033 Key *key = BKE_key_from_object(object);
1034 if (key != nullptr) {
1035 ComponentKey geometry_key((ID *)object->data, NodeType::GEOMETRY);
1036 ComponentKey key_key(&key->id, NodeType::GEOMETRY);
1037 add_relation(key_key, geometry_key, "Shapekeys");
1038 build_nested_shapekey(&object->id, key);
1039 }
1040 /* Materials. */
1041 Material ***materials_ptr = BKE_object_material_array_p(object);
1042 if (materials_ptr != nullptr) {
1043 short *num_materials_ptr = BKE_object_material_len_p(object);
1044 ID *obdata = (ID *)object->data;
1045 build_materials(obdata, *materials_ptr, *num_materials_ptr);
1046 }
1047}
1048
1050{
1051 Camera *camera = (Camera *)object->data;
1052 build_camera(camera);
1053 ComponentKey object_parameters_key(&object->id, NodeType::PARAMETERS);
1054 ComponentKey camera_parameters_key(&camera->id, NodeType::PARAMETERS);
1055 add_relation(camera_parameters_key, object_parameters_key, "Camera -> Object");
1056}
1057
1059{
1060 Light *lamp = (Light *)object->data;
1061 build_light(lamp);
1062 ComponentKey lamp_parameters_key(&lamp->id, NodeType::PARAMETERS);
1063 ComponentKey object_parameters_key(&object->id, NodeType::PARAMETERS);
1064 add_relation(lamp_parameters_key, object_parameters_key, "Light -> Object");
1065 OperationKey object_shading_key(&object->id, NodeType::SHADING, OperationCode::SHADING);
1066 add_relation(lamp_parameters_key, object_shading_key, "Light -> Object Shading");
1067}
1068
1070{
1071 LightProbe *probe = (LightProbe *)object->data;
1072 build_lightprobe(probe);
1075 add_relation(probe_key, object_key, "LightProbe Update");
1076 OperationKey object_shading_key(&object->id, NodeType::SHADING, OperationCode::SHADING);
1077 add_relation(probe_key, object_shading_key, "LightProbe -> Object Shading");
1078}
1079
1081{
1082 Speaker *speaker = (Speaker *)object->data;
1083 build_speaker(speaker);
1084 ComponentKey speaker_key(&speaker->id, NodeType::AUDIO);
1085 ComponentKey object_key(&object->id, NodeType::AUDIO);
1086 add_relation(speaker_key, object_key, "Speaker Update");
1087}
1088
1090{
1091 Object *parent = object->parent;
1092 ID *parent_id = &object->parent->id;
1093 ComponentKey object_transform_key(&object->id, NodeType::TRANSFORM);
1094 /* Type-specific links. */
1095 switch (object->partype) {
1096 /* Armature Deform (Virtual Modifier) */
1097 case PARSKEL: {
1098 ComponentKey parent_transform_key(parent_id, NodeType::TRANSFORM);
1099 add_relation(parent_transform_key, object_transform_key, "Parent Armature Transform");
1100
1101 if (parent->type == OB_ARMATURE) {
1102 ComponentKey object_geometry_key(&object->id, NodeType::GEOMETRY);
1103 ComponentKey parent_pose_key(parent_id, NodeType::EVAL_POSE);
1105 parent_transform_key, object_geometry_key, "Parent Armature Transform -> Geometry");
1106 add_relation(parent_pose_key, object_geometry_key, "Parent Armature Pose -> Geometry");
1107
1109 &object->id, object_geometry_key, "Virtual Armature Modifier");
1110 }
1111
1112 break;
1113 }
1114
1115 /* Vertex Parent */
1116 case PARVERT1:
1117 case PARVERT3: {
1118 ComponentKey parent_key(parent_id, NodeType::GEOMETRY);
1119 add_relation(parent_key, object_transform_key, "Vertex Parent");
1120 /* Original index is used for optimizations of lookups for subdiv
1121 * only meshes.
1122 * TODO(sergey): This optimization got lost at 2.8, so either verify
1123 * we can get rid of this mask here, or bring the optimization
1124 * back. */
1130 ComponentKey transform_key(parent_id, NodeType::TRANSFORM);
1131 add_relation(transform_key, object_transform_key, "Vertex Parent TFM");
1132 break;
1133 }
1134
1135 /* Bone Parent */
1136 case PARBONE: {
1137 if (object->parsubstr[0] != '\0') {
1138 ComponentKey parent_bone_key(parent_id, NodeType::BONE, object->parsubstr);
1139 OperationKey parent_transform_key(
1141 add_relation(parent_bone_key, object_transform_key, "Bone Parent");
1142 add_relation(parent_transform_key, object_transform_key, "Armature Parent");
1143 }
1144 break;
1145 }
1146
1147 default: {
1148 if (object->parent->type == OB_LATTICE) {
1149 /* Lattice Deform Parent - Virtual Modifier. */
1150 ComponentKey parent_key(parent_id, NodeType::TRANSFORM);
1151 ComponentKey geom_key(parent_id, NodeType::GEOMETRY);
1152 add_relation(parent_key, object_transform_key, "Lattice Deform Parent");
1153 add_relation(geom_key, object_transform_key, "Lattice Deform Parent Geom");
1154 }
1155 else if (object->parent->type == OB_CURVES_LEGACY) {
1156 Curve *cu = (Curve *)object->parent->data;
1157
1158 if (cu->flag & CU_PATH) {
1159 /* Follow Path. */
1160 ComponentKey parent_key(parent_id, NodeType::GEOMETRY);
1161 add_relation(parent_key, object_transform_key, "Curve Follow Parent");
1162 ComponentKey transform_key(parent_id, NodeType::TRANSFORM);
1163 add_relation(transform_key, object_transform_key, "Curve Follow TFM");
1164 }
1165 else {
1166 /* Standard Parent. */
1167 ComponentKey parent_key(parent_id, NodeType::TRANSFORM);
1168 add_relation(parent_key, object_transform_key, "Curve Parent");
1169 }
1170 }
1171 else {
1172 /* Standard Parent. */
1173 ComponentKey parent_key(parent_id, NodeType::TRANSFORM);
1174 add_relation(parent_key, object_transform_key, "Parent");
1175 }
1176 break;
1177 }
1178 }
1179 /* Meta-balls are the odd balls here (no pun intended): they will request
1180 * instance-list (formerly known as dupli-list) during evaluation. This is
1181 * their way of interacting with all instanced surfaces, making a nice
1182 * effect when is used form particle system. */
1183 if (object->type == OB_MBALL && parent->transflag & OB_DUPLI) {
1184 ComponentKey parent_geometry_key(parent_id, NodeType::GEOMETRY);
1185 /* NOTE: Meta-balls are evaluating geometry only after their transform,
1186 * so we only hook up to transform channel here. */
1187 add_relation(parent_geometry_key, object_transform_key, "Parent");
1188 }
1189
1190 /* Dupliverts uses original vertex index. */
1191 if (parent->transflag & OB_DUPLIVERTS) {
1193 }
1194}
1195
1196/* Returns the modifier that is last in the modifier stack. */
1197static const ModifierData *get_latter_modifier(const ModifierData *md1, const ModifierData *md2)
1198{
1199 if (md1 == nullptr) {
1200 return md2;
1201 }
1202 if (md2 == nullptr) {
1203 return md1;
1204 }
1205
1206 for (const ModifierData *md = md2->prev; md; md = md->prev) {
1207 if (md == md1) {
1208 return md2;
1209 }
1210 }
1211 return md1;
1212}
1213
1215{
1216 std::optional<ComponentKey> point_cache_key;
1217 bool has_rigid_body_relation = false;
1218 bool has_geometry_eval_relation = false;
1219 const ModifierData *last_input_modifier = nullptr;
1221 *object, *scene_, false, [&](PTCacheID &ptcache_id, ModifierData *md) {
1222 if (!point_cache_key) {
1223 point_cache_key = ComponentKey(&object->id, NodeType::POINT_CACHE);
1224 }
1225
1226 /* Check which components needs the point cache. */
1227 if (!has_geometry_eval_relation) {
1228 has_geometry_eval_relation = true;
1229
1231 add_relation(*point_cache_key, geometry_key, "Point Cache -> Geometry");
1232 }
1233 if (!has_rigid_body_relation && ptcache_id.type == PTCACHE_TYPE_RIGIDBODY) {
1234 if (object->rigidbody_object->type == RBO_TYPE_PASSIVE) {
1235 return true;
1236 }
1237 has_rigid_body_relation = true;
1238
1239 OperationKey transform_key(
1241 add_relation(*point_cache_key, transform_key, "Point Cache -> Rigid Body");
1242 /* Manual changes to effectors need to invalidate simulation.
1243 *
1244 * Don't add this relation for the render pipeline dependency graph as it does not
1245 * contain rigid body simulation. Good thing is that there are no user edits in such
1246 * dependency graph, so the relation is not really needed in it. */
1247 if (!graph_->is_render_pipeline_depsgraph) {
1248 OperationKey rigidbody_rebuild_key(
1250 add_relation(rigidbody_rebuild_key,
1251 *point_cache_key,
1252 "Rigid Body Rebuild -> Point Cache Reset",
1254 }
1255 }
1256
1257 if (md && md->prev) {
1258 last_input_modifier = get_latter_modifier(last_input_modifier, md->prev);
1259 }
1260
1261 return true;
1262 });
1263
1264 /* Manual edits to any dependency (or self) should reset the point cache. */
1265 if (point_cache_key) {
1266 OperationKey transform_eval_key(
1268 add_relation(transform_eval_key,
1269 *point_cache_key,
1270 "Transform Simulation -> Point Cache",
1272
1273 /* For caches in specific modifiers:
1274 * Input data changes from previous modifiers require a point cache reset. */
1275 if (last_input_modifier != nullptr) {
1276 const OperationKey input_modifier_key(
1277 &object->id, NodeType::GEOMETRY, OperationCode::MODIFIER, last_input_modifier->name);
1278 add_relation(input_modifier_key,
1279 *point_cache_key,
1280 "Previous Modifier -> Point Cache",
1282 }
1283 else {
1284 OperationKey geometry_init_key(
1286 add_relation(geometry_init_key,
1287 *point_cache_key,
1288 "Geometry Init -> Point Cache",
1290 }
1291 }
1292}
1293
1295{
1296 if (object->instance_collection == nullptr) {
1297 return;
1298 }
1299
1300 Collection *instance_collection = object->instance_collection;
1301
1302 build_collection(nullptr, instance_collection);
1303
1304 const OperationKey object_transform_final_key(
1306 const OperationKey instancer_key(&object->id, NodeType::INSTANCING, OperationCode::INSTANCER);
1307
1308 FOREACH_COLLECTION_VISIBLE_OBJECT_RECURSIVE_BEGIN (instance_collection, ob, graph_->mode) {
1309 const ComponentKey dupli_transform_key(&ob->id, NodeType::TRANSFORM);
1310 add_relation(dupli_transform_key, object_transform_final_key, "Dupligroup");
1311
1312 /* Hook to special component, to ensure proper visibility/evaluation optimizations. */
1314 instancer_key,
1315 "Instance -> Instancer");
1316 }
1318}
1319
1321{
1322 const OperationKey shading_done_key(&object->id, NodeType::SHADING, OperationCode::SHADING_DONE);
1323
1324 const OperationKey shading_key(&object->id, NodeType::SHADING, OperationCode::SHADING);
1325 add_relation(shading_key, shading_done_key, "Shading -> Done");
1326
1327 /* Hook up shading component to the instance, so that if the object is instanced by a visible
1328 * object the shading component is ensured to be evaluated.
1329 * Don't to flushing to avoid re-evaluation of geometry when the object is used as part of a
1330 * collection used as a boolean modifier operand. */
1331 add_relation(shading_done_key,
1333 "Light Linking -> Instance",
1335}
1336
1338{
1339 const ComponentKey hierarchy_key(&emitter->id, NodeType::HIERARCHY);
1340 const OperationKey shading_done_key(
1342 const OperationKey light_linking_key(
1344
1345 add_relation(hierarchy_key, light_linking_key, "Light Linking From Layer");
1346 add_relation(light_linking_key, shading_done_key, "Light Linking -> Shading Done");
1347
1348 if (emitter->light_linking) {
1350
1351 build_light_linking_collection(emitter, light_linking.receiver_collection);
1352 build_light_linking_collection(emitter, light_linking.blocker_collection);
1353 }
1354}
1355
1357 Collection *collection)
1358{
1359 if (collection == nullptr) {
1360 return;
1361 }
1362
1363 build_collection(nullptr, collection);
1364
1365 /* TODO(sergey): Avoid duplicate dependencies if multiple emitters are using the same collection.
1366 */
1367
1368 const OperationKey emitter_light_linking_key(
1370
1371 const OperationKey collection_parameters_entry_key(
1373 const OperationKey collection_parameters_exit_key(
1375 const OperationKey collection_hierarchy_key(
1377
1378 const OperationKey collection_light_linking_key(
1380
1381 /* Order of parameters evaluation within the receiver collection. */
1382 /* TODO(sergey): Can optimize this out by explicitly separating the different built tags. This
1383 * needs to be done in all places where the collection is built (is not something that can be
1384 * easily solved from just adding the light linking functionality). */
1385 add_relation(collection_parameters_entry_key,
1386 collection_light_linking_key,
1387 "Entry -> Collection Light Linking",
1389 add_relation(collection_light_linking_key,
1390 collection_parameters_exit_key,
1391 "Collection Light Linking -> Exit",
1393
1394 add_relation(collection_hierarchy_key,
1395 collection_light_linking_key,
1396 "Collection Hierarchy -> Light Linking",
1398
1399 /* Order to ensure the emitter's light linking is only evaluated after the receiver collection.
1400 * This is because light linking runtime data is "cached" om the emitter object for the
1401 * simplicity of access, but the mask is allocated per collection bases (so that if two emitters
1402 * share the same receiving collection they share the same runtime data). */
1403 add_relation(collection_light_linking_key,
1404 emitter_light_linking_key,
1405 "Collection -> Object Light Linking");
1406}
1407
1409 NodeType component_type,
1410 const char *component_subdata,
1412 RootPChanMap *root_map)
1413{
1414 OperationKey constraint_op_key(id,
1415 component_type,
1416 component_subdata,
1417 (component_type == NodeType::BONE) ?
1420 /* Add dependencies for each constraint in turn. */
1423 ListBase targets = {nullptr, nullptr};
1424 /* Invalid constraint type. */
1425 if (cti == nullptr) {
1426 continue;
1427 }
1428
1429 const BuilderStack::ScopedEntry stack_entry = stack_.trace(*con);
1430
1431 /* Special case for camera tracking -- it doesn't use targets to
1432 * define relations. */
1433 /* TODO: we can now represent dependencies in a much richer manner,
1434 * so review how this is done. */
1435 if (ELEM(cti->type,
1439 {
1440 bool depends_on_camera = false;
1441 if (cti->type == CONSTRAINT_TYPE_FOLLOWTRACK) {
1443 if (((data->clip) || (data->flag & FOLLOWTRACK_ACTIVECLIP)) && data->track[0]) {
1444 depends_on_camera = true;
1445 }
1446 if (data->depth_ob) {
1447 ComponentKey depth_transform_key(&data->depth_ob->id, NodeType::TRANSFORM);
1448 ComponentKey depth_geometry_key(&data->depth_ob->id, NodeType::GEOMETRY);
1449 add_relation(depth_transform_key, constraint_op_key, cti->name);
1450 add_relation(depth_geometry_key, constraint_op_key, cti->name);
1451 }
1452 }
1453 else if (cti->type == CONSTRAINT_TYPE_OBJECTSOLVER) {
1454 depends_on_camera = true;
1455 }
1456 if (depends_on_camera && scene_->camera != nullptr) {
1457 ComponentKey camera_key(&scene_->camera->id, NodeType::TRANSFORM);
1458 add_relation(camera_key, constraint_op_key, cti->name);
1459 }
1460 /* TODO(sergey): This is more a TimeSource -> MovieClip ->
1461 * Constraint dependency chain. */
1462 TimeSourceKey time_src_key;
1463 add_relation(time_src_key, constraint_op_key, "TimeSrc -> Animation");
1464 }
1465 else if (cti->type == CONSTRAINT_TYPE_TRANSFORM_CACHE) {
1466 /* TODO(kevin): This is more a TimeSource -> CacheFile -> Constraint
1467 * dependency chain. */
1468 TimeSourceKey time_src_key;
1469 add_relation(time_src_key, constraint_op_key, "TimeSrc -> Animation");
1471 if (data->cache_file) {
1472 ComponentKey cache_key(&data->cache_file->id, NodeType::CACHE);
1473 add_relation(cache_key, constraint_op_key, cti->name);
1474 }
1475 }
1476 else if (BKE_constraint_targets_get(con, &targets)) {
1477 LISTBASE_FOREACH (bConstraintTarget *, ct, &targets) {
1478 if (ct->tar == nullptr) {
1479 continue;
1480 }
1482 /* Ignore IK constraints - these are handled separately
1483 * (on pose level). */
1484 }
1486 /* These constraints require path geometry data. */
1487 ComponentKey target_key(&ct->tar->id, NodeType::GEOMETRY);
1488 add_relation(target_key, constraint_op_key, cti->name);
1489 ComponentKey target_transform_key(&ct->tar->id, NodeType::TRANSFORM);
1490 add_relation(target_transform_key, constraint_op_key, cti->name);
1491 }
1492 else if ((ct->tar->type == OB_ARMATURE) && (ct->subtarget[0])) {
1493 OperationCode opcode;
1494 /* relation to bone */
1495 opcode = bone_target_opcode(
1496 &ct->tar->id, ct->subtarget, id, component_subdata, root_map);
1497 /* Armature constraint always wants the final position and chan_mat. */
1498 if (ELEM(con->type, CONSTRAINT_TYPE_ARMATURE)) {
1499 opcode = OperationCode::BONE_DONE;
1500 }
1501 /* if needs bbone shape, reference the segment computation */
1502 if (BKE_constraint_target_uses_bbone(con, ct) &&
1503 check_pchan_has_bbone_segments(ct->tar, ct->subtarget))
1504 {
1506 }
1507 OperationKey target_key(&ct->tar->id, NodeType::BONE, ct->subtarget, opcode);
1508 add_relation(target_key, constraint_op_key, cti->name);
1509 }
1510 else if (ELEM(ct->tar->type, OB_MESH, OB_LATTICE) && (ct->subtarget[0])) {
1511 /* Vertex group. */
1512 /* NOTE: Vertex group is likely to be used to get vertices
1513 * in a world space. This requires to know both geometry
1514 * and transformation of the target object. */
1515 ComponentKey target_transform_key(&ct->tar->id, NodeType::TRANSFORM);
1516 ComponentKey target_geometry_key(&ct->tar->id, NodeType::GEOMETRY);
1517 add_relation(target_transform_key, constraint_op_key, cti->name);
1518 add_relation(target_geometry_key, constraint_op_key, cti->name);
1520 }
1521 else if (con->type == CONSTRAINT_TYPE_SHRINKWRAP) {
1522 bShrinkwrapConstraint *scon = (bShrinkwrapConstraint *)con->data;
1523
1524 /* Constraints which requires the target object surface. */
1525 ComponentKey target_key(&ct->tar->id, NodeType::GEOMETRY);
1526 add_relation(target_key, constraint_op_key, cti->name);
1527
1528 /* Add dependency on normal layers if necessary. */
1529 if (ct->tar->type == OB_MESH && scon->shrinkType != MOD_SHRINKWRAP_NEAREST_VERTEX) {
1532 }
1533 }
1534
1535 /* NOTE: obdata eval now doesn't necessarily depend on the
1536 * object's transform. */
1537 ComponentKey target_transform_key(&ct->tar->id, NodeType::TRANSFORM);
1538 add_relation(target_transform_key, constraint_op_key, cti->name);
1539 }
1540 else {
1541 /* Standard object relation. */
1542 /* TODO: loc vs rot vs scale? */
1543 if (&ct->tar->id == id) {
1544 /* Constraint targeting its own object:
1545 * - This case is fine IF we're dealing with a bone
1546 * constraint pointing to its own armature. In that
1547 * case, it's just transform -> bone.
1548 * - If however it is a real self targeting case, just
1549 * make it depend on the previous constraint (or the
1550 * pre-constraint state). */
1551 if ((ct->tar->type == OB_ARMATURE) && (component_type == NodeType::BONE)) {
1552 OperationKey target_key(
1554 add_relation(target_key, constraint_op_key, cti->name);
1555 }
1556 else {
1557 OperationKey target_key(
1559 add_relation(target_key, constraint_op_key, cti->name);
1560 }
1561 }
1562 else {
1563 /* Normal object dependency. */
1564 OperationKey target_key(
1566 add_relation(target_key, constraint_op_key, cti->name);
1567 }
1568 }
1569 /* Constraints which needs world's matrix for transform.
1570 * TODO(sergey): More constraints here? */
1571 if (ELEM(con->type,
1576 {
1577 /* TODO(sergey): Add used space check. */
1578 ComponentKey target_transform_key(&ct->tar->id, NodeType::TRANSFORM);
1579 add_relation(target_transform_key, constraint_op_key, cti->name);
1580 }
1581 }
1582 BKE_constraint_targets_flush(con, &targets, true);
1583 }
1584 }
1585}
1586
1588{
1589 /* Images. */
1591 /* Animation curves, NLA, and Animation datablock. */
1593 /* Drivers. */
1595
1596 if (check_id_has_anim_component(id)) {
1597 ComponentKey animation_key(id, NodeType::ANIMATION);
1598 ComponentKey parameters_key(id, NodeType::PARAMETERS);
1599 add_relation(animation_key, parameters_key, "Animation -> Parameters");
1601 }
1602}
1603
1605{
1606 AnimData *adt = BKE_animdata_from_id(id);
1607 if (adt == nullptr) {
1608 return;
1609 }
1610 if (adt->action != nullptr) {
1611 build_action(adt->action);
1612 }
1613 if (adt->action == nullptr && BLI_listbase_is_empty(&adt->nla_tracks)) {
1614 return;
1615 }
1616 /* Ensure evaluation order from entry to exit. */
1620 add_relation(animation_entry_key, animation_eval_key, "Init -> Eval");
1621 add_relation(animation_eval_key, animation_exit_key, "Eval -> Exit");
1622 /* Wire up dependency from Actions. */
1623 ComponentKey adt_key(id, NodeType::ANIMATION);
1624 /* Relation from action itself. */
1625 if (adt->action != nullptr) {
1626 ComponentKey action_key(&adt->action->id, NodeType::ANIMATION);
1627 add_relation(action_key, adt_key, "Action -> Animation");
1628 }
1629 /* Get source operations. */
1630 Node *node_from = get_node(adt_key);
1631 BLI_assert(node_from != nullptr);
1632 if (node_from == nullptr) {
1633 return;
1634 }
1635 OperationNode *operation_from = node_from->get_exit_operation();
1636 BLI_assert(operation_from != nullptr);
1637 /* Build relations from animation operation to properties it changes. */
1638 if (adt->action != nullptr) {
1639 build_animdata_action_targets(id, adt->slot_handle, adt_key, operation_from, adt->action);
1640 }
1641 LISTBASE_FOREACH (NlaTrack *, nlt, &adt->nla_tracks) {
1642 if (!BKE_nlatrack_is_enabled(*adt, *nlt)) {
1643 continue;
1644 }
1645 build_animdata_nlastrip_targets(id, adt_key, operation_from, &nlt->strips);
1646 }
1647}
1648
1650 ID *id, PointerRNA id_ptr, ComponentKey &adt_key, OperationNode *operation_from, FCurve *fcu)
1651{
1653 PropertyRNA *prop;
1654 int index;
1655 if (!RNA_path_resolve_full(&id_ptr, fcu->rna_path, &ptr, &prop, &index)) {
1656 return;
1657 }
1658 Node *node_to = rna_node_query_.find_node(&ptr, prop, RNAPointerSource::ENTRY);
1659 if (node_to == nullptr) {
1660 return;
1661 }
1662 OperationNode *operation_to = node_to->get_entry_operation();
1663 /* NOTE: Special case for bones, avoid relation from animation to
1664 * each of the bones. Bone evaluation could only start from pose
1665 * init anyway. */
1666 if (operation_to->opcode == OperationCode::BONE_LOCAL) {
1668 add_relation(adt_key, pose_init_key, "Animation -> Prop", RELATION_CHECK_BEFORE_ADD);
1669 return;
1670 }
1671 graph_->add_new_relation(
1672 operation_from, operation_to, "Animation -> Prop", RELATION_CHECK_BEFORE_ADD);
1673 /* It is possible that animation is writing to a nested ID data-block,
1674 * need to make sure animation is evaluated after target ID is copied. */
1675 const IDNode *id_node_from = operation_from->owner->owner;
1676 const IDNode *id_node_to = operation_to->owner->owner;
1677 if (id_node_from != id_node_to) {
1678 ComponentKey cow_key(id_node_to->id_orig, NodeType::COPY_ON_EVAL);
1679 add_relation(cow_key,
1680 adt_key,
1681 "Animated Copy-on-Eval -> Animation",
1683 }
1684}
1685
1687 ComponentKey &adt_key,
1688 OperationNode *operation_from,
1689 ListBase *curves)
1690{
1691 /* Iterate over all curves and build relations. */
1692 PointerRNA id_ptr = RNA_id_pointer_create(id);
1693 LISTBASE_FOREACH (FCurve *, fcu, curves) {
1694 build_animdata_fcurve_target(id, id_ptr, adt_key, operation_from, fcu);
1695 }
1696}
1697
1699 const int32_t slot_handle,
1700 ComponentKey &adt_key,
1701 OperationNode *operation_from,
1702 bAction *dna_action)
1703{
1704 BLI_assert(id != nullptr);
1705 BLI_assert(operation_from != nullptr);
1706 BLI_assert(dna_action != nullptr);
1707 animrig::Action &action = dna_action->wrap();
1708
1709 if (action.is_empty()) {
1710 return;
1711 }
1712 if (action.is_action_legacy()) {
1713 build_animdata_curves_targets(id, adt_key, operation_from, &action.curves);
1714 return;
1715 }
1716
1717 const animrig::Slot *slot = action.slot_for_handle(slot_handle);
1718 if (slot == nullptr) {
1719 /* If there's no matching slot, there's no Action dependency. */
1720 return;
1721 }
1722
1723 PointerRNA id_ptr = RNA_id_pointer_create(id);
1724
1725 for (animrig::Layer *layer : action.layers()) {
1726 for (animrig::Strip *strip : layer->strips()) {
1727 switch (strip->type()) {
1728 case animrig::Strip::Type::Keyframe: {
1729 animrig::StripKeyframeData &strip_data = strip->data<animrig::StripKeyframeData>(action);
1730 animrig::Channelbag *channels = strip_data.channelbag_for_slot(*slot);
1731 if (channels == nullptr) {
1732 /* Go to next strip. */
1733 break;
1734 }
1735 for (FCurve *fcu : channels->fcurves()) {
1736 build_animdata_fcurve_target(id, id_ptr, adt_key, operation_from, fcu);
1737 }
1738 break;
1739 }
1740 }
1741 }
1742 }
1743}
1744
1746 ComponentKey &adt_key,
1747 OperationNode *operation_from,
1748 ListBase *strips)
1749{
1750 LISTBASE_FOREACH (NlaStrip *, strip, strips) {
1751 if (strip->act != nullptr) {
1752 build_action(strip->act);
1753
1754 ComponentKey action_key(&strip->act->id, NodeType::ANIMATION);
1755 add_relation(action_key, adt_key, "Action -> Animation");
1756
1758 id, strip->action_slot_handle, adt_key, operation_from, strip->act);
1759 }
1760 else if (strip->strips.first != nullptr) {
1761 build_animdata_nlastrip_targets(id, adt_key, operation_from, &strip->strips);
1762 }
1763 }
1764}
1765
1767{
1768 AnimData *adt = BKE_animdata_from_id(id);
1769 if (adt == nullptr || BLI_listbase_is_empty(&adt->drivers)) {
1770 return;
1771 }
1772 ComponentKey adt_key(id, NodeType::ANIMATION);
1774
1775 LISTBASE_FOREACH (FCurve *, fcu, &adt->drivers) {
1776 OperationKey driver_key(id,
1779 fcu->rna_path ? fcu->rna_path : "",
1780 fcu->array_index);
1781
1782 /* create the driver's relations to targets */
1783 build_driver(id, fcu);
1784
1785 /* prevent driver from occurring before its own animation... */
1786 if (adt->action || adt->nla_tracks.first) {
1787 add_relation(adt_key, driver_key, "AnimData Before Drivers");
1788 }
1789
1790 if (data_path_maybe_shared(*id, fcu->rna_path)) {
1791 add_relation(driver_unshare_key, driver_key, "Un-share shared data before drivers");
1792 }
1793 }
1794}
1795
1797{
1798 /* See #DepsgraphNodeBuilder::build_animation_images. */
1799 bool has_image_animation = false;
1800 if (ELEM(GS(id->name), ID_MA, ID_WO)) {
1802 if (ntree != nullptr && ntree->runtime->runtime_flag & NTREE_RUNTIME_FLAG_HAS_IMAGE_ANIMATION)
1803 {
1804 has_image_animation = true;
1805 }
1806 }
1807
1808 if (has_image_animation || BKE_image_user_id_has_animation(id)) {
1809 OperationKey image_animation_key(
1811 TimeSourceKey time_src_key;
1812 add_relation(time_src_key, image_animation_key, "TimeSrc -> Image Animation");
1813
1814 /* The image users of these ids may change during evaluation. Make sure that the image
1815 * animation update happens after evaluation. */
1816 if (GS(id->name) == ID_MA) {
1818 add_relation(material_update_key, image_animation_key, "Material Update -> Image Animation");
1819 }
1820 else if (GS(id->name) == ID_WO) {
1822 add_relation(world_update_key, image_animation_key, "World Update -> Image Animation");
1823 }
1824 else if (GS(id->name) == ID_NT) {
1826 add_relation(ntree_output_key, image_animation_key, "NTree Output -> Image Animation");
1827 }
1828 }
1829}
1830
1832{
1833 if (GS(id->name) != ID_OB) {
1834 return;
1835 }
1836
1837 const Object *object = (Object *)id;
1838 if (object->pd == nullptr || object->pd->forcefield == PFIELD_NULL) {
1839 return;
1840 }
1841
1842 /* Updates to animation data (in the UI, for example by altering FCurve Modifier parameters
1843 * animating force field strength) may need to rebuild the rigid body world. */
1844 ComponentKey animation_key(id, NodeType::ANIMATION);
1846 add_relation(animation_key, rigidbody_key, "Animation -> Rigid Body");
1847}
1848
1850{
1851 if (built_map_.check_is_built_and_tag(dna_action)) {
1852 return;
1853 }
1854
1855 const BuilderStack::ScopedEntry stack_entry = stack_.trace(dna_action->id);
1856
1857 build_parameters(&dna_action->id);
1858 build_idproperties(dna_action->id.properties);
1859
1860 blender::animrig::Action &action = dna_action->wrap();
1861 if (!action.is_empty()) {
1862 TimeSourceKey time_src_key;
1863 ComponentKey animation_key(&dna_action->id, NodeType::ANIMATION);
1864 add_relation(time_src_key, animation_key, "TimeSrc -> Animation");
1865 }
1866}
1867
1869{
1870 ChannelDriver *driver = fcu->driver;
1871 OperationKey driver_key(id,
1874 fcu->rna_path ? fcu->rna_path : "",
1875 fcu->array_index);
1876 /* Driver -> data components (for interleaved evaluation
1877 * bones/constraints/modifiers). */
1878 build_driver_data(id, fcu);
1879 /* Loop over variables to get the target relationships. */
1880 build_driver_variables(id, fcu);
1881 /* It's quite tricky to detect if the driver actually depends on time or
1882 * not, so for now we'll be quite conservative here about optimization and
1883 * consider all python drivers to be depending on time. */
1884 if (driver_depends_on_time(driver)) {
1885 TimeSourceKey time_src_key;
1886 add_relation(time_src_key, driver_key, "TimeSrc -> Driver");
1887 }
1888}
1889
1891{
1892 /* Validate the RNA path pointer just in case. */
1893 const char *rna_path = fcu->rna_path;
1894 if (rna_path == nullptr || rna_path[0] == '\0') {
1895 return;
1896 }
1897 /* Parse the RNA path to find the target property pointer. */
1898 RNAPathKey property_entry_key(id, rna_path, RNAPointerSource::ENTRY);
1899 if (RNA_pointer_is_null(&property_entry_key.ptr)) {
1900 /* TODO(sergey): This would only mean that driver is broken.
1901 * so we can't create relation anyway. However, we need to avoid
1902 * adding drivers which are known to be buggy to a dependency
1903 * graph, in order to save computational power. */
1904 return;
1905 }
1906 OperationKey driver_key(
1908 /* If the target of the driver is a Bone property, find the Armature data,
1909 * and then link the driver to all pose bone evaluation components that use
1910 * it. This is necessary to provide more granular dependencies specifically for
1911 * Bone objects, because the armature data doesn't have per-bone components,
1912 * and generic add_relation can only add one link. */
1913 ID *id_ptr = property_entry_key.ptr.owner_id;
1914 bool is_bone = id_ptr && property_entry_key.ptr.type == &RNA_Bone;
1915 /* If the Bone property is referenced via obj.pose.bones[].bone,
1916 * the RNA pointer refers to the Object ID, so skip to data. */
1917 if (is_bone && GS(id_ptr->name) == ID_OB) {
1918 id_ptr = (ID *)((Object *)id_ptr)->data;
1919 }
1920 if (is_bone && GS(id_ptr->name) == ID_AR) {
1921 /* Drivers on armature-level bone settings (i.e. bbone stuff),
1922 * which will affect the evaluation of corresponding pose bones. */
1923 Bone *bone = (Bone *)property_entry_key.ptr.data;
1924 if (bone == nullptr) {
1925 fprintf(stderr, "Couldn't find armature bone name for driver path - '%s'\n", rna_path);
1926 return;
1927 }
1928
1929 const char *prop_identifier = RNA_property_identifier(property_entry_key.prop);
1930 const bool driver_targets_bbone = STRPREFIX(prop_identifier, "bbone_");
1931
1932 /* Find objects which use this, and make their eval callbacks depend on this. */
1933 for (IDNode *to_node : graph_->id_nodes) {
1934 if (GS(to_node->id_orig->name) != ID_OB) {
1935 continue;
1936 }
1937
1938 /* We only care about objects with pose data which use this. */
1939 Object *object = (Object *)to_node->id_orig;
1940 if (object->data != id_ptr || object->pose == nullptr) {
1941 continue;
1942 }
1943
1944 bPoseChannel *pchan = BKE_pose_channel_find_name(object->pose, bone->name);
1945 if (pchan == nullptr) {
1946 continue;
1947 }
1948
1950 if (driver_targets_bbone) {
1953 }
1954 OperationKey bone_key(&object->id, NodeType::BONE, pchan->name, target_op);
1955 add_relation(driver_key, bone_key, "Arm Bone -> Driver -> Bone");
1956 }
1957 /* Make the driver depend on copy-on-eval, similar to the generic case below. */
1958 if (id_ptr != id) {
1959 ComponentKey cow_key(id_ptr, NodeType::COPY_ON_EVAL);
1961 cow_key, driver_key, "Driven Copy-on-Eval -> Driver", RELATION_CHECK_BEFORE_ADD);
1962 }
1963 }
1964 else {
1965 /* If it's not a Bone, handle the generic single dependency case. */
1966 Node *node_to = get_node(property_entry_key);
1967 if (node_to != nullptr) {
1968 add_relation(driver_key, property_entry_key, "Driver -> Driven Property");
1969 }
1970
1971 /* Similar to the case with f-curves, driver might drive a nested
1972 * data-block, which means driver execution should wait for that
1973 * data-block to be copied. */
1974 {
1975 PointerRNA id_ptr = RNA_id_pointer_create(id);
1977 if (RNA_path_resolve_full(&id_ptr, fcu->rna_path, &ptr, nullptr, nullptr)) {
1978 if (id_ptr.owner_id != ptr.owner_id) {
1979 ComponentKey cow_key(ptr.owner_id, NodeType::COPY_ON_EVAL);
1981 cow_key, driver_key, "Driven Copy-on-Eval -> Driver", RELATION_CHECK_BEFORE_ADD);
1982 }
1983 }
1984 }
1985 if (rna_prop_affects_parameters_node(&property_entry_key.ptr, property_entry_key.prop)) {
1986 RNAPathKey property_exit_key(property_entry_key.id,
1987 property_entry_key.ptr,
1988 property_entry_key.prop,
1991 add_relation(property_exit_key, parameters_key, "Driven Property -> Properties");
1992 }
1993 }
1994
1995 /* Assume drivers on a node tree affect the evaluated output of the node tree. In theory we could
1996 * check if the driven value actually affects the output, i.e. if it drives a node that is linked
1997 * to the output. */
1998 if (GS(id_ptr->name) == ID_NT) {
1999 ComponentKey ntree_output_key(id_ptr, NodeType::NTREE_OUTPUT);
2000 add_relation(driver_key, ntree_output_key, "Drivers -> NTree Output");
2001 if (reinterpret_cast<bNodeTree *>(id_ptr)->type == NTREE_GEOMETRY) {
2002 OperationKey ntree_geo_preprocess_key(
2004 add_relation(driver_key, ntree_geo_preprocess_key, "Drivers -> NTree Geo Preprocess");
2005 }
2006 }
2007}
2008
2010{
2011 ChannelDriver *driver = fcu->driver;
2012 OperationKey driver_key(id,
2015 fcu->rna_path ? fcu->rna_path : "",
2016 fcu->array_index);
2017 const char *rna_path = fcu->rna_path ? fcu->rna_path : "";
2018
2019 const RNAPathKey self_key(id, rna_path, RNAPointerSource::ENTRY);
2020
2021 DriverTargetContext driver_target_context;
2022 driver_target_context.scene = graph_->scene;
2023 driver_target_context.view_layer = graph_->view_layer;
2024
2025 LISTBASE_FOREACH (DriverVar *, dvar, &driver->variables) {
2026 /* Only used targets. */
2028 PointerRNA target_prop;
2029 if (!driver_get_target_property(&driver_target_context, dvar, dtar, &target_prop)) {
2030 continue;
2031 }
2032
2033 /* Property is always expected to be resolved to a non-null RNA property, which is always
2034 * relative to some ID. */
2035 BLI_assert(target_prop.owner_id);
2036
2037 ID *target_id = target_prop.owner_id;
2038
2039 build_id(target_id);
2040 build_driver_id_property(target_prop, dtar->rna_path);
2041
2042 Object *object = nullptr;
2043 if (GS(target_id->name) == ID_OB) {
2044 object = (Object *)target_id;
2045 }
2046 /* Special handling for directly-named bones. */
2047 if ((dtar->flag & DTAR_FLAG_STRUCT_REF) && (object && object->type == OB_ARMATURE) &&
2048 (dtar->pchan_name[0]))
2049 {
2050 bPoseChannel *target_pchan = BKE_pose_channel_find_name(object->pose, dtar->pchan_name);
2051 if (target_pchan == nullptr) {
2052 continue;
2053 }
2054 OperationKey variable_key(
2055 target_id, NodeType::BONE, target_pchan->name, OperationCode::BONE_DONE);
2056 if (is_same_bone_dependency(variable_key, self_key)) {
2057 continue;
2058 }
2059 add_relation(variable_key, driver_key, "Bone Target -> Driver");
2060 }
2061 else if (dtar->flag & DTAR_FLAG_STRUCT_REF) {
2062 /* Get node associated with the object's transforms. */
2063 if (target_id == id) {
2064 /* Ignore input dependency if we're driving properties of
2065 * the same ID, otherwise we'll be ending up in a cyclic
2066 * dependency here. */
2067 continue;
2068 }
2070 add_relation(target_key, driver_key, "Target -> Driver");
2071 }
2072 else if (dtar->rna_path != nullptr && dtar->rna_path[0] != '\0') {
2074 driver_key, self_key, target_id, target_prop, dtar->rna_path);
2075
2076 /* Add relations to all other cameras used by the scene timeline if applicable. */
2077 if (const char *camera_path = get_rna_path_relative_to_scene_camera(
2078 scene_, target_prop, dtar->rna_path))
2079 {
2080 build_driver_scene_camera_variable(driver_key, self_key, scene_, camera_path);
2081 }
2082
2083 /* The RNA getter for `object.data` can write to the mesh datablock due
2084 * to the call to `BKE_mesh_wrapper_ensure_subdivision()`. This relation
2085 * ensures it is safe to call when the driver is evaluated.
2086 *
2087 * For the sake of making the code more generic/defensive, the relation
2088 * is added for any geometry type.
2089 *
2090 * See #96289 for more info. */
2091 if (object != nullptr && OB_TYPE_IS_GEOMETRY(object->type)) {
2092 StringRef rna_path(dtar->rna_path);
2093 if (rna_path == "data" || rna_path.startswith("data.")) {
2094 ComponentKey ob_key(target_id, NodeType::GEOMETRY);
2095 add_relation(ob_key, driver_key, "ID -> Driver");
2096 }
2097 }
2098 }
2099 else {
2100 /* If rna_path is nullptr, and DTAR_FLAG_STRUCT_REF isn't set, this
2101 * is an incomplete target reference, so nothing to do here. */
2102 }
2103 }
2105 }
2106}
2107
2109 const RNAPathKey &self_key,
2110 Scene *scene,
2111 const char *rna_path)
2112{
2113 /* First, add relations to all cameras used in the timeline,
2114 * excluding scene->camera which was already handled by the caller. */
2115 bool animated = false;
2116
2117 LISTBASE_FOREACH (TimeMarker *, marker, &scene->markers) {
2118 if (!ELEM(marker->camera, nullptr, scene->camera)) {
2119 PointerRNA camera_ptr = RNA_id_pointer_create(&marker->camera->id);
2120 build_driver_id_property(camera_ptr, rna_path);
2121 build_driver_rna_path_variable(driver_key, self_key, &scene->id, camera_ptr, rna_path);
2122 animated = true;
2123 }
2124 }
2125
2126 /* If timeline indeed switches the camera, this variable also implicitly depends on time. */
2127 if (animated) {
2128 TimeSourceKey time_src_key;
2129 add_relation(time_src_key, driver_key, "TimeSrc -> Driver Camera Ref");
2130 }
2131}
2132
2134 const RNAPathKey &self_key,
2135 ID *target_id,
2136 const PointerRNA &target_prop,
2137 const char *rna_path)
2138{
2139 RNAPathKey variable_exit_key(target_prop, rna_path, RNAPointerSource::EXIT);
2140 if (RNA_pointer_is_null(&variable_exit_key.ptr)) {
2141 return;
2142 }
2143 if (is_same_bone_dependency(variable_exit_key, self_key) ||
2144 is_same_nodetree_node_dependency(variable_exit_key, self_key))
2145 {
2146 return;
2147 }
2148 add_relation(variable_exit_key, driver_key, "RNA Target -> Driver");
2149
2150 /* It is possible that RNA path points to a property of a different ID than the target_id:
2151 * for example, paths like "data" on Object, "camera" on Scene.
2152 *
2153 * For the demonstration purposes lets consider a driver variable uses Scene ID as target
2154 * and "camera.location.x" as its RNA path. If the scene has 2 different cameras at
2155 * 2 different locations changing the active scene camera is expected to immediately be
2156 * reflected in the variable value. In order to achieve this behavior we create a relation
2157 * from the target ID to the driver so that if the ID property of the target ID changes the
2158 * driver is re-evaluated.
2159 *
2160 * The most straightforward (at the moment of writing this comment) way of figuring out
2161 * such relation is to use copy-on-evaluation operation of the target ID. There are two down
2162 * sides of this approach which are considered a design limitation as there is a belief
2163 * that they are not common in practice or are not reliable due to other issues:
2164 *
2165 * - IDs which are not covered with the copy-on-evaluation mechanism.
2166 *
2167 * Such IDs are either do not have ID properties, or are not part of the dependency
2168 * graph.
2169 *
2170 * - Modifications of evaluated IDs from a Python handler.
2171 * Such modifications are not fully integrated in the dependency graph evaluation as it
2172 * has issues with copy-on-evaluation tagging and the fact that relations are defined by the
2173 * original main database status.
2174 *
2175 * The original report for this is #98618.
2176 *
2177 * The not-so-obvious part is that we don't do such relation for the context properties.
2178 * They are resolved at the graph build time and do not change at runtime (#107081).
2179 * Thus scene has to be excluded as a special case; this is OK because changes to
2180 * scene.camera not caused by animation should actually force a dependency graph rebuild.
2181 */
2182 if (target_id != variable_exit_key.ptr.owner_id && GS(target_id->name) != ID_SCE) {
2183 if (deg_eval_copy_is_needed(GS(target_id->name))) {
2184 ComponentKey target_id_key(target_id, NodeType::COPY_ON_EVAL);
2185 add_relation(target_id_key, driver_key, "Target ID -> Driver");
2186 }
2187 }
2188}
2189
2191 const char *rna_path_from_target_prop)
2192{
2193 if (rna_path_from_target_prop == nullptr || rna_path_from_target_prop[0] == '\0') {
2194 return;
2195 }
2196
2198 PropertyRNA *prop;
2199 int index;
2200 if (!RNA_path_resolve_full(&target_prop, rna_path_from_target_prop, &ptr, &prop, &index)) {
2201 return;
2202 }
2203 if (prop == nullptr) {
2204 return;
2205 }
2207 return;
2208 }
2209 if (ptr.owner_id) {
2210 build_id(ptr.owner_id);
2211 }
2212 const char *prop_identifier = RNA_property_identifier(prop);
2213 /* Custom properties of bones are placed in their components to improve granularity. */
2214 OperationKey id_property_key;
2215 if (RNA_struct_is_a(ptr.type, &RNA_PoseBone)) {
2216 const bPoseChannel *pchan = static_cast<const bPoseChannel *>(ptr.data);
2217 id_property_key = OperationKey(
2218 ptr.owner_id, NodeType::BONE, pchan->name, OperationCode::ID_PROPERTY, prop_identifier);
2219 /* Create relation from the parameters component so that tagging armature for parameters update
2220 * properly propagates updates to all properties on bones and deeper (if needed). */
2221 OperationKey parameters_init_key(
2224 parameters_init_key, id_property_key, "Init -> ID Property", RELATION_CHECK_BEFORE_ADD);
2225 }
2226 else {
2227 id_property_key = OperationKey(
2228 ptr.owner_id, NodeType::PARAMETERS, OperationCode::ID_PROPERTY, prop_identifier);
2229 }
2230 OperationKey parameters_exit_key(
2233 id_property_key, parameters_exit_key, "ID Property -> Done", RELATION_CHECK_BEFORE_ADD);
2234}
2235
2237{
2241 add_relation(parameters_entry_key, parameters_eval_key, "Entry -> Eval");
2242 add_relation(parameters_eval_key, parameters_exit_key, "Entry -> Exit");
2243}
2244
2246{
2248 ComponentKey geometry_key(&object->id, NodeType::GEOMETRY);
2249 ComponentKey transform_key(&object->id, NodeType::TRANSFORM);
2250 add_relation(geometry_key, dimensions_key, "Geometry -> Dimensions");
2251 add_relation(transform_key, dimensions_key, "Transform -> Dimensions");
2252}
2253
2255{
2256 if (built_map_.check_is_built_and_tag(world)) {
2257 return;
2258 }
2259
2260 const BuilderStack::ScopedEntry stack_entry = stack_.trace(world->id);
2261
2263 /* animation */
2264 build_animdata(&world->id);
2265 build_parameters(&world->id);
2266
2267 /* Animated / driven parameters (without nodetree). */
2269 ComponentKey parameters_key(&world->id, NodeType::PARAMETERS);
2270 add_relation(parameters_key, world_key, "World's parameters");
2271
2272 /* world's nodetree */
2273 if (world->nodetree != nullptr) {
2274 build_nodetree(world->nodetree);
2275 OperationKey ntree_key(
2277 add_relation(ntree_key, world_key, "World's NTree");
2278 build_nested_nodetree(&world->id, world->nodetree);
2279 }
2280}
2281
2283{
2284 RigidBodyWorld *rbw = scene->rigidbody_world;
2287 /* Simulation depends on time. */
2288 TimeSourceKey time_src_key;
2289 add_relation(time_src_key, rb_init_key, "TimeSrc -> Rigidbody Init");
2290 /* Simulation should always be run after initialization. */
2291 /* NOTE: It is possible in theory to have dependency cycle which involves
2292 * this relation. We never want it to be killed. */
2293 add_relation(rb_init_key, rb_simulate_key, "Rigidbody [Init -> SimStep]", RELATION_FLAG_GODMODE);
2294 /* Effectors should be evaluated at the time simulation is being
2295 * initialized.
2296 * TODO(sergey): Verify that it indeed goes to initialization and not to a
2297 * simulation. */
2298 ListBase *effector_relations = build_effector_relations(graph_, rbw->effector_weights->group);
2299 LISTBASE_FOREACH (EffectorRelation *, effector_relation, effector_relations) {
2300 ComponentKey effector_transform_key(&effector_relation->ob->id, NodeType::TRANSFORM);
2301 add_relation(effector_transform_key, rb_init_key, "RigidBody Field");
2302 if (effector_relation->pd != nullptr) {
2303 const short shape = effector_relation->pd->shape;
2305 ComponentKey effector_geometry_key(&effector_relation->ob->id, NodeType::GEOMETRY);
2306 add_relation(effector_geometry_key, rb_init_key, "RigidBody Field");
2307 }
2308 if ((effector_relation->pd->forcefield == PFIELD_TEXTURE) &&
2309 (effector_relation->pd->tex != nullptr))
2310 {
2311 ComponentKey tex_key(&effector_relation->pd->tex->id, NodeType::GENERIC_DATABLOCK);
2312 add_relation(tex_key, rb_init_key, "Force field Texture");
2313 }
2314 }
2315 }
2316 /* Objects. */
2317 if (rbw->group != nullptr) {
2318 build_collection(nullptr, rbw->group);
2320 if (object->type != OB_MESH) {
2321 continue;
2322 }
2323 if (object->rigidbody_object == nullptr) {
2324 continue;
2325 }
2326
2327 if (object->parent != nullptr && object->parent->rigidbody_object != nullptr &&
2329 {
2330 /* If we are a child of a compound shape object, the transforms and sim evaluation will be
2331 * handled by the parent compound shape object. Do not add any evaluation triggers
2332 * for the child objects.
2333 */
2334 continue;
2335 }
2336
2337 /* Simulation uses object transformation after parenting and solving constraints. */
2338 OperationKey object_transform_simulation_init_key(
2340 OperationKey object_transform_eval_key(
2342 add_relation(object_transform_simulation_init_key,
2343 rb_simulate_key,
2344 "Object Transform -> Rigidbody Sim Eval");
2345 /* Geometry must be known to create the rigid body. RBO_MESH_BASE
2346 * uses the non-evaluated mesh, so then the evaluation is
2347 * unnecessary. */
2349 /* NOTE: We prefer this relation to be never killed, to avoid
2350 * access partially evaluated mesh from solver. */
2351 ComponentKey object_geometry_key(&object->id, NodeType::GEOMETRY);
2352 add_relation(object_geometry_key,
2353 rb_simulate_key,
2354 "Object Geom Eval -> Rigidbody Sim Eval",
2356 }
2357
2358 /* Final transform is whatever the solver gave to us. */
2359 if (object->rigidbody_object->type == RBO_TYPE_ACTIVE) {
2360 /* We do not have to update the objects final transform after the simulation if it is
2361 * passive or controlled by the animation system in blender.
2362 * (Bullet doesn't move the object at all in these cases).
2363 * But we can't update the depsgraph when the animated property in changed during playback.
2364 * So always assume that active bodies needs updating. */
2365 OperationKey rb_transform_copy_key(
2367 /* Rigid body synchronization depends on the actual simulation. */
2368 add_relation(rb_simulate_key, rb_transform_copy_key, "Rigidbody Sim Eval -> RBO Sync");
2369
2370 OperationKey object_transform_final_key(
2372 add_relation(rb_transform_copy_key,
2373 object_transform_final_key,
2374 "Rigidbody Sync -> Transform Final");
2375 }
2376
2377 /* Relations between colliders and force fields, needed for force field absorption. */
2379 }
2381 }
2382}
2383
2385{
2386 OperationKey obdata_ubereval_key(&object->id, NodeType::GEOMETRY, OperationCode::GEOMETRY_EVAL);
2387 OperationKey eval_init_key(
2389 OperationKey eval_done_key(
2391 ComponentKey eval_key(&object->id, NodeType::PARTICLE_SYSTEM);
2392 if (BKE_ptcache_object_has(scene_, object, 0)) {
2393 ComponentKey point_cache_key(&object->id, NodeType::POINT_CACHE);
2395 eval_key, point_cache_key, "Particle Point Cache", RELATION_FLAG_FLUSH_USER_EDIT_ONLY);
2396 }
2397 /* Particle systems. */
2398 LISTBASE_FOREACH (ParticleSystem *, psys, &object->particlesystem) {
2399 ParticleSettings *part = psys->part;
2400 /* Build particle settings relations.
2401 * NOTE: The call itself ensures settings are only build once. */
2403 /* This particle system. */
2404 OperationKey psys_key(
2406 /* Update particle system when settings changes. */
2407 OperationKey particle_settings_key(
2409 add_relation(particle_settings_key, eval_init_key, "Particle Settings Change");
2410 add_relation(eval_init_key, psys_key, "Init -> PSys");
2411 add_relation(psys_key, eval_done_key, "PSys -> Done");
2412 /* TODO(sergey): Currently particle update is just a placeholder,
2413 * hook it to the ubereval node so particle system is getting updated
2414 * on playback. */
2415 add_relation(psys_key, obdata_ubereval_key, "PSys -> UberEval");
2416 /* Collisions. */
2417 if (part->type != PART_HAIR) {
2419 psys_key, object, part->collision_group, "Particle Collision");
2420 }
2421 else if ((psys->flag & PSYS_HAIR_DYNAMICS) && psys->clmd != nullptr &&
2422 psys->clmd->coll_parms != nullptr)
2423 {
2425 psys_key, object, psys->clmd->coll_parms->group, "Hair Collision");
2426 }
2427 /* Effectors. */
2429 psys_key, object, psys, part->effector_weights, part->type == PART_HAIR, "Particle Field");
2430 /* Boids. */
2431 if (part->boids != nullptr) {
2433 LISTBASE_FOREACH (BoidRule *, rule, &state->rules) {
2434 Object *ruleob = nullptr;
2435 if (rule->type == eBoidRuleType_Avoid) {
2436 ruleob = ((BoidRuleGoalAvoid *)rule)->ob;
2437 }
2438 else if (rule->type == eBoidRuleType_FollowLeader) {
2439 ruleob = ((BoidRuleFollowLeader *)rule)->ob;
2440 }
2441 if (ruleob != nullptr) {
2442 ComponentKey ruleob_key(&ruleob->id, NodeType::TRANSFORM);
2443 add_relation(ruleob_key, psys_key, "Boid Rule");
2444 }
2445 }
2446 }
2447 }
2448 /* Keyed particle targets. */
2450 LISTBASE_FOREACH (ParticleTarget *, particle_target, &psys->targets) {
2451 if (ELEM(particle_target->ob, nullptr, object)) {
2452 continue;
2453 }
2454 /* Make sure target object is pulled into the graph. */
2455 build_object(particle_target->ob);
2456 /* Use geometry component, since that's where particles are
2457 * actually evaluated. */
2458 ComponentKey target_key(&particle_target->ob->id, NodeType::GEOMETRY);
2459 add_relation(target_key, psys_key, "Keyed Target");
2460 }
2461 }
2462 /* Visualization. */
2463 switch (part->ren_as) {
2464 case PART_DRAW_OB:
2465 if (part->instance_object != nullptr) {
2466 /* Make sure object's relations are all built. */
2468 /* Build relation for the particle visualization. */
2470 }
2471 break;
2472 case PART_DRAW_GR:
2473 if (part->instance_collection != nullptr) {
2474 build_collection(nullptr, part->instance_collection);
2476 build_particle_system_visualization_object(object, psys, go->ob);
2477 }
2478 }
2479 break;
2480 }
2481 }
2482 /* Particle depends on the object transform, so that channel is to be ready
2483 * first. */
2484 add_depends_on_transform_relation(&object->id, obdata_ubereval_key, "Particle Eval");
2485}
2486
2488{
2489 if (built_map_.check_is_built_and_tag(part)) {
2490 return;
2491 }
2492
2493 const BuilderStack::ScopedEntry stack_entry = stack_.trace(part->id);
2494
2495 /* Animation data relations. */
2496 build_animdata(&part->id);
2497 build_parameters(&part->id);
2498 OperationKey particle_settings_init_key(
2500 OperationKey particle_settings_eval_key(
2502 OperationKey particle_settings_reset_key(
2505 particle_settings_init_key, particle_settings_eval_key, "Particle Settings Init Order");
2506 add_relation(particle_settings_reset_key, particle_settings_eval_key, "Particle Settings Reset");
2507 /* Texture slots. */
2508 for (MTex *mtex : part->mtex) {
2509 if (mtex == nullptr || mtex->tex == nullptr) {
2510 continue;
2511 }
2512 build_texture(mtex->tex);
2513 ComponentKey texture_key(&mtex->tex->id, NodeType::GENERIC_DATABLOCK);
2514 add_relation(texture_key,
2515 particle_settings_reset_key,
2516 "Particle Texture -> Particle Reset",
2518 add_relation(texture_key, particle_settings_eval_key, "Particle Texture -> Particle Eval");
2519 /* TODO(sergey): Consider moving texture space handling to its own
2520 * function. */
2521 if (mtex->texco == TEXCO_OBJECT && mtex->object != nullptr) {
2522 ComponentKey object_key(&mtex->object->id, NodeType::TRANSFORM);
2523 add_relation(object_key, particle_settings_eval_key, "Particle Texture Space");
2524 }
2525 }
2526 if (check_id_has_anim_component(&part->id)) {
2527 ComponentKey animation_key(&part->id, NodeType::ANIMATION);
2528 add_relation(animation_key, particle_settings_eval_key, "Particle Settings Animation");
2529 }
2530}
2531
2533 ParticleSystem *psys,
2534 Object *draw_object)
2535{
2536 OperationKey psys_key(
2538 OperationKey obdata_ubereval_key(&object->id, NodeType::GEOMETRY, OperationCode::GEOMETRY_EVAL);
2539 ComponentKey dup_ob_key(&draw_object->id, NodeType::TRANSFORM);
2540 add_relation(dup_ob_key, psys_key, "Particle Object Visualization");
2541 if (draw_object->type == OB_MBALL) {
2542 ComponentKey dup_geometry_key(&draw_object->id, NodeType::GEOMETRY);
2543 add_relation(obdata_ubereval_key, dup_geometry_key, "Particle MBall Visualization");
2544 }
2545}
2546
2547/* Shapekeys */
2549{
2550 if (built_map_.check_is_built_and_tag(key)) {
2551 return;
2552 }
2553
2554 const BuilderStack::ScopedEntry stack_entry = stack_.trace(key->id);
2555
2557 /* Attach animdata to geometry. */
2558 build_animdata(&key->id);
2559 build_parameters(&key->id);
2560 /* Connect all blocks properties to the final result evaluation. */
2561 ComponentKey geometry_key(&key->id, NodeType::GEOMETRY);
2563 LISTBASE_FOREACH (KeyBlock *, key_block, &key->block) {
2564 OperationKey key_block_key(
2565 &key->id, NodeType::PARAMETERS, OperationCode::PARAMETERS_EVAL, key_block->name);
2566 add_relation(key_block_key, geometry_key, "Key Block Properties");
2567 add_relation(key_block_key, parameters_eval_key, "Key Block Properties");
2568 }
2569}
2570
2592{
2593 ID *obdata = (ID *)object->data;
2594 /* Init operation of object-level geometry evaluation. */
2596 /* Get nodes for result of obdata's evaluation, and geometry evaluation
2597 * on object. */
2598 ComponentKey obdata_geom_key(obdata, NodeType::GEOMETRY);
2599 ComponentKey geom_key(&object->id, NodeType::GEOMETRY);
2600 /* Link components to each other. */
2601 add_relation(obdata_geom_key, geom_key, "Object Geometry Base Data");
2602 OperationKey obdata_ubereval_key(&object->id, NodeType::GEOMETRY, OperationCode::GEOMETRY_EVAL);
2603 /* Special case: modifiers evaluation queries scene for various things like
2604 * data mask to be used. We add relation here to ensure object is never
2605 * evaluated prior to Scene's evaluated copy is ready. */
2606 ComponentKey scene_key(&scene_->id, NodeType::SCENE);
2607 add_relation(scene_key, obdata_ubereval_key, "Copy-on-Eval Relation", RELATION_FLAG_NO_FLUSH);
2608 /* Relation to the instance, so that instancer can use geometry of this object. */
2611 "Transform -> Instance Geometry");
2612 /* Shader FX. */
2613 if (object->shader_fx.first != nullptr) {
2615 ctx.scene = scene_;
2616 ctx.object = object;
2617 LISTBASE_FOREACH (ShaderFxData *, fx, &object->shader_fx) {
2618 const ShaderFxTypeInfo *fxi = BKE_shaderfx_get_info((ShaderFxType)fx->type);
2619 if (fxi->update_depsgraph) {
2620 DepsNodeHandle handle = create_node_handle(obdata_ubereval_key);
2621 ctx.node = reinterpret_cast<::DepsNodeHandle *>(&handle);
2622 fxi->update_depsgraph(fx, &ctx);
2623 }
2625 TimeSourceKey time_src_key;
2626 add_relation(time_src_key, obdata_ubereval_key, "Time Source");
2627 }
2628 }
2629 }
2630 /* Materials. */
2631 build_materials(&object->id, object->mat, object->totcol);
2632 /* Geometry collision. */
2633 if (ELEM(object->type, OB_MESH, OB_CURVES_LEGACY, OB_LATTICE)) {
2634 // add geometry collider relations
2635 }
2636 /* Make sure uber update is the last in the dependencies.
2637 * Only do it here unless there are modifiers. This avoids transitive relations. */
2638 if (BLI_listbase_is_empty(&object->modifiers)) {
2639 OperationKey obdata_ubereval_key(
2641 add_relation(geom_init_key, obdata_ubereval_key, "Object Geometry UberEval");
2642 }
2643 if (object->type == OB_MBALL) {
2644 Object *mom = BKE_mball_basis_find(scene_, object);
2645 ComponentKey mom_geom_key(&mom->id, NodeType::GEOMETRY);
2646 /* motherball - mom depends on children! */
2647 if (mom == object) {
2648 ComponentKey mom_transform_key(&mom->id, NodeType::TRANSFORM);
2649 add_relation(mom_transform_key, mom_geom_key, "Metaball Motherball Transform -> Geometry");
2650 }
2651 else {
2652 ComponentKey transform_key(&object->id, NodeType::TRANSFORM);
2653 add_relation(geom_key, mom_geom_key, "Metaball Motherball");
2654 add_relation(transform_key, mom_geom_key, "Metaball Motherball");
2655 }
2656 }
2657 /* NOTE: This is compatibility code to support particle systems
2658 *
2659 * for viewport being properly rendered in final render mode.
2660 * This relation is similar to what dag_object_time_update_flags()
2661 * was doing for mesh objects with particle system.
2662 *
2663 * Ideally we need to get rid of this relation. */
2664 if (object_particles_depends_on_time(object)) {
2665 TimeSourceKey time_key;
2666 OperationKey obdata_ubereval_key(
2668 add_relation(time_key, obdata_ubereval_key, "Legacy particle time");
2669 }
2670 /* Object data data-block. */
2672 Key *key = BKE_key_from_object(object);
2673 if (key != nullptr) {
2674 if (key->adt != nullptr) {
2675 if (key->adt->action || key->adt->nla_tracks.first) {
2676 ComponentKey obdata_key((ID *)object->data, NodeType::GEOMETRY);
2677 ComponentKey adt_key(&key->id, NodeType::ANIMATION);
2678 add_relation(adt_key, obdata_key, "Animation");
2679 }
2680 }
2681 }
2682 build_dimensions(object);
2683 /* Synchronization back to original object. */
2684 ComponentKey final_geometry_key(&object->id, NodeType::GEOMETRY);
2685 OperationKey synchronize_key(
2687 add_relation(final_geometry_key, synchronize_key, "Synchronize to Original");
2688 /* Batch cache. */
2689 OperationKey object_data_select_key(
2691 OperationKey object_select_key(
2693 add_relation(object_data_select_key, object_select_key, "Data Selection -> Object Selection");
2695 geom_key, object_select_key, "Object Geometry -> Select Update", RELATION_FLAG_NO_FLUSH);
2696 /* Shading. */
2697 ComponentKey geometry_shading_key(obdata, NodeType::SHADING);
2698 OperationKey object_shading_key(&object->id, NodeType::SHADING, OperationCode::SHADING);
2699 add_relation(geometry_shading_key, object_shading_key, "Geometry Shading -> Object Shading");
2700}
2701
2703{
2704 if (built_map_.check_is_built_and_tag(obdata)) {
2705 return;
2706 }
2707
2708 const BuilderStack::ScopedEntry stack_entry = stack_.trace(*obdata);
2709
2711 /* Animation. */
2712 build_animdata(obdata);
2713 build_parameters(obdata);
2714 /* ShapeKeys. */
2715 Key *key = BKE_key_from_id(obdata);
2716 if (key != nullptr) {
2717 build_shapekeys(key);
2718 }
2719 /* Link object data evaluation node to exit operation. */
2720 OperationKey obdata_geom_eval_key(obdata, NodeType::GEOMETRY, OperationCode::GEOMETRY_EVAL);
2722 add_relation(obdata_geom_eval_key, obdata_geom_done_key, "ObData Geom Eval Done");
2723
2724 /* Link object data evaluation to parameter evaluation. */
2725 ComponentKey parameters_key(obdata, NodeType::PARAMETERS);
2726 add_relation(parameters_key, obdata_geom_eval_key, "ObData Geom Params");
2727
2728 /* Type-specific links. */
2729 const ID_Type id_type = GS(obdata->name);
2730 switch (id_type) {
2731 case ID_ME:
2732 break;
2733 case ID_MB:
2734 break;
2735 case ID_CU_LEGACY: {
2736 Curve *cu = (Curve *)obdata;
2737 if (cu->bevobj != nullptr) {
2738 ComponentKey bevob_geom_key(&cu->bevobj->id, NodeType::GEOMETRY);
2739 add_relation(bevob_geom_key, obdata_geom_eval_key, "Curve Bevel Geometry");
2740 ComponentKey bevob_key(&cu->bevobj->id, NodeType::TRANSFORM);
2741 add_relation(bevob_key, obdata_geom_eval_key, "Curve Bevel Transform");
2742 build_object(cu->bevobj);
2743 }
2744 if (cu->taperobj != nullptr) {
2745 ComponentKey taperob_key(&cu->taperobj->id, NodeType::GEOMETRY);
2746 add_relation(taperob_key, obdata_geom_eval_key, "Curve Taper");
2748 }
2749 if (cu->textoncurve != nullptr) {
2750 ComponentKey textoncurve_geom_key(&cu->textoncurve->id, NodeType::GEOMETRY);
2751 add_relation(textoncurve_geom_key, obdata_geom_eval_key, "Text on Curve Geometry");
2752 ComponentKey textoncurve_key(&cu->textoncurve->id, NodeType::TRANSFORM);
2753 add_relation(textoncurve_key, obdata_geom_eval_key, "Text on Curve Transform");
2755 }
2756 /* Special relation to ensure active spline index gets properly updated.
2757 *
2758 * The active spline index is stored on the Curve data-block, and the curve evaluation might
2759 * create a new curve data-block for the result, which does not intrinsically sharing the
2760 * active spline index. Hence a special relation is added to ensure the modifier stack is
2761 * evaluated when selection changes. */
2762 {
2763 const OperationKey object_data_select_key(
2765 add_relation(object_data_select_key, obdata_geom_eval_key, "Active Spline Update");
2766 }
2767 break;
2768 }
2769 case ID_LT:
2770 break;
2771 case ID_GD_LEGACY: /* Grease Pencil */
2772 {
2773 bGPdata *gpd = (bGPdata *)obdata;
2774
2775 /* Geometry cache needs to be recalculated on frame change
2776 * (e.g. to fix crashes after scrubbing the timeline when
2777 * onion skinning is enabled, since the ghosts need to be
2778 * re-added to the cache once scrubbing ends). */
2779 TimeSourceKey time_key;
2780 ComponentKey geometry_key(obdata, NodeType::GEOMETRY);
2781 add_relation(time_key, geometry_key, "GP Frame Change");
2782
2783 /* Geometry cache also needs to be recalculated when Material
2784 * settings change (e.g. when fill.opacity changes on/off,
2785 * we need to rebuild the bGPDstroke->triangles caches). */
2786 for (int i = 0; i < gpd->totcol; i++) {
2787 Material *ma = gpd->mat[i];
2788 if ((ma != nullptr) && (ma->gp_style != nullptr)) {
2790 add_relation(material_key, geometry_key, "Material -> GP Data");
2791 }
2792 }
2793
2794 /* Layer parenting need react to the parent object transformation. */
2795 LISTBASE_FOREACH (bGPDlayer *, gpl, &gpd->layers) {
2796 if (gpl->parent != nullptr) {
2797 ComponentKey gpd_geom_key(&gpd->id, NodeType::GEOMETRY);
2798
2799 if (gpl->partype == PARBONE) {
2800 ComponentKey bone_key(&gpl->parent->id, NodeType::BONE, gpl->parsubstr);
2801 OperationKey armature_key(
2803
2804 add_relation(bone_key, gpd_geom_key, "Bone Parent");
2805 add_relation(armature_key, gpd_geom_key, "Armature Parent");
2806 }
2807 else {
2808 ComponentKey transform_key(&gpl->parent->id, NodeType::TRANSFORM);
2809 add_relation(transform_key, gpd_geom_key, "GPencil Parent Layer");
2810 }
2811 }
2812 }
2813 break;
2814 }
2815 case ID_CV: {
2816 Curves *curves_id = reinterpret_cast<Curves *>(obdata);
2817 if (curves_id->surface != nullptr) {
2818 build_object(curves_id->surface);
2819
2820 /* The relations between the surface and the curves are handled as part of the modifier
2821 * stack building. */
2822 }
2823 break;
2824 }
2825 case ID_PT:
2826 break;
2827 case ID_VO: {
2828 Volume *volume = (Volume *)obdata;
2829 if (volume->is_sequence) {
2830 TimeSourceKey time_key;
2831 ComponentKey geometry_key(obdata, NodeType::GEOMETRY);
2832 add_relation(time_key, geometry_key, "Volume sequence time");
2833 }
2834 break;
2835 }
2836 case ID_GP: {
2837 GreasePencil &grease_pencil = *reinterpret_cast<GreasePencil *>(obdata);
2838
2839 /* Update geometry when time is changed. */
2840 TimeSourceKey time_key;
2841 ComponentKey geometry_key(&grease_pencil.id, NodeType::GEOMETRY);
2842 add_relation(time_key, geometry_key, "Grease Pencil Frame Change");
2843
2844 /* Add relations for layer parents. */
2845 for (const bke::greasepencil::Layer *layer : grease_pencil.layers()) {
2846 Object *parent = layer->parent;
2847 if (parent == nullptr) {
2848 continue;
2849 }
2850 if (parent->type == OB_ARMATURE && !layer->parent_bone_name().is_empty()) {
2851 ComponentKey bone_key(&parent->id, NodeType::BONE, layer->parent_bone_name().c_str());
2852 OperationKey armature_key(
2854
2855 add_relation(bone_key, geometry_key, "Grease Pencil Layer Bone Parent");
2856 add_relation(armature_key, geometry_key, "Grease Pencil Layer Armature Parent");
2857 }
2858 else {
2859 ComponentKey transform_key(&parent->id, NodeType::TRANSFORM);
2860 add_relation(transform_key, geometry_key, "Grease Pencil Layer Object Parent");
2861 }
2862 }
2863 break;
2864 }
2865 default:
2866 BLI_assert_msg(0, "Should not happen");
2867 break;
2868 }
2869}
2870
2872{
2873 if (built_map_.check_is_built_and_tag(armature)) {
2874 return;
2875 }
2876
2877 const BuilderStack::ScopedEntry stack_entry = stack_.trace(armature->id);
2878
2879 build_idproperties(armature->id.properties);
2880 build_animdata(&armature->id);
2881 build_parameters(&armature->id);
2882 build_armature_bones(&armature->bonebase);
2883 build_armature_bone_collections(armature->collections_span());
2884}
2885
2887{
2888 LISTBASE_FOREACH (Bone *, bone, bones) {
2889 build_idproperties(bone->prop);
2890 build_armature_bones(&bone->childbase);
2891 }
2892}
2893
2896{
2897 for (BoneCollection *bcoll : collections) {
2898 build_idproperties(bcoll->prop);
2899 }
2900}
2901
2903{
2904 if (built_map_.check_is_built_and_tag(camera)) {
2905 return;
2906 }
2907
2908 const BuilderStack::ScopedEntry stack_entry = stack_.trace(camera->id);
2909
2911 build_animdata(&camera->id);
2912 build_parameters(&camera->id);
2913 if (camera->dof.focus_object != nullptr) {
2914 build_object(camera->dof.focus_object);
2915 ComponentKey camera_parameters_key(&camera->id, NodeType::PARAMETERS);
2916 ComponentKey dof_ob_key(&camera->dof.focus_object->id, NodeType::TRANSFORM);
2917 add_relation(dof_ob_key, camera_parameters_key, "Camera DOF");
2918 if (camera->dof.focus_subtarget[0]) {
2919 OperationKey target_key(&camera->dof.focus_object->id,
2921 camera->dof.focus_subtarget,
2923 add_relation(target_key, camera_parameters_key, "Camera DOF subtarget");
2924 }
2925 }
2926}
2927
2928/* Lights */
2930{
2931 if (built_map_.check_is_built_and_tag(lamp)) {
2932 return;
2933 }
2934
2935 const BuilderStack::ScopedEntry stack_entry = stack_.trace(lamp->id);
2936
2938 build_animdata(&lamp->id);
2939 build_parameters(&lamp->id);
2940
2941 ComponentKey lamp_parameters_key(&lamp->id, NodeType::PARAMETERS);
2942
2943 /* For allowing drivers on lamp properties. */
2944 ComponentKey shading_key(&lamp->id, NodeType::SHADING);
2945 add_relation(lamp_parameters_key, shading_key, "Light Shading Parameters");
2946
2947 /* light's nodetree */
2948 if (lamp->nodetree != nullptr) {
2949 build_nodetree(lamp->nodetree);
2950 OperationKey ntree_key(
2952 add_relation(ntree_key, shading_key, "NTree->Light Parameters");
2953 build_nested_nodetree(&lamp->id, lamp->nodetree);
2954 }
2955}
2956
2958{
2959 build_idproperties(socket->prop);
2960
2961 if (socket->type == SOCK_OBJECT) {
2962 Object *object = ((bNodeSocketValueObject *)socket->default_value)->value;
2963 if (object != nullptr) {
2964 build_object(object);
2965 }
2966 }
2967 else if (socket->type == SOCK_IMAGE) {
2968 Image *image = ((bNodeSocketValueImage *)socket->default_value)->value;
2969 if (image != nullptr) {
2970 build_image(image);
2971 }
2972 }
2973 else if (socket->type == SOCK_COLLECTION) {
2974 Collection *collection = ((bNodeSocketValueCollection *)socket->default_value)->value;
2975 if (collection != nullptr) {
2976 build_collection(nullptr, collection);
2977 }
2978 }
2979 else if (socket->type == SOCK_TEXTURE) {
2980 Tex *texture = ((bNodeSocketValueTexture *)socket->default_value)->value;
2981 if (texture != nullptr) {
2983 }
2984 }
2985 else if (socket->type == SOCK_MATERIAL) {
2986 Material *material = ((bNodeSocketValueMaterial *)socket->default_value)->value;
2987 if (material != nullptr) {
2988 build_material(material);
2989 }
2990 }
2991}
2992
2994{
2995 if (ntree == nullptr) {
2996 return;
2997 }
2998 if (built_map_.check_is_built_and_tag(ntree)) {
2999 return;
3000 }
3001
3002 const BuilderStack::ScopedEntry stack_entry = stack_.trace(ntree->id);
3003
3005 build_animdata(&ntree->id);
3006 build_parameters(&ntree->id);
3008 OperationKey ntree_geo_preprocess_key(
3010 if (ntree->type == NTREE_GEOMETRY) {
3012 add_relation(ntree_cow_key, ntree_geo_preprocess_key, "Copy-on-Eval -> Preprocess");
3013 add_relation(ntree_geo_preprocess_key,
3014 ntree_output_key,
3015 "Preprocess -> Output",
3017 }
3018 /* nodetree's nodes... */
3019 for (bNode *bnode : ntree->all_nodes()) {
3020 build_idproperties(bnode->prop);
3021 LISTBASE_FOREACH (bNodeSocket *, socket, &bnode->inputs) {
3022 build_nodetree_socket(socket);
3023 }
3024 LISTBASE_FOREACH (bNodeSocket *, socket, &bnode->outputs) {
3025 build_nodetree_socket(socket);
3026 }
3027
3028 if (ntree->type == NTREE_SHADER && bnode->is_type("ShaderNodeAttribute")) {
3029 NodeShaderAttribute *attr = static_cast<NodeShaderAttribute *>(bnode->storage);
3030 if (attr->type == SHD_ATTRIBUTE_VIEW_LAYER && STREQ(attr->name, "frame_current")) {
3031 TimeSourceKey time_src_key;
3032 add_relation(time_src_key, ntree_output_key, "TimeSrc -> Node");
3033 }
3034 }
3035
3036 ID *id = bnode->id;
3037 if (id == nullptr) {
3038 continue;
3039 }
3040 ID_Type id_type = GS(id->name);
3041 if (id_type == ID_MA) {
3042 build_material((Material *)bnode->id);
3043 ComponentKey material_key(id, NodeType::SHADING);
3044 add_relation(material_key, ntree_output_key, "Material -> Node");
3045 }
3046 else if (id_type == ID_TE) {
3047 build_texture((Tex *)bnode->id);
3049 add_relation(texture_key, ntree_output_key, "Texture -> Node");
3050 }
3051 else if (id_type == ID_IM) {
3052 build_image((Image *)bnode->id);
3054 add_relation(image_key, ntree_output_key, "Image -> Node");
3055 }
3056 else if (id_type == ID_OB) {
3057 build_object((Object *)id);
3058 ComponentKey object_transform_key(id, NodeType::TRANSFORM);
3059 add_relation(object_transform_key, ntree_output_key, "Object Transform -> Node");
3060 if (object_have_geometry_component(reinterpret_cast<Object *>(id))) {
3061 ComponentKey object_geometry_key(id, NodeType::GEOMETRY);
3062 add_relation(object_geometry_key, ntree_output_key, "Object Geometry -> Node");
3063 }
3064 }
3065 else if (id_type == ID_SCE) {
3066 Scene *node_scene = (Scene *)id;
3067 build_scene_parameters(node_scene);
3068 /* Camera is used by defocus node.
3069 *
3070 * On the one hand it's annoying to always pull it in, but on another hand it's also annoying
3071 * to have hardcoded node-type exception here. */
3072 if (node_scene->camera != nullptr) {
3073 build_object(node_scene->camera);
3074 }
3075 }
3076 else if (id_type == ID_TXT) {
3077 /* Ignore script nodes. */
3078 }
3079 else if (id_type == ID_MSK) {
3080 build_mask((Mask *)id);
3082 add_relation(mask_key, ntree_output_key, "Mask -> Node");
3083 }
3084 else if (id_type == ID_MC) {
3087 add_relation(clip_key, ntree_output_key, "Clip -> Node");
3088 }
3089 else if (id_type == ID_VF) {
3090 build_vfont((VFont *)id);
3092 add_relation(vfont_key, ntree_output_key, "VFont -> Node");
3093 }
3094 else if (id_type == ID_GR) {
3095 /* Build relations in the collection itself, but don't hook it up to the tree.
3096 * Relations from the collection to the tree are handled by the modifier's update_depsgraph()
3097 * callback.
3098 *
3099 * Other node trees do not currently support references to collections. Once they do this
3100 * code needs to be reconsidered. */
3101 build_collection(nullptr, reinterpret_cast<Collection *>(id));
3102 }
3103 else if (bnode->is_group()) {
3104 bNodeTree *group_ntree = (bNodeTree *)id;
3105 build_nodetree(group_ntree);
3106 ComponentKey group_output_key(&group_ntree->id, NodeType::NTREE_OUTPUT);
3107 /* This relation is not necessary in all cases (e.g. when the group node is not connected to
3108 * the output). Currently, we lack the infrastructure to check for these cases efficiently.
3109 * That can be added later. */
3110 add_relation(group_output_key, ntree_output_key, "Group Node");
3111 if (group_ntree->type == NTREE_GEOMETRY) {
3112 OperationKey group_preprocess_key(&group_ntree->id,
3115 add_relation(group_preprocess_key, ntree_geo_preprocess_key, "Group Node Preprocess");
3116 }
3117 }
3118 else {
3119 /* Ignore this case. It can happen when the node type is not known currently. Either because
3120 * it belongs to an add-on or because it comes from a different Blender version that does
3121 * support the ID type here already. */
3122 }
3123 }
3124
3125 ntree->ensure_interface_cache();
3126 for (bNodeTreeInterfaceSocket *socket : ntree->interface_inputs()) {
3127 build_idproperties(socket->properties);
3128 }
3129 for (bNodeTreeInterfaceSocket *socket : ntree->interface_outputs()) {
3130 build_idproperties(socket->properties);
3131 }
3132
3133 if (check_id_has_anim_component(&ntree->id)) {
3134 ComponentKey animation_key(&ntree->id, NodeType::ANIMATION);
3135 add_relation(animation_key, ntree_output_key, "NTree Shading Parameters");
3136 if (ntree->type == NTREE_GEOMETRY) {
3137 add_relation(animation_key, ntree_geo_preprocess_key, "NTree Animation -> Preprocess");
3138 }
3139 }
3140}
3141
3142/* Recursively build graph for material */
3144{
3145 if (owner) {
3146 ComponentKey material_key(&material->id, NodeType::SHADING);
3147 OperationKey owner_shading_key(owner, NodeType::SHADING, OperationCode::SHADING);
3148 add_relation(material_key, owner_shading_key, "Material -> Owner Shading");
3149 }
3150
3151 if (built_map_.check_is_built_and_tag(material)) {
3152 return;
3153 }
3154
3155 const BuilderStack::ScopedEntry stack_entry = stack_.trace(material->id);
3156
3157 build_idproperties(material->id.properties);
3158 /* animation */
3159 build_animdata(&material->id);
3160 build_parameters(&material->id);
3161
3162 /* Animated / driven parameters (without nodetree). */
3164 ComponentKey parameters_key(&material->id, NodeType::PARAMETERS);
3165 add_relation(parameters_key, material_key, "Material's parameters");
3166
3167 /* material's nodetree */
3168 if (material->nodetree != nullptr) {
3169 build_nodetree(material->nodetree);
3170 OperationKey ntree_key(
3172 add_relation(ntree_key, material_key, "Material's NTree");
3173 build_nested_nodetree(&material->id, material->nodetree);
3174 }
3175}
3176
3177void DepsgraphRelationBuilder::build_materials(ID *owner, Material **materials, int num_materials)
3178{
3179 for (int i = 0; i < num_materials; i++) {
3180 if (materials[i] == nullptr) {
3181 continue;
3182 }
3183 build_material(materials[i], owner);
3184 }
3185}
3186
3187/* Recursively build graph for texture */
3189{
3190 if (built_map_.check_is_built_and_tag(texture)) {
3191 return;
3192 }
3193
3194 const BuilderStack::ScopedEntry stack_entry = stack_.trace(texture->id);
3195
3196 /* texture itself */
3198 build_idproperties(texture->id.properties);
3199 build_animdata(&texture->id);
3201
3202 /* texture's nodetree */
3203 if (texture->nodetree) {
3204 build_nodetree(texture->nodetree);
3205 OperationKey ntree_key(
3207 add_relation(ntree_key, texture_key, "Texture's NTree");
3208 build_nested_nodetree(&texture->id, texture->nodetree);
3209 }
3210
3211 /* Special cases for different IDs which texture uses. */
3212 if (texture->type == TEX_IMAGE) {
3213 if (texture->ima != nullptr) {
3214 build_image(texture->ima);
3215
3216 ComponentKey image_key(&texture->ima->id, NodeType::GENERIC_DATABLOCK);
3217 add_relation(image_key, texture_key, "Texture Image");
3218 }
3219 }
3220
3221 if (check_id_has_anim_component(&texture->id)) {
3222 ComponentKey animation_key(&texture->id, NodeType::ANIMATION);
3223 add_relation(animation_key, texture_key, "Datablock Animation");
3224 }
3225
3227 ComponentKey image_animation_key(&texture->id, NodeType::IMAGE_ANIMATION);
3228 add_relation(image_animation_key, texture_key, "Datablock Image Animation");
3229 }
3230}
3231
3233{
3234 if (built_map_.check_is_built_and_tag(image)) {
3235 return;
3236 }
3237
3238 const BuilderStack::ScopedEntry stack_entry = stack_.trace(image->id);
3239
3241 build_parameters(&image->id);
3242}
3243
3245{
3246 if (built_map_.check_is_built_and_tag(cache_file)) {
3247 return;
3248 }
3249
3250 const BuilderStack::ScopedEntry stack_entry = stack_.trace(cache_file->id);
3251
3252 build_idproperties(cache_file->id.properties);
3253 /* Animation. */
3254 build_animdata(&cache_file->id);
3255 build_parameters(&cache_file->id);
3256 if (check_id_has_anim_component(&cache_file->id)) {
3257 ComponentKey animation_key(&cache_file->id, NodeType::ANIMATION);
3258 ComponentKey datablock_key(&cache_file->id, NodeType::CACHE);
3259 add_relation(animation_key, datablock_key, "Datablock Animation");
3260 }
3261 if (check_id_has_driver_component(&cache_file->id)) {
3262 ComponentKey animation_key(&cache_file->id, NodeType::PARAMETERS);
3263 ComponentKey datablock_key(&cache_file->id, NodeType::CACHE);
3264 add_relation(animation_key, datablock_key, "Drivers -> Cache Eval");
3265 }
3266
3267 /* Cache file updates */
3268 if (cache_file->is_sequence) {
3269 OperationKey cache_update_key(
3271 TimeSourceKey time_src_key;
3272 add_relation(time_src_key, cache_update_key, "TimeSrc -> Cache File Eval");
3273 }
3274}
3275
3277{
3278 if (built_map_.check_is_built_and_tag(mask)) {
3279 return;
3280 }
3281
3282 const BuilderStack::ScopedEntry stack_entry = stack_.trace(mask->id);
3283
3284 ID *mask_id = &mask->id;
3286 /* F-Curve animation. */
3287 build_animdata(mask_id);
3288 build_parameters(mask_id);
3289 /* Own mask animation. */
3291 TimeSourceKey time_src_key;
3292 add_relation(time_src_key, mask_animation_key, "TimeSrc -> Mask Animation");
3293 /* Final mask evaluation. */
3295 add_relation(mask_animation_key, mask_eval_key, "Mask Animation -> Mask Eval");
3296 /* Build parents. */
3297 LISTBASE_FOREACH (MaskLayer *, mask_layer, &mask->masklayers) {
3298 LISTBASE_FOREACH (MaskSpline *, spline, &mask_layer->splines) {
3299 for (int i = 0; i < spline->tot_point; i++) {
3300 MaskSplinePoint *point = &spline->points[i];
3301 MaskParent *parent = &point->parent;
3302 if (parent == nullptr || parent->id == nullptr) {
3303 continue;
3304 }
3305 build_id(parent->id);
3306 if (parent->id_type == ID_MC) {
3307 OperationKey movieclip_eval_key(
3309 add_relation(movieclip_eval_key, mask_eval_key, "Movie Clip -> Mask Eval");
3310 }
3311 }
3312 }
3313 }
3314}
3315
3317{
3318 if (built_map_.check_is_built_and_tag(linestyle)) {
3319 return;
3320 }
3321
3322 const BuilderStack::ScopedEntry stack_entry = stack_.trace(linestyle->id);
3323
3324 ID *linestyle_id = &linestyle->id;
3325 build_parameters(linestyle_id);
3326 build_idproperties(linestyle_id->properties);
3327 build_animdata(linestyle_id);
3328 build_nodetree(linestyle->nodetree);
3329}
3330
3332{
3333 if (built_map_.check_is_built_and_tag(clip)) {
3334 return;
3335 }
3336
3337 const BuilderStack::ScopedEntry stack_entry = stack_.trace(clip->id);
3338
3339 /* Animation. */
3341 build_animdata(&clip->id);
3342 build_parameters(&clip->id);
3343}
3344
3346{
3347 if (built_map_.check_is_built_and_tag(probe)) {
3348 return;
3349 }
3350
3351 const BuilderStack::ScopedEntry stack_entry = stack_.trace(probe->id);
3352
3354 build_animdata(&probe->id);
3355 build_parameters(&probe->id);
3356}
3357
3359{
3360 if (built_map_.check_is_built_and_tag(speaker)) {
3361 return;
3362 }
3363
3364 const BuilderStack::ScopedEntry stack_entry = stack_.trace(speaker->id);
3365
3367 build_animdata(&speaker->id);
3368 build_parameters(&speaker->id);
3369 if (speaker->sound != nullptr) {
3370 build_sound(speaker->sound);
3371 ComponentKey speaker_key(&speaker->id, NodeType::AUDIO);
3372 ComponentKey sound_key(&speaker->sound->id, NodeType::AUDIO);
3373 add_relation(sound_key, speaker_key, "Sound -> Speaker");
3374 }
3375}
3376
3378{
3379 if (built_map_.check_is_built_and_tag(sound)) {
3380 return;
3381 }
3382
3383 const BuilderStack::ScopedEntry stack_entry = stack_.trace(sound->id);
3384
3386 build_animdata(&sound->id);
3387 build_parameters(&sound->id);
3388
3389 const ComponentKey parameters_key(&sound->id, NodeType::PARAMETERS);
3390 const ComponentKey audio_key(&sound->id, NodeType::AUDIO);
3391
3392 add_relation(parameters_key, audio_key, "Parameters -> Audio");
3393}
3394
3400
3401static bool strip_build_prop_cb(Strip *strip, void *user_data)
3402{
3404
3405 cd->builder->build_idproperties(strip->prop);
3406 if (strip->sound != nullptr) {
3407 cd->builder->build_sound(strip->sound);
3408 ComponentKey sound_key(&strip->sound->id, NodeType::AUDIO);
3409 cd->builder->add_relation(sound_key, cd->sequencer_key, "Sound -> Sequencer");
3410 cd->has_audio_strips = true;
3411 }
3412 if (strip->scene != nullptr) {
3414 /* This is to support 3D audio. */
3415 cd->has_audio_strips = true;
3416 }
3417 if (strip->type == STRIP_TYPE_SCENE && strip->scene != nullptr) {
3418 if (strip->flag & SEQ_SCENE_STRIPS) {
3419 cd->builder->build_scene_sequencer(strip->scene);
3420 ComponentKey sequence_scene_audio_key(&strip->scene->id, NodeType::AUDIO);
3421 cd->builder->add_relation(
3422 sequence_scene_audio_key, cd->sequencer_key, "Sequence Scene Audio -> Sequencer");
3423 ComponentKey sequence_scene_key(&strip->scene->id, NodeType::SEQUENCER);
3424 cd->builder->add_relation(
3425 sequence_scene_key, cd->sequencer_key, "Sequence Scene -> Sequencer");
3426 }
3427 ViewLayer *sequence_view_layer = BKE_view_layer_default_render(strip->scene);
3428 cd->builder->build_scene_speakers(strip->scene, sequence_view_layer);
3429 }
3430 /* TODO(sergey): Movie clip, camera, mask. */
3431 return true;
3432}
3433
3435{
3436 if (scene->ed == nullptr) {
3437 return;
3438 }
3439 if (built_map_.check_is_built_and_tag(scene, BuilderMap::TAG_SCENE_SEQUENCER)) {
3440 return;
3441 }
3442
3443 /* TODO(sergey): Trace as a scene sequencer. */
3444
3445 build_scene_audio(scene);
3446 ComponentKey scene_audio_key(&scene->id, NodeType::AUDIO);
3447 /* Make sure dependencies from sequences data goes to the sequencer evaluation. */
3448 ComponentKey sequencer_key(&scene->id, NodeType::SEQUENCER);
3449
3450 Seq_build_prop_cb_data cb_data = {this, sequencer_key, false};
3451
3453 if (cb_data.has_audio_strips) {
3454 add_relation(sequencer_key, scene_audio_key, "Sequencer -> Audio");
3455 }
3456}
3457
3459{
3460 OperationKey scene_audio_entry_key(&scene->id, NodeType::AUDIO, OperationCode::AUDIO_ENTRY);
3461 OperationKey scene_audio_volume_key(&scene->id, NodeType::AUDIO, OperationCode::AUDIO_VOLUME);
3462 OperationKey scene_sound_eval_key(&scene->id, NodeType::AUDIO, OperationCode::SOUND_EVAL);
3463 add_relation(scene_audio_entry_key, scene_audio_volume_key, "Audio Entry -> Volume");
3464 add_relation(scene_audio_volume_key, scene_sound_eval_key, "Audio Volume -> Sound");
3465
3466 if (scene->audio.flag & AUDIO_VOLUME_ANIMATED) {
3467 ComponentKey scene_anim_key(&scene->id, NodeType::ANIMATION);
3468 add_relation(scene_anim_key, scene_audio_volume_key, "Animation -> Audio Volume");
3469 }
3470}
3471
3473{
3474 BKE_view_layer_synced_ensure(scene, view_layer);
3476 Object *object = base->object;
3477 if (object->type != OB_SPEAKER || !need_pull_base_into_graph(base)) {
3478 continue;
3479 }
3480 build_object(base->object);
3481 }
3482}
3483
3485{
3486 if (built_map_.check_is_built_and_tag(vfont)) {
3487 return;
3488 }
3489
3490 const BuilderStack::ScopedEntry stack_entry = stack_.trace(vfont->id);
3491
3492 build_parameters(&vfont->id);
3494}
3495
3497{
3498 for (IDNode *id_node : graph_->id_nodes) {
3500 }
3501}
3502
3509void DepsgraphRelationBuilder::build_nested_datablock(ID *owner, ID *id, bool flush_cow_changes)
3510{
3511 int relation_flag = 0;
3512 if (!flush_cow_changes) {
3513 relation_flag |= RELATION_FLAG_NO_FLUSH;
3514 }
3515 OperationKey owner_copy_on_write_key(owner, NodeType::COPY_ON_EVAL, OperationCode::COPY_ON_EVAL);
3517 add_relation(id_copy_on_write_key, owner_copy_on_write_key, "Eval Order", relation_flag);
3518}
3519
3521{
3522 if (ntree == nullptr) {
3523 return;
3524 }
3525 /* Don't flush cow changes, because the node tree may change in ways that do not affect the
3526 * owner data block (e.g. when a node is deleted that is not connected to any output).
3527 * Data blocks owning node trees should add a relation to the `NTREE_OUTPUT` node instead. */
3528 build_nested_datablock(owner, &ntree->id, false);
3529}
3530
3532{
3533 if (key == nullptr) {
3534 return;
3535 }
3536 build_nested_datablock(owner, &key->id, true);
3537}
3538
3540{
3541 ID *id_orig = id_node->id_orig;
3542
3543 const ID_Type id_type = GS(id_orig->name);
3544
3545 if (!deg_eval_copy_is_needed(id_type)) {
3546 return;
3547 }
3548
3550 /* XXX: This is a quick hack to make Alt-A to work. */
3551 // add_relation(time_source_key, copy_on_write_key, "Fluxgate capacitor hack");
3552 /* Resat of code is using rather low level trickery, so need to get some
3553 * explicit pointers. */
3554 Node *node_cow = find_node(copy_on_write_key);
3555 OperationNode *op_cow = node_cow->get_exit_operation();
3556 /* Plug any other components to this one. */
3557 for (ComponentNode *comp_node : id_node->components.values()) {
3558 if (comp_node->type == NodeType::COPY_ON_EVAL) {
3559 /* Copy-on-eval component never depends on itself. */
3560 continue;
3561 }
3562 if (!comp_node->depends_on_cow()) {
3563 /* Component explicitly requests to not add relation. */
3564 continue;
3565 }
3567 if ((ELEM(id_type, ID_ME, ID_CV, ID_PT, ID_VO) && comp_node->type == NodeType::GEOMETRY) ||
3568 (id_type == ID_CF && comp_node->type == NodeType::CACHE))
3569 {
3570 rel_flag &= ~RELATION_FLAG_NO_FLUSH;
3571 }
3572 /* TODO(sergey): Needs better solution for this. */
3573 if (id_type == ID_SO) {
3574 rel_flag &= ~RELATION_FLAG_NO_FLUSH;
3575 }
3576 /* Notes on exceptions:
3577 * - View layers have cached array of bases in them, which is not
3578 * copied by copy-on-evaluation, and not preserved. PROBABLY it is better
3579 * to preserve that cache in copy-on-evaluation, but for the time being
3580 * we allow flush to layer collections component which will ensure
3581 * that cached array of bases exists and is up-to-date. */
3582 if (ELEM(comp_node->type, NodeType::LAYER_COLLECTIONS)) {
3583 rel_flag &= ~RELATION_FLAG_NO_FLUSH;
3584 }
3585 /* Mask evaluation operation is part of parameters, and it needs to be re-evaluated when the
3586 * mask is tagged for copy-on-eval.
3587 *
3588 * TODO(@sergey): This needs to be moved out of here.
3589 * In order to do so, moving mask evaluation out of parameters would be helpful and
3590 * semantically correct. */
3591 if (comp_node->type == NodeType::PARAMETERS && id_type == ID_MSK) {
3592 rel_flag &= ~RELATION_FLAG_NO_FLUSH;
3593 }
3594 /* Compatibility with the legacy tagging: groups are only tagged for Copy-on-Write when their
3595 * hierarchy changes, and it needs to be flushed downstream. */
3596 if (id_type == ID_GR && comp_node->type == NodeType::HIERARCHY) {
3597 rel_flag &= ~RELATION_FLAG_NO_FLUSH;
3598 }
3599 /* All entry operations of each component should wait for a proper
3600 * copy of ID. */
3601 OperationNode *op_entry = comp_node->get_entry_operation();
3602 if (op_entry != nullptr) {
3603 Relation *rel = graph_->add_new_relation(op_cow, op_entry, "Copy-on-Eval Dependency");
3604 rel->flag |= rel_flag;
3605 }
3606 /* All dangling operations should also be executed after copy-on-evaluation. */
3607 for (OperationNode *op_node : comp_node->operations_map->values()) {
3608 if (op_node == op_entry) {
3609 continue;
3610 }
3611 if (op_node->inlinks.is_empty()) {
3612 Relation *rel = graph_->add_new_relation(op_cow, op_node, "Copy-on-Eval Dependency");
3613 rel->flag |= rel_flag;
3614 }
3615 else {
3616 bool has_same_comp_dependency = false;
3617 for (Relation *rel_current : op_node->inlinks) {
3618 if (rel_current->from->type != NodeType::OPERATION) {
3619 continue;
3620 }
3621 OperationNode *op_node_from = (OperationNode *)rel_current->from;
3622 if (op_node_from->owner == op_node->owner) {
3623 has_same_comp_dependency = true;
3624 break;
3625 }
3626 }
3627 if (!has_same_comp_dependency) {
3628 Relation *rel = graph_->add_new_relation(op_cow, op_node, "Copy-on-Eval Dependency");
3629 rel->flag |= rel_flag;
3630 }
3631 }
3632 }
3633 /* NOTE: We currently ignore implicit relations to an external
3634 * data-blocks for copy-on-evaluation operations. This means, for example,
3635 * copy-on-evaluation component of Object will not wait for copy-on-evaluation
3636 * component of its Mesh. This is because pointers are all known
3637 * already so remapping will happen all correct. And then If some object
3638 * evaluation step needs geometry, it will have transitive dependency
3639 * to Mesh copy-on-evaluation already. */
3640 }
3641 /* TODO(sergey): This solves crash for now, but causes too many
3642 * updates potentially. */
3643 if (GS(id_orig->name) == ID_OB) {
3644 Object *object = (Object *)id_orig;
3645 ID *object_data_id = (ID *)object->data;
3646 if (object_data_id != nullptr) {
3647 if (deg_eval_copy_is_needed(object_data_id)) {
3648 OperationKey data_copy_on_write_key(
3651 data_copy_on_write_key, copy_on_write_key, "Eval Order", RELATION_FLAG_GODMODE);
3652 }
3653 }
3654 else {
3655 BLI_assert(object->type == OB_EMPTY);
3656 }
3657 }
3658
3659#if 0
3660 /* NOTE: Relation is disabled since AnimationBackup() is disabled.
3661 * See comment in AnimationBackup:init_from_id(). */
3662
3663 /* Copy-on-eval of write will iterate over f-curves to store current values corresponding
3664 * to their RNA path. This means that action must be copied prior to the ID's copy-on-evaluation,
3665 * otherwise depsgraph might try to access freed data. */
3666 AnimData *animation_data = BKE_animdata_from_id(id_orig);
3667 if (animation_data != nullptr) {
3668 if (animation_data->action != nullptr) {
3669 OperationKey action_copy_on_write_key(
3671 add_relation(action_copy_on_write_key,
3672 copy_on_write_key,
3673 "Eval Order",
3675 }
3676 }
3677#endif
3678}
3679
3680/* **** ID traversal callbacks functions **** */
3681
3682void DepsgraphRelationBuilder::modifier_walk(void *user_data,
3683 Object * /*object*/,
3684 ID **idpoin,
3685 LibraryForeachIDCallbackFlag /*cb_flag*/)
3686{
3687 BuilderWalkUserData *data = (BuilderWalkUserData *)user_data;
3688 ID *id = *idpoin;
3689 if (id == nullptr) {
3690 return;
3691 }
3692 data->builder->build_id(id);
3693}
3694
3695void DepsgraphRelationBuilder::constraint_walk(bConstraint * /*con*/,
3696 ID **idpoin,
3697 bool /*is_reference*/,
3698 void *user_data)
3699{
3700 BuilderWalkUserData *data = (BuilderWalkUserData *)user_data;
3701 ID *id = *idpoin;
3702 if (id == nullptr) {
3703 return;
3704 }
3705 data->builder->build_id(id);
3706}
3707
3708} // 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:82
#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:1804
Key * BKE_key_from_object(Object *ob)
Definition key.cc:1824
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:424
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_IP
@ ID_GR
@ ID_SPK
@ ID_MB
@ ID_LT
@ ID_OB
@ ID_GP
@ ID_PA
@ ID_PT
@ ID_PC
@ IDP_TYPE_FILTER_ID
@ DVAR_TYPE_CONTEXT_PROP
@ DTAR_FLAG_STRUCT_REF
@ DTAR_CONTEXT_PROPERTY_ACTIVE_SCENE
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_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
struct ListBase ListBase
@ TEXCO_OBJECT
@ MOD_SHRINKWRAP_TARGET_PROJECT
@ MOD_SHRINKWRAP_NEAREST_VERTEX
@ eModifierType_Collision
@ SHD_ATTRIBUTE_VIEW_LAYER
@ NTREE_SHADER
@ NTREE_GEOMETRY
@ NTREE_RUNTIME_FLAG_HAS_IMAGE_ANIMATION
@ SOCK_TEXTURE
@ SOCK_MATERIAL
@ SOCK_IMAGE
@ SOCK_COLLECTION
@ SOCK_OBJECT
@ PFIELD_FLUIDFLOW
@ PFIELD_SHAPE_SURFACE
@ PFIELD_SHAPE_POINTS
@ PFIELD_VISIBILITY
Object is a sort of wrapper for general info.
#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
struct Object Object
@ OB_DUPLI
@ OB_DUPLIVERTS
@ PARVERT1
@ PARSKEL
@ PARVERT3
@ PARBONE
struct ParticleSettings ParticleSettings
@ PSYS_HAIR_DYNAMICS
@ PART_HAIR
@ PART_DRAW_GR
@ PART_DRAW_OB
@ PART_PHYS_KEYED
@ PART_PHYS_BOIDS
struct ParticleSystem ParticleSystem
Types and defines for representing Rigid Body entities.
@ RBO_TYPE_ACTIVE
@ RBO_TYPE_PASSIVE
@ RB_SHAPE_COMPOUND
@ AUDIO_VOLUME_ANIMATED
@ SEQ_SCENE_STRIPS
@ STRIP_TYPE_SCENE
@ 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
TEX_TEMPLATE DataVec texture(T, FltCoord, float=0.0f) RET
#define this
#define CD_MASK_ORIGINDEX
#define CD_MASK_MDEFORMVERT
#define GS(a)
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:4816
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 for_each_callback(ListBase *seqbase, ForEachFunc callback, void *user_data)
Definition iterator.cc:59
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:137
IDPropertyData data
Definition DNA_ID.h:159
Definition DNA_ID.h:404
IDProperty * properties
Definition DNA_ID.h:446
char name[66]
Definition DNA_ID.h:415
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
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:4227
uint8_t flag
Definition wm_window.cc:139