Depsgraph: fix spurious cycles with identically named idprops on bones.

If multiple bones have a custom property with the same name,
depsgraph didn't distinguish between them, potentially leading
to spurious cycles.

This patch moves ID_PROPERTY operation nodes for bone custom
properties from the parameters component to individual bone
components, thus decoupling them.

Differential Revision: https://developer.blender.org/D13729
This commit is contained in:
Alexander Gavrilov 2022-01-04 14:28:37 +03:00
parent 08aa7861d6
commit 7bcf21e66e
Notes: blender-bot 2023-02-13 19:07:10 +01:00
Referenced by issue #88449: Blender LTS: Maintenance Task 2.93
Referenced by issue #88449, Blender LTS: Maintenance Task 2.93
Referenced by issue #94874, Drivers using bone custom properties don't work on modifiers
Referenced by issue #87039, Pose bone ID property driver causes dependency cycle
4 changed files with 52 additions and 5 deletions

View File

@ -269,6 +269,21 @@ OperationNode *DepsgraphNodeBuilder::add_operation_node(ID *id,
return add_operation_node(id, comp_type, "", opcode, op, name, name_tag);
}
OperationNode *DepsgraphNodeBuilder::ensure_operation_node(ID *id,
NodeType comp_type,
const char *comp_name,
OperationCode opcode,
const DepsEvalOperationCb &op,
const char *name,
int name_tag)
{
OperationNode *operation = find_operation_node(id, comp_type, comp_name, opcode, name, name_tag);
if (operation != nullptr) {
return operation;
}
return add_operation_node(id, comp_type, comp_name, opcode, op, name, name_tag);
}
OperationNode *DepsgraphNodeBuilder::ensure_operation_node(ID *id,
NodeType comp_type,
OperationCode opcode,
@ -1198,8 +1213,16 @@ void DepsgraphNodeBuilder::build_driver_id_property(ID *id, const char *rna_path
return;
}
const char *prop_identifier = RNA_property_identifier((PropertyRNA *)prop);
ensure_operation_node(
id, NodeType::PARAMETERS, OperationCode::ID_PROPERTY, nullptr, prop_identifier);
/* Custom properties of bones are placed in their components to improve granularity. */
if (RNA_struct_is_a(ptr.type, &RNA_PoseBone)) {
const bPoseChannel *pchan = static_cast<const bPoseChannel *>(ptr.data);
ensure_operation_node(
id, NodeType::BONE, pchan->name, OperationCode::ID_PROPERTY, nullptr, prop_identifier);
}
else {
ensure_operation_node(
id, NodeType::PARAMETERS, OperationCode::ID_PROPERTY, nullptr, prop_identifier);
}
}
void DepsgraphNodeBuilder::build_parameters(ID *id)

View File

@ -133,6 +133,13 @@ class DepsgraphNodeBuilder : public DepsgraphBuilder {
const char *name = "",
int name_tag = -1);
OperationNode *ensure_operation_node(ID *id,
NodeType comp_type,
const char *comp_name,
OperationCode opcode,
const DepsEvalOperationCb &op = nullptr,
const char *name = "",
int name_tag = -1);
OperationNode *ensure_operation_node(ID *id,
NodeType comp_type,
OperationCode opcode,

View File

@ -1729,8 +1729,17 @@ void DepsgraphRelationBuilder::build_driver_id_property(ID *id, const char *rna_
return;
}
const char *prop_identifier = RNA_property_identifier((PropertyRNA *)prop);
OperationKey id_property_key(
id, NodeType::PARAMETERS, OperationCode::ID_PROPERTY, prop_identifier);
/* Custom properties of bones are placed in their components to improve granularity. */
OperationKey id_property_key;
if (RNA_struct_is_a(ptr.type, &RNA_PoseBone)) {
const bPoseChannel *pchan = static_cast<const bPoseChannel *>(ptr.data);
id_property_key = OperationKey(
id, NodeType::BONE, pchan->name, OperationCode::ID_PROPERTY, prop_identifier);
}
else {
id_property_key = OperationKey(
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);

View File

@ -181,7 +181,15 @@ RNANodeIdentifier RNANodeQuery::construct_node_identifier(const PointerRNA *ptr,
node_identifier.operation_name_tag = -1;
/* Handling of commonly known scenarios. */
if (rna_prop_affects_parameters_node(ptr, prop)) {
node_identifier.type = NodeType::PARAMETERS;
/* Custom properties of bones are placed in their components to improve granularity. */
if (RNA_struct_is_a(ptr->type, &RNA_PoseBone)) {
const bPoseChannel *pchan = static_cast<const bPoseChannel *>(ptr->data);
node_identifier.type = NodeType::BONE;
node_identifier.component_name = pchan->name;
}
else {
node_identifier.type = NodeType::PARAMETERS;
}
node_identifier.operation_code = OperationCode::ID_PROPERTY;
node_identifier.operation_name = RNA_property_identifier(
reinterpret_cast<const PropertyRNA *>(prop));