From bb7b1cc884819d2a681f1c93b6bb9c015248aff0 Mon Sep 17 00:00:00 2001 From: Sergey Sharybin Date: Tue, 31 Jul 2018 13:23:01 +0200 Subject: Fix T56170: Fake dependency cycle in new depsgraph + interleaved armature update + proxy Make proxy copy result more atomic operation. --- source/blender/blenkernel/BKE_action.h | 1 + source/blender/blenkernel/BKE_armature.h | 11 +++- source/blender/blenkernel/intern/action.c | 61 ++++++++++---------- source/blender/blenkernel/intern/armature_update.c | 65 +++++++++++++++++----- .../intern/builder/deg_builder_nodes_rig.cc | 17 ++++-- .../intern/builder/deg_builder_relations.cc | 4 -- .../intern/builder/deg_builder_relations_rig.cc | 9 +++ 7 files changed, 117 insertions(+), 51 deletions(-) diff --git a/source/blender/blenkernel/BKE_action.h b/source/blender/blenkernel/BKE_action.h index 106866aff0a..263a54eab4e 100644 --- a/source/blender/blenkernel/BKE_action.h +++ b/source/blender/blenkernel/BKE_action.h @@ -201,6 +201,7 @@ void BKE_pose_remove_group_index(struct bPose *pose, const int index); void what_does_obaction(struct Object *ob, struct Object *workob, struct bPose *pose, struct bAction *act, char groupname[], float cframe); /* for proxy */ +void BKE_pose_copyesult_pchan_result(struct bPoseChannel *pchanto, const struct bPoseChannel *pchanfrom); bool BKE_pose_copy_result(struct bPose *to, struct bPose *from); /* clear all transforms */ void BKE_pose_rest(struct bPose *pose); diff --git a/source/blender/blenkernel/BKE_armature.h b/source/blender/blenkernel/BKE_armature.h index 9e100eb9111..17329beb325 100644 --- a/source/blender/blenkernel/BKE_armature.h +++ b/source/blender/blenkernel/BKE_armature.h @@ -231,9 +231,16 @@ void BKE_pose_eval_flush( struct Scene *scene, struct Object *ob); -void BKE_pose_eval_proxy_copy( +void BKE_pose_eval_proxy_pose_init(struct Depsgraph *depsgraph, + struct Object *object); + +void BKE_pose_eval_proxy_pose_done(struct Depsgraph *depsgraph, + struct Object *object); + +void BKE_pose_eval_proxy_copy_bone( struct Depsgraph *depsgraph, - struct Object *ob); + struct Object *object, + int pchan_index); #ifdef __cplusplus } diff --git a/source/blender/blenkernel/intern/action.c b/source/blender/blenkernel/intern/action.c index cbdabe2c440..6f97187f1e3 100644 --- a/source/blender/blenkernel/intern/action.c +++ b/source/blender/blenkernel/intern/action.c @@ -1328,6 +1328,37 @@ void BKE_pose_rest(bPose *pose) } } +void BKE_pose_copyesult_pchan_result(bPoseChannel *pchanto, const bPoseChannel *pchanfrom) +{ + copy_m4_m4(pchanto->pose_mat, pchanfrom->pose_mat); + copy_m4_m4(pchanto->chan_mat, pchanfrom->chan_mat); + + /* used for local constraints */ + copy_v3_v3(pchanto->loc, pchanfrom->loc); + copy_qt_qt(pchanto->quat, pchanfrom->quat); + copy_v3_v3(pchanto->eul, pchanfrom->eul); + copy_v3_v3(pchanto->size, pchanfrom->size); + + copy_v3_v3(pchanto->pose_head, pchanfrom->pose_head); + copy_v3_v3(pchanto->pose_tail, pchanfrom->pose_tail); + + pchanto->roll1 = pchanfrom->roll1; + pchanto->roll2 = pchanfrom->roll2; + pchanto->curveInX = pchanfrom->curveInX; + pchanto->curveInY = pchanfrom->curveInY; + pchanto->curveOutX = pchanfrom->curveOutX; + pchanto->curveOutY = pchanfrom->curveOutY; + pchanto->ease1 = pchanfrom->ease1; + pchanto->ease2 = pchanfrom->ease2; + pchanto->scaleIn = pchanfrom->scaleIn; + pchanto->scaleOut = pchanfrom->scaleOut; + + pchanto->rotmode = pchanfrom->rotmode; + pchanto->flag = pchanfrom->flag; + pchanto->protectflag = pchanfrom->protectflag; + pchanto->bboneflag = pchanfrom->bboneflag; +} + /* both poses should be in sync */ bool BKE_pose_copy_result(bPose *to, bPose *from) { @@ -1346,34 +1377,8 @@ bool BKE_pose_copy_result(bPose *to, bPose *from) for (pchanfrom = from->chanbase.first; pchanfrom; pchanfrom = pchanfrom->next) { pchanto = BKE_pose_channel_find_name(to, pchanfrom->name); - if (pchanto) { - copy_m4_m4(pchanto->pose_mat, pchanfrom->pose_mat); - copy_m4_m4(pchanto->chan_mat, pchanfrom->chan_mat); - - /* used for local constraints */ - copy_v3_v3(pchanto->loc, pchanfrom->loc); - copy_qt_qt(pchanto->quat, pchanfrom->quat); - copy_v3_v3(pchanto->eul, pchanfrom->eul); - copy_v3_v3(pchanto->size, pchanfrom->size); - - copy_v3_v3(pchanto->pose_head, pchanfrom->pose_head); - copy_v3_v3(pchanto->pose_tail, pchanfrom->pose_tail); - - pchanto->roll1 = pchanfrom->roll1; - pchanto->roll2 = pchanfrom->roll2; - pchanto->curveInX = pchanfrom->curveInX; - pchanto->curveInY = pchanfrom->curveInY; - pchanto->curveOutX = pchanfrom->curveOutX; - pchanto->curveOutY = pchanfrom->curveOutY; - pchanto->ease1 = pchanfrom->ease1; - pchanto->ease2 = pchanfrom->ease2; - pchanto->scaleIn = pchanfrom->scaleIn; - pchanto->scaleOut = pchanfrom->scaleOut; - - pchanto->rotmode = pchanfrom->rotmode; - pchanto->flag = pchanfrom->flag; - pchanto->protectflag = pchanfrom->protectflag; - pchanto->bboneflag = pchanfrom->bboneflag; + if (pchanto != NULL) { + BKE_pose_copyesult_pchan_result(pchanto, pchanfrom); } } return true; diff --git a/source/blender/blenkernel/intern/armature_update.c b/source/blender/blenkernel/intern/armature_update.c index 03d370f6e7c..d53c61255fe 100644 --- a/source/blender/blenkernel/intern/armature_update.c +++ b/source/blender/blenkernel/intern/armature_update.c @@ -558,6 +558,17 @@ void BKE_splineik_execute_tree( /* *************** Depsgraph evaluation callbacks ************ */ +static void pose_pchan_index_create(bPose *pose) +{ + const int num_channels = BLI_listbase_count(&pose->chanbase); + pose->chan_array = MEM_malloc_arrayN( + num_channels, sizeof(bPoseChannel *), "pose->chan_array"); + int pchan_index = 0; + for (bPoseChannel *pchan = pose->chanbase.first; pchan != NULL; pchan = pchan->next) { + pose->chan_array[pchan_index++] = pchan; + } +} + BLI_INLINE bPoseChannel *pose_pchan_get_indexed(Object *ob, int pchan_index) { bPose *pose = ob->pose; @@ -585,16 +596,12 @@ void BKE_pose_eval_init(struct Depsgraph *depsgraph, /* imat is needed for solvers. */ invert_m4_m4(ob->imat, ob->obmat); - const int num_channels = BLI_listbase_count(&pose->chanbase); - pose->chan_array = MEM_malloc_arrayN( - num_channels, sizeof(bPoseChannel *), "pose->chan_array"); - /* clear flags */ - int pchan_index = 0; for (bPoseChannel *pchan = pose->chanbase.first; pchan != NULL; pchan = pchan->next) { pchan->flag &= ~(POSE_DONE | POSE_CHAIN | POSE_IKTREE | POSE_IKSPLINE); - pose->chan_array[pchan_index++] = pchan; } + + pose_pchan_index_create(pose); } void BKE_pose_eval_init_ik(struct Depsgraph *depsgraph, @@ -752,12 +759,44 @@ void BKE_pose_eval_flush(struct Depsgraph *depsgraph, pose->chan_array = NULL; } -void BKE_pose_eval_proxy_copy(struct Depsgraph *depsgraph, Object *ob) +void BKE_pose_eval_proxy_pose_init(struct Depsgraph *depsgraph, Object *object) { - BLI_assert(ID_IS_LINKED(ob) && ob->proxy_from != NULL); - DEG_debug_print_eval(depsgraph, __func__, ob->id.name, ob); - if (BKE_pose_copy_result(ob->pose, ob->proxy_from->pose) == false) { - printf("Proxy copy error, lib Object: %s proxy Object: %s\n", - ob->id.name + 2, ob->proxy_from->id.name + 2); - } + BLI_assert(ID_IS_LINKED(object) && object->proxy_from != NULL); + DEG_debug_print_eval(depsgraph, __func__, object->id.name, object); + + pose_pchan_index_create(object->pose); +} + +void BKE_pose_eval_proxy_pose_done(struct Depsgraph *depsgraph, Object *object) +{ + BLI_assert(ID_IS_LINKED(object) && object->proxy_from != NULL); + DEG_debug_print_eval(depsgraph, __func__, object->id.name, object); + + bPose *pose = object->pose; + BLI_assert(pose->chan_array != NULL); + MEM_freeN(pose->chan_array); + pose->chan_array = NULL; +} + +void BKE_pose_eval_proxy_copy_bone( + struct Depsgraph *depsgraph, + Object *object, + int pchan_index) +{ + BLI_assert(ID_IS_LINKED(object) && object->proxy_from != NULL); + DEG_debug_print_eval(depsgraph, __func__, object->id.name, object); + bPoseChannel *pchan = pose_pchan_get_indexed(object, pchan_index); + /* TODO(sergey): Use indexec lookup, once it's guaranteed to be kept + * around for the time while proxies are evaluating. + */ +#if 0 + bPoseChannel *pchan_from = pose_pchan_get_indexed( + object->proxy_from, pchan_index); +#else + bPoseChannel *pchan_from = BKE_pose_channel_find_name( + object->proxy_from->pose, pchan->name); +#endif + BLI_assert(pchan != NULL); + BLI_assert(pchan_from != NULL); + BKE_pose_copyesult_pchan_result(pchan, pchan_from); } 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 88996dc1f56..b1486e82af5 100644 --- a/source/blender/depsgraph/intern/builder/deg_builder_nodes_rig.cc +++ b/source/blender/depsgraph/intern/builder/deg_builder_nodes_rig.cc @@ -314,12 +314,13 @@ void DepsgraphNodeBuilder::build_proxy_rig(Object *object) } op_node = add_operation_node(&object->id, DEG_NODE_TYPE_EVAL_POSE, - function_bind(BKE_pose_eval_proxy_copy, + function_bind(BKE_pose_eval_proxy_pose_init, _1, object_cow), DEG_OPCODE_POSE_INIT); op_node->set_as_entry(); + int pchan_index = 0; LISTBASE_FOREACH (bPoseChannel *, pchan, &object->pose->chanbase) { op_node = add_operation_node(&object->id, DEG_NODE_TYPE_BONE, @@ -334,10 +335,14 @@ void DepsgraphNodeBuilder::build_proxy_rig(Object *object) NULL, DEG_OPCODE_BONE_READY); /* Bone is fully evaluated. */ - op_node = add_operation_node(&object->id, + op_node = add_operation_node( + &object->id, DEG_NODE_TYPE_BONE, pchan->name, - NULL, + function_bind(BKE_pose_eval_proxy_copy_bone, + _1, + object_cow, + pchan_index), DEG_OPCODE_BONE_DONE); op_node->set_as_exit(); @@ -349,10 +354,14 @@ void DepsgraphNodeBuilder::build_proxy_rig(Object *object) DEG_OPCODE_PARAMETERS_EVAL, pchan->name); } + + pchan_index++; } op_node = add_operation_node(&object->id, DEG_NODE_TYPE_EVAL_POSE, - NULL, + function_bind(BKE_pose_eval_proxy_pose_done, + _1, + object_cow), DEG_OPCODE_POSE_DONE); op_node->set_as_exit(); } diff --git a/source/blender/depsgraph/intern/builder/deg_builder_relations.cc b/source/blender/depsgraph/intern/builder/deg_builder_relations.cc index 1d01b3e987b..4f94066f3bb 100644 --- a/source/blender/depsgraph/intern/builder/deg_builder_relations.cc +++ b/source/blender/depsgraph/intern/builder/deg_builder_relations.cc @@ -587,10 +587,6 @@ void DepsgraphRelationBuilder::build_object(Base *base, Object *object) /* Proxy object to copy from. */ if (object->proxy_from != NULL) { build_object(NULL, object->proxy_from); - ComponentKey ob_pose_key(&object->proxy_from->id, DEG_NODE_TYPE_EVAL_POSE); - ComponentKey proxy_pose_key(&object->id, DEG_NODE_TYPE_EVAL_POSE); - add_relation(ob_pose_key, proxy_pose_key, "Proxy Pose"); - ComponentKey ob_transform_key(&object->proxy_from->id, DEG_NODE_TYPE_TRANSFORM); ComponentKey proxy_transform_key(&object->id, DEG_NODE_TYPE_TRANSFORM); add_relation(ob_transform_key, proxy_transform_key, "Proxy Transform"); 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 eaa17d27ffc..811986ea0e8 100644 --- a/source/blender/depsgraph/intern/builder/deg_builder_relations_rig.cc +++ b/source/blender/depsgraph/intern/builder/deg_builder_relations_rig.cc @@ -469,11 +469,20 @@ void DepsgraphRelationBuilder::build_proxy_rig(Object *object) DEG_NODE_TYPE_BONE, pchan->name, DEG_OPCODE_BONE_DONE); + OperationKey from_bone_done_key(&proxy_from->id, + DEG_NODE_TYPE_BONE, + pchan->name, + DEG_OPCODE_BONE_DONE); add_relation(pose_init_key, bone_local_key, "Pose Init -> Bone Local"); add_relation(bone_local_key, bone_ready_key, "Local -> Ready"); add_relation(bone_ready_key, bone_done_key, "Ready -> Done"); add_relation(bone_done_key, pose_done_key, "Bone Done -> Pose Done"); + /* Make sure bone in the proxy is not done before it's FROM is done. */ + add_relation(from_bone_done_key, + bone_done_key, + "From Bone Done -> Pose Done"); + if (pchan->prop != NULL) { OperationKey bone_parameters(&object->id, DEG_NODE_TYPE_PARAMETERS, -- cgit v1.2.3