Fix T56170: Fake dependency cycle in new depsgraph + interleaved armature update...
authorSergey Sharybin <sergey.vfx@gmail.com>
Tue, 31 Jul 2018 11:23:01 +0000 (13:23 +0200)
committerSergey Sharybin <sergey.vfx@gmail.com>
Tue, 31 Jul 2018 11:24:57 +0000 (13:24 +0200)
Make proxy copy result more atomic operation.

source/blender/blenkernel/BKE_action.h
source/blender/blenkernel/BKE_armature.h
source/blender/blenkernel/intern/action.c
source/blender/blenkernel/intern/armature_update.c
source/blender/depsgraph/intern/builder/deg_builder_nodes_rig.cc
source/blender/depsgraph/intern/builder/deg_builder_relations.cc
source/blender/depsgraph/intern/builder/deg_builder_relations_rig.cc

index 106866aff0a64a06ac4be6b331761407107ebd54..263a54eab4e01e0e053679c117dee26f03a35ee0 100644 (file)
@@ -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);
index 9e100eb91110ff702b0e18e8e50e7bcca35bed25..17329beb325c9196b871a6fce128f84981150e8f 100644 (file)
@@ -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
 }
index cbdabe2c4405d86fe104bf42b10ae7fd4f4cc4cb..6f97187f1e3fd3af9767a51b6e4fd4ef07e0a634 100644 (file)
@@ -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;
index 03d370f6e7c5cecd68be9744254ed229689a5246..d53c61255fe9f522d4154e8c16f88d5aad7c2ac4 100644 (file)
@@ -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);
 }
index 88996dc1f5695eb91855a80e008edf833819825e..b1486e82af53e28295a4ae9465f593d50d18d3dc 100644 (file)
@@ -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();
 }
index 1d01b3e987b71370db5463cb8417e2ecfc0a3389..4f94066f3bb660ac3f4f27008e8d63cb4aa26909 100644 (file)
@@ -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");
index eaa17d27ffcc36b24a471375968860c2977b8beb..811986ea0e8dddf413e9916a5a3b4d60980943c6 100644 (file)
@@ -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,