#include "DNA_movieclip_types.h"
#include "DNA_node_types.h"
#include "DNA_particle_types.h"
+#include "DNA_lightprobe_types.h"
#include "DNA_object_types.h"
#include "DNA_rigidbody_types.h"
#include "DNA_scene_types.h"
#include "BKE_particle.h"
#include "BKE_rigidbody.h"
#include "BKE_sound.h"
-#include "BKE_texture.h"
#include "BKE_tracking.h"
#include "BKE_world.h"
#include "intern/nodes/deg_node.h"
#include "intern/nodes/deg_node_component.h"
+#include "intern/nodes/deg_node_id.h"
#include "intern/nodes/deg_node_operation.h"
+#include "intern/nodes/deg_node_time.h"
#include "intern/depsgraph_intern.h"
#include "intern/depsgraph_types.h"
{
BuilderWalkUserData *data = (BuilderWalkUserData *)user_data;
if (*obpoin) {
- data->builder->build_object(*obpoin);
+ data->builder->build_object(NULL, *obpoin);
}
}
if (*idpoin) {
ID *id = *idpoin;
if (GS(id->name) == ID_OB) {
- data->builder->build_object((Object *)id);
+ data->builder->build_object(NULL, (Object *)id);
}
}
}
void DepsgraphRelationBuilder::add_time_relation(TimeSourceDepsNode *timesrc,
DepsNode *node_to,
- const char *description)
+ const char *description,
+ bool check_unique)
{
if (timesrc && node_to) {
- graph_->add_new_relation(timesrc, node_to, description);
+ graph_->add_new_relation(timesrc, node_to, description, check_unique);
}
else {
DEG_DEBUG_PRINTF("add_time_relation(%p = %s, %p = %s, %s) Failed\n",
void DepsgraphRelationBuilder::add_operation_relation(
OperationDepsNode *node_from,
OperationDepsNode *node_to,
- const char *description)
+ const char *description,
+ bool check_unique)
{
if (node_from && node_to) {
- graph_->add_new_relation(node_from, node_to, description);
+ graph_->add_new_relation(node_from, node_to, description, check_unique);
}
else {
DEG_DEBUG_PRINTF("add_operation_relation(%p = %s, %p = %s, %s) Failed\n",
}
}
-void DepsgraphRelationBuilder::add_collision_relations(const OperationKey &key, Scene *scene, Object *object, Group *group, int layer, bool dupli, const char *name)
+void DepsgraphRelationBuilder::add_collision_relations(
+ const OperationKey &key,
+ Scene *scene,
+ Object *object,
+ Group *group,
+ bool dupli,
+ const char *name)
{
unsigned int numcollobj;
- Object **collobjs = get_collisionobjects_ext(scene, object, group, layer, &numcollobj, eModifierType_Collision, dupli);
-
- for (unsigned int i = 0; i < numcollobj; i++)
- {
+ Object **collobjs = get_collisionobjects_ext(scene,
+ object,
+ group,
+ &numcollobj,
+ eModifierType_Collision,
+ dupli);
+ for (unsigned int i = 0; i < numcollobj; i++) {
Object *ob1 = collobjs[i];
ComponentKey trf_key(&ob1->id, DEG_NODE_TYPE_TRANSFORM);
ComponentKey coll_key(&ob1->id, DEG_NODE_TYPE_GEOMETRY);
add_relation(coll_key, key, name);
}
-
- if (collobjs)
+ if (collobjs != NULL) {
MEM_freeN(collobjs);
+ }
}
-void DepsgraphRelationBuilder::add_forcefield_relations(const OperationKey &key, Scene *scene, Object *object, ParticleSystem *psys, EffectorWeights *eff, bool add_absorption, const char *name)
+void DepsgraphRelationBuilder::add_forcefield_relations(
+ const OperationKey &key,
+ Scene *scene,
+ Object *object,
+ ParticleSystem *psys,
+ EffectorWeights *eff,
+ bool add_absorption,
+ const char *name)
{
- ListBase *effectors = pdInitEffectors(scene, object, psys, eff, false);
-
- if (effectors) {
- for (EffectorCache *eff = (EffectorCache *)effectors->first; eff; eff = eff->next) {
+ ListBase *effectors = pdInitEffectors(NULL, scene, object, psys, eff, false);
+ if (effectors != NULL) {
+ LINKLIST_FOREACH(EffectorCache *, eff, effectors) {
if (eff->ob != object) {
ComponentKey eff_key(&eff->ob->id, DEG_NODE_TYPE_TRANSFORM);
add_relation(eff_key, key, name);
}
-
- if (eff->psys) {
+ if (eff->psys != NULL) {
if (eff->ob != object) {
ComponentKey eff_key(&eff->ob->id, DEG_NODE_TYPE_EVAL_PARTICLES);
add_relation(eff_key, key, name);
- /* TODO: remove this when/if EVAL_PARTICLES is sufficient for up to date particles */
+ /* TODO: remove this when/if EVAL_PARTICLES is sufficient
+ * for up to date particles.
+ */
ComponentKey mod_key(&eff->ob->id, DEG_NODE_TYPE_GEOMETRY);
add_relation(mod_key, key, name);
}
else if (eff->psys != psys) {
- OperationKey eff_key(&eff->ob->id, DEG_NODE_TYPE_EVAL_PARTICLES, DEG_OPCODE_PARTICLE_SYSTEM_EVAL, eff->psys->name);
+ OperationKey eff_key(&eff->ob->id,
+ DEG_NODE_TYPE_EVAL_PARTICLES,
+ DEG_OPCODE_PARTICLE_SYSTEM_EVAL,
+ eff->psys->name);
add_relation(eff_key, key, name);
}
}
-
if (eff->pd->forcefield == PFIELD_SMOKEFLOW && eff->pd->f_source) {
- ComponentKey trf_key(&eff->pd->f_source->id, DEG_NODE_TYPE_TRANSFORM);
+ ComponentKey trf_key(&eff->pd->f_source->id,
+ DEG_NODE_TYPE_TRANSFORM);
add_relation(trf_key, key, "Smoke Force Domain");
- ComponentKey eff_key(&eff->pd->f_source->id, DEG_NODE_TYPE_GEOMETRY);
+ ComponentKey eff_key(&eff->pd->f_source->id,
+ DEG_NODE_TYPE_GEOMETRY);
add_relation(eff_key, key, "Smoke Force Domain");
}
-
if (add_absorption && (eff->pd->flag & PFIELD_VISIBILITY)) {
- add_collision_relations(key, scene, object, NULL, eff->ob->lay, true, "Force Absorption");
+ add_collision_relations(key,
+ scene,
+ object,
+ NULL,
+ true,
+ "Force Absorption");
}
}
}
nodetree->id.tag &= ~LIB_TAG_DOIT;
}
}
- FOREACH_NODETREE_END;
+ FOREACH_NODETREE_END
}
void DepsgraphRelationBuilder::build_group(Object *object, Group *group)
OperationKey object_local_transform_key(&object->id,
DEG_NODE_TYPE_TRANSFORM,
DEG_OPCODE_TRANSFORM_LOCAL);
- LINKLIST_FOREACH (GroupObject *, go, &group->gobject) {
- if (!group_done) {
- build_object(go->ob);
+
+ if (!group_done) {
+ LINKLIST_FOREACH(Base *, base, &group->view_layer->object_bases) {
+ build_object(NULL, base->object);
}
- ComponentKey dupli_transform_key(&go->ob->id, DEG_NODE_TYPE_TRANSFORM);
+ group_id->tag |= LIB_TAG_DOIT;
+ }
+
+ LINKLIST_FOREACH (Base *, base, &group->view_layer->object_bases) {
+ ComponentKey dupli_transform_key(&base->object->id, DEG_NODE_TYPE_TRANSFORM);
add_relation(dupli_transform_key, object_local_transform_key, "Dupligroup");
}
- group_id->tag |= LIB_TAG_DOIT;
}
-void DepsgraphRelationBuilder::build_object(Object *object)
+void DepsgraphRelationBuilder::build_object(Base *base, Object *object)
{
if (object->id.tag & LIB_TAG_DOIT) {
+ if (base != NULL) {
+ build_object_flags(base, object);
+ }
return;
}
object->id.tag |= LIB_TAG_DOIT;
OperationKey ob_ubereval_key(&object->id,
DEG_NODE_TYPE_TRANSFORM,
DEG_OPCODE_TRANSFORM_OBJECT_UBEREVAL);
+ /* Various flags, flushing from bases/collections. */
+ build_object_flags(base, object);
/* Parenting. */
if (object->parent != NULL) {
/* Parent relationship. */
}
/* Animation data */
build_animdata(&object->id);
- // XXX: This should be hooked up by the build_animdata code
- if (needs_animdata_node(&object->id)) {
- ComponentKey adt_key(&object->id, DEG_NODE_TYPE_ANIMATION);
- add_relation(adt_key, local_transform_key, "Object Animation");
- }
/* Object data. */
build_object_data(object);
/* Particle systems. */
/* Object that this is a proxy for. */
if (object->proxy != NULL) {
object->proxy->proxy_from = object;
- build_object(object->proxy);
+ build_object(NULL, object->proxy);
/* TODO(sergey): This is an inverted relation, matches old depsgraph
* behavior and need to be investigated if it still need to be inverted.
*/
}
}
+void DepsgraphRelationBuilder::build_object_flags(Base *base, Object *object)
+{
+ if (base == NULL) {
+ return;
+ }
+ OperationKey view_layer_done_key(&scene_->id,
+ DEG_NODE_TYPE_LAYER_COLLECTIONS,
+ DEG_OPCODE_VIEW_LAYER_DONE);
+ OperationKey object_flags_key(&object->id,
+ DEG_NODE_TYPE_LAYER_COLLECTIONS,
+ DEG_OPCODE_OBJECT_BASE_FLAGS);
+ add_relation(view_layer_done_key, object_flags_key, "Base flags flush");
+}
+
void DepsgraphRelationBuilder::build_object_data(Object *object)
{
if (object->data == NULL) {
case OB_CAMERA:
build_camera(object);
break;
+ case OB_LIGHTPROBE:
+ build_lightprobe(object);
+ break;
}
Key *key = BKE_key_from_object(object);
if (key != NULL) {
void DepsgraphRelationBuilder::build_animdata(ID *id)
{
- AnimData *adt = BKE_animdata_from_id(id);
+ /* Animation curves and NLA. */
+ build_animdata_curves(id);
+ /* Drivers. */
+ build_animdata_drivers(id);
+}
- if (adt == NULL)
+void DepsgraphRelationBuilder::build_animdata_curves(ID *id)
+{
+ AnimData *adt = BKE_animdata_from_id(id);
+ if (adt == NULL) {
return;
-
+ }
+ if (adt->action == NULL && adt->nla_tracks.first == NULL) {
+ return;
+ }
+ /* Wire up dependency to time source. */
ComponentKey adt_key(id, DEG_NODE_TYPE_ANIMATION);
+ TimeSourceKey time_src_key;
+ add_relation(time_src_key, adt_key, "TimeSrc -> Animation");
+ /* Build relations from animation operation to properties it changes. */
+ build_animdata_curves_targets(id);
+}
- /* animation */
- if (adt->action || adt->nla_tracks.first) {
- /* wire up dependency to time source */
- TimeSourceKey time_src_key;
- add_relation(time_src_key, adt_key, "TimeSrc -> Animation");
-
- // XXX: Hook up specific update callbacks for special properties which may need it...
-
- // XXX: animdata "hierarchy" - top-level overrides need to go after lower-down
+void DepsgraphRelationBuilder::build_animdata_curves_targets(ID *id)
+{
+ AnimData *adt = BKE_animdata_from_id(id);
+ if (adt == NULL || adt->action == NULL) {
+ return;
+ }
+ /* Get source operation. */
+ ComponentKey adt_key(id, DEG_NODE_TYPE_ANIMATION);
+ DepsNode *node_from = get_node(adt_key);
+ BLI_assert(node_from != NULL);
+ if (node_from == NULL) {
+ return;
+ }
+ OperationDepsNode *operation_from = node_from->get_exit_operation();
+ BLI_assert(operation_from != NULL);
+ /* Iterate over all curves and build relations. */
+ PointerRNA id_ptr;
+ RNA_id_pointer_create(id, &id_ptr);
+ LINKLIST_FOREACH(FCurve *, fcu, &adt->action->curves) {
+ PointerRNA ptr;
+ PropertyRNA *prop;
+ int index;
+ if (!RNA_path_resolve_full(&id_ptr, fcu->rna_path,
+ &ptr, &prop, &index))
+ {
+ continue;
+ }
+ DepsNode *node_to = graph_->find_node_from_pointer(&ptr, prop);
+ if (node_to == NULL) {
+ continue;
+ }
+ OperationDepsNode *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 == DEG_OPCODE_BONE_LOCAL) {
+ OperationKey pose_init_key(id,
+ DEG_NODE_TYPE_EVAL_POSE,
+ DEG_OPCODE_POSE_INIT);
+ add_relation(adt_key, pose_init_key, "Animation -> Prop", true);
+ continue;
+ }
+ graph_->add_new_relation(operation_from, operation_to,
+ "Animation -> Prop",
+ true);
}
+}
- /* drivers */
+void DepsgraphRelationBuilder::build_animdata_drivers(ID *id)
+{
+ AnimData *adt = BKE_animdata_from_id(id);
+ if (adt == NULL) {
+ return;
+ }
+ ComponentKey adt_key(id, DEG_NODE_TYPE_ANIMATION);
LINKLIST_FOREACH (FCurve *, fcu, &adt->drivers) {
OperationKey driver_key(id,
DEG_NODE_TYPE_PARAMETERS,
DEG_OPCODE_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);
-
- /* Create dependency between driver and data affected by it. */
- /* - direct property relationship... */
- //RNAPathKey affected_key(id, fcu->rna_path);
- //add_relation(driver_key, affected_key, "Driver -> Data");
-
/* Driver -> data components (for interleaved evaluation
* bones/constraints/modifiers).
*/
- // XXX: this probably should probably be moved out into a separate function.
- if (strstr(rna_path, "pose.bones[") != NULL) {
- RNAPathKey target_key(id, rna_path);
- add_relation(driver_key, target_key, "Driver -> Target");
+ 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");
}
- else if (GS(id->name) == ID_AR && strstr(rna_path, "bones[")) {
+}
+
+void DepsgraphRelationBuilder::build_driver_data(ID *id, FCurve *fcu)
+{
+ OperationKey driver_key(id,
+ DEG_NODE_TYPE_PARAMETERS,
+ DEG_OPCODE_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);
+ 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.
*/
IDDepsNode *arm_node = graph_->find_id_node(id);
char *bone_name = BLI_str_quoted_substrN(rna_path, "bones[");
-
- if (arm_node && bone_name) {
+ if (arm_node != NULL && bone_name != NULL) {
/* Find objects which use this, and make their eval callbacks
* depend on this.
*/
foreach (DepsRelation *rel, arm_node->outlinks) {
IDDepsNode *to_node = (IDDepsNode *)rel->to;
/* We only care about objects with pose data which use this. */
- if (GS(to_node->id->name) == ID_OB) {
- Object *object = (Object *)to_node->id;
- /* NOTE: object->pose may be NULL. */
- bPoseChannel *pchan = BKE_pose_channel_find_name(
- object->pose, bone_name);
+ 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,
DEG_NODE_TYPE_BONE,
rna_path);
}
}
- else if (GS(id->name) == ID_OB && strstr(rna_path, "modifiers[")) {
- RNAPathKey target_key(id, rna_path);
- add_relation(driver_key, target_key, "Driver -> Target");
- }
- else if (GS(id->name) == ID_KE && strstr(rna_path, "key_blocks[")) {
- RNAPathKey target_key(id, rna_path);
- add_relation(driver_key, target_key, "Driver -> Target");
- }
- else if (strstr(rna_path, "key_blocks[")) {
- RNAPathKey target_key(id, rna_path);
- add_relation(driver_key, target_key, "Driver -> Target");
- }
else {
RNAPathKey target_key(id, rna_path);
add_relation(driver_key, target_key, "Driver -> Target");
}
- /* Ensure that affected prop's update callbacks will be triggered once
- * done.
- */
- /* TODO: Implement this once the functionality to add these links exists
- * RNA.
- */
- /* XXX: the data itself could also set this, if it were to be truly
- * initialised later?
- */
- /* 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_variables(ID *id, FCurve *fcu)
continue;
}
OperationKey variable_key(dtar->id,
- DEG_NODE_TYPE_BONE,
- target_pchan->name,
- DEG_OPCODE_BONE_DONE);
+ DEG_NODE_TYPE_BONE,
+ target_pchan->name,
+ DEG_OPCODE_BONE_DONE);
if (is_same_bone_dependency(variable_key, self_key)) {
continue;
}
if (RNA_pointer_is_null(&variable_key.ptr)) {
continue;
}
- if (is_same_bone_dependency(variable_key, self_key)) {
+ if (is_same_bone_dependency(variable_key, self_key) ||
+ is_same_nodetree_node_dependency(variable_key, self_key) ||
+ is_same_shapekey_dependency(variable_key, self_key))
+ {
continue;
}
- add_relation(variable_key, driver_key, "RNA Bone -> Driver");
+ add_relation(variable_key, driver_key, "RNA Target -> Driver");
}
else {
if (dtar->id == id) {
/* world's nodetree */
if (world->nodetree != NULL) {
build_nodetree(world->nodetree);
- ComponentKey ntree_key(&world->nodetree->id, DEG_NODE_TYPE_PARAMETERS);
- ComponentKey world_key(world_id, DEG_NODE_TYPE_PARAMETERS);
- add_relation(ntree_key, world_key, "NTree->World Parameters");
+ ComponentKey ntree_key(&world->nodetree->id, DEG_NODE_TYPE_SHADING);
+ ComponentKey world_key(world_id, DEG_NODE_TYPE_SHADING);
+ add_relation(ntree_key, world_key, "NTree->World Shading Update");
}
}
/* objects - simulation participants */
if (rbw->group) {
- LINKLIST_FOREACH (GroupObject *, go, &rbw->group->gobject) {
- Object *object = go->ob;
+ LINKLIST_FOREACH (Base *, base, &rbw->group->view_layer->object_bases) {
+ Object *object = base->object;
if (object == NULL || object->type != OB_MESH) {
continue;
}
/* constraints */
if (rbw->constraints) {
- LINKLIST_FOREACH (GroupObject *, go, &rbw->constraints->gobject) {
- Object *object = go->ob;
+ LINKLIST_FOREACH (Base *, base, &rbw->constraints->view_layer->object_bases) {
+ Object *object = base->object;
if (object == NULL || !object->rigidbody_constraint) {
continue;
}
OperationKey eval_init_key(&object->id,
DEG_NODE_TYPE_EVAL_PARTICLES,
DEG_OPCODE_PARTICLE_SYSTEM_EVAL_INIT);
- if (object_particles_depends_on_time(object)) {
- add_relation(time_src_key, eval_init_key, "TimeSrc -> PSys");
- }
/* particle systems */
LINKLIST_FOREACH (ParticleSystem *, psys, &object->particlesystem) {
ParticleSettings *part = psys->part;
- /* particle settings */
- build_animdata(&part->id);
-
- /* this particle system */
- OperationKey psys_key(&object->id, DEG_NODE_TYPE_EVAL_PARTICLES, DEG_OPCODE_PARTICLE_SYSTEM_EVAL, psys->name);
+ /* 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,
+ DEG_NODE_TYPE_EVAL_PARTICLES,
+ DEG_OPCODE_PARTICLE_SYSTEM_EVAL,
+ psys->name);
+
+ /* Update particle system when settings changes. */
+ OperationKey particle_settings_key(&part->id,
+ DEG_NODE_TYPE_PARAMETERS,
+ DEG_OPCODE_PARTICLE_SETTINGS_EVAL);
+ OperationKey particle_settings_recalc_clear_key(
+ &part->id,
+ DEG_NODE_TYPE_PARAMETERS,
+ DEG_OPCODE_PARTICLE_SETTINGS_RECALC_CLEAR);
+ OperationKey psys_settings_key(&object->id,
+ DEG_NODE_TYPE_EVAL_PARTICLES,
+ DEG_OPCODE_PARTICLE_SETTINGS_EVAL,
+ psys->name);
+ add_relation(particle_settings_key, psys_settings_key, "Particle Settings Change");
+ add_relation(psys_settings_key, psys_key, "Particle Settings Update");
+ add_relation(psys_key,
+ particle_settings_recalc_clear_key,
+ "Particle Settings Recalc Clear");
/* XXX: if particle system is later re-enabled, we must do full rebuild? */
if (!psys_check_enabled(object, psys, G.is_rendering))
/* collisions */
if (part->type != PART_HAIR) {
- add_collision_relations(psys_key, scene_, object, part->collision_group, object->lay, true, "Particle Collision");
+ add_collision_relations(psys_key,
+ scene_,
+ object,
+ part->collision_group,
+ true,
+ "Particle Collision");
}
- else if ((psys->flag & PSYS_HAIR_DYNAMICS) && psys->clmd && psys->clmd->coll_parms) {
- add_collision_relations(psys_key, scene_, object, psys->clmd->coll_parms->group, object->lay | scene_->lay, true, "Hair Collision");
+ else if ((psys->flag & PSYS_HAIR_DYNAMICS) &&
+ psys->clmd != NULL &&
+ psys->clmd->coll_parms != NULL)
+ {
+ add_collision_relations(psys_key,
+ scene_,
+ object,
+ psys->clmd->coll_parms->group,
+ true,
+ "Hair Collision");
}
/* effectors */
- add_forcefield_relations(psys_key, scene_, object, psys, part->effector_weights, part->type == PART_HAIR, "Particle Field");
+ add_forcefield_relations(psys_key,
+ scene_,
+ object,
+ psys,
+ part->effector_weights,
+ part->type == PART_HAIR,
+ "Particle Field");
/* boids */
if (part->boids) {
if (part->ren_as == PART_DRAW_OB && part->dup_ob) {
ComponentKey dup_ob_key(&part->dup_ob->id, DEG_NODE_TYPE_TRANSFORM);
add_relation(dup_ob_key, psys_key, "Particle Object Visualization");
+ if (part->dup_ob->type == OB_MBALL) {
+ ComponentKey dup_geometry_key(&part->dup_ob->id,
+ DEG_NODE_TYPE_GEOMETRY);
+ add_relation(obdata_ubereval_key,
+ dup_geometry_key,
+ "Particle MBall Visualization");
+ }
}
}
ComponentKey transform_key(&object->id, DEG_NODE_TYPE_TRANSFORM);
add_relation(transform_key, obdata_ubereval_key, "Partcile Eval");
- /* pointcache */
- // TODO...
+ /* TODO(sergey): Do we need a point cache operations here? */
+}
+
+void DepsgraphRelationBuilder::build_particle_settings(ParticleSettings *part)
+{
+ ID *part_id = &part->id;
+ if (part_id->tag & LIB_TAG_DOIT) {
+ return;
+ }
+ part_id->tag |= LIB_TAG_DOIT;
+
+ /* Animation data relations. */
+ build_animdata(&part->id);
+
+ OperationKey eval_key(part_id,
+ DEG_NODE_TYPE_PARAMETERS,
+ DEG_OPCODE_PARTICLE_SETTINGS_EVAL);
+ OperationKey recalc_clear_key(part_id,
+ DEG_NODE_TYPE_PARAMETERS,
+ DEG_OPCODE_PARTICLE_SETTINGS_RECALC_CLEAR);
+ add_relation(eval_key, recalc_clear_key, "Particle Settings Clear Recalc");
}
void DepsgraphRelationBuilder::build_cloth(Object *object,
/* link components to each other */
add_relation(obdata_geom_key, geom_key, "Object Geometry Base Data");
+ OperationKey obdata_ubereval_key(&object->id,
+ DEG_NODE_TYPE_GEOMETRY,
+ DEG_OPCODE_GEOMETRY_UBEREVAL);
+
+ /* Special case: modifiers and DerivedMesh creation 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,
+ DEG_NODE_TYPE_PARAMETERS,
+ DEG_OPCODE_PLACEHOLDER,
+ "Scene Eval");
+ add_relation(scene_key, obdata_ubereval_key, "CoW Relation");
+
/* Modifiers */
if (object->modifiers.first != NULL) {
- OperationKey obdata_ubereval_key(&object->id,
- DEG_NODE_TYPE_GEOMETRY,
- DEG_OPCODE_GEOMETRY_UBEREVAL);
-
LINKLIST_FOREACH (ModifierData *, md, &object->modifiers) {
const ModifierTypeInfo *mti = modifierType_getInfo((ModifierType)md->type);
-
if (mti->updateDepsgraph) {
DepsNodeHandle handle = create_node_handle(obdata_ubereval_key);
mti->updateDepsgraph(
object,
reinterpret_cast< ::DepsNodeHandle* >(&handle));
}
-
if (BKE_object_modifier_use_time(object, md)) {
TimeSourceKey time_src_key;
add_relation(time_src_key, obdata_ubereval_key, "Time Source");
-
- /* Hacky fix for T45633 (Animated modifiers aren't updated)
- *
- * This check works because BKE_object_modifier_use_time() tests
- * for either the modifier needing time, or that it is animated.
- */
- /* XXX: Remove this hack when these links are added as part of build_animdata() instead */
- if (modifier_dependsOnTime(md) == false && needs_animdata_node(&object->id)) {
- ComponentKey animation_key(&object->id, DEG_NODE_TYPE_ANIMATION);
- add_relation(animation_key, obdata_ubereval_key, "Modifier Animation");
- }
}
-
if (md->type == eModifierType_Cloth) {
build_cloth(object, md);
}
Material *ma = give_current_material(object, a);
if (ma != NULL) {
build_material(ma);
+
+ if (object->type == OB_MESH) {
+ OperationKey material_key(&ma->id,
+ DEG_NODE_TYPE_SHADING,
+ DEG_OPCODE_MATERIAL_UPDATE);
+ OperationKey shading_key(&object->id, DEG_NODE_TYPE_SHADING, DEG_OPCODE_SHADING);
+ add_relation(material_key, shading_key, "Material Update");
+ }
}
}
}
// XXX: these needs geom data, but where is geom stored?
if (cu->bevobj) {
ComponentKey bevob_key(&cu->bevobj->id, DEG_NODE_TYPE_GEOMETRY);
- build_object(cu->bevobj);
+ build_object(NULL, cu->bevobj);
add_relation(bevob_key, geom_key, "Curve Bevel");
}
if (cu->taperobj) {
ComponentKey taperob_key(&cu->taperobj->id, DEG_NODE_TYPE_GEOMETRY);
- build_object(cu->taperobj);
+ build_object(NULL, cu->taperobj);
add_relation(taperob_key, geom_key, "Curve Taper");
}
if (object->type == OB_FONT) {
if (cu->textoncurve) {
ComponentKey textoncurve_key(&cu->textoncurve->id, DEG_NODE_TYPE_GEOMETRY);
- build_object(cu->textoncurve);
+ build_object(NULL, cu->textoncurve);
add_relation(textoncurve_key, geom_key, "Text on Curve");
}
}
if (key) {
build_shapekeys(obdata, key);
}
-
- if (needs_animdata_node(obdata)) {
- ComponentKey animation_key(obdata, DEG_NODE_TYPE_ANIMATION);
- ComponentKey parameters_key(obdata, DEG_NODE_TYPE_PARAMETERS);
- add_relation(animation_key, parameters_key, "Geom Parameters");
- /* Evaluation usually depends on animation.
- * TODO(sergey): Need to re-hook it after granular update is implemented..
- */
- add_relation(animation_key, obdata_geom_eval_key, "Animation");
- }
}
/* Cameras */
}
camera_id->tag |= LIB_TAG_DOIT;
- ComponentKey parameters_key(camera_id, DEG_NODE_TYPE_PARAMETERS);
+ ComponentKey object_parameters_key(&object->id, DEG_NODE_TYPE_PARAMETERS);
+ ComponentKey camera_parameters_key(camera_id, DEG_NODE_TYPE_PARAMETERS);
- if (needs_animdata_node(camera_id)) {
- ComponentKey animation_key(camera_id, DEG_NODE_TYPE_ANIMATION);
- add_relation(animation_key, parameters_key, "Camera Parameters");
- }
+ add_relation(camera_parameters_key, object_parameters_key,
+ "Camera -> Object");
/* DOF */
- if (cam->dof_ob) {
- ComponentKey ob_param_key(&object->id, DEG_NODE_TYPE_PARAMETERS);
+ if (cam->dof_ob != NULL) {
ComponentKey dof_ob_key(&cam->dof_ob->id, DEG_NODE_TYPE_TRANSFORM);
- add_relation(dof_ob_key, ob_param_key, "Camera DOF");
+ add_relation(dof_ob_key, object_parameters_key, "Camera DOF");
}
}
}
lamp_id->tag |= LIB_TAG_DOIT;
- ComponentKey parameters_key(lamp_id, DEG_NODE_TYPE_PARAMETERS);
+ ComponentKey object_parameters_key(&object->id, DEG_NODE_TYPE_PARAMETERS);
+ ComponentKey lamp_parameters_key(lamp_id, DEG_NODE_TYPE_PARAMETERS);
- if (needs_animdata_node(lamp_id)) {
- ComponentKey animation_key(lamp_id, DEG_NODE_TYPE_ANIMATION);
- add_relation(animation_key, parameters_key, "Lamp Parameters");
- }
+ add_relation(lamp_parameters_key, object_parameters_key,
+ "Lamp -> Object");
/* lamp's nodetree */
- if (la->nodetree) {
+ if (la->nodetree != NULL) {
build_nodetree(la->nodetree);
- ComponentKey nodetree_key(&la->nodetree->id, DEG_NODE_TYPE_PARAMETERS);
- add_relation(nodetree_key, parameters_key, "NTree->Lamp Parameters");
+ ComponentKey nodetree_key(&la->nodetree->id, DEG_NODE_TYPE_SHADING);
+ add_relation(nodetree_key, lamp_parameters_key, "NTree->Lamp Parameters");
}
-
/* textures */
build_texture_stack(la->mtex);
+
+ if (DEG_depsgraph_use_copy_on_write()) {
+ /* Make sure copy on write of lamp data is always properly updated for
+ * visible lamps.
+ */
+ OperationKey ob_copy_on_write_key(&object->id,
+ DEG_NODE_TYPE_COPY_ON_WRITE,
+ DEG_OPCODE_COPY_ON_WRITE);
+ OperationKey lamp_copy_on_write_key(lamp_id,
+ DEG_NODE_TYPE_COPY_ON_WRITE,
+ DEG_OPCODE_COPY_ON_WRITE);
+ add_relation(lamp_copy_on_write_key, ob_copy_on_write_key, "Eval Order");
+ }
}
void DepsgraphRelationBuilder::build_nodetree(bNodeTree *ntree)
{
- if (!ntree)
+ if (ntree == NULL) {
return;
-
+ }
ID *ntree_id = &ntree->id;
-
build_animdata(ntree_id);
-
- OperationKey parameters_key(ntree_id,
- DEG_NODE_TYPE_PARAMETERS,
- DEG_OPCODE_PARAMETERS_EVAL);
-
+ ComponentKey shading_key(ntree_id, DEG_NODE_TYPE_SHADING);
/* nodetree's nodes... */
LINKLIST_FOREACH (bNode *, bnode, &ntree->nodes) {
ID *id = bnode->id;
/* nothing for now. */
}
else if (id_type == ID_OB) {
- build_object((Object *)id);
+ 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 (bnode->type == NODE_GROUP) {
bNodeTree *group_ntree = (bNodeTree *)id;
if ((group_ntree->id.tag & LIB_TAG_DOIT) == 0) {
build_nodetree(group_ntree);
group_ntree->id.tag |= LIB_TAG_DOIT;
}
- OperationKey group_parameters_key(&group_ntree->id,
- DEG_NODE_TYPE_PARAMETERS,
- DEG_OPCODE_PARAMETERS_EVAL);
- add_relation(group_parameters_key, parameters_key, "Group Node");
+ ComponentKey group_shading_key(&group_ntree->id,
+ DEG_NODE_TYPE_SHADING);
+ add_relation(group_shading_key, shading_key, "Group Node");
}
else {
BLI_assert(!"Unknown ID type used for node");
}
}
- if (needs_animdata_node(ntree_id)) {
- ComponentKey animation_key(ntree_id, DEG_NODE_TYPE_ANIMATION);
- add_relation(animation_key, parameters_key, "NTree Parameters");
- }
+ OperationKey shading_update_key(ntree_id,
+ DEG_NODE_TYPE_SHADING,
+ DEG_OPCODE_MATERIAL_UPDATE);
+ OperationKey shading_parameters_key(ntree_id,
+ DEG_NODE_TYPE_SHADING_PARAMETERS,
+ DEG_OPCODE_MATERIAL_UPDATE);
+ add_relation(shading_parameters_key, shading_update_key, "NTree Shading Parameters");
}
/* Recursively build graph for material */
if (ma->nodetree != NULL) {
build_nodetree(ma->nodetree);
OperationKey ntree_key(&ma->nodetree->id,
- DEG_NODE_TYPE_PARAMETERS,
- DEG_OPCODE_PARAMETERS_EVAL);
+ DEG_NODE_TYPE_SHADING,
+ DEG_OPCODE_MATERIAL_UPDATE);
OperationKey material_key(&ma->id,
DEG_NODE_TYPE_SHADING,
- DEG_OPCODE_PLACEHOLDER,
- "Material Update");
+ DEG_OPCODE_MATERIAL_UPDATE);
add_relation(ntree_key, material_key, "Material's NTree");
}
}
// TODO: parent object (when that feature is implemented)
}
-bool DepsgraphRelationBuilder::needs_animdata_node(ID *id)
+void DepsgraphRelationBuilder::build_cachefile(CacheFile *cache_file)
{
- AnimData *adt = BKE_animdata_from_id(id);
- if (adt != NULL) {
- return (adt->action != NULL) || (adt->nla_tracks.first != NULL);
- }
- return false;
-}
-
-void DepsgraphRelationBuilder::build_cachefile(CacheFile *cache_file) {
/* Animation. */
build_animdata(&cache_file->id);
}
build_animdata(&clip->id);
}
+void DepsgraphRelationBuilder::build_lightprobe(Object *object)
+{
+ LightProbe *probe = (LightProbe *)object->data;
+ ID *probe_id = &probe->id;
+ if (probe_id->tag & LIB_TAG_DOIT) {
+ return;
+ }
+ probe_id->tag |= LIB_TAG_DOIT;
+ build_animdata(&probe->id);
+
+ OperationKey probe_key(probe_id,
+ DEG_NODE_TYPE_PARAMETERS,
+ DEG_OPCODE_PLACEHOLDER,
+ "LightProbe Eval");
+ OperationKey object_key(&object->id,
+ DEG_NODE_TYPE_PARAMETERS,
+ DEG_OPCODE_PLACEHOLDER,
+ "LightProbe Eval");
+ add_relation(probe_key, object_key, "LightProbe Update");
+}
+
+void DepsgraphRelationBuilder::build_copy_on_write_relations()
+{
+ foreach (IDDepsNode *id_node, graph_->id_nodes) {
+ build_copy_on_write_relations(id_node);
+ }
+}
+
+void DepsgraphRelationBuilder::build_copy_on_write_relations(IDDepsNode *id_node)
+{
+ ID *id_orig = id_node->id_orig;
+
+ TimeSourceKey time_source_key;
+ OperationKey copy_on_write_key(id_orig,
+ DEG_NODE_TYPE_COPY_ON_WRITE,
+ DEG_OPCODE_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.
+ */
+ DepsNode *node_cow = find_node(copy_on_write_key);
+ OperationDepsNode *op_cow = node_cow->get_exit_operation();
+ /* Plug any other components to this one. */
+ GHASH_FOREACH_BEGIN(ComponentDepsNode *, comp_node, id_node->components)
+ {
+ if (comp_node->type == DEG_NODE_TYPE_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;
+ }
+ /* All entry operations of each component should wait for a proper
+ * copy of ID.
+ */
+ OperationDepsNode *op_entry = comp_node->get_entry_operation();
+ if (op_entry != NULL) {
+ graph_->add_new_relation(op_cow, op_entry, "CoW Dependency");
+ }
+ /* All dangling operations should also be executed after copy-on-write. */
+ GHASH_FOREACH_BEGIN(OperationDepsNode *, op_node, comp_node->operations_map)
+ {
+ if (op_node->inlinks.size() == 0) {
+ graph_->add_new_relation(op_cow, op_node, "CoW Dependency");
+ }
+ }
+ 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) {
+ OperationKey data_copy_on_write_key(object_data_id,
+ DEG_NODE_TYPE_COPY_ON_WRITE,
+ DEG_OPCODE_COPY_ON_WRITE);
+ add_relation(data_copy_on_write_key, copy_on_write_key, "Eval Order");
+ }
+ else {
+ BLI_assert(object->type == OB_EMPTY);
+ }
+ }
+}
+
} // namespace DEG