Fix T55973: [2.8] Crash when 'apply pose as rest pose' when bone scale is 0,0,0.
authorBastien Montagne <montagne29@wanadoo.fr>
Thu, 19 Jul 2018 14:48:21 +0000 (16:48 +0200)
committerBastien Montagne <montagne29@wanadoo.fr>
Fri, 20 Jul 2018 08:22:06 +0000 (10:22 +0200)
`BKE_pose_rebuild()` should (ideally) always trigger a rebuild of the
depsgraph, since it can add or remove posechannels.

This function now takes a Main parameter to ensure that related
depsgraphes are tagged as dirty (kept it optional, for some corner cases).

We should also probably double-check calls to that function, think in
theory it should only be called from depsgraph itself? But for now...

12 files changed:
source/blender/blenkernel/BKE_armature.h
source/blender/blenkernel/BKE_object.h
source/blender/blenkernel/intern/armature.c
source/blender/blenkernel/intern/library.c
source/blender/blenkernel/intern/object.c
source/blender/blenkernel/intern/scene.c
source/blender/depsgraph/intern/builder/deg_builder_nodes_rig.cc
source/blender/draw/intern/draw_armature.c
source/blender/editors/armature/armature_utils.c
source/blender/editors/object/object_add.c
source/blender/editors/object/object_relations.c
source/blender/makesrna/intern/rna_object.c

index e1bfb05fb5902c2cf47f5398bf51f3e0fc779736..21d880cf2a7ba193f3ec560194d4b0e29707d8c1 100644 (file)
@@ -100,7 +100,7 @@ void BKE_armature_where_is(struct bArmature *arm);
 void BKE_armature_where_is_bone(struct Bone *bone, struct Bone *prevbone, const bool use_recursion);
 void BKE_pose_clear_pointers(struct bPose *pose);
 void BKE_pose_remap_bone_pointers(struct bArmature *armature, struct bPose *pose);
 void BKE_armature_where_is_bone(struct Bone *bone, struct Bone *prevbone, const bool use_recursion);
 void BKE_pose_clear_pointers(struct bPose *pose);
 void BKE_pose_remap_bone_pointers(struct bArmature *armature, struct bPose *pose);
-void BKE_pose_rebuild(struct Object *ob, struct bArmature *arm);
+void BKE_pose_rebuild(struct Main *bmain, struct Object *ob, struct bArmature *arm);
 void BKE_pose_where_is(struct Depsgraph *depsgraph, struct Scene *scene, struct Object *ob);
 void BKE_pose_where_is_bone(struct Depsgraph *depsgraph, struct Scene *scene, struct Object *ob, struct bPoseChannel *pchan, float ctime, bool do_extra);
 void BKE_pose_where_is_bone_tail(struct bPoseChannel *pchan);
 void BKE_pose_where_is(struct Depsgraph *depsgraph, struct Scene *scene, struct Object *ob);
 void BKE_pose_where_is_bone(struct Depsgraph *depsgraph, struct Scene *scene, struct Object *ob, struct bPoseChannel *pchan, float ctime, bool do_extra);
 void BKE_pose_where_is_bone_tail(struct bPoseChannel *pchan);
index 0122185fd2a3fabfb1b1b9a4b3b6c0cbfe84cf11..79e4f1d448a968df7200c6efc7b5e9a7561b5368 100644 (file)
@@ -75,7 +75,7 @@ bool BKE_object_support_modifier_type_check(const struct Object *ob, int modifie
 void BKE_object_link_modifiers(struct Scene *scene, struct Object *ob_dst, const struct Object *ob_src);
 void BKE_object_free_modifiers(struct Object *ob, const int flag);
 
 void BKE_object_link_modifiers(struct Scene *scene, struct Object *ob_dst, const struct Object *ob_src);
 void BKE_object_free_modifiers(struct Object *ob, const int flag);
 
-void BKE_object_make_proxy(struct Object *ob, struct Object *target, struct Object *gob);
+void BKE_object_make_proxy(struct Main *bmain, struct Object *ob, struct Object *target, struct Object *gob);
 void BKE_object_copy_proxy_drivers(struct Object *ob, struct Object *target);
 
 bool BKE_object_exists_check(struct Main *bmain, const struct Object *obtest);
 void BKE_object_copy_proxy_drivers(struct Object *ob, struct Object *target);
 
 bool BKE_object_exists_check(struct Main *bmain, const struct Object *obtest);
index bd9ee7c9e5ffea8f177edac6f965370e6eb8c8fb..6be4574a62ee844419b897f48e091af7b8c80814 100644 (file)
@@ -71,6 +71,8 @@
 #include "BKE_object.h"
 #include "BKE_scene.h"
 
 #include "BKE_object.h"
 #include "BKE_scene.h"
 
+#include "DEG_depsgraph_build.h"
+
 #include "BIK_api.h"
 
 /* **************** Generic Functions, data level *************** */
 #include "BIK_api.h"
 
 /* **************** Generic Functions, data level *************** */
@@ -1951,9 +1953,14 @@ void BKE_pose_remap_bone_pointers(bArmature *armature, bPose *pose)
        BLI_ghash_free(bone_hash, NULL, NULL);
 }
 
        BLI_ghash_free(bone_hash, NULL, NULL);
 }
 
-/* only after leave editmode, duplicating, validating older files, library syncing */
-/* NOTE: pose->flag is set for it */
-void BKE_pose_rebuild(Object *ob, bArmature *arm)
+/**
+ * Only after leave editmode, duplicating, validating older files, library syncing.
+ *
+ * \note pose->flag is set for it.
+ *
+ * \param bmain May be NULL, only used to tag depsgraph as being dirty...
+ */
+void BKE_pose_rebuild(Main *bmain, Object *ob, bArmature *arm)
 {
        Bone *bone;
        bPose *pose;
 {
        Bone *bone;
        bPose *pose;
@@ -1998,12 +2005,17 @@ void BKE_pose_rebuild(Object *ob, bArmature *arm)
                pose_proxy_synchronize(ob, ob->proxy, arm->layer_protected);
        }
 
                pose_proxy_synchronize(ob, ob->proxy, arm->layer_protected);
        }
 
-       BKE_pose_update_constraint_flags(ob->pose); /* for IK detection for example */
+       BKE_pose_update_constraint_flags(pose); /* for IK detection for example */
+
+       pose->flag &= ~POSE_RECALC;
+       pose->flag |= POSE_WAS_REBUILT;
 
 
-       ob->pose->flag &= ~POSE_RECALC;
-       ob->pose->flag |= POSE_WAS_REBUILT;
+       BKE_pose_channels_hash_make(pose);
 
 
-       BKE_pose_channels_hash_make(ob->pose);
+       /* Rebuilding poses forces us to also rebuild the dependency graph, since there is one node per pose/bone... */
+       if (bmain != NULL) {
+               DEG_relations_tag_update(bmain);
+       }
 }
 
 /* ********************** THE POSE SOLVER ******************* */
 }
 
 /* ********************** THE POSE SOLVER ******************* */
@@ -2277,8 +2289,10 @@ void BKE_pose_where_is(struct Depsgraph *depsgraph, Scene *scene, Object *ob)
 
        if (ELEM(NULL, arm, scene))
                return;
 
        if (ELEM(NULL, arm, scene))
                return;
-       if ((ob->pose == NULL) || (ob->pose->flag & POSE_RECALC))
-               BKE_pose_rebuild(ob, arm);
+       if ((ob->pose == NULL) || (ob->pose->flag & POSE_RECALC)) {
+               /* WARNING! passing NULL bmain here means we won't tag depsgraph's as dirty - hopefully this is OK. */
+               BKE_pose_rebuild(NULL, ob, arm);
+       }
 
        ctime = BKE_scene_frame_get(scene); /* not accurate... */
 
 
        ctime = BKE_scene_frame_get(scene); /* not accurate... */
 
index c2cdc8df1e671fc68d9f2cfc4e1933c2b7d44588..351214ed72b5d41d827c5a6a73e2c65725b4bfd7 100644 (file)
@@ -2464,7 +2464,7 @@ void BKE_library_make_local(
         * Try "make all local" in 04_01_H.lighting.blend from Agent327 without this, e.g. */
        for (Object *ob = bmain->object.first; ob; ob = ob->id.next) {
                if (ob->data != NULL && ob->type == OB_ARMATURE && ob->pose != NULL && ob->pose->flag & POSE_RECALC) {
         * Try "make all local" in 04_01_H.lighting.blend from Agent327 without this, e.g. */
        for (Object *ob = bmain->object.first; ob; ob = ob->id.next) {
                if (ob->data != NULL && ob->type == OB_ARMATURE && ob->pose != NULL && ob->pose->flag & POSE_RECALC) {
-                       BKE_pose_rebuild(ob, ob->data);
+                       BKE_pose_rebuild(bmain, ob, ob->data);
                }
        }
 
                }
        }
 
index 14794bd7061262a5733894a314cc406c1d9fa79c..33ea13c9a387a08640b6d784cd0c3f1fd6771a97 100644 (file)
@@ -1150,7 +1150,7 @@ void BKE_object_transform_copy(Object *ob_tar, const Object *ob_src)
  *
  * \param flag  Copying options (see BKE_library.h's LIB_ID_COPY_... flags for more).
  */
  *
  * \param flag  Copying options (see BKE_library.h's LIB_ID_COPY_... flags for more).
  */
-void BKE_object_copy_data(Main *UNUSED(bmain), Object *ob_dst, const Object *ob_src, const int flag)
+void BKE_object_copy_data(Main *bmain, Object *ob_dst, const Object *ob_src, const int flag)
 {
        ModifierData *md;
 
 {
        ModifierData *md;
 
@@ -1180,7 +1180,7 @@ void BKE_object_copy_data(Main *UNUSED(bmain), Object *ob_dst, const Object *ob_
                copy_object_pose(ob_dst, ob_src, flag_subdata);
                /* backwards compat... non-armatures can get poses in older files? */
                if (ob_src->type == OB_ARMATURE)
                copy_object_pose(ob_dst, ob_src, flag_subdata);
                /* backwards compat... non-armatures can get poses in older files? */
                if (ob_src->type == OB_ARMATURE)
-                       BKE_pose_rebuild(ob_dst, ob_dst->data);
+                       BKE_pose_rebuild(bmain, ob_dst, ob_dst->data);
        }
        defgroup_copy_list(&ob_dst->defbase, &ob_src->defbase);
        BKE_object_facemap_copy_list(&ob_dst->fmaps, &ob_src->fmaps);
        }
        defgroup_copy_list(&ob_dst->defbase, &ob_src->defbase);
        BKE_object_facemap_copy_list(&ob_dst->fmaps, &ob_src->fmaps);
@@ -1359,7 +1359,7 @@ void BKE_object_copy_proxy_drivers(Object *ob, Object *target)
 /*             local_object->proxy == pointer to library object, saved in files and read */
 /*             local_object->proxy_group == pointer to collection dupli-object, saved in files and read */
 
 /*             local_object->proxy == pointer to library object, saved in files and read */
 /*             local_object->proxy_group == pointer to collection dupli-object, saved in files and read */
 
-void BKE_object_make_proxy(Object *ob, Object *target, Object *cob)
+void BKE_object_make_proxy(Main *bmain, Object *ob, Object *target, Object *cob)
 {
        /* paranoia checks */
        if (ID_IS_LINKED(ob) || !ID_IS_LINKED(target)) {
 {
        /* paranoia checks */
        if (ID_IS_LINKED(ob) || !ID_IS_LINKED(target)) {
@@ -1434,7 +1434,7 @@ void BKE_object_make_proxy(Object *ob, Object *target, Object *cob)
        if (target->type == OB_ARMATURE) {
                copy_object_pose(ob, target, 0);   /* data copy, object pointers in constraints */
                BKE_pose_rest(ob->pose);            /* clear all transforms in channels */
        if (target->type == OB_ARMATURE) {
                copy_object_pose(ob, target, 0);   /* data copy, object pointers in constraints */
                BKE_pose_rest(ob->pose);            /* clear all transforms in channels */
-               BKE_pose_rebuild(ob, ob->data); /* set all internal links */
+               BKE_pose_rebuild(bmain, ob, ob->data); /* set all internal links */
 
                armature_set_id_extern(ob);
        }
 
                armature_set_id_extern(ob);
        }
@@ -2698,8 +2698,10 @@ void BKE_object_handle_update_ex(Depsgraph *depsgraph,
                         * with poses we do it ahead of BKE_object_where_is_calc to ensure animation
                         * is evaluated on the rebuilt pose, otherwise we get incorrect poses
                         * on file load */
                         * with poses we do it ahead of BKE_object_where_is_calc to ensure animation
                         * is evaluated on the rebuilt pose, otherwise we get incorrect poses
                         * on file load */
-                       if (ob->pose == NULL || (ob->pose->flag & POSE_RECALC))
-                               BKE_pose_rebuild(ob, ob->data);
+                       if (ob->pose == NULL || (ob->pose->flag & POSE_RECALC)) {
+                               /* No need to pass bmain here, we assume we do not need to rebuild DEG from here... */
+                               BKE_pose_rebuild(NULL, ob, ob->data);
+                       }
                }
        }
        /* XXX new animsys warning: depsgraph tag OB_RECALC_DATA should not skip drivers,
                }
        }
        /* XXX new animsys warning: depsgraph tag OB_RECALC_DATA should not skip drivers,
index f99a30b75d07ecc4a6b85b1c770535d16b264dbd..3650fa21c1c1543ba1cbaa8b3522630457daf383 100644 (file)
@@ -1288,7 +1288,7 @@ static void scene_armature_depsgraph_workaround(Main *bmain, Depsgraph *depsgrap
        for (ob = bmain->object.first; ob; ob = ob->id.next) {
                if (ob->type == OB_ARMATURE && ob->adt && ob->adt->recalc & ADT_RECALC_ANIM) {
                        if (ob->pose == NULL || (ob->pose->flag & POSE_RECALC)) {
        for (ob = bmain->object.first; ob; ob = ob->id.next) {
                if (ob->type == OB_ARMATURE && ob->adt && ob->adt->recalc & ADT_RECALC_ANIM) {
                        if (ob->pose == NULL || (ob->pose->flag & POSE_RECALC)) {
-                               BKE_pose_rebuild(ob, ob->data);
+                               BKE_pose_rebuild(bmain, ob, ob->data);
                        }
                }
        }
                        }
                }
        }
index 00d7a5da45570f498475cd4d6baa1c979b9d7bf8..043148a0f70712c19e565d087badd10a977c9b56 100644 (file)
@@ -161,7 +161,8 @@ void DepsgraphNodeBuilder::build_rig(Object *object)
        build_armature(armature);
        /* Rebuild pose if not up to date. */
        if (object->pose == NULL || (object->pose->flag & POSE_RECALC)) {
        build_armature(armature);
        /* Rebuild pose if not up to date. */
        if (object->pose == NULL || (object->pose->flag & POSE_RECALC)) {
-               BKE_pose_rebuild(object, armature);
+               /* By definition, no need to tag depsgraph as dirty from here, so we can pass NULL bmain. */
+               BKE_pose_rebuild(NULL, object, armature);
                /* XXX: Without this animation gets lost in certain circumstances
                 * after loading file. Need to investigate further since it does
                 * not happen with simple scenes..
                /* XXX: Without this animation gets lost in certain circumstances
                 * after loading file. Need to investigate further since it does
                 * not happen with simple scenes..
index b49ca4d0d004f0b7229663fc333d3a15d8232c0a..8b90d3285416c8198048fa425f5c7026aeefd9e7 100644 (file)
@@ -1623,7 +1623,7 @@ static void draw_armature_pose(Object *ob, const float const_color[4])
 
        /* We can't safely draw non-updated pose, might contain NULL bone pointers... */
        if (ob->pose->flag & POSE_RECALC) {
 
        /* We can't safely draw non-updated pose, might contain NULL bone pointers... */
        if (ob->pose->flag & POSE_RECALC) {
-               BKE_pose_rebuild(ob, arm);
+               BKE_pose_rebuild(NULL, ob, arm);
        }
 
        // if (!(base->flag & OB_FROMDUPLI)) // TODO
        }
 
        // if (!(base->flag & OB_FROMDUPLI)) // TODO
index 02d45a4e041d315d135c5414078ff73bc91146b1..c93bfb5d8c30d68c588934e6a7557fcf0305e0ed 100644 (file)
@@ -681,7 +681,7 @@ void ED_armature_from_edit(Main *bmain, bArmature *arm)
        /* so all users of this armature should get rebuilt */
        for (obt = bmain->object.first; obt; obt = obt->id.next) {
                if (obt->data == arm) {
        /* so all users of this armature should get rebuilt */
        for (obt = bmain->object.first; obt; obt = obt->id.next) {
                if (obt->data == arm) {
-                       BKE_pose_rebuild(obt, arm);
+                       BKE_pose_rebuild(bmain, obt, arm);
                }
        }
 
                }
        }
 
index a8917f4c4aa4aa6d1e58a1ec3209d27bbd0ddf98..8c60dd01e89e0724afd26371d3830b231834b1b0 100644 (file)
@@ -2222,7 +2222,7 @@ static Base *object_add_duplicate_internal(Main *bmain, Scene *scene, ViewLayer
                                        ID_NEW_REMAP_US2(obn->data)
                                        else {
                                                obn->data = ID_NEW_SET(obn->data, BKE_armature_copy(bmain, obn->data));
                                        ID_NEW_REMAP_US2(obn->data)
                                        else {
                                                obn->data = ID_NEW_SET(obn->data, BKE_armature_copy(bmain, obn->data));
-                                               BKE_pose_rebuild(obn, obn->data);
+                                               BKE_pose_rebuild(bmain, obn, obn->data);
                                                didit = 1;
                                        }
                                        id_us_min(id);
                                                didit = 1;
                                        }
                                        id_us_min(id);
index 324b6eca34ae92bd8089df7439cac8e8e46df9e7..2c3ff8b6afe53fc658e61c91cb92e02f6dce4925 100644 (file)
@@ -360,7 +360,7 @@ static int make_proxy_exec(bContext *C, wmOperator *op)
                newob = BKE_object_add_from(bmain, scene, view_layer, OB_EMPTY, name, gob ? gob : ob);
 
                /* set layers OK */
                newob = BKE_object_add_from(bmain, scene, view_layer, OB_EMPTY, name, gob ? gob : ob);
 
                /* set layers OK */
-               BKE_object_make_proxy(newob, ob, gob);
+               BKE_object_make_proxy(bmain, newob, ob, gob);
 
                /* Set back pointer immediately so dependency graph knows that this is
                 * is a proxy and will act accordingly. Otherwise correctness of graph
 
                /* Set back pointer immediately so dependency graph knows that this is
                 * is a proxy and will act accordingly. Otherwise correctness of graph
@@ -1809,7 +1809,7 @@ static void single_obdata_users(Main *bmain, Scene *scene, ViewLayer *view_layer
                                        case OB_ARMATURE:
                                                DEG_id_tag_update(&ob->id, OB_RECALC_DATA);
                                                ob->data = ID_NEW_SET(ob->data, BKE_armature_copy(bmain, ob->data));
                                        case OB_ARMATURE:
                                                DEG_id_tag_update(&ob->id, OB_RECALC_DATA);
                                                ob->data = ID_NEW_SET(ob->data, BKE_armature_copy(bmain, ob->data));
-                                               BKE_pose_rebuild(ob, ob->data);
+                                               BKE_pose_rebuild(bmain, ob, ob->data);
                                                break;
                                        case OB_SPEAKER:
                                                ob->data = ID_NEW_SET(ob->data, BKE_speaker_copy(bmain, ob->data));
                                                break;
                                        case OB_SPEAKER:
                                                ob->data = ID_NEW_SET(ob->data, BKE_speaker_copy(bmain, ob->data));
index 2bdfbade53aa5c11775e49c2805911c7995f1d07..ac1a6d512c368340cb9194e46fcfacae54fa78f1 100644 (file)
@@ -356,10 +356,12 @@ static void rna_Object_data_set(PointerRNA *ptr, PointerRNA value)
                ob->data = id;
                test_object_materials(G_MAIN, ob, id);
 
                ob->data = id;
                test_object_materials(G_MAIN, ob, id);
 
-               if (GS(id->name) == ID_CU)
+               if (GS(id->name) == ID_CU) {
                        BKE_curve_type_test(ob);
                        BKE_curve_type_test(ob);
-               else if (ob->type == OB_ARMATURE)
-                       BKE_pose_rebuild(ob, ob->data);
+               }
+               else if (ob->type == OB_ARMATURE) {
+                       BKE_pose_rebuild(G_MAIN, ob, ob->data);
+               }
        }
 }
 
        }
 }