Fix (unreported) crash in some case when remapping armature data.

Those bone pointers in object's pose bite again - turns out they can be accessed
before pose actually gets rebuilt in some cases (e.g. from undo writefile), so
we need to clear the pointers immediately.
This commit is contained in:
Bastien Montagne 2016-07-21 16:15:00 +02:00
parent b156674251
commit af2deb5438
3 changed files with 16 additions and 4 deletions

View File

@ -95,6 +95,7 @@ float distfactor_to_bone(const float vec[3], const float b1[3], const float b2[3
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_rebuild(struct Object *ob, struct bArmature *arm);
void BKE_pose_where_is(struct Scene *scene, struct Object *ob);
void BKE_pose_where_is_bone(struct Scene *scene, struct Object *ob, struct bPoseChannel *pchan, float ctime, bool do_extra);

View File

@ -1906,6 +1906,17 @@ static int rebuild_pose_bone(bPose *pose, Bone *bone, bPoseChannel *parchan, int
return counter;
}
/**
* Clear pointers of object's pose (needed in remap case, since we cannot always wait for a complete pose rebuild).
*/
void BKE_pose_clear_pointers(bPose *pose)
{
for (bPoseChannel *pchan = pose->chanbase.first; pchan; pchan = pchan->next) {
pchan->bone = NULL;
pchan->child = 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)
@ -1926,10 +1937,7 @@ void BKE_pose_rebuild(Object *ob, bArmature *arm)
pose = ob->pose;
/* clear */
for (pchan = pose->chanbase.first; pchan; pchan = pchan->next) {
pchan->bone = NULL;
pchan->child = NULL;
}
BKE_pose_clear_pointers(pose);
/* first step, check if all channels are there */
for (bone = arm->bonebase.first; bone; bone = bone->next) {

View File

@ -296,6 +296,9 @@ static void libblock_remap_data_preprocess(IDRemap *r_id_remap_data)
if (ob->pose && (!old_id || ob->data == old_id)) {
BLI_assert(ob->type == OB_ARMATURE);
ob->pose->flag |= POSE_RECALC;
/* We need to clear pose bone pointers immediately, things like undo writefile may be called
* before pose is actually recomputed, can lead to segfault... */
BKE_pose_clear_pointers(ob->pose);
}
}
break;