Welcome to mirror list, hosted at ThFree Co, Russian Federation.

git.blender.org/blender.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
Diffstat (limited to 'source/blender/depsgraph/intern/builder/deg_builder_relations.cc')
-rw-r--r--source/blender/depsgraph/intern/builder/deg_builder_relations.cc4415
1 files changed, 2036 insertions, 2379 deletions
diff --git a/source/blender/depsgraph/intern/builder/deg_builder_relations.cc b/source/blender/depsgraph/intern/builder/deg_builder_relations.cc
index 489b688eaaa..87a8875f819 100644
--- a/source/blender/depsgraph/intern/builder/deg_builder_relations.cc
+++ b/source/blender/depsgraph/intern/builder/deg_builder_relations.cc
@@ -27,7 +27,7 @@
#include <stdio.h>
#include <stdlib.h>
-#include <cstring> /* required for STREQ later on. */
+#include <cstring> /* required for STREQ later on. */
#include "MEM_guardedalloc.h"
@@ -121,61 +121,60 @@ namespace DEG {
*/
static bool python_driver_depends_on_time(ChannelDriver *driver)
{
- if (driver->expression[0] == '\0') {
- /* Empty expression depends on nothing. */
- return false;
- }
- if (strchr(driver->expression, '(') != NULL) {
- /* Function calls are considered dependent on a time. */
- return true;
- }
- if (strstr(driver->expression, "frame") != NULL) {
- /* Variable `frame` depends on time. */
- /* TODO(sergey): This is a bit weak, but not sure about better way of
- * handling this. */
- return true;
- }
- /* Possible indirect time relation s should be handled via variable
- * targets. */
- return false;
+ if (driver->expression[0] == '\0') {
+ /* Empty expression depends on nothing. */
+ return false;
+ }
+ if (strchr(driver->expression, '(') != NULL) {
+ /* Function calls are considered dependent on a time. */
+ return true;
+ }
+ if (strstr(driver->expression, "frame") != NULL) {
+ /* Variable `frame` depends on time. */
+ /* TODO(sergey): This is a bit weak, but not sure about better way of
+ * handling this. */
+ return true;
+ }
+ /* Possible indirect time relation s should be handled via variable
+ * targets. */
+ return false;
}
static bool particle_system_depends_on_time(ParticleSystem *psys)
{
- ParticleSettings *part = psys->part;
- /* Non-hair particles we always consider dependent on time. */
- if (part->type != PART_HAIR) {
- return true;
- }
- /* Dynamics always depends on time. */
- if (psys->flag & PSYS_HAIR_DYNAMICS) {
- return true;
- }
- /* TODO(sergey): Check what else makes hair dependent on time. */
- return false;
+ ParticleSettings *part = psys->part;
+ /* Non-hair particles we always consider dependent on time. */
+ if (part->type != PART_HAIR) {
+ return true;
+ }
+ /* Dynamics always depends on time. */
+ if (psys->flag & PSYS_HAIR_DYNAMICS) {
+ return true;
+ }
+ /* TODO(sergey): Check what else makes hair dependent on time. */
+ return false;
}
static bool object_particles_depends_on_time(Object *object)
{
- if (object->type != OB_MESH) {
- return false;
- }
- LISTBASE_FOREACH (ParticleSystem *, psys, &object->particlesystem) {
- if (particle_system_depends_on_time(psys)) {
- return true;
- }
- }
- return false;
+ if (object->type != OB_MESH) {
+ return false;
+ }
+ LISTBASE_FOREACH (ParticleSystem *, psys, &object->particlesystem) {
+ if (particle_system_depends_on_time(psys)) {
+ return true;
+ }
+ }
+ return false;
}
static bool check_id_has_anim_component(ID *id)
{
- AnimData *adt = BKE_animdata_from_id(id);
- if (adt == NULL) {
- return false;
- }
- return (adt->action != NULL) ||
- (!BLI_listbase_is_empty(&adt->nla_tracks));
+ AnimData *adt = BKE_animdata_from_id(id);
+ if (adt == NULL) {
+ return false;
+ }
+ return (adt->action != NULL) || (!BLI_listbase_is_empty(&adt->nla_tracks));
}
static OperationCode bone_target_opcode(ID *target,
@@ -184,267 +183,251 @@ static OperationCode bone_target_opcode(ID *target,
const char *component_subdata,
RootPChanMap *root_map)
{
- /* Same armature. */
- if (target == id) {
- /* Using "done" here breaks in-chain deps, while using
- * "ready" here breaks most production rigs instead.
- * So, we do a compromise here, and only do this when an
- * IK chain conflict may occur. */
- if (root_map->has_common_root(component_subdata, subtarget)) {
- return OperationCode::BONE_READY;
- }
- }
- return OperationCode::BONE_DONE;
+ /* Same armature. */
+ if (target == id) {
+ /* Using "done" here breaks in-chain deps, while using
+ * "ready" here breaks most production rigs instead.
+ * So, we do a compromise here, and only do this when an
+ * IK chain conflict may occur. */
+ if (root_map->has_common_root(component_subdata, subtarget)) {
+ return OperationCode::BONE_READY;
+ }
+ }
+ return OperationCode::BONE_DONE;
}
static bool bone_has_segments(Object *object, const char *bone_name)
{
- /* Proxies don't have BONE_SEGMENTS */
- if (ID_IS_LINKED(object) && object->proxy_from != NULL) {
- return false;
- }
- /* Only B-Bones have segments. */
- bPoseChannel *pchan = BKE_pose_channel_find_name(object->pose, bone_name);
- return pchan && pchan->bone && pchan->bone->segments > 1;
+ /* Proxies don't have BONE_SEGMENTS */
+ if (ID_IS_LINKED(object) && object->proxy_from != NULL) {
+ return false;
+ }
+ /* Only B-Bones have segments. */
+ bPoseChannel *pchan = BKE_pose_channel_find_name(object->pose, bone_name);
+ return pchan && pchan->bone && pchan->bone->segments > 1;
}
/* **** General purpose functions **** */
-DepsgraphRelationBuilder::DepsgraphRelationBuilder(Main *bmain,
- Depsgraph *graph)
- : DepsgraphBuilder(bmain, graph),
- scene_(NULL),
- rna_node_query_(graph)
+DepsgraphRelationBuilder::DepsgraphRelationBuilder(Main *bmain, Depsgraph *graph)
+ : DepsgraphBuilder(bmain, graph), scene_(NULL), rna_node_query_(graph)
{
}
-TimeSourceNode *DepsgraphRelationBuilder::get_node(
- const TimeSourceKey &key) const
+TimeSourceNode *DepsgraphRelationBuilder::get_node(const TimeSourceKey &key) const
{
- if (key.id) {
- /* XXX TODO */
- return NULL;
- }
- else {
- return graph_->time_source;
- }
+ if (key.id) {
+ /* XXX TODO */
+ return NULL;
+ }
+ else {
+ return graph_->time_source;
+ }
}
-ComponentNode *DepsgraphRelationBuilder::get_node(
- const ComponentKey &key) const
+ComponentNode *DepsgraphRelationBuilder::get_node(const ComponentKey &key) const
{
- IDNode *id_node = graph_->find_id_node(key.id);
- if (!id_node) {
- fprintf(stderr, "find_node component: Could not find ID %s\n",
- (key.id != NULL) ? key.id->name : "<null>");
- return NULL;
- }
+ IDNode *id_node = graph_->find_id_node(key.id);
+ if (!id_node) {
+ fprintf(stderr,
+ "find_node component: Could not find ID %s\n",
+ (key.id != NULL) ? key.id->name : "<null>");
+ return NULL;
+ }
- ComponentNode *node = id_node->find_component(key.type, key.name);
- return node;
+ ComponentNode *node = id_node->find_component(key.type, key.name);
+ return node;
}
-OperationNode *DepsgraphRelationBuilder::get_node(
- const OperationKey &key) const
+OperationNode *DepsgraphRelationBuilder::get_node(const OperationKey &key) const
{
- OperationNode *op_node = find_node(key);
- if (op_node == NULL) {
- fprintf(stderr, "find_node_operation: Failed for (%s, '%s')\n",
- operationCodeAsString(key.opcode), key.name);
- }
- return op_node;
+ OperationNode *op_node = find_node(key);
+ if (op_node == NULL) {
+ fprintf(stderr,
+ "find_node_operation: Failed for (%s, '%s')\n",
+ operationCodeAsString(key.opcode),
+ key.name);
+ }
+ return op_node;
}
Node *DepsgraphRelationBuilder::get_node(const RNAPathKey &key)
{
- return rna_node_query_.find_node(&key.ptr, key.prop, key.source);
+ return rna_node_query_.find_node(&key.ptr, key.prop, key.source);
}
-OperationNode *DepsgraphRelationBuilder::find_node(
- const OperationKey &key) const
+OperationNode *DepsgraphRelationBuilder::find_node(const OperationKey &key) const
{
- IDNode *id_node = graph_->find_id_node(key.id);
- if (!id_node) {
- return NULL;
- }
- ComponentNode *comp_node = id_node->find_component(key.component_type,
- key.component_name);
- if (!comp_node) {
- return NULL;
- }
- return comp_node->find_operation(key.opcode, key.name, key.name_tag);
+ IDNode *id_node = graph_->find_id_node(key.id);
+ if (!id_node) {
+ return NULL;
+ }
+ ComponentNode *comp_node = id_node->find_component(key.component_type, key.component_name);
+ if (!comp_node) {
+ return NULL;
+ }
+ return comp_node->find_operation(key.opcode, key.name, key.name_tag);
}
bool DepsgraphRelationBuilder::has_node(const OperationKey &key) const
{
- return find_node(key) != NULL;
+ return find_node(key) != NULL;
}
-void DepsgraphRelationBuilder::add_modifier_to_transform_relation(
- const DepsNodeHandle *handle,
- const char *description)
+void DepsgraphRelationBuilder::add_modifier_to_transform_relation(const DepsNodeHandle *handle,
+ const char *description)
{
- IDNode *id_node = handle->node->owner->owner;
- ID *id = id_node->id_orig;
- ComponentKey geometry_key(id, NodeType::GEOMETRY);
- /* Wire up the actual relation. */
- add_depends_on_transform_relation(id, geometry_key, description);
+ IDNode *id_node = handle->node->owner->owner;
+ ID *id = id_node->id_orig;
+ ComponentKey geometry_key(id, NodeType::GEOMETRY);
+ /* Wire up the actual relation. */
+ add_depends_on_transform_relation(id, geometry_key, description);
}
-void DepsgraphRelationBuilder::add_customdata_mask(
- Object *object,
- const DEGCustomDataMeshMasks &customdata_masks)
+void DepsgraphRelationBuilder::add_customdata_mask(Object *object,
+ const DEGCustomDataMeshMasks &customdata_masks)
{
- if (customdata_masks != DEGCustomDataMeshMasks() && object != NULL && object->type == OB_MESH) {
- DEG::IDNode *id_node = graph_->find_id_node(&object->id);
+ if (customdata_masks != DEGCustomDataMeshMasks() && object != NULL && object->type == OB_MESH) {
+ DEG::IDNode *id_node = graph_->find_id_node(&object->id);
- if (id_node == NULL) {
- BLI_assert(!"ID should always be valid");
- }
- else {
- id_node->customdata_masks |= customdata_masks;
- }
- }
+ if (id_node == NULL) {
+ BLI_assert(!"ID should always be valid");
+ }
+ else {
+ id_node->customdata_masks |= customdata_masks;
+ }
+ }
}
void DepsgraphRelationBuilder::add_special_eval_flag(ID *id, uint32_t flag)
{
- DEG::IDNode *id_node = graph_->find_id_node(id);
- if (id_node == NULL) {
- BLI_assert(!"ID should always be valid");
- }
- else {
- id_node->eval_flags |= flag;
- }
-}
-
-Relation *DepsgraphRelationBuilder::add_time_relation(
- TimeSourceNode *timesrc,
- Node *node_to,
- const char *description,
- int flags)
-{
- if (timesrc && node_to) {
- return graph_->add_new_relation(
- timesrc, node_to, description, flags);
- }
- else {
- DEG_DEBUG_PRINTF((::Depsgraph *)graph_,
- BUILD, "add_time_relation(%p = %s, %p = %s, %s) Failed\n",
- timesrc, (timesrc) ? timesrc->identifier().c_str() : "<None>",
- node_to, (node_to) ? node_to->identifier().c_str() : "<None>",
- description);
- }
- return NULL;
-}
-
-Relation *DepsgraphRelationBuilder::add_operation_relation(
- OperationNode *node_from,
- OperationNode *node_to,
- const char *description,
- int flags)
-{
- if (node_from && node_to) {
- return graph_->add_new_relation(node_from,
- node_to,
- description,
- flags);
- }
- else {
- DEG_DEBUG_PRINTF((::Depsgraph *)graph_,
- BUILD, "add_operation_relation(%p = %s, %p = %s, %s) Failed\n",
- node_from, (node_from) ? node_from->identifier().c_str() : "<None>",
- node_to, (node_to) ? node_to->identifier().c_str() : "<None>",
- description);
- }
- return NULL;
-}
-
-void DepsgraphRelationBuilder::add_particle_collision_relations(
- const OperationKey &key,
- Object *object,
- Collection *collection,
- const char *name)
-{
- ListBase *relations = build_collision_relations(graph_, collection, eModifierType_Collision);
-
- LISTBASE_FOREACH (CollisionRelation *, relation, relations) {
- if (relation->ob != object) {
- ComponentKey trf_key(&relation->ob->id, NodeType::TRANSFORM);
- add_relation(trf_key, key, name);
-
- ComponentKey coll_key(&relation->ob->id, NodeType::GEOMETRY);
- add_relation(coll_key, key, name);
- }
- }
-}
-
-void DepsgraphRelationBuilder::add_particle_forcefield_relations(
- const OperationKey &key,
- Object *object,
- ParticleSystem *psys,
- EffectorWeights *eff,
- bool add_absorption,
- const char *name)
-{
- ListBase *relations = build_effector_relations(graph_, eff->group);
-
- LISTBASE_FOREACH (EffectorRelation *, relation, relations) {
- if (relation->ob != object) {
- /* Relation to forcefield object, optionally including geometry. */
- ComponentKey eff_key(&relation->ob->id, NodeType::TRANSFORM);
- add_relation(eff_key, key, name);
-
- if (ELEM(relation->pd->shape, PFIELD_SHAPE_SURFACE, PFIELD_SHAPE_POINTS) ||
- relation->pd->forcefield == PFIELD_GUIDE)
- {
- ComponentKey mod_key(&relation->ob->id, NodeType::GEOMETRY);
- add_relation(mod_key, key, name);
- }
-
- /* Smoke flow relations. */
- if (relation->pd->forcefield == PFIELD_SMOKEFLOW && relation->pd->f_source) {
- ComponentKey trf_key(&relation->pd->f_source->id,
- NodeType::TRANSFORM);
- add_relation(trf_key, key, "Smoke Force Domain");
- ComponentKey eff_key(&relation->pd->f_source->id,
- NodeType::GEOMETRY);
- add_relation(eff_key, key, "Smoke Force Domain");
- }
-
- /* Absorption forces need collision relation. */
- if (add_absorption && (relation->pd->flag & PFIELD_VISIBILITY)) {
- add_particle_collision_relations(key,
- object,
- NULL,
- "Force Absorption");
- }
- }
-
- if (relation->psys) {
- if (relation->ob != object) {
- ComponentKey eff_key(&relation->ob->id,
- NodeType::PARTICLE_SYSTEM);
- add_relation(eff_key, key, name);
- /* TODO: remove this when/if EVAL_PARTICLES is sufficient
- * for up to date particles. */
- ComponentKey mod_key(&relation->ob->id, NodeType::GEOMETRY);
- add_relation(mod_key, key, name);
- }
- else if (relation->psys != psys) {
- OperationKey eff_key(&relation->ob->id,
- NodeType::PARTICLE_SYSTEM,
- OperationCode::PARTICLE_SYSTEM_EVAL,
- relation->psys->name);
- add_relation(eff_key, key, name);
- }
- }
- }
+ DEG::IDNode *id_node = graph_->find_id_node(id);
+ if (id_node == NULL) {
+ BLI_assert(!"ID should always be valid");
+ }
+ else {
+ id_node->eval_flags |= flag;
+ }
+}
+
+Relation *DepsgraphRelationBuilder::add_time_relation(TimeSourceNode *timesrc,
+ Node *node_to,
+ const char *description,
+ int flags)
+{
+ if (timesrc && node_to) {
+ return graph_->add_new_relation(timesrc, node_to, description, flags);
+ }
+ else {
+ DEG_DEBUG_PRINTF((::Depsgraph *)graph_,
+ BUILD,
+ "add_time_relation(%p = %s, %p = %s, %s) Failed\n",
+ timesrc,
+ (timesrc) ? timesrc->identifier().c_str() : "<None>",
+ node_to,
+ (node_to) ? node_to->identifier().c_str() : "<None>",
+ description);
+ }
+ return NULL;
+}
+
+Relation *DepsgraphRelationBuilder::add_operation_relation(OperationNode *node_from,
+ OperationNode *node_to,
+ const char *description,
+ int flags)
+{
+ if (node_from && node_to) {
+ return graph_->add_new_relation(node_from, node_to, description, flags);
+ }
+ else {
+ DEG_DEBUG_PRINTF((::Depsgraph *)graph_,
+ BUILD,
+ "add_operation_relation(%p = %s, %p = %s, %s) Failed\n",
+ node_from,
+ (node_from) ? node_from->identifier().c_str() : "<None>",
+ node_to,
+ (node_to) ? node_to->identifier().c_str() : "<None>",
+ description);
+ }
+ return NULL;
+}
+
+void DepsgraphRelationBuilder::add_particle_collision_relations(const OperationKey &key,
+ Object *object,
+ Collection *collection,
+ const char *name)
+{
+ ListBase *relations = build_collision_relations(graph_, collection, eModifierType_Collision);
+
+ LISTBASE_FOREACH (CollisionRelation *, relation, relations) {
+ if (relation->ob != object) {
+ ComponentKey trf_key(&relation->ob->id, NodeType::TRANSFORM);
+ add_relation(trf_key, key, name);
+
+ ComponentKey coll_key(&relation->ob->id, NodeType::GEOMETRY);
+ add_relation(coll_key, key, name);
+ }
+ }
+}
+
+void DepsgraphRelationBuilder::add_particle_forcefield_relations(const OperationKey &key,
+ Object *object,
+ ParticleSystem *psys,
+ EffectorWeights *eff,
+ bool add_absorption,
+ const char *name)
+{
+ ListBase *relations = build_effector_relations(graph_, eff->group);
+
+ LISTBASE_FOREACH (EffectorRelation *, relation, relations) {
+ if (relation->ob != object) {
+ /* Relation to forcefield object, optionally including geometry. */
+ ComponentKey eff_key(&relation->ob->id, NodeType::TRANSFORM);
+ add_relation(eff_key, key, name);
+
+ if (ELEM(relation->pd->shape, PFIELD_SHAPE_SURFACE, PFIELD_SHAPE_POINTS) ||
+ relation->pd->forcefield == PFIELD_GUIDE) {
+ ComponentKey mod_key(&relation->ob->id, NodeType::GEOMETRY);
+ add_relation(mod_key, key, name);
+ }
+
+ /* Smoke flow relations. */
+ if (relation->pd->forcefield == PFIELD_SMOKEFLOW && relation->pd->f_source) {
+ ComponentKey trf_key(&relation->pd->f_source->id, NodeType::TRANSFORM);
+ add_relation(trf_key, key, "Smoke Force Domain");
+ ComponentKey eff_key(&relation->pd->f_source->id, NodeType::GEOMETRY);
+ add_relation(eff_key, key, "Smoke Force Domain");
+ }
+
+ /* Absorption forces need collision relation. */
+ if (add_absorption && (relation->pd->flag & PFIELD_VISIBILITY)) {
+ add_particle_collision_relations(key, object, NULL, "Force Absorption");
+ }
+ }
+
+ if (relation->psys) {
+ if (relation->ob != object) {
+ ComponentKey eff_key(&relation->ob->id, NodeType::PARTICLE_SYSTEM);
+ add_relation(eff_key, key, name);
+ /* TODO: remove this when/if EVAL_PARTICLES is sufficient
+ * for up to date particles. */
+ ComponentKey mod_key(&relation->ob->id, NodeType::GEOMETRY);
+ add_relation(mod_key, key, name);
+ }
+ else if (relation->psys != psys) {
+ OperationKey eff_key(&relation->ob->id,
+ NodeType::PARTICLE_SYSTEM,
+ OperationCode::PARTICLE_SYSTEM_EVAL,
+ relation->psys->name);
+ add_relation(eff_key, key, name);
+ }
+ }
+ }
}
Depsgraph *DepsgraphRelationBuilder::getGraph()
{
- return graph_;
+ return graph_;
}
/* **** Functions to build relations between entities **** */
@@ -455,549 +438,491 @@ void DepsgraphRelationBuilder::begin_build()
void DepsgraphRelationBuilder::build_id(ID *id)
{
- if (id == NULL) {
- return;
- }
- switch (GS(id->name)) {
- case ID_AC:
- build_action((bAction *)id);
- break;
- case ID_AR:
- build_armature((bArmature *)id);
- break;
- case ID_CA:
- build_camera((Camera *)id);
- break;
- case ID_GR:
- build_collection(NULL, NULL, (Collection *)id);
- break;
- case ID_OB:
- build_object(NULL, (Object *)id);
- break;
- case ID_KE:
- build_shapekeys((Key *)id);
- break;
- case ID_LA:
- build_light((Light *)id);
- break;
- case ID_LP:
- build_lightprobe((LightProbe *)id);
- break;
- case ID_NT:
- build_nodetree((bNodeTree *)id);
- break;
- case ID_MA:
- build_material((Material *)id);
- break;
- case ID_TE:
- build_texture((Tex *)id);
- break;
- case ID_IM:
- build_image((Image *)id);
- break;
- case ID_WO:
- build_world((World *)id);
- break;
- case ID_MSK:
- build_mask((Mask *)id);
- break;
- case ID_MC:
- build_movieclip((MovieClip *)id);
- break;
- case ID_ME:
- case ID_CU:
- case ID_MB:
- case ID_LT:
- build_object_data_geometry_datablock(id);
- break;
- case ID_SPK:
- build_speaker((Speaker *)id);
- break;
- case ID_TXT:
- /* Not a part of dependency graph. */
- break;
- case ID_CF:
- build_cachefile((CacheFile *)id);
- break;
- default:
- fprintf(stderr, "Unhandled ID %s\n", id->name);
- BLI_assert(!"Should never happen");
- break;
- }
-}
-
-void DepsgraphRelationBuilder::build_collection(
- LayerCollection *from_layer_collection,
- Object *object,
- Collection *collection)
-{
- if (from_layer_collection != NULL) {
- /* If we came from layer collection we don't go deeper, view layer
- * builder takes care of going deeper.
- *
- * NOTE: Do early output before tagging build as done, so possbile
- * subsequent builds from outside of the layer collection properly
- * recurses into all the nested objects and collections. */
- return;
- }
- const bool group_done = built_map_.checkIsBuiltAndTag(collection);
- OperationKey object_transform_final_key(object != NULL ? &object->id : NULL,
- NodeType::TRANSFORM,
- OperationCode::TRANSFORM_FINAL);
- ComponentKey duplicator_key(object != NULL ? &object->id : NULL,
- NodeType::DUPLI);
- if (!group_done) {
- LISTBASE_FOREACH (CollectionObject *, cob, &collection->gobject) {
- build_object(NULL, cob->ob);
- }
- LISTBASE_FOREACH (CollectionChild *, child, &collection->children) {
- build_collection(NULL, NULL, child->collection);
- }
- }
- if (object != NULL) {
- FOREACH_COLLECTION_VISIBLE_OBJECT_RECURSIVE_BEGIN(collection, ob, graph_->mode)
- {
- ComponentKey dupli_transform_key(&ob->id, NodeType::TRANSFORM);
- add_relation(dupli_transform_key,
- object_transform_final_key,
- "Dupligroup");
- /* Hook to special component, to ensure proper visibility/evaluation
- * optimizations. */
- add_relation(dupli_transform_key, duplicator_key, "Dupligroup");
- const NodeType dupli_geometry_component_type =
- geometry_tag_to_component(&ob->id);
- if (dupli_geometry_component_type != NodeType::UNDEFINED) {
- ComponentKey dupli_geometry_component_key(
- &ob->id, dupli_geometry_component_type);
- add_relation(dupli_geometry_component_key,
- duplicator_key,
- "Dupligroup");
- }
- }
- FOREACH_COLLECTION_VISIBLE_OBJECT_RECURSIVE_END;
- }
+ if (id == NULL) {
+ return;
+ }
+ switch (GS(id->name)) {
+ case ID_AC:
+ build_action((bAction *)id);
+ break;
+ case ID_AR:
+ build_armature((bArmature *)id);
+ break;
+ case ID_CA:
+ build_camera((Camera *)id);
+ break;
+ case ID_GR:
+ build_collection(NULL, NULL, (Collection *)id);
+ break;
+ case ID_OB:
+ build_object(NULL, (Object *)id);
+ break;
+ case ID_KE:
+ build_shapekeys((Key *)id);
+ break;
+ case ID_LA:
+ build_light((Light *)id);
+ break;
+ case ID_LP:
+ build_lightprobe((LightProbe *)id);
+ break;
+ case ID_NT:
+ build_nodetree((bNodeTree *)id);
+ break;
+ case ID_MA:
+ build_material((Material *)id);
+ break;
+ case ID_TE:
+ build_texture((Tex *)id);
+ break;
+ case ID_IM:
+ build_image((Image *)id);
+ break;
+ case ID_WO:
+ build_world((World *)id);
+ break;
+ case ID_MSK:
+ build_mask((Mask *)id);
+ break;
+ case ID_MC:
+ build_movieclip((MovieClip *)id);
+ break;
+ case ID_ME:
+ case ID_CU:
+ case ID_MB:
+ case ID_LT:
+ build_object_data_geometry_datablock(id);
+ break;
+ case ID_SPK:
+ build_speaker((Speaker *)id);
+ break;
+ case ID_TXT:
+ /* Not a part of dependency graph. */
+ break;
+ case ID_CF:
+ build_cachefile((CacheFile *)id);
+ break;
+ default:
+ fprintf(stderr, "Unhandled ID %s\n", id->name);
+ BLI_assert(!"Should never happen");
+ break;
+ }
+}
+
+void DepsgraphRelationBuilder::build_collection(LayerCollection *from_layer_collection,
+ Object *object,
+ Collection *collection)
+{
+ if (from_layer_collection != NULL) {
+ /* If we came from layer collection we don't go deeper, view layer
+ * builder takes care of going deeper.
+ *
+ * NOTE: Do early output before tagging build as done, so possbile
+ * subsequent builds from outside of the layer collection properly
+ * recurses into all the nested objects and collections. */
+ return;
+ }
+ const bool group_done = built_map_.checkIsBuiltAndTag(collection);
+ OperationKey object_transform_final_key(
+ object != NULL ? &object->id : NULL, NodeType::TRANSFORM, OperationCode::TRANSFORM_FINAL);
+ ComponentKey duplicator_key(object != NULL ? &object->id : NULL, NodeType::DUPLI);
+ if (!group_done) {
+ LISTBASE_FOREACH (CollectionObject *, cob, &collection->gobject) {
+ build_object(NULL, cob->ob);
+ }
+ LISTBASE_FOREACH (CollectionChild *, child, &collection->children) {
+ build_collection(NULL, NULL, child->collection);
+ }
+ }
+ if (object != NULL) {
+ FOREACH_COLLECTION_VISIBLE_OBJECT_RECURSIVE_BEGIN (collection, ob, graph_->mode) {
+ ComponentKey dupli_transform_key(&ob->id, NodeType::TRANSFORM);
+ add_relation(dupli_transform_key, object_transform_final_key, "Dupligroup");
+ /* Hook to special component, to ensure proper visibility/evaluation
+ * optimizations. */
+ add_relation(dupli_transform_key, duplicator_key, "Dupligroup");
+ const NodeType dupli_geometry_component_type = geometry_tag_to_component(&ob->id);
+ if (dupli_geometry_component_type != NodeType::UNDEFINED) {
+ ComponentKey dupli_geometry_component_key(&ob->id, dupli_geometry_component_type);
+ add_relation(dupli_geometry_component_key, duplicator_key, "Dupligroup");
+ }
+ }
+ FOREACH_COLLECTION_VISIBLE_OBJECT_RECURSIVE_END;
+ }
}
void DepsgraphRelationBuilder::build_object(Base *base, Object *object)
{
- if (built_map_.checkIsBuiltAndTag(object)) {
- if (base != NULL) {
- build_object_flags(base, object);
- }
- return;
- }
- /* Object Transforms */
- OperationCode base_op = (object->parent) ? OperationCode::TRANSFORM_PARENT
- : OperationCode::TRANSFORM_LOCAL;
- OperationKey base_op_key(&object->id, NodeType::TRANSFORM, base_op);
- OperationKey init_transform_key(
- &object->id, NodeType::TRANSFORM, OperationCode::TRANSFORM_INIT);
- OperationKey local_transform_key(
- &object->id, NodeType::TRANSFORM, OperationCode::TRANSFORM_LOCAL);
- OperationKey parent_transform_key(
- &object->id, NodeType::TRANSFORM, OperationCode::TRANSFORM_PARENT);
- OperationKey final_transform_key(
- &object->id, NodeType::TRANSFORM, OperationCode::TRANSFORM_FINAL);
- OperationKey ob_eval_key(
- &object->id, NodeType::TRANSFORM, OperationCode::TRANSFORM_EVAL);
- add_relation(init_transform_key, local_transform_key, "Transform Init");
- /* Various flags, flushing from bases/collections. */
- build_object_flags(base, object);
- /* Parenting. */
- if (object->parent != NULL) {
- /* Make sure parent object's relations are built. */
- build_object(NULL, object->parent);
- /* Parent relationship. */
- build_object_parent(object);
- /* Local -> parent. */
- add_relation(local_transform_key,
- parent_transform_key,
- "ObLocal -> ObParent");
- }
- /* Modifiers. */
- if (object->modifiers.first != NULL) {
- BuilderWalkUserData data;
- data.builder = this;
- modifiers_foreachIDLink(object, modifier_walk, &data);
- }
- /* Grease Pencil Modifiers. */
- if (object->greasepencil_modifiers.first != NULL) {
- BuilderWalkUserData data;
- data.builder = this;
- BKE_gpencil_modifiers_foreachIDLink(object, modifier_walk, &data);
- }
- /* Shader FX. */
- if (object->shader_fx.first != NULL) {
- BuilderWalkUserData data;
- data.builder = this;
- BKE_shaderfx_foreachIDLink(object, modifier_walk, &data);
- }
- /* Constraints. */
- if (object->constraints.first != NULL) {
- BuilderWalkUserData data;
- data.builder = this;
- BKE_constraints_id_loop(&object->constraints, constraint_walk, &data);
- }
- /* Object constraints. */
- OperationKey object_transform_simulation_init_key(
- &object->id,
- NodeType::TRANSFORM,
- OperationCode::TRANSFORM_SIMULATION_INIT);
- if (object->constraints.first != NULL) {
- OperationKey constraint_key(&object->id,
- NodeType::TRANSFORM,
- OperationCode::TRANSFORM_CONSTRAINTS);
- /* Constraint relations. */
- build_constraints(&object->id,
- NodeType::TRANSFORM,
- "",
- &object->constraints,
- NULL);
- /* operation order */
- add_relation(base_op_key, constraint_key, "ObBase-> Constraint Stack");
- add_relation(constraint_key, final_transform_key, "ObConstraints -> Done");
- add_relation(constraint_key, ob_eval_key, "Constraint -> Transform Eval");
- add_relation(ob_eval_key,
- object_transform_simulation_init_key,
- "Transform Eval -> Simulation Init");
- add_relation(object_transform_simulation_init_key,
- final_transform_key,
- "Simulation -> Final Transform");
- }
- else {
- add_relation(base_op_key, ob_eval_key, "Eval");
- add_relation(ob_eval_key,
- object_transform_simulation_init_key,
- "Transform Eval -> Simulation Init");
- add_relation(object_transform_simulation_init_key,
- final_transform_key,
- "Simulation -> Final Transform");
- }
- /* Animation data */
- build_animdata(&object->id);
- /* Object data. */
- build_object_data(object);
- /* Particle systems. */
- if (object->particlesystem.first != NULL) {
- build_particle_systems(object);
- }
- /* Proxy object to copy from. */
- if (object->proxy_from != NULL) {
- build_object(NULL, object->proxy_from);
- ComponentKey ob_transform_key(
- &object->proxy_from->id, NodeType::TRANSFORM);
- ComponentKey proxy_transform_key(&object->id, NodeType::TRANSFORM);
- add_relation(ob_transform_key, proxy_transform_key, "Proxy Transform");
- }
- if (object->proxy_group != NULL) {
- build_object(NULL, object->proxy_group);
- OperationKey proxy_group_eval_key(&object->proxy_group->id,
- NodeType::TRANSFORM,
- OperationCode::TRANSFORM_EVAL);
- add_relation(proxy_group_eval_key,
- final_transform_key,
- "Proxy Group Transform");
- }
- /* Object dupligroup. */
- if (object->instance_collection != NULL) {
- build_collection(NULL, object, object->instance_collection);
- }
- /* Point caches. */
- build_object_pointcache(object);
- /* Syncronization back to original object. */
- OperationKey synchronize_key(&object->id,
- NodeType::SYNCHRONIZATION,
- OperationCode::SYNCHRONIZE_TO_ORIGINAL);
- add_relation(
- final_transform_key, synchronize_key, "Synchronize to Original");
- /* Parameters. */
- build_parameters(&object->id);
+ if (built_map_.checkIsBuiltAndTag(object)) {
+ if (base != NULL) {
+ build_object_flags(base, object);
+ }
+ return;
+ }
+ /* Object Transforms */
+ OperationCode base_op = (object->parent) ? OperationCode::TRANSFORM_PARENT :
+ OperationCode::TRANSFORM_LOCAL;
+ OperationKey base_op_key(&object->id, NodeType::TRANSFORM, base_op);
+ OperationKey init_transform_key(&object->id, NodeType::TRANSFORM, OperationCode::TRANSFORM_INIT);
+ OperationKey local_transform_key(
+ &object->id, NodeType::TRANSFORM, OperationCode::TRANSFORM_LOCAL);
+ OperationKey parent_transform_key(
+ &object->id, NodeType::TRANSFORM, OperationCode::TRANSFORM_PARENT);
+ OperationKey final_transform_key(
+ &object->id, NodeType::TRANSFORM, OperationCode::TRANSFORM_FINAL);
+ OperationKey ob_eval_key(&object->id, NodeType::TRANSFORM, OperationCode::TRANSFORM_EVAL);
+ add_relation(init_transform_key, local_transform_key, "Transform Init");
+ /* Various flags, flushing from bases/collections. */
+ build_object_flags(base, object);
+ /* Parenting. */
+ if (object->parent != NULL) {
+ /* Make sure parent object's relations are built. */
+ build_object(NULL, object->parent);
+ /* Parent relationship. */
+ build_object_parent(object);
+ /* Local -> parent. */
+ add_relation(local_transform_key, parent_transform_key, "ObLocal -> ObParent");
+ }
+ /* Modifiers. */
+ if (object->modifiers.first != NULL) {
+ BuilderWalkUserData data;
+ data.builder = this;
+ modifiers_foreachIDLink(object, modifier_walk, &data);
+ }
+ /* Grease Pencil Modifiers. */
+ if (object->greasepencil_modifiers.first != NULL) {
+ BuilderWalkUserData data;
+ data.builder = this;
+ BKE_gpencil_modifiers_foreachIDLink(object, modifier_walk, &data);
+ }
+ /* Shader FX. */
+ if (object->shader_fx.first != NULL) {
+ BuilderWalkUserData data;
+ data.builder = this;
+ BKE_shaderfx_foreachIDLink(object, modifier_walk, &data);
+ }
+ /* Constraints. */
+ if (object->constraints.first != NULL) {
+ BuilderWalkUserData data;
+ data.builder = this;
+ BKE_constraints_id_loop(&object->constraints, constraint_walk, &data);
+ }
+ /* Object constraints. */
+ OperationKey object_transform_simulation_init_key(
+ &object->id, NodeType::TRANSFORM, OperationCode::TRANSFORM_SIMULATION_INIT);
+ if (object->constraints.first != NULL) {
+ OperationKey constraint_key(
+ &object->id, NodeType::TRANSFORM, OperationCode::TRANSFORM_CONSTRAINTS);
+ /* Constraint relations. */
+ build_constraints(&object->id, NodeType::TRANSFORM, "", &object->constraints, NULL);
+ /* operation order */
+ add_relation(base_op_key, constraint_key, "ObBase-> Constraint Stack");
+ add_relation(constraint_key, final_transform_key, "ObConstraints -> Done");
+ add_relation(constraint_key, ob_eval_key, "Constraint -> Transform Eval");
+ add_relation(
+ ob_eval_key, object_transform_simulation_init_key, "Transform Eval -> Simulation Init");
+ add_relation(object_transform_simulation_init_key,
+ final_transform_key,
+ "Simulation -> Final Transform");
+ }
+ else {
+ add_relation(base_op_key, ob_eval_key, "Eval");
+ add_relation(
+ ob_eval_key, object_transform_simulation_init_key, "Transform Eval -> Simulation Init");
+ add_relation(object_transform_simulation_init_key,
+ final_transform_key,
+ "Simulation -> Final Transform");
+ }
+ /* Animation data */
+ build_animdata(&object->id);
+ /* Object data. */
+ build_object_data(object);
+ /* Particle systems. */
+ if (object->particlesystem.first != NULL) {
+ build_particle_systems(object);
+ }
+ /* Proxy object to copy from. */
+ if (object->proxy_from != NULL) {
+ build_object(NULL, object->proxy_from);
+ ComponentKey ob_transform_key(&object->proxy_from->id, NodeType::TRANSFORM);
+ ComponentKey proxy_transform_key(&object->id, NodeType::TRANSFORM);
+ add_relation(ob_transform_key, proxy_transform_key, "Proxy Transform");
+ }
+ if (object->proxy_group != NULL) {
+ build_object(NULL, object->proxy_group);
+ OperationKey proxy_group_eval_key(
+ &object->proxy_group->id, NodeType::TRANSFORM, OperationCode::TRANSFORM_EVAL);
+ add_relation(proxy_group_eval_key, final_transform_key, "Proxy Group Transform");
+ }
+ /* Object dupligroup. */
+ if (object->instance_collection != NULL) {
+ build_collection(NULL, object, object->instance_collection);
+ }
+ /* Point caches. */
+ build_object_pointcache(object);
+ /* Syncronization back to original object. */
+ OperationKey synchronize_key(
+ &object->id, NodeType::SYNCHRONIZATION, OperationCode::SYNCHRONIZE_TO_ORIGINAL);
+ add_relation(final_transform_key, synchronize_key, "Synchronize to Original");
+ /* Parameters. */
+ build_parameters(&object->id);
}
void DepsgraphRelationBuilder::build_object_flags(Base *base, Object *object)
{
- if (base == NULL) {
- return;
- }
- OperationKey view_layer_done_key(&scene_->id,
- NodeType::LAYER_COLLECTIONS,
- OperationCode::VIEW_LAYER_EVAL);
- OperationKey object_flags_key(&object->id,
- NodeType::OBJECT_FROM_LAYER,
- OperationCode::OBJECT_BASE_FLAGS);
- add_relation(view_layer_done_key, object_flags_key, "Base flags flush");
- /* Syncronization back to original object. */
- OperationKey synchronize_key(&object->id,
- NodeType::SYNCHRONIZATION,
- OperationCode::SYNCHRONIZE_TO_ORIGINAL);
- add_relation(
- object_flags_key, synchronize_key, "Synchronize to Original");
+ if (base == NULL) {
+ return;
+ }
+ OperationKey view_layer_done_key(
+ &scene_->id, NodeType::LAYER_COLLECTIONS, OperationCode::VIEW_LAYER_EVAL);
+ OperationKey object_flags_key(
+ &object->id, NodeType::OBJECT_FROM_LAYER, OperationCode::OBJECT_BASE_FLAGS);
+ add_relation(view_layer_done_key, object_flags_key, "Base flags flush");
+ /* Syncronization back to original object. */
+ OperationKey synchronize_key(
+ &object->id, NodeType::SYNCHRONIZATION, OperationCode::SYNCHRONIZE_TO_ORIGINAL);
+ add_relation(object_flags_key, synchronize_key, "Synchronize to Original");
}
void DepsgraphRelationBuilder::build_object_data(Object *object)
{
- if (object->data == NULL) {
- return;
- }
- ID *obdata_id = (ID *)object->data;
- /* Object data animation. */
- if (!built_map_.checkIsBuilt(obdata_id)) {
- build_animdata(obdata_id);
- }
- /* type-specific data. */
- switch (object->type) {
- case OB_MESH:
- case OB_CURVE:
- case OB_FONT:
- case OB_SURF:
- case OB_MBALL:
- case OB_LATTICE:
- case OB_GPENCIL:
- {
- build_object_data_geometry(object);
- /* TODO(sergey): Only for until we support granular
- * update of curves. */
- if (object->type == OB_FONT) {
- Curve *curve = (Curve *)object->data;
- if (curve->textoncurve) {
- add_special_eval_flag(&curve->textoncurve->id, DAG_EVAL_NEED_CURVE_PATH);
- }
- }
- break;
- }
- case OB_ARMATURE:
- if (ID_IS_LINKED(object) && object->proxy_from != NULL) {
- build_proxy_rig(object);
- }
- else {
- build_rig(object);
- }
- break;
- case OB_LAMP:
- build_object_data_light(object);
- break;
- case OB_CAMERA:
- build_object_data_camera(object);
- break;
- case OB_LIGHTPROBE:
- build_object_data_lightprobe(object);
- break;
- case OB_SPEAKER:
- build_object_data_speaker(object);
- break;
- }
- Key *key = BKE_key_from_object(object);
- if (key != NULL) {
- ComponentKey geometry_key((ID *)object->data, NodeType::GEOMETRY);
- ComponentKey key_key(&key->id, NodeType::GEOMETRY);
- add_relation(key_key, geometry_key, "Shapekeys");
- build_nested_shapekey(&object->id, key);
- }
+ if (object->data == NULL) {
+ return;
+ }
+ ID *obdata_id = (ID *)object->data;
+ /* Object data animation. */
+ if (!built_map_.checkIsBuilt(obdata_id)) {
+ build_animdata(obdata_id);
+ }
+ /* type-specific data. */
+ switch (object->type) {
+ case OB_MESH:
+ case OB_CURVE:
+ case OB_FONT:
+ case OB_SURF:
+ case OB_MBALL:
+ case OB_LATTICE:
+ case OB_GPENCIL: {
+ build_object_data_geometry(object);
+ /* TODO(sergey): Only for until we support granular
+ * update of curves. */
+ if (object->type == OB_FONT) {
+ Curve *curve = (Curve *)object->data;
+ if (curve->textoncurve) {
+ add_special_eval_flag(&curve->textoncurve->id, DAG_EVAL_NEED_CURVE_PATH);
+ }
+ }
+ break;
+ }
+ case OB_ARMATURE:
+ if (ID_IS_LINKED(object) && object->proxy_from != NULL) {
+ build_proxy_rig(object);
+ }
+ else {
+ build_rig(object);
+ }
+ break;
+ case OB_LAMP:
+ build_object_data_light(object);
+ break;
+ case OB_CAMERA:
+ build_object_data_camera(object);
+ break;
+ case OB_LIGHTPROBE:
+ build_object_data_lightprobe(object);
+ break;
+ case OB_SPEAKER:
+ build_object_data_speaker(object);
+ break;
+ }
+ Key *key = BKE_key_from_object(object);
+ if (key != NULL) {
+ ComponentKey geometry_key((ID *)object->data, NodeType::GEOMETRY);
+ ComponentKey key_key(&key->id, NodeType::GEOMETRY);
+ add_relation(key_key, geometry_key, "Shapekeys");
+ build_nested_shapekey(&object->id, key);
+ }
}
void DepsgraphRelationBuilder::build_object_data_camera(Object *object)
{
- Camera *camera = (Camera *)object->data;
- build_camera(camera);
- ComponentKey object_parameters_key(&object->id, NodeType::PARAMETERS);
- ComponentKey camera_parameters_key(&camera->id, NodeType::PARAMETERS);
- add_relation(camera_parameters_key, object_parameters_key, "Camera -> Object");
+ Camera *camera = (Camera *)object->data;
+ build_camera(camera);
+ ComponentKey object_parameters_key(&object->id, NodeType::PARAMETERS);
+ ComponentKey camera_parameters_key(&camera->id, NodeType::PARAMETERS);
+ add_relation(camera_parameters_key, object_parameters_key, "Camera -> Object");
}
void DepsgraphRelationBuilder::build_object_data_light(Object *object)
{
- Light *lamp = (Light *)object->data;
- build_light(lamp);
- ComponentKey lamp_parameters_key(&lamp->id, NodeType::PARAMETERS);
- ComponentKey object_parameters_key(&object->id, NodeType::PARAMETERS);
- add_relation(lamp_parameters_key, object_parameters_key, "Light -> Object");
+ Light *lamp = (Light *)object->data;
+ build_light(lamp);
+ ComponentKey lamp_parameters_key(&lamp->id, NodeType::PARAMETERS);
+ ComponentKey object_parameters_key(&object->id, NodeType::PARAMETERS);
+ add_relation(lamp_parameters_key, object_parameters_key, "Light -> Object");
}
void DepsgraphRelationBuilder::build_object_data_lightprobe(Object *object)
{
- LightProbe *probe = (LightProbe *)object->data;
- build_lightprobe(probe);
- OperationKey probe_key(&probe->id,
- NodeType::PARAMETERS,
- OperationCode::LIGHT_PROBE_EVAL);
- OperationKey object_key(&object->id,
- NodeType::PARAMETERS,
- OperationCode::LIGHT_PROBE_EVAL);
- add_relation(probe_key, object_key, "LightProbe Update");
+ LightProbe *probe = (LightProbe *)object->data;
+ build_lightprobe(probe);
+ OperationKey probe_key(&probe->id, NodeType::PARAMETERS, OperationCode::LIGHT_PROBE_EVAL);
+ OperationKey object_key(&object->id, NodeType::PARAMETERS, OperationCode::LIGHT_PROBE_EVAL);
+ add_relation(probe_key, object_key, "LightProbe Update");
}
void DepsgraphRelationBuilder::build_object_data_speaker(Object *object)
{
- Speaker *speaker = (Speaker *)object->data;
- build_speaker(speaker);
- OperationKey probe_key(&speaker->id,
- NodeType::PARAMETERS,
- OperationCode::SPEAKER_EVAL);
- OperationKey object_key(&object->id,
- NodeType::PARAMETERS,
- OperationCode::SPEAKER_EVAL);
- add_relation(probe_key, object_key, "Speaker Update");
+ Speaker *speaker = (Speaker *)object->data;
+ build_speaker(speaker);
+ OperationKey probe_key(&speaker->id, NodeType::PARAMETERS, OperationCode::SPEAKER_EVAL);
+ OperationKey object_key(&object->id, NodeType::PARAMETERS, OperationCode::SPEAKER_EVAL);
+ add_relation(probe_key, object_key, "Speaker Update");
}
void DepsgraphRelationBuilder::build_object_parent(Object *object)
{
- Object *parent = object->parent;
- ID *parent_id = &object->parent->id;
- ComponentKey ob_key(&object->id, NodeType::TRANSFORM);
- /* Type-specific links/ */
- switch (object->partype) {
- /* Armature Deform (Virtual Modifier) */
- case PARSKEL:
- {
- ComponentKey parent_key(parent_id, NodeType::TRANSFORM);
- add_relation(parent_key, ob_key, "Armature Deform Parent");
- break;
- }
-
- /* Vertex Parent */
- case PARVERT1:
- case PARVERT3:
- {
- ComponentKey parent_key(parent_id, NodeType::GEOMETRY);
- add_relation(parent_key, ob_key, "Vertex Parent");
- /* Original index is used for optimizations of lookups for subdiv
- * only meshes.
- * TODO(sergey): This optimization got lost at 2.8, so either verify
- * we can get rid of this mask here, or bring the optimization
- * back. */
- add_customdata_mask(object->parent,
- DEGCustomDataMeshMasks::MaskVert(CD_MASK_ORIGINDEX) |
- DEGCustomDataMeshMasks::MaskEdge(CD_MASK_ORIGINDEX) |
- DEGCustomDataMeshMasks::MaskFace(CD_MASK_ORIGINDEX) |
- DEGCustomDataMeshMasks::MaskPoly(CD_MASK_ORIGINDEX));
- ComponentKey transform_key(parent_id, NodeType::TRANSFORM);
- add_relation(transform_key, ob_key, "Vertex Parent TFM");
- break;
- }
-
- /* Bone Parent */
- case PARBONE:
- {
- ComponentKey parent_bone_key(
- parent_id, NodeType::BONE, object->parsubstr);
- OperationKey parent_transform_key(parent_id,
- NodeType::TRANSFORM,
- OperationCode::TRANSFORM_FINAL);
- add_relation(parent_bone_key, ob_key, "Bone Parent");
- add_relation(parent_transform_key, ob_key, "Armature Parent");
- break;
- }
-
- default:
- {
- if (object->parent->type == OB_LATTICE) {
- /* Lattice Deform Parent - Virtual Modifier. */
- ComponentKey parent_key(parent_id, NodeType::TRANSFORM);
- ComponentKey geom_key(parent_id, NodeType::GEOMETRY);
- add_relation(parent_key, ob_key, "Lattice Deform Parent");
- add_relation(geom_key, ob_key, "Lattice Deform Parent Geom");
- }
- else if (object->parent->type == OB_CURVE) {
- Curve *cu = (Curve *)object->parent->data;
-
- if (cu->flag & CU_PATH) {
- /* Follow Path. */
- ComponentKey parent_key(parent_id, NodeType::GEOMETRY);
- add_relation(parent_key, ob_key, "Curve Follow Parent");
- ComponentKey transform_key(parent_id, NodeType::TRANSFORM);
- add_relation(transform_key, ob_key, "Curve Follow TFM");
- }
- else {
- /* Standard Parent. */
- ComponentKey parent_key(parent_id, NodeType::TRANSFORM);
- add_relation(parent_key, ob_key, "Curve Parent");
- }
- }
- else {
- /* Standard Parent. */
- ComponentKey parent_key(parent_id, NodeType::TRANSFORM);
- add_relation(parent_key, ob_key, "Parent");
- }
- break;
- }
- }
- /* Metaballs are the odd balls here (no pun intended): they will request
- * instance-list (formerly known as dupli-list) during evaluation. This is
- * their way of interacting with all instanced surfaces, making a nice
- * effect when is used form particle system. */
- if (object->type == OB_MBALL && parent->transflag & OB_DUPLI) {
- ComponentKey parent_geometry_key(parent_id, NodeType::GEOMETRY);
- /* NOTE: Metaballs are evaluating geometry only after their transform,
- * so we onl;y hook up to transform channel here. */
- add_relation(parent_geometry_key, ob_key, "Parent");
- }
-
- /* Dupliverts uses original vertex index. */
- if (parent->transflag & OB_DUPLIVERTS) {
- add_customdata_mask(parent, DEGCustomDataMeshMasks::MaskVert(CD_MASK_ORIGINDEX));
- }
+ Object *parent = object->parent;
+ ID *parent_id = &object->parent->id;
+ ComponentKey ob_key(&object->id, NodeType::TRANSFORM);
+ /* Type-specific links/ */
+ switch (object->partype) {
+ /* Armature Deform (Virtual Modifier) */
+ case PARSKEL: {
+ ComponentKey parent_key(parent_id, NodeType::TRANSFORM);
+ add_relation(parent_key, ob_key, "Armature Deform Parent");
+ break;
+ }
+
+ /* Vertex Parent */
+ case PARVERT1:
+ case PARVERT3: {
+ ComponentKey parent_key(parent_id, NodeType::GEOMETRY);
+ add_relation(parent_key, ob_key, "Vertex Parent");
+ /* Original index is used for optimizations of lookups for subdiv
+ * only meshes.
+ * TODO(sergey): This optimization got lost at 2.8, so either verify
+ * we can get rid of this mask here, or bring the optimization
+ * back. */
+ add_customdata_mask(object->parent,
+ DEGCustomDataMeshMasks::MaskVert(CD_MASK_ORIGINDEX) |
+ DEGCustomDataMeshMasks::MaskEdge(CD_MASK_ORIGINDEX) |
+ DEGCustomDataMeshMasks::MaskFace(CD_MASK_ORIGINDEX) |
+ DEGCustomDataMeshMasks::MaskPoly(CD_MASK_ORIGINDEX));
+ ComponentKey transform_key(parent_id, NodeType::TRANSFORM);
+ add_relation(transform_key, ob_key, "Vertex Parent TFM");
+ break;
+ }
+
+ /* Bone Parent */
+ case PARBONE: {
+ ComponentKey parent_bone_key(parent_id, NodeType::BONE, object->parsubstr);
+ OperationKey parent_transform_key(
+ parent_id, NodeType::TRANSFORM, OperationCode::TRANSFORM_FINAL);
+ add_relation(parent_bone_key, ob_key, "Bone Parent");
+ add_relation(parent_transform_key, ob_key, "Armature Parent");
+ break;
+ }
+
+ default: {
+ if (object->parent->type == OB_LATTICE) {
+ /* Lattice Deform Parent - Virtual Modifier. */
+ ComponentKey parent_key(parent_id, NodeType::TRANSFORM);
+ ComponentKey geom_key(parent_id, NodeType::GEOMETRY);
+ add_relation(parent_key, ob_key, "Lattice Deform Parent");
+ add_relation(geom_key, ob_key, "Lattice Deform Parent Geom");
+ }
+ else if (object->parent->type == OB_CURVE) {
+ Curve *cu = (Curve *)object->parent->data;
+
+ if (cu->flag & CU_PATH) {
+ /* Follow Path. */
+ ComponentKey parent_key(parent_id, NodeType::GEOMETRY);
+ add_relation(parent_key, ob_key, "Curve Follow Parent");
+ ComponentKey transform_key(parent_id, NodeType::TRANSFORM);
+ add_relation(transform_key, ob_key, "Curve Follow TFM");
+ }
+ else {
+ /* Standard Parent. */
+ ComponentKey parent_key(parent_id, NodeType::TRANSFORM);
+ add_relation(parent_key, ob_key, "Curve Parent");
+ }
+ }
+ else {
+ /* Standard Parent. */
+ ComponentKey parent_key(parent_id, NodeType::TRANSFORM);
+ add_relation(parent_key, ob_key, "Parent");
+ }
+ break;
+ }
+ }
+ /* Metaballs are the odd balls here (no pun intended): they will request
+ * instance-list (formerly known as dupli-list) during evaluation. This is
+ * their way of interacting with all instanced surfaces, making a nice
+ * effect when is used form particle system. */
+ if (object->type == OB_MBALL && parent->transflag & OB_DUPLI) {
+ ComponentKey parent_geometry_key(parent_id, NodeType::GEOMETRY);
+ /* NOTE: Metaballs are evaluating geometry only after their transform,
+ * so we onl;y hook up to transform channel here. */
+ add_relation(parent_geometry_key, ob_key, "Parent");
+ }
+
+ /* Dupliverts uses original vertex index. */
+ if (parent->transflag & OB_DUPLIVERTS) {
+ add_customdata_mask(parent, DEGCustomDataMeshMasks::MaskVert(CD_MASK_ORIGINDEX));
+ }
}
void DepsgraphRelationBuilder::build_object_pointcache(Object *object)
{
- ComponentKey point_cache_key(&object->id, NodeType::POINT_CACHE);
- /* Different point caches are affecting different aspects of life of the
- * object. We keep track of those aspects and avoid duplicate relations. */
- enum {
- FLAG_TRANSFORM = (1 << 0),
- FLAG_GEOMETRY = (1 << 1),
- FLAG_ALL = (FLAG_TRANSFORM | FLAG_GEOMETRY),
- };
- ListBase ptcache_id_list;
- BKE_ptcache_ids_from_object(&ptcache_id_list, object, scene_, 0);
- int handled_components = 0;
- LISTBASE_FOREACH (PTCacheID *, ptcache_id, &ptcache_id_list) {
- /* Check which components needs the point cache. */
- int flag = -1;
- if (ptcache_id->type == PTCACHE_TYPE_RIGIDBODY) {
- flag = FLAG_TRANSFORM;
- OperationKey transform_key(
- &object->id,
- NodeType::TRANSFORM,
- OperationCode::TRANSFORM_SIMULATION_INIT);
- add_relation(point_cache_key,
- transform_key,
- "Point Cache -> Rigid Body");
- }
- else {
- flag = FLAG_GEOMETRY;
- OperationKey geometry_key(&object->id,
- NodeType::GEOMETRY,
- OperationCode::GEOMETRY_EVAL);
- add_relation(
- point_cache_key, geometry_key, "Point Cache -> Geometry");
- }
- BLI_assert(flag != -1);
- /* Tag that we did handle that component. */
- handled_components |= flag;
- if (handled_components == FLAG_ALL) {
- break;
- }
- }
- /* Manual edits to any dependency (or self) should reset the point cache. */
- if (!BLI_listbase_is_empty(&ptcache_id_list)) {
- OperationKey transform_eval_key(
- &object->id,
- NodeType::TRANSFORM,
- OperationCode::TRANSFORM_EVAL);
- OperationKey geometry_init_key(&object->id,
- NodeType::GEOMETRY,
- OperationCode::GEOMETRY_EVAL_INIT);
- add_relation(transform_eval_key,
- point_cache_key,
- "Transform Simulation -> Point Cache",
- RELATION_FLAG_FLUSH_USER_EDIT_ONLY);
- add_relation(geometry_init_key,
- point_cache_key,
- "Geometry Init -> Point Cache",
- RELATION_FLAG_FLUSH_USER_EDIT_ONLY);
- }
- BLI_freelistN(&ptcache_id_list);
+ ComponentKey point_cache_key(&object->id, NodeType::POINT_CACHE);
+ /* Different point caches are affecting different aspects of life of the
+ * object. We keep track of those aspects and avoid duplicate relations. */
+ enum {
+ FLAG_TRANSFORM = (1 << 0),
+ FLAG_GEOMETRY = (1 << 1),
+ FLAG_ALL = (FLAG_TRANSFORM | FLAG_GEOMETRY),
+ };
+ ListBase ptcache_id_list;
+ BKE_ptcache_ids_from_object(&ptcache_id_list, object, scene_, 0);
+ int handled_components = 0;
+ LISTBASE_FOREACH (PTCacheID *, ptcache_id, &ptcache_id_list) {
+ /* Check which components needs the point cache. */
+ int flag = -1;
+ if (ptcache_id->type == PTCACHE_TYPE_RIGIDBODY) {
+ flag = FLAG_TRANSFORM;
+ OperationKey transform_key(
+ &object->id, NodeType::TRANSFORM, OperationCode::TRANSFORM_SIMULATION_INIT);
+ add_relation(point_cache_key, transform_key, "Point Cache -> Rigid Body");
+ }
+ else {
+ flag = FLAG_GEOMETRY;
+ OperationKey geometry_key(&object->id, NodeType::GEOMETRY, OperationCode::GEOMETRY_EVAL);
+ add_relation(point_cache_key, geometry_key, "Point Cache -> Geometry");
+ }
+ BLI_assert(flag != -1);
+ /* Tag that we did handle that component. */
+ handled_components |= flag;
+ if (handled_components == FLAG_ALL) {
+ break;
+ }
+ }
+ /* Manual edits to any dependency (or self) should reset the point cache. */
+ if (!BLI_listbase_is_empty(&ptcache_id_list)) {
+ OperationKey transform_eval_key(
+ &object->id, NodeType::TRANSFORM, OperationCode::TRANSFORM_EVAL);
+ OperationKey geometry_init_key(
+ &object->id, NodeType::GEOMETRY, OperationCode::GEOMETRY_EVAL_INIT);
+ add_relation(transform_eval_key,
+ point_cache_key,
+ "Transform Simulation -> Point Cache",
+ RELATION_FLAG_FLUSH_USER_EDIT_ONLY);
+ add_relation(geometry_init_key,
+ point_cache_key,
+ "Geometry Init -> Point Cache",
+ RELATION_FLAG_FLUSH_USER_EDIT_ONLY);
+ }
+ BLI_freelistN(&ptcache_id_list);
}
void DepsgraphRelationBuilder::build_constraints(ID *id,
@@ -1006,1069 +931,879 @@ void DepsgraphRelationBuilder::build_constraints(ID *id,
ListBase *constraints,
RootPChanMap *root_map)
{
- OperationKey constraint_op_key(
- id,
- component_type,
- component_subdata,
- (component_type == NodeType::BONE)
- ? OperationCode::BONE_CONSTRAINTS
- : OperationCode::TRANSFORM_CONSTRAINTS);
- /* Add dependencies for each constraint in turn. */
- for (bConstraint *con = (bConstraint *)constraints->first; con; con = con->next) {
- const bConstraintTypeInfo *cti = BKE_constraint_typeinfo_get(con);
- /* Invalid constraint type. */
- if (cti == NULL) {
- continue;
- }
- /* Special case for camera tracking -- it doesn't use targets to
- * define relations. */
- /* TODO: we can now represent dependencies in a much richer manner,
- * so review how this is done. */
- if (ELEM(cti->type,
- CONSTRAINT_TYPE_FOLLOWTRACK,
- CONSTRAINT_TYPE_CAMERASOLVER,
- CONSTRAINT_TYPE_OBJECTSOLVER))
- {
- bool depends_on_camera = false;
- if (cti->type == CONSTRAINT_TYPE_FOLLOWTRACK) {
- bFollowTrackConstraint *data = (bFollowTrackConstraint *)con->data;
- if (((data->clip) ||
- (data->flag & FOLLOWTRACK_ACTIVECLIP)) && data->track[0])
- {
- depends_on_camera = true;
- }
- if (data->depth_ob) {
- ComponentKey depth_transform_key(&data->depth_ob->id,
- NodeType::TRANSFORM);
- ComponentKey depth_geometry_key(&data->depth_ob->id,
- NodeType::GEOMETRY);
- add_relation(depth_transform_key, constraint_op_key, cti->name);
- add_relation(depth_geometry_key, constraint_op_key, cti->name);
- }
- }
- else if (cti->type == CONSTRAINT_TYPE_OBJECTSOLVER) {
- depends_on_camera = true;
- }
- if (depends_on_camera && scene_->camera != NULL) {
- ComponentKey camera_key(&scene_->camera->id, NodeType::TRANSFORM);
- add_relation(camera_key, constraint_op_key, cti->name);
- }
- /* TODO(sergey): This is more a TimeSource -> MovieClip ->
- * Constraint dependency chain. */
- TimeSourceKey time_src_key;
- add_relation(time_src_key, constraint_op_key, "TimeSrc -> Animation");
- }
- else if (cti->type == CONSTRAINT_TYPE_TRANSFORM_CACHE) {
- /* TODO(kevin): This is more a TimeSource -> CacheFile -> Constraint
- * dependency chain. */
- TimeSourceKey time_src_key;
- add_relation(time_src_key, constraint_op_key, "TimeSrc -> Animation");
- bTransformCacheConstraint *data = (bTransformCacheConstraint *)con->data;
- if (data->cache_file) {
- ComponentKey cache_key(&data->cache_file->id, NodeType::CACHE);
- add_relation(cache_key, constraint_op_key, cti->name);
- }
- }
- else if (cti->get_constraint_targets) {
- ListBase targets = {NULL, NULL};
- cti->get_constraint_targets(con, &targets);
- LISTBASE_FOREACH (bConstraintTarget *, ct, &targets) {
- if (ct->tar == NULL) {
- continue;
- }
- if (ELEM(con->type,
- CONSTRAINT_TYPE_KINEMATIC,
- CONSTRAINT_TYPE_SPLINEIK))
- {
- /* Ignore IK constraints - these are handled separately
- * (on pose level). */
- }
- else if (ELEM(con->type,
- CONSTRAINT_TYPE_FOLLOWPATH,
- CONSTRAINT_TYPE_CLAMPTO))
- {
- /* These constraints require path geometry data. */
- ComponentKey target_key(&ct->tar->id, NodeType::GEOMETRY);
- add_relation(target_key, constraint_op_key, cti->name);
- ComponentKey target_transform_key(&ct->tar->id,
- NodeType::TRANSFORM);
- add_relation(target_transform_key, constraint_op_key, cti->name);
- }
- else if ((ct->tar->type == OB_ARMATURE) && (ct->subtarget[0])) {
- OperationCode opcode;
- /* relation to bone */
- opcode = bone_target_opcode(&ct->tar->id, ct->subtarget,
- id, component_subdata, root_map);
- /* Armature constraint always wants the final position and chan_mat. */
- if (ELEM(con->type, CONSTRAINT_TYPE_ARMATURE)) {
- opcode = OperationCode::BONE_DONE;
- }
- /* if needs bbone shape, reference the segment computation */
- if (BKE_constraint_target_uses_bbone(con, ct) &&
- bone_has_segments(ct->tar, ct->subtarget))
- {
- opcode = OperationCode::BONE_SEGMENTS;
- }
- OperationKey target_key(&ct->tar->id,
- NodeType::BONE,
- ct->subtarget,
- opcode);
- add_relation(target_key, constraint_op_key, cti->name);
- }
- else if (ELEM(ct->tar->type, OB_MESH, OB_LATTICE) &&
- (ct->subtarget[0]))
- {
- /* Vertex group. */
- /* NOTE: Vertex group is likely to be used to get vertices
- * in a world space. This requires to know both geometry
- * and transformation of the target object. */
- ComponentKey target_transform_key(
- &ct->tar->id, NodeType::TRANSFORM);
- ComponentKey target_geometry_key(
- &ct->tar->id, NodeType::GEOMETRY);
- add_relation(
- target_transform_key, constraint_op_key, cti->name);
- add_relation(
- target_geometry_key, constraint_op_key, cti->name);
- add_customdata_mask(ct->tar, DEGCustomDataMeshMasks::MaskVert(CD_MASK_MDEFORMVERT));
- }
- else if (con->type == CONSTRAINT_TYPE_SHRINKWRAP) {
- bShrinkwrapConstraint *scon = (bShrinkwrapConstraint *) con->data;
-
- /* Constraints which requires the target object surface. */
- ComponentKey target_key(&ct->tar->id, NodeType::GEOMETRY);
- add_relation(target_key, constraint_op_key, cti->name);
-
- /* Add dependency on normal layers if necessary. */
- if (ct->tar->type == OB_MESH && scon->shrinkType != MOD_SHRINKWRAP_NEAREST_VERTEX) {
- bool track = (scon->flag & CON_SHRINKWRAP_TRACK_NORMAL) != 0;
- if (track || BKE_shrinkwrap_needs_normals(scon->shrinkType, scon->shrinkMode)) {
- add_customdata_mask(ct->tar,
- DEGCustomDataMeshMasks::MaskVert(CD_MASK_NORMAL) |
- DEGCustomDataMeshMasks::MaskLoop(CD_MASK_CUSTOMLOOPNORMAL));
- }
- if (scon->shrinkType == MOD_SHRINKWRAP_TARGET_PROJECT) {
- add_special_eval_flag(&ct->tar->id, DAG_EVAL_NEED_SHRINKWRAP_BOUNDARY);
- }
- }
-
- /* NOTE: obdata eval now doesn't necessarily depend on the
- * object's transform. */
- ComponentKey target_transform_key(&ct->tar->id,
- NodeType::TRANSFORM);
- add_relation(target_transform_key, constraint_op_key, cti->name);
- }
- else {
- /* Standard object relation. */
- // TODO: loc vs rot vs scale?
- if (&ct->tar->id == id) {
- /* Constraint targeting own object:
- * - This case is fine IFF we're dealing with a bone
- * constraint pointing to its own armature. In that
- * case, it's just transform -> bone.
- * - If however it is a real self targeting case, just
- * make it depend on the previous constraint (or the
- * pre-constraint state). */
- if ((ct->tar->type == OB_ARMATURE) &&
- (component_type == NodeType::BONE))
- {
- OperationKey target_key(&ct->tar->id,
- NodeType::TRANSFORM,
- OperationCode::TRANSFORM_FINAL);
- add_relation(target_key, constraint_op_key, cti->name);
- }
- else {
- OperationKey target_key(&ct->tar->id,
- NodeType::TRANSFORM,
- OperationCode::TRANSFORM_LOCAL);
- add_relation(target_key, constraint_op_key, cti->name);
- }
- }
- else {
- /* Normal object dependency. */
- OperationKey target_key(&ct->tar->id,
- NodeType::TRANSFORM,
- OperationCode::TRANSFORM_FINAL);
- add_relation(target_key, constraint_op_key, cti->name);
- }
- }
- /* Constraints which needs world's matrix for transform.
- * TODO(sergey): More constraints here? */
- if (ELEM(con->type,
- CONSTRAINT_TYPE_ROTLIKE,
- CONSTRAINT_TYPE_SIZELIKE,
- CONSTRAINT_TYPE_LOCLIKE,
- CONSTRAINT_TYPE_TRANSLIKE))
- {
- /* TODO(sergey): Add used space check. */
- ComponentKey target_transform_key(&ct->tar->id,
- NodeType::TRANSFORM);
- add_relation(target_transform_key, constraint_op_key, cti->name);
- }
- }
- if (cti->flush_constraint_targets) {
- cti->flush_constraint_targets(con, &targets, 1);
- }
- }
- }
+ OperationKey constraint_op_key(id,
+ component_type,
+ component_subdata,
+ (component_type == NodeType::BONE) ?
+ OperationCode::BONE_CONSTRAINTS :
+ OperationCode::TRANSFORM_CONSTRAINTS);
+ /* Add dependencies for each constraint in turn. */
+ for (bConstraint *con = (bConstraint *)constraints->first; con; con = con->next) {
+ const bConstraintTypeInfo *cti = BKE_constraint_typeinfo_get(con);
+ /* Invalid constraint type. */
+ if (cti == NULL) {
+ continue;
+ }
+ /* Special case for camera tracking -- it doesn't use targets to
+ * define relations. */
+ /* TODO: we can now represent dependencies in a much richer manner,
+ * so review how this is done. */
+ if (ELEM(cti->type,
+ CONSTRAINT_TYPE_FOLLOWTRACK,
+ CONSTRAINT_TYPE_CAMERASOLVER,
+ CONSTRAINT_TYPE_OBJECTSOLVER)) {
+ bool depends_on_camera = false;
+ if (cti->type == CONSTRAINT_TYPE_FOLLOWTRACK) {
+ bFollowTrackConstraint *data = (bFollowTrackConstraint *)con->data;
+ if (((data->clip) || (data->flag & FOLLOWTRACK_ACTIVECLIP)) && data->track[0]) {
+ depends_on_camera = true;
+ }
+ if (data->depth_ob) {
+ ComponentKey depth_transform_key(&data->depth_ob->id, NodeType::TRANSFORM);
+ ComponentKey depth_geometry_key(&data->depth_ob->id, NodeType::GEOMETRY);
+ add_relation(depth_transform_key, constraint_op_key, cti->name);
+ add_relation(depth_geometry_key, constraint_op_key, cti->name);
+ }
+ }
+ else if (cti->type == CONSTRAINT_TYPE_OBJECTSOLVER) {
+ depends_on_camera = true;
+ }
+ if (depends_on_camera && scene_->camera != NULL) {
+ ComponentKey camera_key(&scene_->camera->id, NodeType::TRANSFORM);
+ add_relation(camera_key, constraint_op_key, cti->name);
+ }
+ /* TODO(sergey): This is more a TimeSource -> MovieClip ->
+ * Constraint dependency chain. */
+ TimeSourceKey time_src_key;
+ add_relation(time_src_key, constraint_op_key, "TimeSrc -> Animation");
+ }
+ else if (cti->type == CONSTRAINT_TYPE_TRANSFORM_CACHE) {
+ /* TODO(kevin): This is more a TimeSource -> CacheFile -> Constraint
+ * dependency chain. */
+ TimeSourceKey time_src_key;
+ add_relation(time_src_key, constraint_op_key, "TimeSrc -> Animation");
+ bTransformCacheConstraint *data = (bTransformCacheConstraint *)con->data;
+ if (data->cache_file) {
+ ComponentKey cache_key(&data->cache_file->id, NodeType::CACHE);
+ add_relation(cache_key, constraint_op_key, cti->name);
+ }
+ }
+ else if (cti->get_constraint_targets) {
+ ListBase targets = {NULL, NULL};
+ cti->get_constraint_targets(con, &targets);
+ LISTBASE_FOREACH (bConstraintTarget *, ct, &targets) {
+ if (ct->tar == NULL) {
+ continue;
+ }
+ if (ELEM(con->type, CONSTRAINT_TYPE_KINEMATIC, CONSTRAINT_TYPE_SPLINEIK)) {
+ /* Ignore IK constraints - these are handled separately
+ * (on pose level). */
+ }
+ else if (ELEM(con->type, CONSTRAINT_TYPE_FOLLOWPATH, CONSTRAINT_TYPE_CLAMPTO)) {
+ /* These constraints require path geometry data. */
+ ComponentKey target_key(&ct->tar->id, NodeType::GEOMETRY);
+ add_relation(target_key, constraint_op_key, cti->name);
+ ComponentKey target_transform_key(&ct->tar->id, NodeType::TRANSFORM);
+ add_relation(target_transform_key, constraint_op_key, cti->name);
+ }
+ else if ((ct->tar->type == OB_ARMATURE) && (ct->subtarget[0])) {
+ OperationCode opcode;
+ /* relation to bone */
+ opcode = bone_target_opcode(
+ &ct->tar->id, ct->subtarget, id, component_subdata, root_map);
+ /* Armature constraint always wants the final position and chan_mat. */
+ if (ELEM(con->type, CONSTRAINT_TYPE_ARMATURE)) {
+ opcode = OperationCode::BONE_DONE;
+ }
+ /* if needs bbone shape, reference the segment computation */
+ if (BKE_constraint_target_uses_bbone(con, ct) &&
+ bone_has_segments(ct->tar, ct->subtarget)) {
+ opcode = OperationCode::BONE_SEGMENTS;
+ }
+ OperationKey target_key(&ct->tar->id, NodeType::BONE, ct->subtarget, opcode);
+ add_relation(target_key, constraint_op_key, cti->name);
+ }
+ else if (ELEM(ct->tar->type, OB_MESH, OB_LATTICE) && (ct->subtarget[0])) {
+ /* Vertex group. */
+ /* NOTE: Vertex group is likely to be used to get vertices
+ * in a world space. This requires to know both geometry
+ * and transformation of the target object. */
+ ComponentKey target_transform_key(&ct->tar->id, NodeType::TRANSFORM);
+ ComponentKey target_geometry_key(&ct->tar->id, NodeType::GEOMETRY);
+ add_relation(target_transform_key, constraint_op_key, cti->name);
+ add_relation(target_geometry_key, constraint_op_key, cti->name);
+ add_customdata_mask(ct->tar, DEGCustomDataMeshMasks::MaskVert(CD_MASK_MDEFORMVERT));
+ }
+ else if (con->type == CONSTRAINT_TYPE_SHRINKWRAP) {
+ bShrinkwrapConstraint *scon = (bShrinkwrapConstraint *)con->data;
+
+ /* Constraints which requires the target object surface. */
+ ComponentKey target_key(&ct->tar->id, NodeType::GEOMETRY);
+ add_relation(target_key, constraint_op_key, cti->name);
+
+ /* Add dependency on normal layers if necessary. */
+ if (ct->tar->type == OB_MESH && scon->shrinkType != MOD_SHRINKWRAP_NEAREST_VERTEX) {
+ bool track = (scon->flag & CON_SHRINKWRAP_TRACK_NORMAL) != 0;
+ if (track || BKE_shrinkwrap_needs_normals(scon->shrinkType, scon->shrinkMode)) {
+ add_customdata_mask(ct->tar,
+ DEGCustomDataMeshMasks::MaskVert(CD_MASK_NORMAL) |
+ DEGCustomDataMeshMasks::MaskLoop(CD_MASK_CUSTOMLOOPNORMAL));
+ }
+ if (scon->shrinkType == MOD_SHRINKWRAP_TARGET_PROJECT) {
+ add_special_eval_flag(&ct->tar->id, DAG_EVAL_NEED_SHRINKWRAP_BOUNDARY);
+ }
+ }
+
+ /* NOTE: obdata eval now doesn't necessarily depend on the
+ * object's transform. */
+ ComponentKey target_transform_key(&ct->tar->id, NodeType::TRANSFORM);
+ add_relation(target_transform_key, constraint_op_key, cti->name);
+ }
+ else {
+ /* Standard object relation. */
+ // TODO: loc vs rot vs scale?
+ if (&ct->tar->id == id) {
+ /* Constraint targeting own object:
+ * - This case is fine IFF we're dealing with a bone
+ * constraint pointing to its own armature. In that
+ * case, it's just transform -> bone.
+ * - If however it is a real self targeting case, just
+ * make it depend on the previous constraint (or the
+ * pre-constraint state). */
+ if ((ct->tar->type == OB_ARMATURE) && (component_type == NodeType::BONE)) {
+ OperationKey target_key(
+ &ct->tar->id, NodeType::TRANSFORM, OperationCode::TRANSFORM_FINAL);
+ add_relation(target_key, constraint_op_key, cti->name);
+ }
+ else {
+ OperationKey target_key(
+ &ct->tar->id, NodeType::TRANSFORM, OperationCode::TRANSFORM_LOCAL);
+ add_relation(target_key, constraint_op_key, cti->name);
+ }
+ }
+ else {
+ /* Normal object dependency. */
+ OperationKey target_key(
+ &ct->tar->id, NodeType::TRANSFORM, OperationCode::TRANSFORM_FINAL);
+ add_relation(target_key, constraint_op_key, cti->name);
+ }
+ }
+ /* Constraints which needs world's matrix for transform.
+ * TODO(sergey): More constraints here? */
+ if (ELEM(con->type,
+ CONSTRAINT_TYPE_ROTLIKE,
+ CONSTRAINT_TYPE_SIZELIKE,
+ CONSTRAINT_TYPE_LOCLIKE,
+ CONSTRAINT_TYPE_TRANSLIKE)) {
+ /* TODO(sergey): Add used space check. */
+ ComponentKey target_transform_key(&ct->tar->id, NodeType::TRANSFORM);
+ add_relation(target_transform_key, constraint_op_key, cti->name);
+ }
+ }
+ if (cti->flush_constraint_targets) {
+ cti->flush_constraint_targets(con, &targets, 1);
+ }
+ }
+ }
}
void DepsgraphRelationBuilder::build_animdata(ID *id)
{
- /* Images. */
- build_animation_images(id);
- /* Animation curves and NLA. */
- build_animdata_curves(id);
- /* Drivers. */
- build_animdata_drivers(id);
+ /* Images. */
+ build_animation_images(id);
+ /* Animation curves and NLA. */
+ build_animdata_curves(id);
+ /* Drivers. */
+ build_animdata_drivers(id);
}
void DepsgraphRelationBuilder::build_animdata_curves(ID *id)
{
- AnimData *adt = BKE_animdata_from_id(id);
- if (adt == NULL) {
- return;
- }
- if (adt->action != NULL) {
- build_action(adt->action);
- }
- if (adt->action == NULL && BLI_listbase_is_empty(&adt->nla_tracks)) {
- return;
- }
- /* Ensure evaluation order from entry to exit. */
- OperationKey animation_entry_key(
- id, NodeType::ANIMATION, OperationCode::ANIMATION_ENTRY);
- OperationKey animation_eval_key(
- id, NodeType::ANIMATION, OperationCode::ANIMATION_EVAL);
- OperationKey animation_exit_key(
- id, NodeType::ANIMATION, OperationCode::ANIMATION_EXIT);
- add_relation(animation_entry_key, animation_eval_key, "Init -> Eval");
- add_relation(animation_eval_key, animation_exit_key, "Eval -> Exit");
- /* Wire up dependency from action. */
- ComponentKey adt_key(id, NodeType::ANIMATION);
- /* Relation from action itself. */
- if (adt->action != NULL) {
- ComponentKey action_key(&adt->action->id, NodeType::ANIMATION);
- add_relation(action_key, adt_key, "Action -> Animation");
- }
- /* Get source operations. */
- Node *node_from = get_node(adt_key);
- BLI_assert(node_from != NULL);
- if (node_from == NULL) {
- return;
- }
- OperationNode *operation_from = node_from->get_exit_operation();
- BLI_assert(operation_from != NULL);
- /* Build relations from animation operation to properties it changes. */
- if (adt->action != NULL) {
- build_animdata_curves_targets(
- id, adt_key, operation_from, &adt->action->curves);
- }
- LISTBASE_FOREACH(NlaTrack *, nlt, &adt->nla_tracks) {
- build_animdata_nlastrip_targets(
- id, adt_key, operation_from, &nlt->strips);
- }
-}
-
-void DepsgraphRelationBuilder::build_animdata_curves_targets(
- ID *id, ComponentKey &adt_key,
- OperationNode *operation_from,
- ListBase *curves)
-{
- /* Iterate over all curves and build relations. */
- PointerRNA id_ptr;
- RNA_id_pointer_create(id, &id_ptr);
- LISTBASE_FOREACH (FCurve *, fcu, curves) {
- PointerRNA ptr;
- PropertyRNA *prop;
- int index;
- if (!RNA_path_resolve_full(
- &id_ptr, fcu->rna_path, &ptr, &prop, &index))
- {
- continue;
- }
- Node *node_to = rna_node_query_.find_node(
- &ptr, prop, RNAPointerSource::ENTRY);
- if (node_to == NULL) {
- continue;
- }
- OperationNode *operation_to = node_to->get_entry_operation();
- /* NOTE: Special case for bones, avoid relation from animation to
- * each of the bones. Bone evaluation could only start from pose
- * init anyway. */
- if (operation_to->opcode == OperationCode::BONE_LOCAL) {
- OperationKey pose_init_key(
- id, NodeType::EVAL_POSE, OperationCode::POSE_INIT);
- add_relation(adt_key,
- pose_init_key,
- "Animation -> Prop",
- RELATION_CHECK_BEFORE_ADD);
- continue;
- }
- graph_->add_new_relation(operation_from, operation_to,
- "Animation -> Prop",
- RELATION_CHECK_BEFORE_ADD);
- /* It is possible that animation is writing to a nested ID datablock,
- * need to make sure animation is evaluated after target ID is copied. */
- const IDNode *id_node_from = operation_from->owner->owner;
- const IDNode *id_node_to = operation_to->owner->owner;
- if (id_node_from != id_node_to) {
- ComponentKey cow_key(id_node_to->id_orig, NodeType::COPY_ON_WRITE);
- add_relation(cow_key,
- adt_key,
- "Animated CoW -> Animation",
- RELATION_CHECK_BEFORE_ADD);
- }
- }
-}
-
-void DepsgraphRelationBuilder::build_animdata_nlastrip_targets(
- ID *id, ComponentKey &adt_key,
- OperationNode *operation_from,
- ListBase *strips)
-{
- LISTBASE_FOREACH (NlaStrip *, strip, strips) {
- if (strip->act != NULL) {
- build_action(strip->act);
-
- ComponentKey action_key(&strip->act->id, NodeType::ANIMATION);
- add_relation(action_key, adt_key, "Action -> Animation");
-
- build_animdata_curves_targets(
- id, adt_key, operation_from, &strip->act->curves);
- }
- else if (strip->strips.first != NULL) {
- build_animdata_nlastrip_targets(
- id, adt_key, operation_from, &strip->strips);
- }
- }
+ AnimData *adt = BKE_animdata_from_id(id);
+ if (adt == NULL) {
+ return;
+ }
+ if (adt->action != NULL) {
+ build_action(adt->action);
+ }
+ if (adt->action == NULL && BLI_listbase_is_empty(&adt->nla_tracks)) {
+ return;
+ }
+ /* Ensure evaluation order from entry to exit. */
+ OperationKey animation_entry_key(id, NodeType::ANIMATION, OperationCode::ANIMATION_ENTRY);
+ OperationKey animation_eval_key(id, NodeType::ANIMATION, OperationCode::ANIMATION_EVAL);
+ OperationKey animation_exit_key(id, NodeType::ANIMATION, OperationCode::ANIMATION_EXIT);
+ add_relation(animation_entry_key, animation_eval_key, "Init -> Eval");
+ add_relation(animation_eval_key, animation_exit_key, "Eval -> Exit");
+ /* Wire up dependency from action. */
+ ComponentKey adt_key(id, NodeType::ANIMATION);
+ /* Relation from action itself. */
+ if (adt->action != NULL) {
+ ComponentKey action_key(&adt->action->id, NodeType::ANIMATION);
+ add_relation(action_key, adt_key, "Action -> Animation");
+ }
+ /* Get source operations. */
+ Node *node_from = get_node(adt_key);
+ BLI_assert(node_from != NULL);
+ if (node_from == NULL) {
+ return;
+ }
+ OperationNode *operation_from = node_from->get_exit_operation();
+ BLI_assert(operation_from != NULL);
+ /* Build relations from animation operation to properties it changes. */
+ if (adt->action != NULL) {
+ build_animdata_curves_targets(id, adt_key, operation_from, &adt->action->curves);
+ }
+ LISTBASE_FOREACH (NlaTrack *, nlt, &adt->nla_tracks) {
+ build_animdata_nlastrip_targets(id, adt_key, operation_from, &nlt->strips);
+ }
+}
+
+void DepsgraphRelationBuilder::build_animdata_curves_targets(ID *id,
+ ComponentKey &adt_key,
+ OperationNode *operation_from,
+ ListBase *curves)
+{
+ /* Iterate over all curves and build relations. */
+ PointerRNA id_ptr;
+ RNA_id_pointer_create(id, &id_ptr);
+ LISTBASE_FOREACH (FCurve *, fcu, curves) {
+ PointerRNA ptr;
+ PropertyRNA *prop;
+ int index;
+ if (!RNA_path_resolve_full(&id_ptr, fcu->rna_path, &ptr, &prop, &index)) {
+ continue;
+ }
+ Node *node_to = rna_node_query_.find_node(&ptr, prop, RNAPointerSource::ENTRY);
+ if (node_to == NULL) {
+ continue;
+ }
+ OperationNode *operation_to = node_to->get_entry_operation();
+ /* NOTE: Special case for bones, avoid relation from animation to
+ * each of the bones. Bone evaluation could only start from pose
+ * init anyway. */
+ if (operation_to->opcode == OperationCode::BONE_LOCAL) {
+ OperationKey pose_init_key(id, NodeType::EVAL_POSE, OperationCode::POSE_INIT);
+ add_relation(adt_key, pose_init_key, "Animation -> Prop", RELATION_CHECK_BEFORE_ADD);
+ continue;
+ }
+ graph_->add_new_relation(
+ operation_from, operation_to, "Animation -> Prop", RELATION_CHECK_BEFORE_ADD);
+ /* It is possible that animation is writing to a nested ID datablock,
+ * need to make sure animation is evaluated after target ID is copied. */
+ const IDNode *id_node_from = operation_from->owner->owner;
+ const IDNode *id_node_to = operation_to->owner->owner;
+ if (id_node_from != id_node_to) {
+ ComponentKey cow_key(id_node_to->id_orig, NodeType::COPY_ON_WRITE);
+ add_relation(cow_key, adt_key, "Animated CoW -> Animation", RELATION_CHECK_BEFORE_ADD);
+ }
+ }
+}
+
+void DepsgraphRelationBuilder::build_animdata_nlastrip_targets(ID *id,
+ ComponentKey &adt_key,
+ OperationNode *operation_from,
+ ListBase *strips)
+{
+ LISTBASE_FOREACH (NlaStrip *, strip, strips) {
+ if (strip->act != NULL) {
+ build_action(strip->act);
+
+ ComponentKey action_key(&strip->act->id, NodeType::ANIMATION);
+ add_relation(action_key, adt_key, "Action -> Animation");
+
+ build_animdata_curves_targets(id, adt_key, operation_from, &strip->act->curves);
+ }
+ else if (strip->strips.first != NULL) {
+ build_animdata_nlastrip_targets(id, adt_key, operation_from, &strip->strips);
+ }
+ }
}
void DepsgraphRelationBuilder::build_animdata_drivers(ID *id)
{
- AnimData *adt = BKE_animdata_from_id(id);
- if (adt == NULL) {
- return;
- }
- ComponentKey adt_key(id, NodeType::ANIMATION);
- LISTBASE_FOREACH (FCurve *, fcu, &adt->drivers) {
- OperationKey driver_key(id,
- NodeType::PARAMETERS,
- OperationCode::DRIVER,
- fcu->rna_path ? fcu->rna_path : "",
- fcu->array_index);
-
- /* create the driver's relations to targets */
- build_driver(id, fcu);
- /* Special case for array drivers: we can not multithread them because
- * of the way how they work internally: animation system will write the
- * whole array back to RNA even when changing individual array value.
- *
- * Some tricky things here:
- * - array_index is -1 for single channel drivers, meaning we only have
- * to do some magic when array_index is not -1.
- * - We do relation from next array index to a previous one, so we don't
- * have to deal with array index 0.
- *
- * TODO(sergey): Avoid liner lookup somehow. */
- if (fcu->array_index > 0) {
- FCurve *fcu_prev = NULL;
- LISTBASE_FOREACH (FCurve *, fcu_candidate, &adt->drivers) {
- /* Writing to different RNA paths is */
- const char *rna_path = fcu->rna_path ? fcu->rna_path : "";
- if (!STREQ(fcu_candidate->rna_path, rna_path)) {
- continue;
- }
- /* We only do relation from previous fcurve to previous one. */
- if (fcu_candidate->array_index >= fcu->array_index) {
- continue;
- }
- /* Choose fcurve with highest possible array index. */
- if (fcu_prev == NULL ||
- fcu_candidate->array_index > fcu_prev->array_index)
- {
- fcu_prev = fcu_candidate;
- }
- }
- if (fcu_prev != NULL) {
- OperationKey prev_driver_key(id,
- NodeType::PARAMETERS,
- OperationCode::DRIVER,
- fcu_prev->rna_path ? fcu_prev->rna_path : "",
- fcu_prev->array_index);
- OperationKey driver_key(id,
- NodeType::PARAMETERS,
- OperationCode::DRIVER,
- fcu->rna_path ? fcu->rna_path : "",
- fcu->array_index);
- add_relation(prev_driver_key, driver_key, "Driver Order");
- }
- }
-
- /* prevent driver from occurring before own animation... */
- if (adt->action || adt->nla_tracks.first) {
- add_relation(adt_key, driver_key, "AnimData Before Drivers");
- }
- }
+ AnimData *adt = BKE_animdata_from_id(id);
+ if (adt == NULL) {
+ return;
+ }
+ ComponentKey adt_key(id, NodeType::ANIMATION);
+ LISTBASE_FOREACH (FCurve *, fcu, &adt->drivers) {
+ OperationKey driver_key(id,
+ NodeType::PARAMETERS,
+ OperationCode::DRIVER,
+ fcu->rna_path ? fcu->rna_path : "",
+ fcu->array_index);
+
+ /* create the driver's relations to targets */
+ build_driver(id, fcu);
+ /* Special case for array drivers: we can not multithread them because
+ * of the way how they work internally: animation system will write the
+ * whole array back to RNA even when changing individual array value.
+ *
+ * Some tricky things here:
+ * - array_index is -1 for single channel drivers, meaning we only have
+ * to do some magic when array_index is not -1.
+ * - We do relation from next array index to a previous one, so we don't
+ * have to deal with array index 0.
+ *
+ * TODO(sergey): Avoid liner lookup somehow. */
+ if (fcu->array_index > 0) {
+ FCurve *fcu_prev = NULL;
+ LISTBASE_FOREACH (FCurve *, fcu_candidate, &adt->drivers) {
+ /* Writing to different RNA paths is */
+ const char *rna_path = fcu->rna_path ? fcu->rna_path : "";
+ if (!STREQ(fcu_candidate->rna_path, rna_path)) {
+ continue;
+ }
+ /* We only do relation from previous fcurve to previous one. */
+ if (fcu_candidate->array_index >= fcu->array_index) {
+ continue;
+ }
+ /* Choose fcurve with highest possible array index. */
+ if (fcu_prev == NULL || fcu_candidate->array_index > fcu_prev->array_index) {
+ fcu_prev = fcu_candidate;
+ }
+ }
+ if (fcu_prev != NULL) {
+ OperationKey prev_driver_key(id,
+ NodeType::PARAMETERS,
+ OperationCode::DRIVER,
+ fcu_prev->rna_path ? fcu_prev->rna_path : "",
+ fcu_prev->array_index);
+ OperationKey driver_key(id,
+ NodeType::PARAMETERS,
+ OperationCode::DRIVER,
+ fcu->rna_path ? fcu->rna_path : "",
+ fcu->array_index);
+ add_relation(prev_driver_key, driver_key, "Driver Order");
+ }
+ }
+
+ /* prevent driver from occurring before own animation... */
+ if (adt->action || adt->nla_tracks.first) {
+ add_relation(adt_key, driver_key, "AnimData Before Drivers");
+ }
+ }
}
void DepsgraphRelationBuilder::build_animation_images(ID *id)
{
- /* TODO: can we check for existance of node for performance? */
- if (BKE_image_user_id_has_animation(id)) {
- OperationKey image_animation_key(id,
- NodeType::ANIMATION,
- OperationCode::IMAGE_ANIMATION);
- TimeSourceKey time_src_key;
- add_relation(time_src_key, image_animation_key, "TimeSrc -> Image Animation");
- }
+ /* TODO: can we check for existance of node for performance? */
+ if (BKE_image_user_id_has_animation(id)) {
+ OperationKey image_animation_key(id, NodeType::ANIMATION, OperationCode::IMAGE_ANIMATION);
+ TimeSourceKey time_src_key;
+ add_relation(time_src_key, image_animation_key, "TimeSrc -> Image Animation");
+ }
}
void DepsgraphRelationBuilder::build_action(bAction *action)
{
- if (built_map_.checkIsBuiltAndTag(action)) {
- return;
- }
- TimeSourceKey time_src_key;
- ComponentKey animation_key(&action->id, NodeType::ANIMATION);
- add_relation(time_src_key, animation_key, "TimeSrc -> Animation");
+ if (built_map_.checkIsBuiltAndTag(action)) {
+ return;
+ }
+ TimeSourceKey time_src_key;
+ ComponentKey animation_key(&action->id, NodeType::ANIMATION);
+ add_relation(time_src_key, animation_key, "TimeSrc -> Animation");
}
void DepsgraphRelationBuilder::build_driver(ID *id, FCurve *fcu)
{
- ChannelDriver *driver = fcu->driver;
- OperationKey driver_key(id,
- NodeType::PARAMETERS,
- OperationCode::DRIVER,
- fcu->rna_path ? fcu->rna_path : "",
- fcu->array_index);
- /* Driver -> data components (for interleaved evaluation
- * bones/constraints/modifiers). */
- build_driver_data(id, fcu);
- /* Loop over variables to get the target relationships. */
- build_driver_variables(id, fcu);
- /* It's quite tricky to detect if the driver actually depends on time or
- * not, so for now we'll be quite conservative here about optimization and
- * consider all python drivers to be depending on time. */
- if ((driver->type == DRIVER_TYPE_PYTHON) &&
- python_driver_depends_on_time(driver))
- {
- TimeSourceKey time_src_key;
- add_relation(time_src_key, driver_key, "TimeSrc -> Driver");
- }
+ ChannelDriver *driver = fcu->driver;
+ OperationKey driver_key(id,
+ NodeType::PARAMETERS,
+ OperationCode::DRIVER,
+ fcu->rna_path ? fcu->rna_path : "",
+ fcu->array_index);
+ /* Driver -> data components (for interleaved evaluation
+ * bones/constraints/modifiers). */
+ build_driver_data(id, fcu);
+ /* Loop over variables to get the target relationships. */
+ build_driver_variables(id, fcu);
+ /* It's quite tricky to detect if the driver actually depends on time or
+ * not, so for now we'll be quite conservative here about optimization and
+ * consider all python drivers to be depending on time. */
+ if ((driver->type == DRIVER_TYPE_PYTHON) && python_driver_depends_on_time(driver)) {
+ TimeSourceKey time_src_key;
+ add_relation(time_src_key, driver_key, "TimeSrc -> Driver");
+ }
}
void DepsgraphRelationBuilder::build_driver_data(ID *id, FCurve *fcu)
{
- OperationKey driver_key(id,
- NodeType::PARAMETERS,
- OperationCode::DRIVER,
- fcu->rna_path ? fcu->rna_path : "",
- fcu->array_index);
- const char *rna_path = fcu->rna_path ? fcu->rna_path : "";
- if (GS(id->name) == ID_AR && strstr(rna_path, "bones[")) {
- /* Drivers on armature-level bone settings (i.e. bbone stuff),
- * which will affect the evaluation of corresponding pose bones. */
- IDNode *arm_node = graph_->find_id_node(id);
- char *bone_name = BLI_str_quoted_substrN(rna_path, "bones[");
- if (arm_node != NULL && bone_name != NULL) {
- /* Find objects which use this, and make their eval callbacks
- * depend on this. */
- for (Relation *rel : arm_node->outlinks) {
- IDNode *to_node = (IDNode *)rel->to;
- /* We only care about objects with pose data which use this. */
- if (GS(to_node->id_orig->name) == ID_OB) {
- Object *object = (Object *)to_node->id_orig;
- // NOTE: object->pose may be NULL
- bPoseChannel *pchan = BKE_pose_channel_find_name(object->pose,
- bone_name);
- if (pchan != NULL) {
- OperationKey bone_key(&object->id,
- NodeType::BONE,
- pchan->name,
- OperationCode::BONE_LOCAL);
- add_relation(driver_key,
- bone_key,
- "Arm Bone -> Driver -> Bone");
- }
- }
- }
- /* Free temp data. */
- MEM_freeN(bone_name);
- bone_name = NULL;
- }
- else {
- fprintf(stderr,
- "Couldn't find armature bone name for driver path - '%s'\n",
- rna_path);
- }
- }
- else if (rna_path != NULL && rna_path[0] != '\0') {
- RNAPathKey property_entry_key(id, rna_path, RNAPointerSource::ENTRY);
- if (RNA_pointer_is_null(&property_entry_key.ptr)) {
- /* TODO(sergey): This would only mean that driver is broken.
- * so we can't create relation anyway. However, we need to avoid
- * adding drivers which are known to be buggy to a dependency
- * graph, in order to save computational power. */
- return;
- }
- add_relation(
- driver_key, property_entry_key, "Driver -> Driven Property");
- /* Similar to the case with f-curves, driver might drive a nested
- * datablock, which means driver execution should wait for that
- * datablock to be copied. */
- {
- PointerRNA id_ptr;
- PointerRNA ptr;
- RNA_id_pointer_create(id, &id_ptr);
- if (RNA_path_resolve_full(&id_ptr, fcu->rna_path, &ptr, NULL, NULL)) {
- if (id_ptr.id.data != ptr.id.data) {
- ComponentKey cow_key((ID *)ptr.id.data,
- NodeType::COPY_ON_WRITE);
- add_relation(cow_key,
- driver_key,
- "Driven CoW -> Driver",
- RELATION_CHECK_BEFORE_ADD);
- }
- }
- }
- if (property_entry_key.prop != NULL &&
- RNA_property_is_idprop(property_entry_key.prop))
- {
- RNAPathKey property_exit_key(id, rna_path, RNAPointerSource::EXIT);
- OperationKey parameters_key(id,
- NodeType::PARAMETERS,
- OperationCode::PARAMETERS_EVAL);
- add_relation(property_exit_key,
- parameters_key,
- "Driven Property -> Properties");
- }
- }
+ OperationKey driver_key(id,
+ NodeType::PARAMETERS,
+ OperationCode::DRIVER,
+ fcu->rna_path ? fcu->rna_path : "",
+ fcu->array_index);
+ const char *rna_path = fcu->rna_path ? fcu->rna_path : "";
+ if (GS(id->name) == ID_AR && strstr(rna_path, "bones[")) {
+ /* Drivers on armature-level bone settings (i.e. bbone stuff),
+ * which will affect the evaluation of corresponding pose bones. */
+ IDNode *arm_node = graph_->find_id_node(id);
+ char *bone_name = BLI_str_quoted_substrN(rna_path, "bones[");
+ if (arm_node != NULL && bone_name != NULL) {
+ /* Find objects which use this, and make their eval callbacks
+ * depend on this. */
+ for (Relation *rel : arm_node->outlinks) {
+ IDNode *to_node = (IDNode *)rel->to;
+ /* We only care about objects with pose data which use this. */
+ if (GS(to_node->id_orig->name) == ID_OB) {
+ Object *object = (Object *)to_node->id_orig;
+ // NOTE: object->pose may be NULL
+ bPoseChannel *pchan = BKE_pose_channel_find_name(object->pose, bone_name);
+ if (pchan != NULL) {
+ OperationKey bone_key(
+ &object->id, NodeType::BONE, pchan->name, OperationCode::BONE_LOCAL);
+ add_relation(driver_key, bone_key, "Arm Bone -> Driver -> Bone");
+ }
+ }
+ }
+ /* Free temp data. */
+ MEM_freeN(bone_name);
+ bone_name = NULL;
+ }
+ else {
+ fprintf(stderr, "Couldn't find armature bone name for driver path - '%s'\n", rna_path);
+ }
+ }
+ else if (rna_path != NULL && rna_path[0] != '\0') {
+ RNAPathKey property_entry_key(id, rna_path, RNAPointerSource::ENTRY);
+ if (RNA_pointer_is_null(&property_entry_key.ptr)) {
+ /* TODO(sergey): This would only mean that driver is broken.
+ * so we can't create relation anyway. However, we need to avoid
+ * adding drivers which are known to be buggy to a dependency
+ * graph, in order to save computational power. */
+ return;
+ }
+ add_relation(driver_key, property_entry_key, "Driver -> Driven Property");
+ /* Similar to the case with f-curves, driver might drive a nested
+ * datablock, which means driver execution should wait for that
+ * datablock to be copied. */
+ {
+ PointerRNA id_ptr;
+ PointerRNA ptr;
+ RNA_id_pointer_create(id, &id_ptr);
+ if (RNA_path_resolve_full(&id_ptr, fcu->rna_path, &ptr, NULL, NULL)) {
+ if (id_ptr.id.data != ptr.id.data) {
+ ComponentKey cow_key((ID *)ptr.id.data, NodeType::COPY_ON_WRITE);
+ add_relation(cow_key, driver_key, "Driven CoW -> Driver", RELATION_CHECK_BEFORE_ADD);
+ }
+ }
+ }
+ if (property_entry_key.prop != NULL && RNA_property_is_idprop(property_entry_key.prop)) {
+ RNAPathKey property_exit_key(id, rna_path, RNAPointerSource::EXIT);
+ OperationKey parameters_key(id, NodeType::PARAMETERS, OperationCode::PARAMETERS_EVAL);
+ add_relation(property_exit_key, parameters_key, "Driven Property -> Properties");
+ }
+ }
}
void DepsgraphRelationBuilder::build_driver_variables(ID *id, FCurve *fcu)
{
- ChannelDriver *driver = fcu->driver;
- OperationKey driver_key(id,
- NodeType::PARAMETERS,
- OperationCode::DRIVER,
- fcu->rna_path ? fcu->rna_path : "",
- fcu->array_index);
- const char *rna_path = fcu->rna_path ? fcu->rna_path : "";
- const RNAPathKey self_key(id, rna_path, RNAPointerSource::ENTRY);
- LISTBASE_FOREACH (DriverVar *, dvar, &driver->variables) {
- /* Only used targets. */
- DRIVER_TARGETS_USED_LOOPER_BEGIN(dvar)
- {
- if (dtar->id == NULL) {
- continue;
- }
- build_id(dtar->id);
- build_driver_id_property(dtar->id, dtar->rna_path);
- /* Initialize relations coming to proxy_from. */
- Object *proxy_from = NULL;
- if ((GS(dtar->id->name) == ID_OB) &&
- (((Object *)dtar->id)->proxy_from != NULL))
- {
- proxy_from = ((Object *)dtar->id)->proxy_from;
- build_id(&proxy_from->id);
- }
- /* Special handling for directly-named bones. */
- if ((dtar->flag & DTAR_FLAG_STRUCT_REF) &&
- (((Object *)dtar->id)->type == OB_ARMATURE) &&
- (dtar->pchan_name[0]))
- {
- Object *object = (Object *)dtar->id;
- bPoseChannel *target_pchan =
- BKE_pose_channel_find_name(object->pose,
- dtar->pchan_name);
- if (target_pchan == NULL) {
- continue;
- }
- OperationKey variable_key(dtar->id,
- NodeType::BONE,
- target_pchan->name,
- OperationCode::BONE_DONE);
- if (is_same_bone_dependency(variable_key, self_key)) {
- continue;
- }
- add_relation(variable_key, driver_key, "Bone Target -> Driver");
- }
- else if (dtar->flag & DTAR_FLAG_STRUCT_REF) {
- /* Get node associated with the object's transforms. */
- if (dtar->id == id) {
- /* Ignore input dependency if we're driving properties of
- * the same ID, otherwise we'll be ending up in a cyclic
- * dependency here. */
- continue;
- }
- OperationKey target_key(dtar->id,
- NodeType::TRANSFORM,
- OperationCode::TRANSFORM_FINAL);
- add_relation(target_key, driver_key, "Target -> Driver");
- }
- else if (dtar->rna_path != NULL && dtar->rna_path[0] != '\0') {
- RNAPathKey variable_exit_key(
- dtar->id, dtar->rna_path, RNAPointerSource::EXIT);
- if (RNA_pointer_is_null(&variable_exit_key.ptr)) {
- continue;
- }
- if (is_same_bone_dependency(variable_exit_key, self_key) ||
- is_same_nodetree_node_dependency(variable_exit_key, self_key))
- {
- continue;
- }
- add_relation(variable_exit_key,
- driver_key,
- "RNA Target -> Driver");
- if (proxy_from != NULL) {
- RNAPathKey proxy_from_variable_key(&proxy_from->id,
- dtar->rna_path,
- RNAPointerSource::EXIT);
- RNAPathKey variable_entry_key(
- dtar->id, dtar->rna_path, RNAPointerSource::ENTRY);
- add_relation(proxy_from_variable_key,
- variable_entry_key,
- "Proxy From -> Variable");
- }
- }
- else {
- /* If rna_path is NULL, and DTAR_FLAG_STRUCT_REF isn't set, this
- * is an incomplete target reference, so nothing to do here. */
- }
- }
- DRIVER_TARGETS_LOOPER_END;
- }
-}
-
-void DepsgraphRelationBuilder::build_driver_id_property(ID *id,
- const char *rna_path)
-{
- if (id == NULL || rna_path == NULL) {
- return;
- }
- PointerRNA id_ptr, ptr;
- PropertyRNA *prop;
- RNA_id_pointer_create(id, &id_ptr);
- if (!RNA_path_resolve_full(&id_ptr, rna_path, &ptr, &prop, NULL)) {
- return;
- }
- if (prop == NULL) {
- return;
- }
- if (!RNA_property_is_idprop(prop)) {
- return;
- }
- const char *prop_identifier = RNA_property_identifier((PropertyRNA *)prop);
- OperationKey id_property_key(id,
- NodeType::PARAMETERS,
- OperationCode::ID_PROPERTY,
- prop_identifier);
- OperationKey parameters_exit_key(id,
- NodeType::PARAMETERS,
- OperationCode::PARAMETERS_EXIT);
- add_relation(id_property_key,
- parameters_exit_key,
- "ID Property -> Done",
- RELATION_CHECK_BEFORE_ADD);
+ ChannelDriver *driver = fcu->driver;
+ OperationKey driver_key(id,
+ NodeType::PARAMETERS,
+ OperationCode::DRIVER,
+ fcu->rna_path ? fcu->rna_path : "",
+ fcu->array_index);
+ const char *rna_path = fcu->rna_path ? fcu->rna_path : "";
+ const RNAPathKey self_key(id, rna_path, RNAPointerSource::ENTRY);
+ LISTBASE_FOREACH (DriverVar *, dvar, &driver->variables) {
+ /* Only used targets. */
+ DRIVER_TARGETS_USED_LOOPER_BEGIN (dvar) {
+ if (dtar->id == NULL) {
+ continue;
+ }
+ build_id(dtar->id);
+ build_driver_id_property(dtar->id, dtar->rna_path);
+ /* Initialize relations coming to proxy_from. */
+ Object *proxy_from = NULL;
+ if ((GS(dtar->id->name) == ID_OB) && (((Object *)dtar->id)->proxy_from != NULL)) {
+ proxy_from = ((Object *)dtar->id)->proxy_from;
+ build_id(&proxy_from->id);
+ }
+ /* Special handling for directly-named bones. */
+ if ((dtar->flag & DTAR_FLAG_STRUCT_REF) && (((Object *)dtar->id)->type == OB_ARMATURE) &&
+ (dtar->pchan_name[0])) {
+ Object *object = (Object *)dtar->id;
+ bPoseChannel *target_pchan = BKE_pose_channel_find_name(object->pose, dtar->pchan_name);
+ if (target_pchan == NULL) {
+ continue;
+ }
+ OperationKey variable_key(
+ dtar->id, NodeType::BONE, target_pchan->name, OperationCode::BONE_DONE);
+ if (is_same_bone_dependency(variable_key, self_key)) {
+ continue;
+ }
+ add_relation(variable_key, driver_key, "Bone Target -> Driver");
+ }
+ else if (dtar->flag & DTAR_FLAG_STRUCT_REF) {
+ /* Get node associated with the object's transforms. */
+ if (dtar->id == id) {
+ /* Ignore input dependency if we're driving properties of
+ * the same ID, otherwise we'll be ending up in a cyclic
+ * dependency here. */
+ continue;
+ }
+ OperationKey target_key(dtar->id, NodeType::TRANSFORM, OperationCode::TRANSFORM_FINAL);
+ add_relation(target_key, driver_key, "Target -> Driver");
+ }
+ else if (dtar->rna_path != NULL && dtar->rna_path[0] != '\0') {
+ RNAPathKey variable_exit_key(dtar->id, dtar->rna_path, RNAPointerSource::EXIT);
+ if (RNA_pointer_is_null(&variable_exit_key.ptr)) {
+ continue;
+ }
+ if (is_same_bone_dependency(variable_exit_key, self_key) ||
+ is_same_nodetree_node_dependency(variable_exit_key, self_key)) {
+ continue;
+ }
+ add_relation(variable_exit_key, driver_key, "RNA Target -> Driver");
+ if (proxy_from != NULL) {
+ RNAPathKey proxy_from_variable_key(
+ &proxy_from->id, dtar->rna_path, RNAPointerSource::EXIT);
+ RNAPathKey variable_entry_key(dtar->id, dtar->rna_path, RNAPointerSource::ENTRY);
+ add_relation(proxy_from_variable_key, variable_entry_key, "Proxy From -> Variable");
+ }
+ }
+ else {
+ /* If rna_path is NULL, and DTAR_FLAG_STRUCT_REF isn't set, this
+ * is an incomplete target reference, so nothing to do here. */
+ }
+ }
+ DRIVER_TARGETS_LOOPER_END;
+ }
+}
+
+void DepsgraphRelationBuilder::build_driver_id_property(ID *id, const char *rna_path)
+{
+ if (id == NULL || rna_path == NULL) {
+ return;
+ }
+ PointerRNA id_ptr, ptr;
+ PropertyRNA *prop;
+ RNA_id_pointer_create(id, &id_ptr);
+ if (!RNA_path_resolve_full(&id_ptr, rna_path, &ptr, &prop, NULL)) {
+ return;
+ }
+ if (prop == NULL) {
+ return;
+ }
+ if (!RNA_property_is_idprop(prop)) {
+ return;
+ }
+ const char *prop_identifier = RNA_property_identifier((PropertyRNA *)prop);
+ OperationKey id_property_key(
+ id, NodeType::PARAMETERS, OperationCode::ID_PROPERTY, prop_identifier);
+ OperationKey parameters_exit_key(id, NodeType::PARAMETERS, OperationCode::PARAMETERS_EXIT);
+ add_relation(
+ id_property_key, parameters_exit_key, "ID Property -> Done", RELATION_CHECK_BEFORE_ADD);
}
void DepsgraphRelationBuilder::build_parameters(ID *id)
{
- OperationKey parameters_entry_key(
- id, NodeType::PARAMETERS, OperationCode::PARAMETERS_ENTRY);
- OperationKey parameters_eval_key(
- id, NodeType::PARAMETERS, OperationCode::PARAMETERS_EVAL);
- OperationKey parameters_exit_key(
- id, NodeType::PARAMETERS, OperationCode::PARAMETERS_EXIT);
- add_relation(
- parameters_entry_key, parameters_eval_key, "Entry -> Eval");
- add_relation(
- parameters_eval_key, parameters_exit_key, "Entry -> Exit");
+ OperationKey parameters_entry_key(id, NodeType::PARAMETERS, OperationCode::PARAMETERS_ENTRY);
+ OperationKey parameters_eval_key(id, NodeType::PARAMETERS, OperationCode::PARAMETERS_EVAL);
+ OperationKey parameters_exit_key(id, NodeType::PARAMETERS, OperationCode::PARAMETERS_EXIT);
+ add_relation(parameters_entry_key, parameters_eval_key, "Entry -> Eval");
+ add_relation(parameters_eval_key, parameters_exit_key, "Entry -> Exit");
}
void DepsgraphRelationBuilder::build_world(World *world)
{
- if (built_map_.checkIsBuiltAndTag(world)) {
- return;
- }
- /* animation */
- build_animdata(&world->id);
- build_parameters(&world->id);
- /* world's nodetree */
- if (world->nodetree != NULL) {
- build_nodetree(world->nodetree);
- OperationKey ntree_key(&world->nodetree->id,
- NodeType::SHADING,
- OperationCode::MATERIAL_UPDATE);
- OperationKey world_key(&world->id,
- NodeType::SHADING,
- OperationCode::WORLD_UPDATE);
- add_relation(ntree_key, world_key, "World's NTree");
- build_nested_nodetree(&world->id, world->nodetree);
- }
+ if (built_map_.checkIsBuiltAndTag(world)) {
+ return;
+ }
+ /* animation */
+ build_animdata(&world->id);
+ build_parameters(&world->id);
+ /* world's nodetree */
+ if (world->nodetree != NULL) {
+ build_nodetree(world->nodetree);
+ OperationKey ntree_key(
+ &world->nodetree->id, NodeType::SHADING, OperationCode::MATERIAL_UPDATE);
+ OperationKey world_key(&world->id, NodeType::SHADING, OperationCode::WORLD_UPDATE);
+ add_relation(ntree_key, world_key, "World's NTree");
+ build_nested_nodetree(&world->id, world->nodetree);
+ }
}
void DepsgraphRelationBuilder::build_rigidbody(Scene *scene)
{
- RigidBodyWorld *rbw = scene->rigidbody_world;
- OperationKey rb_init_key(&scene->id,
- NodeType::TRANSFORM,
- OperationCode::RIGIDBODY_REBUILD);
- OperationKey rb_simulate_key(&scene->id,
- NodeType::TRANSFORM,
- OperationCode::RIGIDBODY_SIM);
- /* Simulation depends on time. */
- TimeSourceKey time_src_key;
- add_relation(time_src_key, rb_init_key, "TimeSrc -> Rigidbody Init");
- /* Simulation should always be run after initialization. */
- /* NOTE: It is possible in theory to have dependency cycle which involves
- * this relation. We never want it to be killed. */
- add_relation(rb_init_key,
- rb_simulate_key,
- "Rigidbody [Init -> SimStep]",
- RELATION_FLAG_GODMODE);
- /* Effectors should be evaluated at the time simulation is being
- * initialized.
- * TODO(sergey): Verify that it indeed goes to initialization and not to a
- * simulation. */
- ListBase *effector_relations =
- build_effector_relations(graph_, rbw->effector_weights->group);
- LISTBASE_FOREACH (EffectorRelation *, effector_relation, effector_relations) {
- ComponentKey effector_transform_key(
- &effector_relation->ob->id, NodeType::TRANSFORM);
- add_relation(effector_transform_key, rb_init_key, "RigidBody Field");
- if (effector_relation->pd != NULL) {
- const short shape = effector_relation->pd->shape;
- if (ELEM(shape, PFIELD_SHAPE_SURFACE, PFIELD_SHAPE_POINTS)) {
- ComponentKey effector_geometry_key(
- &effector_relation->ob->id, NodeType::GEOMETRY);
- add_relation(
- effector_geometry_key, rb_init_key, "RigidBody Field");
- }
- }
- }
- /* Objects. */
- if (rbw->group != NULL) {
- build_collection(NULL, NULL, rbw->group);
- FOREACH_COLLECTION_OBJECT_RECURSIVE_BEGIN(rbw->group, object)
- {
- if (object->type != OB_MESH) {
- continue;
- }
- OperationKey rb_transform_copy_key(
- &object->id,
- NodeType::TRANSFORM,
- OperationCode::RIGIDBODY_TRANSFORM_COPY);
- /* Rigid body synchronization depends on the actual simulation. */
- add_relation(rb_simulate_key,
- rb_transform_copy_key,
- "Rigidbody Sim Eval -> RBO Sync");
- /* Simulation uses object transformation after parenting and solving
- * contraints. */
- OperationKey object_transform_simulation_init_key(
- &object->id,
- NodeType::TRANSFORM,
- OperationCode::TRANSFORM_SIMULATION_INIT);
- OperationKey object_transform_eval_key(
- &object->id,
- NodeType::TRANSFORM,
- OperationCode::TRANSFORM_EVAL);
- add_relation(object_transform_simulation_init_key,
- rb_simulate_key,
- "Object Transform -> Rigidbody Sim Eval");
- /* Geometry must be known to create the rigid body. RBO_MESH_BASE
- * uses the non-evaluated mesh, so then the evaluation is
- * unnecessary. */
- if (object->rigidbody_object != NULL &&
- object->rigidbody_object->mesh_source != RBO_MESH_BASE)
- {
- /* NOTE: We prefer this relation to be never killed, to avoid
- * access partially evaluated mesh from solver. */
- ComponentKey object_geometry_key(
- &object->id, NodeType::GEOMETRY);
- add_relation(object_geometry_key,
- rb_simulate_key,
- "Object Geom Eval -> Rigidbody Rebuild",
- RELATION_FLAG_GODMODE);
- }
- /* Final transform is whetever solver gave to us. */
- OperationKey object_transform_final_key(
- &object->id,
- NodeType::TRANSFORM,
- OperationCode::TRANSFORM_FINAL);
- add_relation(rb_transform_copy_key,
- object_transform_final_key,
- "Rigidbody Sync -> Transform Final");
- }
- FOREACH_COLLECTION_OBJECT_RECURSIVE_END;
- }
- /* Constraints. */
- if (rbw->constraints != NULL) {
- FOREACH_COLLECTION_OBJECT_RECURSIVE_BEGIN(rbw->constraints, object)
- {
- RigidBodyCon *rbc = object->rigidbody_constraint;
- if (rbc == NULL || rbc->ob1 == NULL || rbc->ob2 == NULL) {
- /* When either ob1 or ob2 is NULL, the constraint doesn't
- * work. */
- continue;
- }
- /* Make sure indirectly linked objects are fully built. */
- build_object(NULL, object);
- build_object(NULL, rbc->ob1);
- build_object(NULL, rbc->ob2);
- /* final result of the constraint object's transform controls how
- * the constraint affects the physics sim for these objects. */
- ComponentKey trans_key(&object->id, NodeType::TRANSFORM);
- OperationKey ob1_key(&rbc->ob1->id,
- NodeType::TRANSFORM,
- OperationCode::RIGIDBODY_TRANSFORM_COPY);
- OperationKey ob2_key(&rbc->ob2->id,
- NodeType::TRANSFORM,
- OperationCode::RIGIDBODY_TRANSFORM_COPY);
- /* Constrained-objects sync depends on the constraint-holder. */
- add_relation(
- trans_key, ob1_key, "RigidBodyConstraint -> RBC.Object_1");
- add_relation(
- trans_key, ob2_key, "RigidBodyConstraint -> RBC.Object_2");
- /* Ensure that sim depends on this constraint's transform. */
- add_relation(trans_key,
- rb_simulate_key,
- "RigidBodyConstraint Transform -> RB Simulation");
- }
- FOREACH_COLLECTION_OBJECT_RECURSIVE_END;
- }
+ RigidBodyWorld *rbw = scene->rigidbody_world;
+ OperationKey rb_init_key(&scene->id, NodeType::TRANSFORM, OperationCode::RIGIDBODY_REBUILD);
+ OperationKey rb_simulate_key(&scene->id, NodeType::TRANSFORM, OperationCode::RIGIDBODY_SIM);
+ /* Simulation depends on time. */
+ TimeSourceKey time_src_key;
+ add_relation(time_src_key, rb_init_key, "TimeSrc -> Rigidbody Init");
+ /* Simulation should always be run after initialization. */
+ /* NOTE: It is possible in theory to have dependency cycle which involves
+ * this relation. We never want it to be killed. */
+ add_relation(rb_init_key, rb_simulate_key, "Rigidbody [Init -> SimStep]", RELATION_FLAG_GODMODE);
+ /* Effectors should be evaluated at the time simulation is being
+ * initialized.
+ * TODO(sergey): Verify that it indeed goes to initialization and not to a
+ * simulation. */
+ ListBase *effector_relations = build_effector_relations(graph_, rbw->effector_weights->group);
+ LISTBASE_FOREACH (EffectorRelation *, effector_relation, effector_relations) {
+ ComponentKey effector_transform_key(&effector_relation->ob->id, NodeType::TRANSFORM);
+ add_relation(effector_transform_key, rb_init_key, "RigidBody Field");
+ if (effector_relation->pd != NULL) {
+ const short shape = effector_relation->pd->shape;
+ if (ELEM(shape, PFIELD_SHAPE_SURFACE, PFIELD_SHAPE_POINTS)) {
+ ComponentKey effector_geometry_key(&effector_relation->ob->id, NodeType::GEOMETRY);
+ add_relation(effector_geometry_key, rb_init_key, "RigidBody Field");
+ }
+ }
+ }
+ /* Objects. */
+ if (rbw->group != NULL) {
+ build_collection(NULL, NULL, rbw->group);
+ FOREACH_COLLECTION_OBJECT_RECURSIVE_BEGIN (rbw->group, object) {
+ if (object->type != OB_MESH) {
+ continue;
+ }
+ OperationKey rb_transform_copy_key(
+ &object->id, NodeType::TRANSFORM, OperationCode::RIGIDBODY_TRANSFORM_COPY);
+ /* Rigid body synchronization depends on the actual simulation. */
+ add_relation(rb_simulate_key, rb_transform_copy_key, "Rigidbody Sim Eval -> RBO Sync");
+ /* Simulation uses object transformation after parenting and solving
+ * contraints. */
+ OperationKey object_transform_simulation_init_key(
+ &object->id, NodeType::TRANSFORM, OperationCode::TRANSFORM_SIMULATION_INIT);
+ OperationKey object_transform_eval_key(
+ &object->id, NodeType::TRANSFORM, OperationCode::TRANSFORM_EVAL);
+ add_relation(object_transform_simulation_init_key,
+ rb_simulate_key,
+ "Object Transform -> Rigidbody Sim Eval");
+ /* Geometry must be known to create the rigid body. RBO_MESH_BASE
+ * uses the non-evaluated mesh, so then the evaluation is
+ * unnecessary. */
+ if (object->rigidbody_object != NULL &&
+ object->rigidbody_object->mesh_source != RBO_MESH_BASE) {
+ /* NOTE: We prefer this relation to be never killed, to avoid
+ * access partially evaluated mesh from solver. */
+ ComponentKey object_geometry_key(&object->id, NodeType::GEOMETRY);
+ add_relation(object_geometry_key,
+ rb_simulate_key,
+ "Object Geom Eval -> Rigidbody Rebuild",
+ RELATION_FLAG_GODMODE);
+ }
+ /* Final transform is whetever solver gave to us. */
+ OperationKey object_transform_final_key(
+ &object->id, NodeType::TRANSFORM, OperationCode::TRANSFORM_FINAL);
+ add_relation(
+ rb_transform_copy_key, object_transform_final_key, "Rigidbody Sync -> Transform Final");
+ }
+ FOREACH_COLLECTION_OBJECT_RECURSIVE_END;
+ }
+ /* Constraints. */
+ if (rbw->constraints != NULL) {
+ FOREACH_COLLECTION_OBJECT_RECURSIVE_BEGIN (rbw->constraints, object) {
+ RigidBodyCon *rbc = object->rigidbody_constraint;
+ if (rbc == NULL || rbc->ob1 == NULL || rbc->ob2 == NULL) {
+ /* When either ob1 or ob2 is NULL, the constraint doesn't
+ * work. */
+ continue;
+ }
+ /* Make sure indirectly linked objects are fully built. */
+ build_object(NULL, object);
+ build_object(NULL, rbc->ob1);
+ build_object(NULL, rbc->ob2);
+ /* final result of the constraint object's transform controls how
+ * the constraint affects the physics sim for these objects. */
+ ComponentKey trans_key(&object->id, NodeType::TRANSFORM);
+ OperationKey ob1_key(
+ &rbc->ob1->id, NodeType::TRANSFORM, OperationCode::RIGIDBODY_TRANSFORM_COPY);
+ OperationKey ob2_key(
+ &rbc->ob2->id, NodeType::TRANSFORM, OperationCode::RIGIDBODY_TRANSFORM_COPY);
+ /* Constrained-objects sync depends on the constraint-holder. */
+ add_relation(trans_key, ob1_key, "RigidBodyConstraint -> RBC.Object_1");
+ add_relation(trans_key, ob2_key, "RigidBodyConstraint -> RBC.Object_2");
+ /* Ensure that sim depends on this constraint's transform. */
+ add_relation(trans_key, rb_simulate_key, "RigidBodyConstraint Transform -> RB Simulation");
+ }
+ FOREACH_COLLECTION_OBJECT_RECURSIVE_END;
+ }
}
void DepsgraphRelationBuilder::build_particle_systems(Object *object)
{
- TimeSourceKey time_src_key;
- OperationKey obdata_ubereval_key(&object->id,
- NodeType::GEOMETRY,
- OperationCode::GEOMETRY_EVAL);
- OperationKey eval_init_key(&object->id,
- NodeType::PARTICLE_SYSTEM,
- OperationCode::PARTICLE_SYSTEM_INIT);
- OperationKey eval_done_key(&object->id,
- NodeType::PARTICLE_SYSTEM,
- OperationCode::PARTICLE_SYSTEM_DONE);
- ComponentKey eval_key(&object->id, NodeType::PARTICLE_SYSTEM);
- if (BKE_ptcache_object_has(scene_, object, 0)) {
- ComponentKey point_cache_key(&object->id, NodeType::POINT_CACHE);
- add_relation(eval_key,
- point_cache_key,
- "Particle Point Cache",
- RELATION_FLAG_FLUSH_USER_EDIT_ONLY);
- }
- /* Particle systems. */
- LISTBASE_FOREACH (ParticleSystem *, psys, &object->particlesystem) {
- ParticleSettings *part = psys->part;
- /* Build particle settings relations.
- * NOTE: The call itself ensures settings are only build once. */
- build_particle_settings(part);
- /* This particle system. */
- OperationKey psys_key(&object->id,
- NodeType::PARTICLE_SYSTEM,
- OperationCode::PARTICLE_SYSTEM_EVAL,
- psys->name);
- /* Update particle system when settings changes. */
- OperationKey particle_settings_key(&part->id,
- NodeType::PARTICLE_SETTINGS,
- OperationCode::PARTICLE_SETTINGS_EVAL);
- add_relation(particle_settings_key,
- eval_init_key,
- "Particle Settings Change");
- add_relation(eval_init_key, psys_key, "Init -> PSys");
- add_relation(psys_key, eval_done_key, "PSys -> Done");
- /* TODO(sergey): Currently particle update is just a placeholder,
- * hook it to the ubereval node so particle system is getting updated
- * on playback. */
- add_relation(psys_key, obdata_ubereval_key, "PSys -> UberEval");
- /* Collisions. */
- if (part->type != PART_HAIR) {
- add_particle_collision_relations(psys_key,
- object,
- part->collision_group,
- "Particle Collision");
- }
- else if ((psys->flag & PSYS_HAIR_DYNAMICS) &&
- psys->clmd != NULL &&
- psys->clmd->coll_parms != NULL)
- {
- add_particle_collision_relations(psys_key,
- object,
- psys->clmd->coll_parms->group,
- "Hair Collision");
- }
- /* Effectors. */
- add_particle_forcefield_relations(psys_key,
- object,
- psys,
- part->effector_weights,
- part->type == PART_HAIR,
- "Particle Field");
- /* Boids .*/
- if (part->boids != NULL) {
- LISTBASE_FOREACH (BoidState *, state, &part->boids->states) {
- LISTBASE_FOREACH (BoidRule *, rule, &state->rules) {
- Object *ruleob = NULL;
- if (rule->type == eBoidRuleType_Avoid) {
- ruleob = ((BoidRuleGoalAvoid *)rule)->ob;
- }
- else if (rule->type == eBoidRuleType_FollowLeader) {
- ruleob = ((BoidRuleFollowLeader *)rule)->ob;
- }
- if (ruleob != NULL) {
- ComponentKey ruleob_key(&ruleob->id,
- NodeType::TRANSFORM);
- add_relation(ruleob_key, psys_key, "Boid Rule");
- }
- }
- }
- }
- /* Keyed particle targets. */
- if (part->phystype == PART_PHYS_KEYED) {
- LISTBASE_FOREACH (ParticleTarget *, particle_target, &psys->targets) {
- if (particle_target->ob == NULL ||
- particle_target->ob == object)
- {
- continue;
- }
- /* Make sure target object is pulled into the graph. */
- build_object(NULL, particle_target->ob);
- /* Use geometry component, since that's where particles are
- * actually evaluated. */
- ComponentKey target_key(&particle_target->ob->id,
- NodeType::GEOMETRY);
- add_relation(target_key, psys_key, "Keyed Target");
- }
- }
- /* Visualization. */
- switch (part->ren_as) {
- case PART_DRAW_OB:
- if (part->instance_object != NULL) {
- /* Make sure object's relations are all built. */
- build_object(NULL, part->instance_object);
- /* Build relation for the particle visualization. */
- build_particle_system_visualization_object(
- object, psys, part->instance_object);
- }
- break;
- case PART_DRAW_GR:
- if (part->instance_collection != NULL) {
- build_collection(NULL, NULL, part->instance_collection);
- LISTBASE_FOREACH (CollectionObject *, go, &part->instance_collection->gobject) {
- build_particle_system_visualization_object(
- object, psys, go->ob);
- }
- }
- break;
- }
- }
- /* Particle depends on the object transform, so that channel is to be ready
- * first. */
- add_depends_on_transform_relation(
- &object->id, obdata_ubereval_key, "Particle Eval");
+ TimeSourceKey time_src_key;
+ OperationKey obdata_ubereval_key(&object->id, NodeType::GEOMETRY, OperationCode::GEOMETRY_EVAL);
+ OperationKey eval_init_key(
+ &object->id, NodeType::PARTICLE_SYSTEM, OperationCode::PARTICLE_SYSTEM_INIT);
+ OperationKey eval_done_key(
+ &object->id, NodeType::PARTICLE_SYSTEM, OperationCode::PARTICLE_SYSTEM_DONE);
+ ComponentKey eval_key(&object->id, NodeType::PARTICLE_SYSTEM);
+ if (BKE_ptcache_object_has(scene_, object, 0)) {
+ ComponentKey point_cache_key(&object->id, NodeType::POINT_CACHE);
+ add_relation(
+ eval_key, point_cache_key, "Particle Point Cache", RELATION_FLAG_FLUSH_USER_EDIT_ONLY);
+ }
+ /* Particle systems. */
+ LISTBASE_FOREACH (ParticleSystem *, psys, &object->particlesystem) {
+ ParticleSettings *part = psys->part;
+ /* Build particle settings relations.
+ * NOTE: The call itself ensures settings are only build once. */
+ build_particle_settings(part);
+ /* This particle system. */
+ OperationKey psys_key(
+ &object->id, NodeType::PARTICLE_SYSTEM, OperationCode::PARTICLE_SYSTEM_EVAL, psys->name);
+ /* Update particle system when settings changes. */
+ OperationKey particle_settings_key(
+ &part->id, NodeType::PARTICLE_SETTINGS, OperationCode::PARTICLE_SETTINGS_EVAL);
+ add_relation(particle_settings_key, eval_init_key, "Particle Settings Change");
+ add_relation(eval_init_key, psys_key, "Init -> PSys");
+ add_relation(psys_key, eval_done_key, "PSys -> Done");
+ /* TODO(sergey): Currently particle update is just a placeholder,
+ * hook it to the ubereval node so particle system is getting updated
+ * on playback. */
+ add_relation(psys_key, obdata_ubereval_key, "PSys -> UberEval");
+ /* Collisions. */
+ if (part->type != PART_HAIR) {
+ add_particle_collision_relations(
+ psys_key, object, part->collision_group, "Particle Collision");
+ }
+ else if ((psys->flag & PSYS_HAIR_DYNAMICS) && psys->clmd != NULL &&
+ psys->clmd->coll_parms != NULL) {
+ add_particle_collision_relations(
+ psys_key, object, psys->clmd->coll_parms->group, "Hair Collision");
+ }
+ /* Effectors. */
+ add_particle_forcefield_relations(
+ psys_key, object, psys, part->effector_weights, part->type == PART_HAIR, "Particle Field");
+ /* Boids .*/
+ if (part->boids != NULL) {
+ LISTBASE_FOREACH (BoidState *, state, &part->boids->states) {
+ LISTBASE_FOREACH (BoidRule *, rule, &state->rules) {
+ Object *ruleob = NULL;
+ if (rule->type == eBoidRuleType_Avoid) {
+ ruleob = ((BoidRuleGoalAvoid *)rule)->ob;
+ }
+ else if (rule->type == eBoidRuleType_FollowLeader) {
+ ruleob = ((BoidRuleFollowLeader *)rule)->ob;
+ }
+ if (ruleob != NULL) {
+ ComponentKey ruleob_key(&ruleob->id, NodeType::TRANSFORM);
+ add_relation(ruleob_key, psys_key, "Boid Rule");
+ }
+ }
+ }
+ }
+ /* Keyed particle targets. */
+ if (part->phystype == PART_PHYS_KEYED) {
+ LISTBASE_FOREACH (ParticleTarget *, particle_target, &psys->targets) {
+ if (particle_target->ob == NULL || particle_target->ob == object) {
+ continue;
+ }
+ /* Make sure target object is pulled into the graph. */
+ build_object(NULL, particle_target->ob);
+ /* Use geometry component, since that's where particles are
+ * actually evaluated. */
+ ComponentKey target_key(&particle_target->ob->id, NodeType::GEOMETRY);
+ add_relation(target_key, psys_key, "Keyed Target");
+ }
+ }
+ /* Visualization. */
+ switch (part->ren_as) {
+ case PART_DRAW_OB:
+ if (part->instance_object != NULL) {
+ /* Make sure object's relations are all built. */
+ build_object(NULL, part->instance_object);
+ /* Build relation for the particle visualization. */
+ build_particle_system_visualization_object(object, psys, part->instance_object);
+ }
+ break;
+ case PART_DRAW_GR:
+ if (part->instance_collection != NULL) {
+ build_collection(NULL, NULL, part->instance_collection);
+ LISTBASE_FOREACH (CollectionObject *, go, &part->instance_collection->gobject) {
+ build_particle_system_visualization_object(object, psys, go->ob);
+ }
+ }
+ break;
+ }
+ }
+ /* Particle depends on the object transform, so that channel is to be ready
+ * first. */
+ add_depends_on_transform_relation(&object->id, obdata_ubereval_key, "Particle Eval");
}
void DepsgraphRelationBuilder::build_particle_settings(ParticleSettings *part)
{
- if (built_map_.checkIsBuiltAndTag(part)) {
- return;
- }
- /* Animation data relations. */
- build_animdata(&part->id);
- build_parameters(&part->id);
- OperationKey particle_settings_init_key(&part->id,
- NodeType::PARTICLE_SETTINGS,
- OperationCode::PARTICLE_SETTINGS_INIT);
- OperationKey particle_settings_eval_key(&part->id,
- NodeType::PARTICLE_SETTINGS,
- OperationCode::PARTICLE_SETTINGS_EVAL);
- OperationKey particle_settings_reset_key(
- &part->id,
- NodeType::PARTICLE_SETTINGS,
- OperationCode::PARTICLE_SETTINGS_RESET);
- add_relation(particle_settings_init_key,
- particle_settings_eval_key,
- "Particle Settings Init Order");
- add_relation(particle_settings_reset_key,
- particle_settings_eval_key,
- "Particle Settings Reset");
- /* Texture slots. */
- for (int mtex_index = 0; mtex_index < MAX_MTEX; ++mtex_index) {
- MTex *mtex = part->mtex[mtex_index];
- if (mtex == NULL || mtex->tex == NULL) {
- continue;
- }
- build_texture(mtex->tex);
- ComponentKey texture_key(&mtex->tex->id,
- NodeType::GENERIC_DATABLOCK);
- add_relation(texture_key,
- particle_settings_reset_key,
- "Particle Texture",
- RELATION_FLAG_FLUSH_USER_EDIT_ONLY);
- /* TODO(sergey): Consider moving texture space handling to an own
- * function. */
- if (mtex->texco == TEXCO_OBJECT && mtex->object != NULL) {
- ComponentKey object_key(&mtex->object->id, NodeType::TRANSFORM);
- add_relation(object_key,
- particle_settings_eval_key,
- "Particle Texture Space");
- }
- }
- if (check_id_has_anim_component(&part->id)) {
- ComponentKey animation_key(&part->id, NodeType::ANIMATION);
- add_relation(animation_key,
- particle_settings_eval_key,
- "Particle Settings Animation");
- }
-}
-
-void DepsgraphRelationBuilder::build_particle_system_visualization_object(
- Object *object,
- ParticleSystem *psys,
- Object *draw_object)
-{
- OperationKey psys_key(&object->id,
- NodeType::PARTICLE_SYSTEM,
- OperationCode::PARTICLE_SYSTEM_EVAL,
- psys->name);
- OperationKey obdata_ubereval_key(&object->id,
- NodeType::GEOMETRY,
- OperationCode::GEOMETRY_EVAL);
- ComponentKey dup_ob_key(&draw_object->id, NodeType::TRANSFORM);
- add_relation(dup_ob_key, psys_key, "Particle Object Visualization");
- if (draw_object->type == OB_MBALL) {
- ComponentKey dup_geometry_key(&draw_object->id, NodeType::GEOMETRY);
- add_relation(obdata_ubereval_key,
- dup_geometry_key,
- "Particle MBall Visualization");
- }
+ if (built_map_.checkIsBuiltAndTag(part)) {
+ return;
+ }
+ /* Animation data relations. */
+ build_animdata(&part->id);
+ build_parameters(&part->id);
+ OperationKey particle_settings_init_key(
+ &part->id, NodeType::PARTICLE_SETTINGS, OperationCode::PARTICLE_SETTINGS_INIT);
+ OperationKey particle_settings_eval_key(
+ &part->id, NodeType::PARTICLE_SETTINGS, OperationCode::PARTICLE_SETTINGS_EVAL);
+ OperationKey particle_settings_reset_key(
+ &part->id, NodeType::PARTICLE_SETTINGS, OperationCode::PARTICLE_SETTINGS_RESET);
+ add_relation(
+ particle_settings_init_key, particle_settings_eval_key, "Particle Settings Init Order");
+ add_relation(particle_settings_reset_key, particle_settings_eval_key, "Particle Settings Reset");
+ /* Texture slots. */
+ for (int mtex_index = 0; mtex_index < MAX_MTEX; ++mtex_index) {
+ MTex *mtex = part->mtex[mtex_index];
+ if (mtex == NULL || mtex->tex == NULL) {
+ continue;
+ }
+ build_texture(mtex->tex);
+ ComponentKey texture_key(&mtex->tex->id, NodeType::GENERIC_DATABLOCK);
+ add_relation(texture_key,
+ particle_settings_reset_key,
+ "Particle Texture",
+ RELATION_FLAG_FLUSH_USER_EDIT_ONLY);
+ /* TODO(sergey): Consider moving texture space handling to an own
+ * function. */
+ if (mtex->texco == TEXCO_OBJECT && mtex->object != NULL) {
+ ComponentKey object_key(&mtex->object->id, NodeType::TRANSFORM);
+ add_relation(object_key, particle_settings_eval_key, "Particle Texture Space");
+ }
+ }
+ if (check_id_has_anim_component(&part->id)) {
+ ComponentKey animation_key(&part->id, NodeType::ANIMATION);
+ add_relation(animation_key, particle_settings_eval_key, "Particle Settings Animation");
+ }
+}
+
+void DepsgraphRelationBuilder::build_particle_system_visualization_object(Object *object,
+ ParticleSystem *psys,
+ Object *draw_object)
+{
+ OperationKey psys_key(
+ &object->id, NodeType::PARTICLE_SYSTEM, OperationCode::PARTICLE_SYSTEM_EVAL, psys->name);
+ OperationKey obdata_ubereval_key(&object->id, NodeType::GEOMETRY, OperationCode::GEOMETRY_EVAL);
+ ComponentKey dup_ob_key(&draw_object->id, NodeType::TRANSFORM);
+ add_relation(dup_ob_key, psys_key, "Particle Object Visualization");
+ if (draw_object->type == OB_MBALL) {
+ ComponentKey dup_geometry_key(&draw_object->id, NodeType::GEOMETRY);
+ add_relation(obdata_ubereval_key, dup_geometry_key, "Particle MBall Visualization");
+ }
}
/* Shapekeys */
void DepsgraphRelationBuilder::build_shapekeys(Key *key)
{
- if (built_map_.checkIsBuiltAndTag(key)) {
- return;
- }
- /* Attach animdata to geometry. */
- build_animdata(&key->id);
- build_parameters(&key->id);
- /* Connect all blocks properties to the final result evaluation. */
- ComponentKey geometry_key(&key->id, NodeType::GEOMETRY);
- OperationKey parameters_eval_key(&key->id,
- NodeType::PARAMETERS,
- OperationCode::PARAMETERS_EVAL);
- LISTBASE_FOREACH (KeyBlock *, key_block, &key->block) {
- OperationKey key_block_key(&key->id,
- NodeType::PARAMETERS,
- OperationCode::PARAMETERS_EVAL,
- key_block->name);
- add_relation(key_block_key, geometry_key, "Key Block Properties");
- add_relation(key_block_key, parameters_eval_key, "Key Block Properties");
- }
+ if (built_map_.checkIsBuiltAndTag(key)) {
+ return;
+ }
+ /* Attach animdata to geometry. */
+ build_animdata(&key->id);
+ build_parameters(&key->id);
+ /* Connect all blocks properties to the final result evaluation. */
+ ComponentKey geometry_key(&key->id, NodeType::GEOMETRY);
+ OperationKey parameters_eval_key(&key->id, NodeType::PARAMETERS, OperationCode::PARAMETERS_EVAL);
+ LISTBASE_FOREACH (KeyBlock *, key_block, &key->block) {
+ OperationKey key_block_key(
+ &key->id, NodeType::PARAMETERS, OperationCode::PARAMETERS_EVAL, key_block->name);
+ add_relation(key_block_key, geometry_key, "Key Block Properties");
+ add_relation(key_block_key, parameters_eval_key, "Key Block Properties");
+ }
}
/**
@@ -2092,535 +1827,475 @@ void DepsgraphRelationBuilder::build_shapekeys(Key *key)
* downstream re-evaluation of the individual instances of this geometry. */
void DepsgraphRelationBuilder::build_object_data_geometry(Object *object)
{
- ID *obdata = (ID *)object->data;
- /* Init operation of object-level geometry evaluation. */
- OperationKey geom_init_key(&object->id,
- NodeType::GEOMETRY,
- OperationCode::GEOMETRY_EVAL_INIT);
- /* Get nodes for result of obdata's evaluation, and geometry evaluation
- * on object. */
- ComponentKey obdata_geom_key(obdata, NodeType::GEOMETRY);
- ComponentKey geom_key(&object->id, NodeType::GEOMETRY);
- /* Link components to each other. */
- add_relation(obdata_geom_key, geom_key, "Object Geometry Base Data");
- OperationKey obdata_ubereval_key(&object->id,
- NodeType::GEOMETRY,
- OperationCode::GEOMETRY_EVAL);
- /* Special case: modifiers evaluation queries scene for various things like
- * data mask to be used. We add relation here to ensure object is never
- * evaluated prior to Scene's CoW is ready. */
- OperationKey scene_key(&scene_->id,
- NodeType::LAYER_COLLECTIONS,
- OperationCode::VIEW_LAYER_EVAL);
- Relation *rel = add_relation(scene_key, obdata_ubereval_key, "CoW Relation");
- rel->flag |= RELATION_FLAG_NO_FLUSH;
- /* Modifiers */
- if (object->modifiers.first != NULL) {
- ModifierUpdateDepsgraphContext ctx = {};
- ctx.scene = scene_;
- ctx.object = object;
- LISTBASE_FOREACH (ModifierData *, md, &object->modifiers) {
- const ModifierTypeInfo *mti = modifierType_getInfo((ModifierType)md->type);
- if (mti->updateDepsgraph) {
- DepsNodeHandle handle = create_node_handle(obdata_ubereval_key);
- ctx.node = reinterpret_cast< ::DepsNodeHandle* >(&handle);
- mti->updateDepsgraph(md, &ctx);
- }
- if (BKE_object_modifier_use_time(object, md)) {
- TimeSourceKey time_src_key;
- add_relation(time_src_key, obdata_ubereval_key, "Time Source");
- }
- }
- }
- /* Grease Pencil Modifiers. */
- if (object->greasepencil_modifiers.first != NULL) {
- ModifierUpdateDepsgraphContext ctx = {};
- ctx.scene = scene_;
- ctx.object = object;
- LISTBASE_FOREACH (GpencilModifierData *, md, &object->greasepencil_modifiers) {
- const GpencilModifierTypeInfo *mti = BKE_gpencil_modifierType_getInfo((GpencilModifierType)md->type);
- if (mti->updateDepsgraph) {
- DepsNodeHandle handle = create_node_handle(obdata_ubereval_key);
- ctx.node = reinterpret_cast< ::DepsNodeHandle* >(&handle);
- mti->updateDepsgraph(md, &ctx);
- }
- if (BKE_object_modifier_gpencil_use_time(object, md)) {
- TimeSourceKey time_src_key;
- add_relation(time_src_key, obdata_ubereval_key, "Time Source");
- }
- }
- }
- /* Shader FX. */
- if (object->shader_fx.first != NULL) {
- ModifierUpdateDepsgraphContext ctx = {};
- ctx.scene = scene_;
- ctx.object = object;
- LISTBASE_FOREACH (ShaderFxData *, fx, &object->shader_fx) {
- const ShaderFxTypeInfo *fxi = BKE_shaderfxType_getInfo((ShaderFxType)fx->type);
- if (fxi->updateDepsgraph) {
- DepsNodeHandle handle = create_node_handle(obdata_ubereval_key);
- ctx.node = reinterpret_cast< ::DepsNodeHandle* >(&handle);
- fxi->updateDepsgraph(fx, &ctx);
- }
- if (BKE_object_shaderfx_use_time(object, fx)) {
- TimeSourceKey time_src_key;
- add_relation(time_src_key, obdata_ubereval_key, "Time Source");
- }
- }
- }
- /* Materials. */
- if (object->totcol) {
- for (int a = 1; a <= object->totcol; a++) {
- Material *ma = give_current_material(object, a);
- if (ma != NULL) {
- build_material(ma);
-
- if (object->type == OB_MESH) {
- OperationKey material_key(&ma->id,
- NodeType::SHADING,
- OperationCode::MATERIAL_UPDATE);
- OperationKey shading_key(&object->id,
- NodeType::SHADING,
- OperationCode::SHADING);
- add_relation(material_key, shading_key, "Material Update");
- }
- }
- }
- }
- /* Geometry collision. */
- if (ELEM(object->type, OB_MESH, OB_CURVE, OB_LATTICE)) {
- // add geometry collider relations
- }
- /* Make sure uber update is the last in the dependencies. */
- if (object->type != OB_ARMATURE) {
- /* Armatures does no longer require uber node. */
- OperationKey obdata_ubereval_key(&object->id,
- NodeType::GEOMETRY,
- OperationCode::GEOMETRY_EVAL);
- add_relation(geom_init_key,
- obdata_ubereval_key,
- "Object Geometry UberEval");
- if (object->totcol != 0 && object->type == OB_MESH) {
- ComponentKey object_shading_key(&object->id, NodeType::SHADING);
- Relation *rel = add_relation(obdata_ubereval_key,
- object_shading_key,
- "Object Geometry batch Update");
- rel->flag |= RELATION_FLAG_NO_FLUSH;
- }
- }
- if (object->type == OB_MBALL) {
- Object *mom = BKE_mball_basis_find(scene_, object);
- ComponentKey mom_geom_key(&mom->id, NodeType::GEOMETRY);
- /* motherball - mom depends on children! */
- if (mom == object) {
- ComponentKey mom_transform_key(&mom->id,
- NodeType::TRANSFORM);
- add_relation(mom_transform_key,
- mom_geom_key,
- "Metaball Motherball Transform -> Geometry");
- }
- else {
- ComponentKey transform_key(&object->id, NodeType::TRANSFORM);
- add_relation(geom_key, mom_geom_key, "Metaball Motherball");
- add_relation(transform_key, mom_geom_key, "Metaball Motherball");
- }
- }
- /* NOTE: This is compatibility code to support particle systems
- *
- * for viewport being properly rendered in final render mode.
- * This relation is similar to what dag_object_time_update_flags()
- * was doing for mesh objects with particle system.
- *
- * Ideally we need to get rid of this relation. */
- if (object_particles_depends_on_time(object)) {
- TimeSourceKey time_key;
- OperationKey obdata_ubereval_key(&object->id,
- NodeType::GEOMETRY,
- OperationCode::GEOMETRY_EVAL);
- add_relation(time_key, obdata_ubereval_key, "Legacy particle time");
- }
- /* Object data datablock. */
- build_object_data_geometry_datablock((ID *)object->data);
- Key *key = BKE_key_from_object(object);
- if (key != NULL) {
- if (key->adt != NULL) {
- if (key->adt->action || key->adt->nla_tracks.first) {
- ComponentKey obdata_key((ID *)object->data,
- NodeType::GEOMETRY);
- ComponentKey adt_key(&key->id, NodeType::ANIMATION);
- add_relation(adt_key, obdata_key, "Animation");
- }
- }
- }
- /* Syncronization back to original object. */
- ComponentKey final_geometry_jey(&object->id, NodeType::GEOMETRY);
- OperationKey synchronize_key(&object->id,
- NodeType::SYNCHRONIZATION,
- OperationCode::SYNCHRONIZE_TO_ORIGINAL);
- add_relation(
- final_geometry_jey, synchronize_key, "Synchronize to Original");
+ ID *obdata = (ID *)object->data;
+ /* Init operation of object-level geometry evaluation. */
+ OperationKey geom_init_key(&object->id, NodeType::GEOMETRY, OperationCode::GEOMETRY_EVAL_INIT);
+ /* Get nodes for result of obdata's evaluation, and geometry evaluation
+ * on object. */
+ ComponentKey obdata_geom_key(obdata, NodeType::GEOMETRY);
+ ComponentKey geom_key(&object->id, NodeType::GEOMETRY);
+ /* Link components to each other. */
+ add_relation(obdata_geom_key, geom_key, "Object Geometry Base Data");
+ OperationKey obdata_ubereval_key(&object->id, NodeType::GEOMETRY, OperationCode::GEOMETRY_EVAL);
+ /* Special case: modifiers evaluation queries scene for various things like
+ * data mask to be used. We add relation here to ensure object is never
+ * evaluated prior to Scene's CoW is ready. */
+ OperationKey scene_key(&scene_->id, NodeType::LAYER_COLLECTIONS, OperationCode::VIEW_LAYER_EVAL);
+ Relation *rel = add_relation(scene_key, obdata_ubereval_key, "CoW Relation");
+ rel->flag |= RELATION_FLAG_NO_FLUSH;
+ /* Modifiers */
+ if (object->modifiers.first != NULL) {
+ ModifierUpdateDepsgraphContext ctx = {};
+ ctx.scene = scene_;
+ ctx.object = object;
+ LISTBASE_FOREACH (ModifierData *, md, &object->modifiers) {
+ const ModifierTypeInfo *mti = modifierType_getInfo((ModifierType)md->type);
+ if (mti->updateDepsgraph) {
+ DepsNodeHandle handle = create_node_handle(obdata_ubereval_key);
+ ctx.node = reinterpret_cast<::DepsNodeHandle *>(&handle);
+ mti->updateDepsgraph(md, &ctx);
+ }
+ if (BKE_object_modifier_use_time(object, md)) {
+ TimeSourceKey time_src_key;
+ add_relation(time_src_key, obdata_ubereval_key, "Time Source");
+ }
+ }
+ }
+ /* Grease Pencil Modifiers. */
+ if (object->greasepencil_modifiers.first != NULL) {
+ ModifierUpdateDepsgraphContext ctx = {};
+ ctx.scene = scene_;
+ ctx.object = object;
+ LISTBASE_FOREACH (GpencilModifierData *, md, &object->greasepencil_modifiers) {
+ const GpencilModifierTypeInfo *mti = BKE_gpencil_modifierType_getInfo(
+ (GpencilModifierType)md->type);
+ if (mti->updateDepsgraph) {
+ DepsNodeHandle handle = create_node_handle(obdata_ubereval_key);
+ ctx.node = reinterpret_cast<::DepsNodeHandle *>(&handle);
+ mti->updateDepsgraph(md, &ctx);
+ }
+ if (BKE_object_modifier_gpencil_use_time(object, md)) {
+ TimeSourceKey time_src_key;
+ add_relation(time_src_key, obdata_ubereval_key, "Time Source");
+ }
+ }
+ }
+ /* Shader FX. */
+ if (object->shader_fx.first != NULL) {
+ ModifierUpdateDepsgraphContext ctx = {};
+ ctx.scene = scene_;
+ ctx.object = object;
+ LISTBASE_FOREACH (ShaderFxData *, fx, &object->shader_fx) {
+ const ShaderFxTypeInfo *fxi = BKE_shaderfxType_getInfo((ShaderFxType)fx->type);
+ if (fxi->updateDepsgraph) {
+ DepsNodeHandle handle = create_node_handle(obdata_ubereval_key);
+ ctx.node = reinterpret_cast<::DepsNodeHandle *>(&handle);
+ fxi->updateDepsgraph(fx, &ctx);
+ }
+ if (BKE_object_shaderfx_use_time(object, fx)) {
+ TimeSourceKey time_src_key;
+ add_relation(time_src_key, obdata_ubereval_key, "Time Source");
+ }
+ }
+ }
+ /* Materials. */
+ if (object->totcol) {
+ for (int a = 1; a <= object->totcol; a++) {
+ Material *ma = give_current_material(object, a);
+ if (ma != NULL) {
+ build_material(ma);
+
+ if (object->type == OB_MESH) {
+ OperationKey material_key(&ma->id, NodeType::SHADING, OperationCode::MATERIAL_UPDATE);
+ OperationKey shading_key(&object->id, NodeType::SHADING, OperationCode::SHADING);
+ add_relation(material_key, shading_key, "Material Update");
+ }
+ }
+ }
+ }
+ /* Geometry collision. */
+ if (ELEM(object->type, OB_MESH, OB_CURVE, OB_LATTICE)) {
+ // add geometry collider relations
+ }
+ /* Make sure uber update is the last in the dependencies. */
+ if (object->type != OB_ARMATURE) {
+ /* Armatures does no longer require uber node. */
+ OperationKey obdata_ubereval_key(
+ &object->id, NodeType::GEOMETRY, OperationCode::GEOMETRY_EVAL);
+ add_relation(geom_init_key, obdata_ubereval_key, "Object Geometry UberEval");
+ if (object->totcol != 0 && object->type == OB_MESH) {
+ ComponentKey object_shading_key(&object->id, NodeType::SHADING);
+ Relation *rel = add_relation(
+ obdata_ubereval_key, object_shading_key, "Object Geometry batch Update");
+ rel->flag |= RELATION_FLAG_NO_FLUSH;
+ }
+ }
+ if (object->type == OB_MBALL) {
+ Object *mom = BKE_mball_basis_find(scene_, object);
+ ComponentKey mom_geom_key(&mom->id, NodeType::GEOMETRY);
+ /* motherball - mom depends on children! */
+ if (mom == object) {
+ ComponentKey mom_transform_key(&mom->id, NodeType::TRANSFORM);
+ add_relation(mom_transform_key, mom_geom_key, "Metaball Motherball Transform -> Geometry");
+ }
+ else {
+ ComponentKey transform_key(&object->id, NodeType::TRANSFORM);
+ add_relation(geom_key, mom_geom_key, "Metaball Motherball");
+ add_relation(transform_key, mom_geom_key, "Metaball Motherball");
+ }
+ }
+ /* NOTE: This is compatibility code to support particle systems
+ *
+ * for viewport being properly rendered in final render mode.
+ * This relation is similar to what dag_object_time_update_flags()
+ * was doing for mesh objects with particle system.
+ *
+ * Ideally we need to get rid of this relation. */
+ if (object_particles_depends_on_time(object)) {
+ TimeSourceKey time_key;
+ OperationKey obdata_ubereval_key(
+ &object->id, NodeType::GEOMETRY, OperationCode::GEOMETRY_EVAL);
+ add_relation(time_key, obdata_ubereval_key, "Legacy particle time");
+ }
+ /* Object data datablock. */
+ build_object_data_geometry_datablock((ID *)object->data);
+ Key *key = BKE_key_from_object(object);
+ if (key != NULL) {
+ if (key->adt != NULL) {
+ if (key->adt->action || key->adt->nla_tracks.first) {
+ ComponentKey obdata_key((ID *)object->data, NodeType::GEOMETRY);
+ ComponentKey adt_key(&key->id, NodeType::ANIMATION);
+ add_relation(adt_key, obdata_key, "Animation");
+ }
+ }
+ }
+ /* Syncronization back to original object. */
+ ComponentKey final_geometry_jey(&object->id, NodeType::GEOMETRY);
+ OperationKey synchronize_key(
+ &object->id, NodeType::SYNCHRONIZATION, OperationCode::SYNCHRONIZE_TO_ORIGINAL);
+ add_relation(final_geometry_jey, synchronize_key, "Synchronize to Original");
}
void DepsgraphRelationBuilder::build_object_data_geometry_datablock(ID *obdata)
{
- if (built_map_.checkIsBuiltAndTag(obdata)) {
- return;
- }
- /* Animation. */
- build_animdata(obdata);
- build_parameters(obdata);
- /* ShapeKeys. */
- Key *key = BKE_key_from_id(obdata);
- if (key != NULL) {
- build_shapekeys(key);
- }
- /* Link object data evaluation node to exit operation. */
- OperationKey obdata_geom_eval_key(
- obdata, NodeType::GEOMETRY, OperationCode::GEOMETRY_EVAL);
- OperationKey obdata_geom_done_key(obdata,
- NodeType::GEOMETRY,
- OperationCode::GEOMETRY_EVAL_DONE);
- add_relation(obdata_geom_eval_key,
- obdata_geom_done_key,
- "ObData Geom Eval Done");
- /* Type-specific links. */
- const ID_Type id_type = GS(obdata->name);
- switch (id_type) {
- case ID_ME:
- break;
- case ID_MB:
- break;
- case ID_CU:
- {
- Curve *cu = (Curve *)obdata;
- if (cu->bevobj != NULL) {
- ComponentKey bevob_geom_key(
- &cu->bevobj->id,
- NodeType::GEOMETRY);
- add_relation(
- bevob_geom_key,
- obdata_geom_eval_key,
- "Curve Bevel Geometry");
- ComponentKey bevob_key(
- &cu->bevobj->id,
- NodeType::TRANSFORM);
- add_relation(
- bevob_key,
- obdata_geom_eval_key,
- "Curve Bevel Transform");
- build_object(NULL, cu->bevobj);
- }
- if (cu->taperobj != NULL) {
- ComponentKey taperob_key(
- &cu->taperobj->id,
- NodeType::GEOMETRY);
- add_relation(taperob_key, obdata_geom_eval_key, "Curve Taper");
- build_object(NULL, cu->taperobj);
- }
- if (cu->textoncurve != NULL) {
- ComponentKey textoncurve_key(
- &cu->textoncurve->id,
- NodeType::GEOMETRY);
- add_relation(
- textoncurve_key,
- obdata_geom_eval_key,
- "Text on Curve");
- build_object(NULL, cu->textoncurve);
- }
- break;
- }
- case ID_LT:
- break;
- case ID_GD: /* Grease Pencil */
- {
- bGPdata *gpd = (bGPdata *)obdata;
-
- /* Geometry cache needs to be recalculated on frame change
- * (e.g. to fix crashes after scrubbing the timeline when
- * onion skinning is enabled, since the ghosts need to be
- * re-added to the cache once scrubbing ends). */
- TimeSourceKey time_key;
- ComponentKey geometry_key(obdata, NodeType::GEOMETRY);
- add_relation(time_key,
- geometry_key,
- "GP Frame Change");
-
- /* Geometry cache also needs to be recalculated when Material
- * settings change (e.g. when fill.opacity changes on/off,
- * we need to rebuild the bGPDstroke->triangles caches). */
- for (int i = 0; i < gpd->totcol; i++) {
- Material *ma = gpd->mat[i];
- if ((ma != NULL) && (ma->gp_style != NULL)) {
- OperationKey material_key(&ma->id,
- NodeType::SHADING,
- OperationCode::MATERIAL_UPDATE);
- add_relation(material_key,
- geometry_key,
- "Material -> GP Data");
- }
- }
- break;
- }
- default:
- BLI_assert(!"Should not happen");
- break;
- }
+ if (built_map_.checkIsBuiltAndTag(obdata)) {
+ return;
+ }
+ /* Animation. */
+ build_animdata(obdata);
+ build_parameters(obdata);
+ /* ShapeKeys. */
+ Key *key = BKE_key_from_id(obdata);
+ if (key != NULL) {
+ build_shapekeys(key);
+ }
+ /* Link object data evaluation node to exit operation. */
+ OperationKey obdata_geom_eval_key(obdata, NodeType::GEOMETRY, OperationCode::GEOMETRY_EVAL);
+ OperationKey obdata_geom_done_key(obdata, NodeType::GEOMETRY, OperationCode::GEOMETRY_EVAL_DONE);
+ add_relation(obdata_geom_eval_key, obdata_geom_done_key, "ObData Geom Eval Done");
+ /* Type-specific links. */
+ const ID_Type id_type = GS(obdata->name);
+ switch (id_type) {
+ case ID_ME:
+ break;
+ case ID_MB:
+ break;
+ case ID_CU: {
+ Curve *cu = (Curve *)obdata;
+ if (cu->bevobj != NULL) {
+ ComponentKey bevob_geom_key(&cu->bevobj->id, NodeType::GEOMETRY);
+ add_relation(bevob_geom_key, obdata_geom_eval_key, "Curve Bevel Geometry");
+ ComponentKey bevob_key(&cu->bevobj->id, NodeType::TRANSFORM);
+ add_relation(bevob_key, obdata_geom_eval_key, "Curve Bevel Transform");
+ build_object(NULL, cu->bevobj);
+ }
+ if (cu->taperobj != NULL) {
+ ComponentKey taperob_key(&cu->taperobj->id, NodeType::GEOMETRY);
+ add_relation(taperob_key, obdata_geom_eval_key, "Curve Taper");
+ build_object(NULL, cu->taperobj);
+ }
+ if (cu->textoncurve != NULL) {
+ ComponentKey textoncurve_key(&cu->textoncurve->id, NodeType::GEOMETRY);
+ add_relation(textoncurve_key, obdata_geom_eval_key, "Text on Curve");
+ build_object(NULL, cu->textoncurve);
+ }
+ break;
+ }
+ case ID_LT:
+ break;
+ case ID_GD: /* Grease Pencil */
+ {
+ bGPdata *gpd = (bGPdata *)obdata;
+
+ /* Geometry cache needs to be recalculated on frame change
+ * (e.g. to fix crashes after scrubbing the timeline when
+ * onion skinning is enabled, since the ghosts need to be
+ * re-added to the cache once scrubbing ends). */
+ TimeSourceKey time_key;
+ ComponentKey geometry_key(obdata, NodeType::GEOMETRY);
+ add_relation(time_key, geometry_key, "GP Frame Change");
+
+ /* Geometry cache also needs to be recalculated when Material
+ * settings change (e.g. when fill.opacity changes on/off,
+ * we need to rebuild the bGPDstroke->triangles caches). */
+ for (int i = 0; i < gpd->totcol; i++) {
+ Material *ma = gpd->mat[i];
+ if ((ma != NULL) && (ma->gp_style != NULL)) {
+ OperationKey material_key(&ma->id, NodeType::SHADING, OperationCode::MATERIAL_UPDATE);
+ add_relation(material_key, geometry_key, "Material -> GP Data");
+ }
+ }
+ break;
+ }
+ default:
+ BLI_assert(!"Should not happen");
+ break;
+ }
}
void DepsgraphRelationBuilder::build_armature(bArmature *armature)
{
- if (built_map_.checkIsBuiltAndTag(armature)) {
- return;
- }
- build_animdata(&armature->id);
- build_parameters(&armature->id);
+ if (built_map_.checkIsBuiltAndTag(armature)) {
+ return;
+ }
+ build_animdata(&armature->id);
+ build_parameters(&armature->id);
}
void DepsgraphRelationBuilder::build_camera(Camera *camera)
{
- if (built_map_.checkIsBuiltAndTag(camera)) {
- return;
- }
- build_parameters(&camera->id);
- if (camera->dof_ob != NULL) {
- ComponentKey camera_parameters_key(&camera->id, NodeType::PARAMETERS);
- ComponentKey dof_ob_key(&camera->dof_ob->id, NodeType::TRANSFORM);
- add_relation(dof_ob_key, camera_parameters_key, "Camera DOF");
- }
+ if (built_map_.checkIsBuiltAndTag(camera)) {
+ return;
+ }
+ build_parameters(&camera->id);
+ if (camera->dof_ob != NULL) {
+ ComponentKey camera_parameters_key(&camera->id, NodeType::PARAMETERS);
+ ComponentKey dof_ob_key(&camera->dof_ob->id, NodeType::TRANSFORM);
+ add_relation(dof_ob_key, camera_parameters_key, "Camera DOF");
+ }
}
/* Lights */
void DepsgraphRelationBuilder::build_light(Light *lamp)
{
- if (built_map_.checkIsBuiltAndTag(lamp)) {
- return;
- }
- build_parameters(&lamp->id);
- /* light's nodetree */
- if (lamp->nodetree != NULL) {
- build_nodetree(lamp->nodetree);
- ComponentKey lamp_parameters_key(&lamp->id, NodeType::PARAMETERS);
- ComponentKey nodetree_key(&lamp->nodetree->id, NodeType::SHADING);
- add_relation(nodetree_key, lamp_parameters_key, "NTree->Light Parameters");
- build_nested_nodetree(&lamp->id, lamp->nodetree);
- }
+ if (built_map_.checkIsBuiltAndTag(lamp)) {
+ return;
+ }
+ build_parameters(&lamp->id);
+ /* light's nodetree */
+ if (lamp->nodetree != NULL) {
+ build_nodetree(lamp->nodetree);
+ ComponentKey lamp_parameters_key(&lamp->id, NodeType::PARAMETERS);
+ ComponentKey nodetree_key(&lamp->nodetree->id, NodeType::SHADING);
+ add_relation(nodetree_key, lamp_parameters_key, "NTree->Light Parameters");
+ build_nested_nodetree(&lamp->id, lamp->nodetree);
+ }
}
void DepsgraphRelationBuilder::build_nodetree(bNodeTree *ntree)
{
- if (ntree == NULL) {
- return;
- }
- if (built_map_.checkIsBuiltAndTag(ntree)) {
- return;
- }
- build_animdata(&ntree->id);
- build_parameters(&ntree->id);
- ComponentKey shading_key(&ntree->id, NodeType::SHADING);
- /* nodetree's nodes... */
- LISTBASE_FOREACH (bNode *, bnode, &ntree->nodes) {
- ID *id = bnode->id;
- if (id == NULL) {
- continue;
- }
- ID_Type id_type = GS(id->name);
- if (id_type == ID_MA) {
- build_material((Material *)bnode->id);
- }
- else if (id_type == ID_TE) {
- build_texture((Tex *)bnode->id);
- }
- else if (id_type == ID_IM) {
- build_image((Image *)bnode->id);
- }
- else if (id_type == ID_OB) {
- build_object(NULL, (Object *)id);
- }
- else if (id_type == ID_SCE) {
- /* Scenes are used by compositor trees, and handled by render
- * pipeline. No need to build dependencies for them here. */
- }
- else if (id_type == ID_TXT) {
- /* Ignore script nodes. */
- }
- else if (id_type == ID_MSK) {
- build_mask((Mask *)id);
- }
- else if (id_type == ID_MC) {
- build_movieclip((MovieClip *)id);
- }
- else if (ELEM(bnode->type, NODE_GROUP, NODE_CUSTOM_GROUP)) {
- bNodeTree *group_ntree = (bNodeTree *)id;
- build_nodetree(group_ntree);
- ComponentKey group_shading_key(&group_ntree->id,
- NodeType::SHADING);
- add_relation(group_shading_key, shading_key, "Group Node");
- }
- else {
- BLI_assert(!"Unknown ID type used for node");
- }
- }
-
- OperationKey shading_update_key(&ntree->id,
- NodeType::SHADING,
- OperationCode::MATERIAL_UPDATE);
- OperationKey shading_parameters_key(&ntree->id,
- NodeType::SHADING_PARAMETERS,
- OperationCode::MATERIAL_UPDATE);
- add_relation(shading_parameters_key, shading_update_key, "NTree Shading Parameters");
-
- if (check_id_has_anim_component(&ntree->id)) {
- ComponentKey animation_key(&ntree->id, NodeType::ANIMATION);
- add_relation(animation_key, shading_parameters_key, "NTree Shading Parameters");
- }
- ComponentKey parameters_key(&ntree->id, NodeType::PARAMETERS);
- add_relation(parameters_key, shading_parameters_key, "NTree Shading Parameters");
+ if (ntree == NULL) {
+ return;
+ }
+ if (built_map_.checkIsBuiltAndTag(ntree)) {
+ return;
+ }
+ build_animdata(&ntree->id);
+ build_parameters(&ntree->id);
+ ComponentKey shading_key(&ntree->id, NodeType::SHADING);
+ /* nodetree's nodes... */
+ LISTBASE_FOREACH (bNode *, bnode, &ntree->nodes) {
+ ID *id = bnode->id;
+ if (id == NULL) {
+ continue;
+ }
+ ID_Type id_type = GS(id->name);
+ if (id_type == ID_MA) {
+ build_material((Material *)bnode->id);
+ }
+ else if (id_type == ID_TE) {
+ build_texture((Tex *)bnode->id);
+ }
+ else if (id_type == ID_IM) {
+ build_image((Image *)bnode->id);
+ }
+ else if (id_type == ID_OB) {
+ build_object(NULL, (Object *)id);
+ }
+ else if (id_type == ID_SCE) {
+ /* Scenes are used by compositor trees, and handled by render
+ * pipeline. No need to build dependencies for them here. */
+ }
+ else if (id_type == ID_TXT) {
+ /* Ignore script nodes. */
+ }
+ else if (id_type == ID_MSK) {
+ build_mask((Mask *)id);
+ }
+ else if (id_type == ID_MC) {
+ build_movieclip((MovieClip *)id);
+ }
+ else if (ELEM(bnode->type, NODE_GROUP, NODE_CUSTOM_GROUP)) {
+ bNodeTree *group_ntree = (bNodeTree *)id;
+ build_nodetree(group_ntree);
+ ComponentKey group_shading_key(&group_ntree->id, NodeType::SHADING);
+ add_relation(group_shading_key, shading_key, "Group Node");
+ }
+ else {
+ BLI_assert(!"Unknown ID type used for node");
+ }
+ }
+
+ OperationKey shading_update_key(&ntree->id, NodeType::SHADING, OperationCode::MATERIAL_UPDATE);
+ OperationKey shading_parameters_key(
+ &ntree->id, NodeType::SHADING_PARAMETERS, OperationCode::MATERIAL_UPDATE);
+ add_relation(shading_parameters_key, shading_update_key, "NTree Shading Parameters");
+
+ if (check_id_has_anim_component(&ntree->id)) {
+ ComponentKey animation_key(&ntree->id, NodeType::ANIMATION);
+ add_relation(animation_key, shading_parameters_key, "NTree Shading Parameters");
+ }
+ ComponentKey parameters_key(&ntree->id, NodeType::PARAMETERS);
+ add_relation(parameters_key, shading_parameters_key, "NTree Shading Parameters");
}
/* Recursively build graph for material */
void DepsgraphRelationBuilder::build_material(Material *material)
{
- if (built_map_.checkIsBuiltAndTag(material)) {
- return;
- }
- /* animation */
- build_animdata(&material->id);
- build_parameters(&material->id);
- /* material's nodetree */
- if (material->nodetree != NULL) {
- build_nodetree(material->nodetree);
- OperationKey ntree_key(&material->nodetree->id,
- NodeType::SHADING,
- OperationCode::MATERIAL_UPDATE);
- OperationKey material_key(&material->id,
- NodeType::SHADING,
- OperationCode::MATERIAL_UPDATE);
- add_relation(ntree_key, material_key, "Material's NTree");
- build_nested_nodetree(&material->id, material->nodetree);
- }
+ if (built_map_.checkIsBuiltAndTag(material)) {
+ return;
+ }
+ /* animation */
+ build_animdata(&material->id);
+ build_parameters(&material->id);
+ /* material's nodetree */
+ if (material->nodetree != NULL) {
+ build_nodetree(material->nodetree);
+ OperationKey ntree_key(
+ &material->nodetree->id, NodeType::SHADING, OperationCode::MATERIAL_UPDATE);
+ OperationKey material_key(&material->id, NodeType::SHADING, OperationCode::MATERIAL_UPDATE);
+ add_relation(ntree_key, material_key, "Material's NTree");
+ build_nested_nodetree(&material->id, material->nodetree);
+ }
}
/* Recursively build graph for texture */
void DepsgraphRelationBuilder::build_texture(Tex *texture)
{
- if (built_map_.checkIsBuiltAndTag(texture)) {
- return;
- }
- /* texture itself */
- build_animdata(&texture->id);
- build_parameters(&texture->id);
- /* texture's nodetree */
- build_nodetree(texture->nodetree);
- /* Special cases for different IDs which texture uses. */
- if (texture->type == TEX_IMAGE) {
- if (texture->ima != NULL) {
- build_image(texture->ima);
- }
- }
- build_nested_nodetree(&texture->id, texture->nodetree);
- if (check_id_has_anim_component(&texture->id)) {
- ComponentKey animation_key(&texture->id, NodeType::ANIMATION);
- ComponentKey datablock_key(&texture->id,
- NodeType::GENERIC_DATABLOCK);
- add_relation(animation_key, datablock_key, "Datablock Animation");
- }
+ if (built_map_.checkIsBuiltAndTag(texture)) {
+ return;
+ }
+ /* texture itself */
+ build_animdata(&texture->id);
+ build_parameters(&texture->id);
+ /* texture's nodetree */
+ build_nodetree(texture->nodetree);
+ /* Special cases for different IDs which texture uses. */
+ if (texture->type == TEX_IMAGE) {
+ if (texture->ima != NULL) {
+ build_image(texture->ima);
+ }
+ }
+ build_nested_nodetree(&texture->id, texture->nodetree);
+ if (check_id_has_anim_component(&texture->id)) {
+ ComponentKey animation_key(&texture->id, NodeType::ANIMATION);
+ ComponentKey datablock_key(&texture->id, NodeType::GENERIC_DATABLOCK);
+ add_relation(animation_key, datablock_key, "Datablock Animation");
+ }
}
void DepsgraphRelationBuilder::build_image(Image *image)
{
- if (built_map_.checkIsBuiltAndTag(image)) {
- return;
- }
- build_parameters(&image->id);
+ if (built_map_.checkIsBuiltAndTag(image)) {
+ return;
+ }
+ build_parameters(&image->id);
}
void DepsgraphRelationBuilder::build_compositor(Scene *scene)
{
- /* For now, just a plain wrapper? */
- build_nodetree(scene->nodetree);
+ /* For now, just a plain wrapper? */
+ build_nodetree(scene->nodetree);
}
void DepsgraphRelationBuilder::build_gpencil(bGPdata *gpd)
{
- if (built_map_.checkIsBuiltAndTag(gpd)) {
- return;
- }
- /* animation */
- build_animdata(&gpd->id);
- build_parameters(&gpd->id);
+ if (built_map_.checkIsBuiltAndTag(gpd)) {
+ return;
+ }
+ /* animation */
+ build_animdata(&gpd->id);
+ build_parameters(&gpd->id);
- // TODO: parent object (when that feature is implemented)
+ // TODO: parent object (when that feature is implemented)
}
void DepsgraphRelationBuilder::build_cachefile(CacheFile *cache_file)
{
- if (built_map_.checkIsBuiltAndTag(cache_file)) {
- return;
- }
- /* Animation. */
- build_animdata(&cache_file->id);
- build_parameters(&cache_file->id);
- if (check_id_has_anim_component(&cache_file->id)) {
- ComponentKey animation_key(&cache_file->id, NodeType::ANIMATION);
- ComponentKey datablock_key(&cache_file->id,
- NodeType::CACHE);
- add_relation(animation_key, datablock_key, "Datablock Animation");
- }
+ if (built_map_.checkIsBuiltAndTag(cache_file)) {
+ return;
+ }
+ /* Animation. */
+ build_animdata(&cache_file->id);
+ build_parameters(&cache_file->id);
+ if (check_id_has_anim_component(&cache_file->id)) {
+ ComponentKey animation_key(&cache_file->id, NodeType::ANIMATION);
+ ComponentKey datablock_key(&cache_file->id, NodeType::CACHE);
+ add_relation(animation_key, datablock_key, "Datablock Animation");
+ }
}
void DepsgraphRelationBuilder::build_mask(Mask *mask)
{
- if (built_map_.checkIsBuiltAndTag(mask)) {
- return;
- }
- ID *mask_id = &mask->id;
- /* F-Curve animation. */
- build_animdata(mask_id);
- build_parameters(mask_id);
- /* Own mask animation. */
- OperationKey mask_animation_key(mask_id,
- NodeType::ANIMATION,
- OperationCode::MASK_ANIMATION);
- TimeSourceKey time_src_key;
- add_relation(time_src_key, mask_animation_key, "TimeSrc -> Mask Animation");
- /* Final mask evaluation. */
- ComponentKey parameters_key(mask_id, NodeType::PARAMETERS);
- add_relation(mask_animation_key, parameters_key, "Mask Animation -> Mask Eval");
+ if (built_map_.checkIsBuiltAndTag(mask)) {
+ return;
+ }
+ ID *mask_id = &mask->id;
+ /* F-Curve animation. */
+ build_animdata(mask_id);
+ build_parameters(mask_id);
+ /* Own mask animation. */
+ OperationKey mask_animation_key(mask_id, NodeType::ANIMATION, OperationCode::MASK_ANIMATION);
+ TimeSourceKey time_src_key;
+ add_relation(time_src_key, mask_animation_key, "TimeSrc -> Mask Animation");
+ /* Final mask evaluation. */
+ ComponentKey parameters_key(mask_id, NodeType::PARAMETERS);
+ add_relation(mask_animation_key, parameters_key, "Mask Animation -> Mask Eval");
}
void DepsgraphRelationBuilder::build_movieclip(MovieClip *clip)
{
- if (built_map_.checkIsBuiltAndTag(clip)) {
- return;
- }
- /* Animation. */
- build_animdata(&clip->id);
- build_parameters(&clip->id);
+ if (built_map_.checkIsBuiltAndTag(clip)) {
+ return;
+ }
+ /* Animation. */
+ build_animdata(&clip->id);
+ build_parameters(&clip->id);
}
void DepsgraphRelationBuilder::build_lightprobe(LightProbe *probe)
{
- if (built_map_.checkIsBuiltAndTag(probe)) {
- return;
- }
- build_animdata(&probe->id);
- build_parameters(&probe->id);
+ if (built_map_.checkIsBuiltAndTag(probe)) {
+ return;
+ }
+ build_animdata(&probe->id);
+ build_parameters(&probe->id);
}
void DepsgraphRelationBuilder::build_speaker(Speaker *speaker)
{
- if (built_map_.checkIsBuiltAndTag(speaker)) {
- return;
- }
- build_animdata(&speaker->id);
- build_parameters(&speaker->id);
+ if (built_map_.checkIsBuiltAndTag(speaker)) {
+ return;
+ }
+ build_animdata(&speaker->id);
+ build_parameters(&speaker->id);
}
void DepsgraphRelationBuilder::build_copy_on_write_relations()
{
- for (IDNode *id_node : graph_->id_nodes) {
- build_copy_on_write_relations(id_node);
- }
+ for (IDNode *id_node : graph_->id_nodes) {
+ build_copy_on_write_relations(id_node);
+ }
}
/* Nested datablocks (node trees, shape keys) requires special relation to
@@ -2630,150 +2305,132 @@ void DepsgraphRelationBuilder::build_copy_on_write_relations()
*/
void DepsgraphRelationBuilder::build_nested_datablock(ID *owner, ID *id)
{
- OperationKey owner_copy_on_write_key(owner,
- NodeType::COPY_ON_WRITE,
- OperationCode::COPY_ON_WRITE);
- OperationKey id_copy_on_write_key(id,
- NodeType::COPY_ON_WRITE,
- OperationCode::COPY_ON_WRITE);
- add_relation(id_copy_on_write_key,
- owner_copy_on_write_key,
- "Eval Order");
+ OperationKey owner_copy_on_write_key(
+ owner, NodeType::COPY_ON_WRITE, OperationCode::COPY_ON_WRITE);
+ OperationKey id_copy_on_write_key(id, NodeType::COPY_ON_WRITE, OperationCode::COPY_ON_WRITE);
+ add_relation(id_copy_on_write_key, owner_copy_on_write_key, "Eval Order");
}
-void DepsgraphRelationBuilder::build_nested_nodetree(ID *owner,
- bNodeTree *ntree)
+void DepsgraphRelationBuilder::build_nested_nodetree(ID *owner, bNodeTree *ntree)
{
- if (ntree == NULL) {
- return;
- }
- build_nested_datablock(owner, &ntree->id);
+ if (ntree == NULL) {
+ return;
+ }
+ build_nested_datablock(owner, &ntree->id);
}
void DepsgraphRelationBuilder::build_nested_shapekey(ID *owner, Key *key)
{
- if (key == NULL) {
- return;
- }
- build_nested_datablock(owner, &key->id);
+ if (key == NULL) {
+ return;
+ }
+ build_nested_datablock(owner, &key->id);
}
void DepsgraphRelationBuilder::build_copy_on_write_relations(IDNode *id_node)
{
- ID *id_orig = id_node->id_orig;
- const ID_Type id_type = GS(id_orig->name);
- TimeSourceKey time_source_key;
- OperationKey copy_on_write_key(id_orig,
- NodeType::COPY_ON_WRITE,
- OperationCode::COPY_ON_WRITE);
- /* XXX: This is a quick hack to make Alt-A to work. */
- // add_relation(time_source_key, copy_on_write_key, "Fluxgate capacitor hack");
- /* Resat of code is using rather low level trickery, so need to get some
- * explicit pointers. */
- Node *node_cow = find_node(copy_on_write_key);
- OperationNode *op_cow = node_cow->get_exit_operation();
- /* Plug any other components to this one. */
- GHASH_FOREACH_BEGIN(ComponentNode *, comp_node, id_node->components)
- {
- if (comp_node->type == NodeType::COPY_ON_WRITE) {
- /* Copy-on-write component never depends on itself. */
- continue;
- }
- if (!comp_node->depends_on_cow()) {
- /* Component explicitly requests to not add relation. */
- continue;
- }
- int rel_flag = (RELATION_FLAG_NO_FLUSH | RELATION_FLAG_GODMODE);
- if (id_type == ID_ME && comp_node->type == NodeType::GEOMETRY) {
- rel_flag &= ~RELATION_FLAG_NO_FLUSH;
- }
- /* Notes on exceptions:
- * - Parameters component is where drivers are living. Changing any
- * of the (custom) properties in the original datablock (even the
- * ones which do not imply other component update) need to make
- * sure drivers are properly updated.
- * This way, for example, changing ID property will properly poke
- * all drivers to be updated.
- *
- * - View layers have cached array of bases in them, which is not
- * copied by copy-on-write, and not preserved. PROBABLY it is better
- * to preserve that cache in copy-on-write, but for the time being
- * we allow flush to layer collections component which will ensure
- * that cached array fo bases exists and is up-to-date. */
- if (comp_node->type == NodeType::PARAMETERS ||
- comp_node->type == NodeType::LAYER_COLLECTIONS)
- {
- rel_flag &= ~RELATION_FLAG_NO_FLUSH;
- }
- /* All entry operations of each component should wait for a proper
- * copy of ID. */
- OperationNode *op_entry = comp_node->get_entry_operation();
- if (op_entry != NULL) {
- Relation *rel = graph_->add_new_relation(
- op_cow, op_entry, "CoW Dependency");
- rel->flag |= rel_flag;
- }
- /* All dangling operations should also be executed after copy-on-write. */
- GHASH_FOREACH_BEGIN(OperationNode *, op_node, comp_node->operations_map)
- {
- if (op_node == op_entry) {
- continue;
- }
- if (op_node->inlinks.size() == 0) {
- Relation *rel = graph_->add_new_relation(
- op_cow, op_node, "CoW Dependency");
- rel->flag |= rel_flag;
- }
- else {
- bool has_same_comp_dependency = false;
- for (Relation *rel_current : op_node->inlinks) {
- if (rel_current->from->type != NodeType::OPERATION) {
- continue;
- }
- OperationNode *op_node_from =
- (OperationNode *)rel_current->from;
- if (op_node_from->owner == op_node->owner) {
- has_same_comp_dependency = true;
- break;
- }
- }
- if (!has_same_comp_dependency) {
- Relation *rel = graph_->add_new_relation(
- op_cow, op_node, "CoW Dependency");
- rel->flag |= rel_flag;
- }
- }
- }
- GHASH_FOREACH_END();
- /* NOTE: We currently ignore implicit relations to an external
- * datablocks for copy-on-write operations. This means, for example,
- * copy-on-write component of Object will not wait for copy-on-write
- * component of it's Mesh. This is because pointers are all known
- * already so remapping will happen all correct. And then If some object
- * evaluation step needs geometry, it will have transitive dependency
- * to Mesh copy-on-write already. */
- }
- GHASH_FOREACH_END();
- /* TODO(sergey): This solves crash for now, but causes too many
- * updates potentially. */
- if (GS(id_orig->name) == ID_OB) {
- Object *object = (Object *)id_orig;
- ID *object_data_id = (ID *)object->data;
- if (object_data_id != NULL) {
- if (deg_copy_on_write_is_needed(object_data_id)) {
- OperationKey data_copy_on_write_key(object_data_id,
- NodeType::COPY_ON_WRITE,
- OperationCode::COPY_ON_WRITE);
- add_relation(data_copy_on_write_key,
- copy_on_write_key,
- "Eval Order",
- RELATION_FLAG_GODMODE);
- }
- }
- else {
- BLI_assert(object->type == OB_EMPTY);
- }
- }
+ ID *id_orig = id_node->id_orig;
+ const ID_Type id_type = GS(id_orig->name);
+ TimeSourceKey time_source_key;
+ OperationKey copy_on_write_key(id_orig, NodeType::COPY_ON_WRITE, OperationCode::COPY_ON_WRITE);
+ /* XXX: This is a quick hack to make Alt-A to work. */
+ // add_relation(time_source_key, copy_on_write_key, "Fluxgate capacitor hack");
+ /* Resat of code is using rather low level trickery, so need to get some
+ * explicit pointers. */
+ Node *node_cow = find_node(copy_on_write_key);
+ OperationNode *op_cow = node_cow->get_exit_operation();
+ /* Plug any other components to this one. */
+ GHASH_FOREACH_BEGIN (ComponentNode *, comp_node, id_node->components) {
+ if (comp_node->type == NodeType::COPY_ON_WRITE) {
+ /* Copy-on-write component never depends on itself. */
+ continue;
+ }
+ if (!comp_node->depends_on_cow()) {
+ /* Component explicitly requests to not add relation. */
+ continue;
+ }
+ int rel_flag = (RELATION_FLAG_NO_FLUSH | RELATION_FLAG_GODMODE);
+ if (id_type == ID_ME && comp_node->type == NodeType::GEOMETRY) {
+ rel_flag &= ~RELATION_FLAG_NO_FLUSH;
+ }
+ /* Notes on exceptions:
+ * - Parameters component is where drivers are living. Changing any
+ * of the (custom) properties in the original datablock (even the
+ * ones which do not imply other component update) need to make
+ * sure drivers are properly updated.
+ * This way, for example, changing ID property will properly poke
+ * all drivers to be updated.
+ *
+ * - View layers have cached array of bases in them, which is not
+ * copied by copy-on-write, and not preserved. PROBABLY it is better
+ * to preserve that cache in copy-on-write, but for the time being
+ * we allow flush to layer collections component which will ensure
+ * that cached array fo bases exists and is up-to-date. */
+ if (comp_node->type == NodeType::PARAMETERS ||
+ comp_node->type == NodeType::LAYER_COLLECTIONS) {
+ rel_flag &= ~RELATION_FLAG_NO_FLUSH;
+ }
+ /* All entry operations of each component should wait for a proper
+ * copy of ID. */
+ OperationNode *op_entry = comp_node->get_entry_operation();
+ if (op_entry != NULL) {
+ Relation *rel = graph_->add_new_relation(op_cow, op_entry, "CoW Dependency");
+ rel->flag |= rel_flag;
+ }
+ /* All dangling operations should also be executed after copy-on-write. */
+ GHASH_FOREACH_BEGIN (OperationNode *, op_node, comp_node->operations_map) {
+ if (op_node == op_entry) {
+ continue;
+ }
+ if (op_node->inlinks.size() == 0) {
+ Relation *rel = graph_->add_new_relation(op_cow, op_node, "CoW Dependency");
+ rel->flag |= rel_flag;
+ }
+ else {
+ bool has_same_comp_dependency = false;
+ for (Relation *rel_current : op_node->inlinks) {
+ if (rel_current->from->type != NodeType::OPERATION) {
+ continue;
+ }
+ OperationNode *op_node_from = (OperationNode *)rel_current->from;
+ if (op_node_from->owner == op_node->owner) {
+ has_same_comp_dependency = true;
+ break;
+ }
+ }
+ if (!has_same_comp_dependency) {
+ Relation *rel = graph_->add_new_relation(op_cow, op_node, "CoW Dependency");
+ rel->flag |= rel_flag;
+ }
+ }
+ }
+ GHASH_FOREACH_END();
+ /* NOTE: We currently ignore implicit relations to an external
+ * datablocks for copy-on-write operations. This means, for example,
+ * copy-on-write component of Object will not wait for copy-on-write
+ * component of it's Mesh. This is because pointers are all known
+ * already so remapping will happen all correct. And then If some object
+ * evaluation step needs geometry, it will have transitive dependency
+ * to Mesh copy-on-write already. */
+ }
+ GHASH_FOREACH_END();
+ /* TODO(sergey): This solves crash for now, but causes too many
+ * updates potentially. */
+ if (GS(id_orig->name) == ID_OB) {
+ Object *object = (Object *)id_orig;
+ ID *object_data_id = (ID *)object->data;
+ if (object_data_id != NULL) {
+ if (deg_copy_on_write_is_needed(object_data_id)) {
+ OperationKey data_copy_on_write_key(
+ object_data_id, NodeType::COPY_ON_WRITE, OperationCode::COPY_ON_WRITE);
+ add_relation(
+ data_copy_on_write_key, copy_on_write_key, "Eval Order", RELATION_FLAG_GODMODE);
+ }
+ }
+ else {
+ BLI_assert(object->type == OB_EMPTY);
+ }
+ }
}
/* **** ID traversal callbacks functions **** */
@@ -2783,12 +2440,12 @@ void DepsgraphRelationBuilder::modifier_walk(void *user_data,
struct ID **idpoin,
int /*cb_flag*/)
{
- BuilderWalkUserData *data = (BuilderWalkUserData *)user_data;
- ID *id = *idpoin;
- if (id == NULL) {
- return;
- }
- data->builder->build_id(id);
+ BuilderWalkUserData *data = (BuilderWalkUserData *)user_data;
+ ID *id = *idpoin;
+ if (id == NULL) {
+ return;
+ }
+ data->builder->build_id(id);
}
void DepsgraphRelationBuilder::constraint_walk(bConstraint * /*con*/,
@@ -2796,12 +2453,12 @@ void DepsgraphRelationBuilder::constraint_walk(bConstraint * /*con*/,
bool /*is_reference*/,
void *user_data)
{
- BuilderWalkUserData *data = (BuilderWalkUserData *)user_data;
- ID *id = *idpoin;
- if (id == NULL) {
- return;
- }
- data->builder->build_id(id);
+ BuilderWalkUserData *data = (BuilderWalkUserData *)user_data;
+ ID *id = *idpoin;
+ if (id == NULL) {
+ return;
+ }
+ data->builder->build_id(id);
}
} // namespace DEG