Fix T87631: Crash undoing edit-mode bone duplication

Edit mode could leave pose channels in the object that didn't
have an associated bone.

These are now cleared when freeing edit-mode data.
This commit is contained in:
Campbell Barton 2021-04-28 13:20:12 +10:00
parent a4191c2d18
commit 6eb2f71875
Notes: blender-bot 2023-02-14 05:51:15 +01:00
Referenced by commit 28828e0041, Add NULL check to Object.pose from 6eb2f71875
Referenced by commit 2bf3a960bd, Remove include accidentally added in 6eb2f71875
Referenced by issue #87631, Segfault on undo-ing mode switching and bone duplication
4 changed files with 22 additions and 9 deletions

View File

@ -178,6 +178,7 @@ void BKE_armature_where_is_bone(struct Bone *bone,
void BKE_pose_clear_pointers(struct bPose *pose);
void BKE_pose_remap_bone_pointers(struct bArmature *armature, struct bPose *pose);
void BKE_pchan_rebuild_bbone_handles(struct bPose *pose, struct bPoseChannel *pchan);
void BKE_pose_channels_clear_with_null_bone(struct bPose *pose, const bool do_id_user);
void BKE_pose_rebuild(struct Main *bmain,
struct Object *ob,
struct bArmature *arm,

View File

@ -2515,6 +2515,17 @@ void BKE_pchan_rebuild_bbone_handles(bPose *pose, bPoseChannel *pchan)
pchan->bbone_next = pose_channel_find_bone(pose, pchan->bone->bbone_next);
}
void BKE_pose_channels_clear_with_null_bone(bPose *pose, const bool do_id_user)
{
LISTBASE_FOREACH_MUTABLE (bPoseChannel *, pchan, &pose->chanbase) {
if (pchan->bone == NULL) {
BKE_pose_channel_free_ex(pchan, do_id_user);
BKE_pose_channels_hash_free(pose);
BLI_freelinkN(&pose->chanbase, pchan);
}
}
}
/**
* Only after leave editmode, duplicating, validating older files, library syncing.
*
@ -2526,7 +2537,7 @@ void BKE_pose_rebuild(Main *bmain, Object *ob, bArmature *arm, const bool do_id_
{
Bone *bone;
bPose *pose;
bPoseChannel *pchan, *next;
bPoseChannel *pchan;
int counter = 0;
/* only done here */
@ -2549,14 +2560,7 @@ void BKE_pose_rebuild(Main *bmain, Object *ob, bArmature *arm, const bool do_id_
}
/* and a check for garbage */
for (pchan = pose->chanbase.first; pchan; pchan = next) {
next = pchan->next;
if (pchan->bone == NULL) {
BKE_pose_channel_free_ex(pchan, do_id_user);
BKE_pose_channels_hash_free(pose);
BLI_freelinkN(&pose->chanbase, pchan);
}
}
BKE_pose_channels_clear_with_null_bone(pose, do_id_user);
BKE_pose_channels_hash_make(pose);

View File

@ -55,6 +55,7 @@
#include "IMB_imbuf_types.h"
#include "BKE_anim_visualization.h"
#include "BKE_armature.h"
#include "BKE_collection.h"
#include "BKE_constraint.h"
#include "BKE_context.h"
@ -578,6 +579,12 @@ static bool ED_object_editmode_load_free_ex(Main *bmain,
if (free_data) {
ED_armature_edit_free(obedit->data);
if (load_data == false) {
/* Don't keep unused pose channels created by duplicating bones
* which may have been deleted/undone, see: T87631. */
BKE_pose_channels_clear_with_null_bone(obedit->pose, true);
}
}
/* TODO(sergey): Pose channels might have been changed, so need
* to inform dependency graph about this. But is it really the

View File

@ -33,6 +33,7 @@
#include "BLT_translation.h"
#include "BKE_armature.h"
#include "BKE_global.h"
#include "BKE_main.h"
#include "BKE_material.h"