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