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