diff options
author | Sergey Sharybin <sergey.vfx@gmail.com> | 2017-12-06 12:38:34 +0300 |
---|---|---|
committer | Sergey Sharybin <sergey.vfx@gmail.com> | 2017-12-06 12:38:34 +0300 |
commit | 5389ca18596aee628c9c05044ce8bbd6188a3f45 (patch) | |
tree | 3b2448bb7381d2b29cf47f1cca97d983b8e2d686 /source/blender/depsgraph | |
parent | 16b9e91bf1db35b54a292049ec8d1c2d5669c163 (diff) | |
parent | 1027ddfa2d2dc115da8fc48d0bea801a1ff1ce2b (diff) |
Merge branch 'master' into blender2.8
Diffstat (limited to 'source/blender/depsgraph')
8 files changed, 488 insertions, 399 deletions
diff --git a/source/blender/depsgraph/CMakeLists.txt b/source/blender/depsgraph/CMakeLists.txt index 89ba6e27aed..9495321a0ff 100644 --- a/source/blender/depsgraph/CMakeLists.txt +++ b/source/blender/depsgraph/CMakeLists.txt @@ -80,6 +80,7 @@ set(SRC intern/builder/deg_builder_nodes.h intern/builder/deg_builder_pchanmap.h intern/builder/deg_builder_relations.h + intern/builder/deg_builder_relations_impl.h intern/builder/deg_builder_transitive.h intern/eval/deg_eval.h intern/eval/deg_eval_copy_on_write.h diff --git a/source/blender/depsgraph/intern/builder/deg_builder_nodes_rig.cc b/source/blender/depsgraph/intern/builder/deg_builder_nodes_rig.cc index dfe97d02ec6..f6f2dcce467 100644 --- a/source/blender/depsgraph/intern/builder/deg_builder_nodes_rig.cc +++ b/source/blender/depsgraph/intern/builder/deg_builder_nodes_rig.cc @@ -359,6 +359,15 @@ void DepsgraphNodeBuilder::build_proxy_rig(Object *object) NULL, DEG_OPCODE_BONE_DONE); op_node->set_as_exit(); + + /* Custom properties. */ + if (pchan->prop != NULL) { + add_operation_node(&object->id, + DEG_NODE_TYPE_PARAMETERS, + NULL, + DEG_OPCODE_PARAMETERS_EVAL, + pchan->name); + } } op_node = add_operation_node(&object->id, DEG_NODE_TYPE_EVAL_POSE, diff --git a/source/blender/depsgraph/intern/builder/deg_builder_relations.cc b/source/blender/depsgraph/intern/builder/deg_builder_relations.cc index aeb9f9ab937..5c984535cb8 100644 --- a/source/blender/depsgraph/intern/builder/deg_builder_relations.cc +++ b/source/blender/depsgraph/intern/builder/deg_builder_relations.cc @@ -120,10 +120,10 @@ struct BuilderWalkUserData { DepsgraphRelationBuilder *builder; }; -static void modifier_walk(void *user_data, - struct Object * /*object*/, - struct Object **obpoin, - int /*cb_flag*/) +void modifier_walk(void *user_data, + struct Object * /*object*/, + struct Object **obpoin, + int /*cb_flag*/) { BuilderWalkUserData *data = (BuilderWalkUserData *)user_data; if (*obpoin) { @@ -275,10 +275,11 @@ bool DepsgraphRelationBuilder::has_node(const OperationKey &key) const 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", @@ -291,10 +292,11 @@ void DepsgraphRelationBuilder::add_time_relation(TimeSourceDepsNode *timesrc, 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", @@ -304,13 +306,22 @@ void DepsgraphRelationBuilder::add_operation_relation( } } -void DepsgraphRelationBuilder::add_collision_relations(const OperationKey &key, Scene *scene, Object *object, Group *group, 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, &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); @@ -319,47 +330,62 @@ void DepsgraphRelationBuilder::add_collision_relations(const OperationKey &key, 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(NULL, scene, object, psys, eff, false); - - if (effectors) { - for (EffectorCache *eff = (EffectorCache *)effectors->first; eff; eff = eff->next) { + 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, true, "Force Absorption"); + add_collision_relations(key, + scene, + object, + NULL, + true, + "Force Absorption"); } } } @@ -496,11 +522,6 @@ void DepsgraphRelationBuilder::build_object(Base *base, Object *object) } /* 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. */ @@ -900,25 +921,85 @@ void DepsgraphRelationBuilder::build_constraints(ID *id, void DepsgraphRelationBuilder::build_animdata(ID *id) { - AnimData *adt = BKE_animdata_from_id(id); + /* Animation curves and NLA. */ + build_animdata_curves(id); + /* Drivers. */ + build_animdata_drievrs(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_drievrs(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, @@ -990,45 +1071,34 @@ void DepsgraphRelationBuilder::build_driver(ID *id, FCurve *fcu) DEG_OPCODE_DRIVER, fcu->rna_path ? fcu->rna_path : "", fcu->array_index); - bPoseChannel *pchan = NULL; - const char *rna_path = fcu->rna_path ? fcu->rna_path : ""; - const ID_Type id_type = GS(id->name); - - /* 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) { - /* interleaved drivers during bone eval */ - /* TODO: ideally, if this is for a constraint, it goes to said - * constraint. - */ - Object *object = (Object *)id; - char *bone_name = BLI_str_quoted_substrN(rna_path, "pose.bones["); - pchan = BKE_pose_channel_find_name(object->pose, bone_name); - if (bone_name != NULL) { - MEM_freeN(bone_name); - bone_name = NULL; - } - if (pchan != NULL) { - OperationKey bone_key(id, - DEG_NODE_TYPE_BONE, - pchan->name, - DEG_OPCODE_BONE_LOCAL); - add_relation(driver_key, bone_key, "Driver -> Bone"); - } - else { - fprintf(stderr, - "Couldn't find bone name for driver path - '%s'\n", - rna_path); - } + 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 (id_type == 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. */ @@ -1067,55 +1137,23 @@ void DepsgraphRelationBuilder::build_driver(ID *id, FCurve *fcu) rna_path); } } - else if (id_type == ID_OB && strstr(rna_path, "modifiers[")) { - OperationKey modifier_key(id, - DEG_NODE_TYPE_GEOMETRY, - DEG_OPCODE_GEOMETRY_UBEREVAL); - if (has_node(modifier_key)) { - add_relation(driver_key, modifier_key, "Driver -> Modifier"); - } - else { - printf("Unexisting driver RNA path: %s\n", rna_path); - } - } - else if (id_type == ID_KE && strstr(rna_path, "key_blocks[")) { - /* Shape key driver - hook into the base geometry operation. */ - // XXX: double check where this points - Key *shape_key = (Key *)id; - ComponentKey geometry_key(shape_key->from, DEG_NODE_TYPE_GEOMETRY); - add_relation(driver_key, geometry_key, "Driver -> ShapeKey Geom"); - } - else if (strstr(rna_path, "key_blocks[")) { - ComponentKey geometry_key(id, DEG_NODE_TYPE_GEOMETRY); - add_relation(driver_key, geometry_key, "Driver -> ShapeKey Geom"); - } else { - if (GS(id->name) == ID_OB) { - /* assume that driver affects a transform... */ - OperationKey local_transform_key(id, - DEG_NODE_TYPE_TRANSFORM, - DEG_OPCODE_TRANSFORM_LOCAL); - add_relation(driver_key, - local_transform_key, - "Driver -> Transform"); - } - else if (GS(id->name) == ID_KE) { - ComponentKey geometry_key(id, DEG_NODE_TYPE_GEOMETRY); - add_relation(driver_key, - geometry_key, - "Driver -> Shapekey Geometry"); - } + 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. */ +} + +void DepsgraphRelationBuilder::build_driver_variables(ID *id, FCurve *fcu) +{ + ChannelDriver *driver = fcu->driver; + 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); + LINKLIST_FOREACH (DriverVar *, dvar, &driver->variables) { /* Only used targets. */ DRIVER_TARGETS_USED_LOOPER(dvar) @@ -1124,31 +1162,25 @@ void DepsgraphRelationBuilder::build_driver(ID *id, FCurve *fcu) continue; } /* Special handling for directly-named bones. */ - if ((dtar->flag & DTAR_FLAG_STRUCT_REF) && (dtar->pchan_name[0])) { + 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) { - /* Get node associated with bone. */ - // XXX: watch the space! - /* Some cases can't use final bone transform, for example: - * - Driving the bone with itself (addressed here) - * - Relations inside an IK chain (TODO?) - */ - if (dtar->id == id && - pchan != NULL && - STREQ(pchan->name, target_pchan->name)) - { - continue; - } - OperationKey target_key(dtar->id, - DEG_NODE_TYPE_BONE, - target_pchan->name, - DEG_OPCODE_BONE_DONE); - add_relation(target_key, - driver_key, - "Bone Target -> Driver"); + BKE_pose_channel_find_name(object->pose, + dtar->pchan_name); + if (target_pchan == NULL) { + continue; } + OperationKey variable_key(dtar->id, + DEG_NODE_TYPE_BONE, + target_pchan->name, + DEG_OPCODE_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. */ @@ -1164,32 +1196,15 @@ void DepsgraphRelationBuilder::build_driver(ID *id, FCurve *fcu) DEG_OPCODE_TRANSFORM_FINAL); add_relation(target_key, driver_key, "Target -> Driver"); } - else if (dtar->rna_path && strstr(dtar->rna_path, "pose.bones[")) { - /* Workaround for ensuring that local bone transforms don't end - * up having to wait for pose eval to finish (to prevent cycles). - */ - Object *object = (Object *)dtar->id; - char *bone_name = BLI_str_quoted_substrN(dtar->rna_path, - "pose.bones["); - bPoseChannel *target_pchan = - BKE_pose_channel_find_name(object->pose, bone_name); - if (bone_name != NULL) { - MEM_freeN(bone_name); - bone_name = NULL; + else if (dtar->rna_path) { + RNAPathKey variable_key(dtar->id, dtar->rna_path); + if (RNA_pointer_is_null(&variable_key.ptr)) { + continue; } - if (target_pchan != NULL) { - if (dtar->id == id && - pchan != NULL && - STREQ(pchan->name, target_pchan->name)) - { - continue; - } - OperationKey bone_key(dtar->id, - DEG_NODE_TYPE_BONE, - target_pchan->name, - DEG_OPCODE_BONE_LOCAL); - add_relation(bone_key, driver_key, "RNA Bone -> Driver"); + if (is_same_bone_dependency(variable_key, self_key)) { + continue; } + add_relation(variable_key, driver_key, "RNA Bone -> Driver"); } else { if (dtar->id == id) { @@ -1207,16 +1222,6 @@ void DepsgraphRelationBuilder::build_driver(ID *id, FCurve *fcu) } DRIVER_TARGETS_LOOPER_END } - /* 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_world(World *world) @@ -1574,7 +1579,6 @@ void DepsgraphRelationBuilder::build_obdata_geom(Object *object) if (object->modifiers.first != NULL) { 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( @@ -1584,23 +1588,10 @@ void DepsgraphRelationBuilder::build_obdata_geom(Object *object) 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); } @@ -1733,16 +1724,6 @@ void DepsgraphRelationBuilder::build_obdata_geom(Object *object) 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 */ @@ -1762,11 +1743,6 @@ void DepsgraphRelationBuilder::build_camera(Object *object) add_relation(camera_parameters_key, object_parameters_key, "Camera -> Object"); - if (needs_animdata_node(camera_id)) { - ComponentKey animation_key(camera_id, DEG_NODE_TYPE_ANIMATION); - add_relation(animation_key, camera_parameters_key, "Camera Parameters"); - } - /* DOF */ if (cam->dof_ob != NULL) { ComponentKey dof_ob_key(&cam->dof_ob->id, DEG_NODE_TYPE_TRANSFORM); @@ -1790,18 +1766,12 @@ void DepsgraphRelationBuilder::build_lamp(Object *object) add_relation(lamp_parameters_key, object_parameters_key, "Lamp -> Object"); - if (needs_animdata_node(lamp_id)) { - ComponentKey animation_key(lamp_id, DEG_NODE_TYPE_ANIMATION); - add_relation(animation_key, lamp_parameters_key, "Lamp Parameters"); - } - /* lamp's nodetree */ - if (la->nodetree) { + if (la->nodetree != NULL) { build_nodetree(la->nodetree); 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); @@ -1866,11 +1836,6 @@ void DepsgraphRelationBuilder::build_nodetree(bNodeTree *ntree) } } - if (needs_animdata_node(ntree_id)) { - ComponentKey animation_key(ntree_id, DEG_NODE_TYPE_ANIMATION); - add_relation(animation_key, shading_key, "NTree Parameters"); - } - OperationKey shading_update_key(ntree_id, DEG_NODE_TYPE_SHADING, DEG_OPCODE_MATERIAL_UPDATE); @@ -1951,15 +1916,6 @@ void DepsgraphRelationBuilder::build_gpencil(bGPdata *gpd) // TODO: parent object (when that feature is implemented) } -bool DepsgraphRelationBuilder::needs_animdata_node(ID *id) -{ - 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); diff --git a/source/blender/depsgraph/intern/builder/deg_builder_relations.h b/source/blender/depsgraph/intern/builder/deg_builder_relations.h index 569383fe479..9f661b8e825 100644 --- a/source/blender/depsgraph/intern/builder/deg_builder_relations.h +++ b/source/blender/depsgraph/intern/builder/deg_builder_relations.h @@ -31,6 +31,7 @@ #pragma once #include <cstdio> +#include <cstring> #include "intern/depsgraph_types.h" @@ -43,6 +44,7 @@ #include "BLI_string.h" #include "intern/nodes/deg_node.h" +#include "intern/nodes/deg_node_component.h" #include "intern/nodes/deg_node_operation.h" struct Base; @@ -175,17 +177,20 @@ struct DepsgraphRelationBuilder template <typename KeyFrom, typename KeyTo> void add_relation(const KeyFrom& key_from, const KeyTo& key_to, - const char *description); + const char *description, + bool check_unique = false); template <typename KeyTo> void add_relation(const TimeSourceKey& key_from, const KeyTo& key_to, - const char *description); + const char *description, + bool check_unique = false); template <typename KeyType> void add_node_handle_relation(const KeyType& key_from, const DepsNodeHandle *handle, - const char *description); + const char *description, + bool check_unique = false); void build_view_layer(Scene *scene, ViewLayer *view_layer); void build_group(Object *object, Group *group); @@ -199,7 +204,12 @@ struct DepsgraphRelationBuilder ListBase *constraints, RootPChanMap *root_map); void build_animdata(ID *id); + void build_animdata_curves(ID *id); + void build_animdata_curves_targets(ID *id); + void build_animdata_drievrs(ID *id); void build_driver(ID *id, FCurve *fcurve); + void build_driver_data(ID *id, FCurve *fcurve); + void build_driver_variables(ID *id, FCurve *fcurve); void build_world(World *world); void build_rigidbody(Scene *scene); void build_particles(Object *object); @@ -276,16 +286,19 @@ protected: void add_time_relation(TimeSourceDepsNode *timesrc, DepsNode *node_to, - const char *description); + const char *description, + bool check_unique = false); void add_operation_relation(OperationDepsNode *node_from, OperationDepsNode *node_to, - const char *description); + const char *description, + bool check_unique = false); template <typename KeyType> DepsNodeHandle create_node_handle(const KeyType& key, const char *default_name = ""); - bool needs_animdata_node(ID *id); + template <typename KeyFrom, typename KeyTo> + bool is_same_bone_dependency(const KeyFrom& key_from, const KeyTo& key_to); private: /* State which never changes, same for the whole builder time. */ @@ -298,10 +311,12 @@ private: struct DepsNodeHandle { - DepsNodeHandle(DepsgraphRelationBuilder *builder, OperationDepsNode *node, const char *default_name = "") : - builder(builder), - node(node), - default_name(default_name) + DepsNodeHandle(DepsgraphRelationBuilder *builder, + OperationDepsNode *node, + const char *default_name = "") + : builder(builder), + node(node), + default_name(default_name) { BLI_assert(node != NULL); } @@ -311,92 +326,7 @@ struct DepsNodeHandle const char *default_name; }; -/* Utilities for Builders ----------------------------------------------------- */ - -template <typename KeyType> -OperationDepsNode *DepsgraphRelationBuilder::find_operation_node(const KeyType& key) -{ - DepsNode *node = get_node(key); - return node != NULL ? node->get_exit_operation() : NULL; -} - -template <typename KeyFrom, typename KeyTo> -void DepsgraphRelationBuilder::add_relation(const KeyFrom &key_from, - const KeyTo &key_to, - const char *description) -{ - DepsNode *node_from = get_node(key_from); - DepsNode *node_to = get_node(key_to); - OperationDepsNode *op_from = node_from ? node_from->get_exit_operation() : NULL; - OperationDepsNode *op_to = node_to ? node_to->get_entry_operation() : NULL; - if (op_from && op_to) { - add_operation_relation(op_from, op_to, description); - } - else { - if (!op_from) { - /* XXX TODO handle as error or report if needed */ - fprintf(stderr, "add_relation(%s) - Could not find op_from (%s)\n", - description, key_from.identifier().c_str()); - } - else { - fprintf(stderr, "add_relation(%s) - Failed, but op_from (%s) was ok\n", - description, key_from.identifier().c_str()); - } - if (!op_to) { - /* XXX TODO handle as error or report if needed */ - fprintf(stderr, "add_relation(%s) - Could not find op_to (%s)\n", - description, key_to.identifier().c_str()); - } - else { - fprintf(stderr, "add_relation(%s) - Failed, but op_to (%s) was ok\n", - description, key_to.identifier().c_str()); - } - } -} - -template <typename KeyTo> -void DepsgraphRelationBuilder::add_relation(const TimeSourceKey &key_from, - const KeyTo &key_to, - const char *description) -{ - TimeSourceDepsNode *time_from = get_node(key_from); - DepsNode *node_to = get_node(key_to); - OperationDepsNode *op_to = node_to ? node_to->get_entry_operation() : NULL; - if (time_from != NULL && op_to != NULL) { - add_time_relation(time_from, op_to, description); - } -} - -template <typename KeyType> -void DepsgraphRelationBuilder::add_node_handle_relation( - const KeyType &key_from, - const DepsNodeHandle *handle, - const char *description) -{ - DepsNode *node_from = get_node(key_from); - OperationDepsNode *op_from = node_from ? node_from->get_exit_operation() : NULL; - OperationDepsNode *op_to = handle->node->get_entry_operation(); - if (op_from != NULL && op_to != NULL) { - add_operation_relation(op_from, op_to, description); - } - else { - if (!op_from) { - fprintf(stderr, "add_node_handle_relation(%s) - Could not find op_from (%s)\n", - description, key_from.identifier().c_str()); - } - if (!op_to) { - fprintf(stderr, "add_node_handle_relation(%s) - Could not find op_to (%s)\n", - description, key_from.identifier().c_str()); - } - } -} +} // namespace DEG -template <typename KeyType> -DepsNodeHandle DepsgraphRelationBuilder::create_node_handle( - const KeyType &key, - const char *default_name) -{ - return DepsNodeHandle(this, get_node(key), default_name); -} -} // namespace DEG +#include "intern/builder/deg_builder_relations_impl.h" diff --git a/source/blender/depsgraph/intern/builder/deg_builder_relations_impl.h b/source/blender/depsgraph/intern/builder/deg_builder_relations_impl.h new file mode 100644 index 00000000000..ba55a83b767 --- /dev/null +++ b/source/blender/depsgraph/intern/builder/deg_builder_relations_impl.h @@ -0,0 +1,155 @@ +/* + * ***** BEGIN GPL LICENSE BLOCK ***** + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software Foundation, + * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + * + * The Original Code is Copyright (C) 2013 Blender Foundation. + * All rights reserved. + * + * Original Author: Lukas Toenne + * Contributor(s): Sergey SHarybin + * + * ***** END GPL LICENSE BLOCK ***** + */ + +/** \file blender/depsgraph/intern/builder/deg_builder_relations_impl.h + * \ingroup depsgraph + */ + +#pragma once + +namespace DEG { + +template <typename KeyType> +OperationDepsNode *DepsgraphRelationBuilder::find_operation_node(const KeyType& key) +{ + DepsNode *node = get_node(key); + return node != NULL ? node->get_exit_operation() : NULL; +} + +template <typename KeyFrom, typename KeyTo> +void DepsgraphRelationBuilder::add_relation(const KeyFrom &key_from, + const KeyTo &key_to, + const char *description, + bool check_unique) +{ + DepsNode *node_from = get_node(key_from); + DepsNode *node_to = get_node(key_to); + OperationDepsNode *op_from = node_from ? node_from->get_exit_operation() : NULL; + OperationDepsNode *op_to = node_to ? node_to->get_entry_operation() : NULL; + if (op_from && op_to) { + add_operation_relation(op_from, op_to, description, check_unique); + } + else { + if (!op_from) { + /* XXX TODO handle as error or report if needed */ + fprintf(stderr, "add_relation(%s) - Could not find op_from (%s)\n", + description, key_from.identifier().c_str()); + } + else { + fprintf(stderr, "add_relation(%s) - Failed, but op_from (%s) was ok\n", + description, key_from.identifier().c_str()); + } + if (!op_to) { + /* XXX TODO handle as error or report if needed */ + fprintf(stderr, "add_relation(%s) - Could not find op_to (%s)\n", + description, key_to.identifier().c_str()); + } + else { + fprintf(stderr, "add_relation(%s) - Failed, but op_to (%s) was ok\n", + description, key_to.identifier().c_str()); + } + } +} + +template <typename KeyTo> +void DepsgraphRelationBuilder::add_relation(const TimeSourceKey &key_from, + const KeyTo &key_to, + const char *description, + bool check_unique) +{ + TimeSourceDepsNode *time_from = get_node(key_from); + DepsNode *node_to = get_node(key_to); + OperationDepsNode *op_to = node_to ? node_to->get_entry_operation() : NULL; + if (time_from != NULL && op_to != NULL) { + add_time_relation(time_from, op_to, description, check_unique); + } +} + +template <typename KeyType> +void DepsgraphRelationBuilder::add_node_handle_relation( + const KeyType &key_from, + const DepsNodeHandle *handle, + const char *description, + bool check_unique) +{ + DepsNode *node_from = get_node(key_from); + OperationDepsNode *op_from = node_from ? node_from->get_exit_operation() : NULL; + OperationDepsNode *op_to = handle->node->get_entry_operation(); + if (op_from != NULL && op_to != NULL) { + add_operation_relation(op_from, op_to, description, check_unique); + } + else { + if (!op_from) { + fprintf(stderr, "add_node_handle_relation(%s) - Could not find op_from (%s)\n", + description, key_from.identifier().c_str()); + } + if (!op_to) { + fprintf(stderr, "add_node_handle_relation(%s) - Could not find op_to (%s)\n", + description, key_from.identifier().c_str()); + } + } +} + +template <typename KeyType> +DepsNodeHandle DepsgraphRelationBuilder::create_node_handle( + const KeyType &key, + const char *default_name) +{ + return DepsNodeHandle(this, get_node(key), default_name); +} + +/* Rig compatibility: we check if bone is using local transform as a variable + * for driver on itself and ignore those relations to avoid "false-positive" + * dependency cycles. + */ +template <typename KeyFrom, typename KeyTo> +bool DepsgraphRelationBuilder::is_same_bone_dependency(const KeyFrom& key_from, + const KeyTo& key_to) +{ + /* Get operations for requested keys. */ + DepsNode *node_from = get_node(key_from); + DepsNode *node_to = get_node(key_to); + if (node_from == NULL || node_to == NULL) { + return false; + } + OperationDepsNode *op_from = node_from->get_exit_operation(); + OperationDepsNode *op_to = node_to->get_entry_operation(); + if (op_from == NULL || op_to == NULL) { + return false; + } + /* We are only interested in relations like BONE_DONE -> BONE_LOCAL... */ + if (!(op_from->opcode == DEG_OPCODE_BONE_DONE && + op_to->opcode == DEG_OPCODE_BONE_LOCAL)) { + return false; + } + /* ... BUT, we also need to check if it's same bone. */ + if (!STREQ(op_from->owner->name, op_to->owner->name)) { + return false; + } + return true; +} + +} // namespace DEG diff --git a/source/blender/depsgraph/intern/builder/deg_builder_relations_rig.cc b/source/blender/depsgraph/intern/builder/deg_builder_relations_rig.cc index 2a2108e8480..2aff1ca33c7 100644 --- a/source/blender/depsgraph/intern/builder/deg_builder_relations_rig.cc +++ b/source/blender/depsgraph/intern/builder/deg_builder_relations_rig.cc @@ -324,11 +324,6 @@ void DepsgraphRelationBuilder::build_rig(Object *object) "Armature Eval"); add_relation(armature_key, init_key, "Data dependency"); - if (needs_animdata_node(&object->id)) { - ComponentKey animation_key(&object->id, DEG_NODE_TYPE_ANIMATION); - add_relation(animation_key, init_key, "Rig Animation"); - } - /* IK Solvers... * - These require separate processing steps are pose-level * to be executed between chains of bones (i.e. once the diff --git a/source/blender/depsgraph/intern/depsgraph.cc b/source/blender/depsgraph/intern/depsgraph.cc index e30e00e61b5..4fea8b49706 100644 --- a/source/blender/depsgraph/intern/depsgraph.cc +++ b/source/blender/depsgraph/intern/depsgraph.cc @@ -103,41 +103,39 @@ Depsgraph::~Depsgraph() /* Query Conditions from RNA ----------------------- */ -static bool pointer_to_id_node_criteria(const PointerRNA *ptr, - const PropertyRNA *prop, - ID **id) -{ - if (ptr->type == NULL) { - return false; - } - if (prop != NULL) { - if (RNA_struct_is_ID(ptr->type)) { - *id = (ID *)ptr->data; - return true; - } - } - return false; -} - -static bool pointer_to_component_node_criteria(const PointerRNA *ptr, - const PropertyRNA *prop, - ID **id, - eDepsNode_Type *type, - const char **subdata) +static bool pointer_to_component_node_criteria( + const PointerRNA *ptr, + const PropertyRNA *prop, + ID **id, + eDepsNode_Type *type, + const char **subdata, + eDepsOperation_Code *operation_code, + const char **operation_name, + int *operation_name_tag) { if (ptr->type == NULL) { return false; } /* Set default values for returns. */ - *id = (ID *)ptr->id.data; /* For obvious reasons... */ - *subdata = ""; /* Default to no subdata (e.g. bone) name - * lookup in most cases. */ + *id = (ID *)ptr->id.data; + *subdata = ""; + *operation_code = DEG_OPCODE_OPERATION; + *operation_name = ""; + *operation_name_tag = -1; /* Handling of commonly known scenarios. */ if (ptr->type == &RNA_PoseBone) { bPoseChannel *pchan = (bPoseChannel *)ptr->data; - /* Bone - generally, we just want the bone component. */ - *type = DEG_NODE_TYPE_BONE; - *subdata = pchan->name; + if (prop != NULL && RNA_property_is_idprop(prop)) { + *type = DEG_NODE_TYPE_PARAMETERS; + *subdata = ""; + *operation_code = DEG_OPCODE_PARAMETERS_EVAL; + *operation_name = pchan->name;; + } + else { + /* Bone - generally, we just want the bone component. */ + *type = DEG_NODE_TYPE_BONE; + *subdata = pchan->name; + } return true; } else if (ptr->type == &RNA_Bone) { @@ -200,7 +198,12 @@ static bool pointer_to_component_node_criteria(const PointerRNA *ptr, * owns it. */ *id = key->from; - *type = DEG_NODE_TYPE_PARAMETERS; + *type = DEG_NODE_TYPE_GEOMETRY; + return true; + } + else if (ptr->type == &RNA_Key) { + *id = (ID *)ptr->id.data; + *type = DEG_NODE_TYPE_GEOMETRY; return true; } else if (RNA_struct_is_a(ptr->type, &RNA_Sequence)) { @@ -213,6 +216,9 @@ static bool pointer_to_component_node_criteria(const PointerRNA *ptr, if (prop != NULL) { /* All unknown data effectively falls under "parameter evaluation". */ *type = DEG_NODE_TYPE_PARAMETERS; + *operation_code = DEG_OPCODE_PARAMETERS_EVAL; + *operation_name = ""; + *operation_name_tag = -1; return true; } return false; @@ -223,20 +229,32 @@ DepsNode *Depsgraph::find_node_from_pointer(const PointerRNA *ptr, const PropertyRNA *prop) const { ID *id; - eDepsNode_Type type; - const char *name; - - /* Get querying conditions. */ - if (pointer_to_id_node_criteria(ptr, prop, &id)) { - return find_id_node(id); - } - else if (pointer_to_component_node_criteria(ptr, prop, &id, &type, &name)) { + eDepsNode_Type node_type; + const char *component_name, *operation_name; + eDepsOperation_Code operation_code; + int operation_name_tag; + + if (pointer_to_component_node_criteria( + ptr, prop, + &id, &node_type, &component_name, + &operation_code, &operation_name, &operation_name_tag)) + { IDDepsNode *id_node = find_id_node(id); - if (id_node != NULL) { - return id_node->find_component(type, name); + if (id_node == NULL) { + return NULL; + } + ComponentDepsNode *comp_node = + id_node->find_component(node_type, component_name); + if (comp_node == NULL) { + return NULL; + } + if (operation_code == DEG_OPCODE_OPERATION) { + return comp_node; } + return comp_node->find_operation(operation_code, + operation_name, + operation_name_tag); } - return NULL; } @@ -318,10 +336,18 @@ void Depsgraph::clear_id_nodes() /* Add new relationship between two nodes. */ DepsRelation *Depsgraph::add_new_relation(OperationDepsNode *from, OperationDepsNode *to, - const char *description) + const char *description, + bool check_unique) { + DepsRelation *rel = NULL; + if (check_unique) { + rel = check_nodes_connected(from, to, description); + } + if (rel != NULL) { + return rel; + } /* Create new relation, and add it to the graph. */ - DepsRelation *rel = OBJECT_GUARDED_NEW(DepsRelation, from, to, description); + rel = OBJECT_GUARDED_NEW(DepsRelation, from, to, description); /* TODO(sergey): Find a better place for this. */ #ifdef WITH_OPENSUBDIV ComponentDepsNode *comp_node = from->owner; @@ -341,13 +367,38 @@ DepsRelation *Depsgraph::add_new_relation(OperationDepsNode *from, /* Add new relation between two nodes */ DepsRelation *Depsgraph::add_new_relation(DepsNode *from, DepsNode *to, - const char *description) + const char *description, + bool check_unique) { + DepsRelation *rel = NULL; + if (check_unique) { + rel = check_nodes_connected(from, to, description); + } + if (rel != NULL) { + return rel; + } /* Create new relation, and add it to the graph. */ - DepsRelation *rel = OBJECT_GUARDED_NEW(DepsRelation, from, to, description); + rel = OBJECT_GUARDED_NEW(DepsRelation, from, to, description); return rel; } +DepsRelation *Depsgraph::check_nodes_connected(const DepsNode *from, + const DepsNode *to, + const char *description) +{ + foreach (DepsRelation *rel, from->outlinks) { + BLI_assert(rel->from == from); + if (rel->to != to) { + continue; + } + if (description != NULL && !STREQ(rel->name, description)) { + continue; + } + return rel; + } + return NULL; +} + /* ************************ */ /* Relationships Management */ @@ -359,24 +410,6 @@ DepsRelation::DepsRelation(DepsNode *from, name(description), flag(0) { -#ifndef NDEBUG -/* - for (OperationDepsNode::Relations::const_iterator it = from->outlinks.begin(); - it != from->outlinks.end(); - ++it) - { - DepsRelation *rel = *it; - if (rel->from == from && - rel->to == to && - rel->type == type && - rel->name == description) - { - BLI_assert(!"Duplicated relation, should not happen!"); - } - } -*/ -#endif - /* Hook it up to the nodes which use it. * * NOTE: We register relation in the nodes which this link connects to here diff --git a/source/blender/depsgraph/intern/depsgraph.h b/source/blender/depsgraph/intern/depsgraph.h index d841ae045f2..8a34be0c7a2 100644 --- a/source/blender/depsgraph/intern/depsgraph.h +++ b/source/blender/depsgraph/intern/depsgraph.h @@ -123,11 +123,21 @@ struct Depsgraph { /* Add new relationship between two nodes. */ DepsRelation *add_new_relation(OperationDepsNode *from, OperationDepsNode *to, - const char *description); + const char *description, + bool check_unique = false); DepsRelation *add_new_relation(DepsNode *from, DepsNode *to, - const char *description); + const char *description, + bool check_unique = false); + + /* Check whether two nodes are connected by relation with given + * description. Description might be NULL to check ANY relation between + * given nodes. + */ + DepsRelation *check_nodes_connected(const DepsNode *from, + const DepsNode *to, + const char *description); /* Tag a specific node as needing updates. */ void add_entry_tag(OperationDepsNode *node); |