diff options
-rw-r--r-- | source/blender/depsgraph/intern/builder/deg_builder_relations.cc | 63 | ||||
-rw-r--r-- | source/blender/depsgraph/intern/builder/deg_builder_rna.cc | 6 |
2 files changed, 46 insertions, 23 deletions
diff --git a/source/blender/depsgraph/intern/builder/deg_builder_relations.cc b/source/blender/depsgraph/intern/builder/deg_builder_relations.cc index 3f6e33eed61..4c4bc01a3dd 100644 --- a/source/blender/depsgraph/intern/builder/deg_builder_relations.cc +++ b/source/blender/depsgraph/intern/builder/deg_builder_relations.cc @@ -1327,25 +1327,47 @@ void DepsgraphRelationBuilder::build_driver(ID *id, FCurve *fcu) 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 && STRPREFIX(rna_path, "bones[")) { + /* Validate the RNA path pointer just in case. */ + const char *rna_path = fcu->rna_path; + if (rna_path == NULL || rna_path[0] == '\0') { + return; + } + /* Parse the RNA path to find the target property pointer. */ + 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; + } + OperationKey driver_key( + id, NodeType::PARAMETERS, OperationCode::DRIVER, rna_path, fcu->array_index); + /* If the target of the driver is a Bone property, find the Armature data, + * and then link the driver to all pose bone evaluation components that use + * it. This is necessary to provide more granular dependencies specifically for + * Bone objects, because the armature data doesn't have per-bone components, + * and generic add_relation can only add one link. */ + ID *id_ptr = (ID *)property_entry_key.ptr.id.data; + bool is_bone = id_ptr && property_entry_key.ptr.type == &RNA_Bone; + /* If the Bone property is referenced via obj.pose.bones[].bone, + * the RNA pointer refers to the Object ID, so skip to data. */ + if (is_bone && GS(id_ptr->name) == ID_OB) { + id_ptr = (ID *)((Object *)id_ptr)->data; + } + if (is_bone && GS(id_ptr->name) == ID_AR) { /* Drivers on armature-level bone settings (i.e. bbone stuff), * which will affect the evaluation of corresponding pose bones. */ - char *bone_name = BLI_str_quoted_substrN(rna_path, "bones["); - if (bone_name != NULL) { + Bone *bone = (Bone *)property_entry_key.ptr.data; + if (bone != NULL) { /* Find objects which use this, and make their eval callbacks * depend on this. */ for (IDNode *to_node : graph_->id_nodes) { if (GS(to_node->id_orig->name) == ID_OB) { Object *object = (Object *)to_node->id_orig; /* We only care about objects with pose data which use this. */ - if (object->data == id && object->pose != NULL) { - bPoseChannel *pchan = BKE_pose_channel_find_name(object->pose, bone_name); + if (object->data == id_ptr && object->pose != 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); @@ -1354,23 +1376,18 @@ void DepsgraphRelationBuilder::build_driver_data(ID *id, FCurve *fcu) } } } - /* Free temp data. */ - MEM_freeN(bone_name); - bone_name = NULL; + /* Make the driver depend on COW, similar to the generic case below. */ + if (id_ptr != id) { + ComponentKey cow_key(id_ptr, NodeType::COPY_ON_WRITE); + add_relation(cow_key, driver_key, "Driven CoW -> Driver", RELATION_CHECK_BEFORE_ADD); + } } 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; - } + else { + /* If it's not a Bone, handle the generic single dependency case. */ 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 diff --git a/source/blender/depsgraph/intern/builder/deg_builder_rna.cc b/source/blender/depsgraph/intern/builder/deg_builder_rna.cc index 1238cdc70c6..ea5f86a31a8 100644 --- a/source/blender/depsgraph/intern/builder/deg_builder_rna.cc +++ b/source/blender/depsgraph/intern/builder/deg_builder_rna.cc @@ -211,6 +211,12 @@ RNANodeIdentifier RNANodeQuery::construct_node_identifier(const PointerRNA *ptr, * bone components, instead of using this generic code. */ node_identifier.type = NodeType::PARAMETERS; node_identifier.operation_code = OperationCode::ARMATURE_EVAL; + /* If trying to look up via an Object, e.g. due to lookup via + * obj.pose.bones[].bone in a driver attached to the Object, + * redirect to its data. */ + if (GS(node_identifier.id->name) == ID_OB) { + node_identifier.id = (ID *)((Object *)node_identifier.id)->data; + } return node_identifier; } else if (RNA_struct_is_a(ptr->type, &RNA_Constraint)) { |