Fix T48470: Bendy Bones: Custom Handle References not being cleared when bone deleted
In addition to the original bug report, I've gone through cleaning up a range of related bugs which only became clear when hunting around the code... * Custom Handle References weren't getting cleared when the bones they used got deleted. But, neither was the custom bone shape location/transform reference. * Various places where posebone settings are copied around were also missing code to handle the new Bendy Bone properties. (WHY DO WE HAVE SO MANY VARIATIONS OF COPYING POSE DATA!?!?) * If duplicating a Bendy Bone with custom references, and the custom references are also selected/duplicated, the new Bendy Bones will use the corresponding duplicated bones
This commit is contained in:
parent
75a31c3670
commit
6e416b6bdf
Notes:
blender-bot
2023-02-14 07:52:40 +01:00
Referenced by issue #48470, Bendy Bones: Custom Handle References not being cleared when bone deleted
|
@ -598,7 +598,16 @@ void BKE_pose_copy_data(bPose **dst, bPose *src, const bool copy_constraints)
|
|||
outPose = MEM_callocN(sizeof(bPose), "pose");
|
||||
|
||||
BLI_duplicatelist(&outPose->chanbase, &src->chanbase);
|
||||
|
||||
|
||||
/* Rebuild ghash here too, so that name lookups below won't be too bad...
|
||||
* BUT this will have the penalty that the ghash will be built twice
|
||||
* if BKE_pose_rebuild() gets called after this...
|
||||
*/
|
||||
if (outPose->chanbase.first != outPose->chanbase.last) {
|
||||
outPose->chanhash = NULL;
|
||||
BKE_pose_channels_hash_make(outPose);
|
||||
}
|
||||
|
||||
outPose->iksolver = src->iksolver;
|
||||
outPose->ikdata = NULL;
|
||||
outPose->ikparam = MEM_dupallocN(src->ikparam);
|
||||
|
@ -610,10 +619,16 @@ void BKE_pose_copy_data(bPose **dst, bPose *src, const bool copy_constraints)
|
|||
id_us_plus(&pchan->custom->id);
|
||||
}
|
||||
|
||||
/* warning, O(n2) here, but it's a rarely used feature. */
|
||||
/* warning, O(n2) here, if done without the hash, but these are rarely used features. */
|
||||
if (pchan->custom_tx) {
|
||||
pchan->custom_tx = BKE_pose_channel_find_name(outPose, pchan->custom_tx->name);
|
||||
}
|
||||
if (pchan->bbone_prev) {
|
||||
pchan->bbone_prev = BKE_pose_channel_find_name(outPose, pchan->bbone_prev->name);
|
||||
}
|
||||
if (pchan->bbone_next) {
|
||||
pchan->bbone_next = BKE_pose_channel_find_name(outPose, pchan->bbone_next->name);
|
||||
}
|
||||
|
||||
if (copy_constraints) {
|
||||
BKE_constraints_copy(&listb, &pchan->constraints, true); // BKE_constraints_copy NULLs listb
|
||||
|
@ -728,7 +743,7 @@ void BKE_pose_channels_remove(
|
|||
Object *ob,
|
||||
bool (*filter_fn)(const char *bone_name, void *user_data), void *user_data)
|
||||
{
|
||||
/* First erase any associated pose channel */
|
||||
/* Erase any associated pose channel, along with any references to them */
|
||||
if (ob->pose) {
|
||||
bPoseChannel *pchan, *pchan_next;
|
||||
bConstraint *con;
|
||||
|
@ -737,6 +752,7 @@ void BKE_pose_channels_remove(
|
|||
pchan_next = pchan->next;
|
||||
|
||||
if (filter_fn(pchan->name, user_data)) {
|
||||
/* Bone itself is being removed */
|
||||
BKE_pose_channel_free(pchan);
|
||||
if (ob->pose->chanhash) {
|
||||
BLI_ghash_remove(ob->pose->chanhash, pchan->name, NULL, NULL);
|
||||
|
@ -744,6 +760,7 @@ void BKE_pose_channels_remove(
|
|||
BLI_freelinkN(&ob->pose->chanbase, pchan);
|
||||
}
|
||||
else {
|
||||
/* Maybe something the bone references is being removed instead? */
|
||||
for (con = pchan->constraints.first; con; con = con->next) {
|
||||
const bConstraintTypeInfo *cti = BKE_constraint_typeinfo_get(con);
|
||||
ListBase targets = {NULL, NULL};
|
||||
|
@ -767,6 +784,20 @@ void BKE_pose_channels_remove(
|
|||
cti->flush_constraint_targets(con, &targets, 0);
|
||||
}
|
||||
}
|
||||
|
||||
if (pchan->bbone_prev) {
|
||||
if (filter_fn(pchan->bbone_prev->name, user_data))
|
||||
pchan->bbone_prev = NULL;
|
||||
}
|
||||
if (pchan->bbone_next) {
|
||||
if (filter_fn(pchan->bbone_next->name, user_data))
|
||||
pchan->bbone_next = NULL;
|
||||
}
|
||||
|
||||
if (pchan->custom_tx) {
|
||||
if (filter_fn(pchan->custom_tx->name, user_data))
|
||||
pchan->custom_tx = NULL;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -880,6 +911,15 @@ static void copy_pose_channel_data(bPoseChannel *pchan, const bPoseChannel *chan
|
|||
copy_m4_m4(pchan->pose_mat, (float(*)[4])chan->pose_mat);
|
||||
pchan->flag = chan->flag;
|
||||
|
||||
pchan->roll1 = chan->roll1;
|
||||
pchan->roll2 = chan->roll2;
|
||||
pchan->curveInX = chan->curveInX;
|
||||
pchan->curveInY = chan->curveInY;
|
||||
pchan->curveOutX = chan->curveOutX;
|
||||
pchan->curveOutY = chan->curveOutY;
|
||||
pchan->scaleIn = chan->scaleIn;
|
||||
pchan->scaleOut = chan->scaleOut;
|
||||
|
||||
con = chan->constraints.first;
|
||||
for (pcon = pchan->constraints.first; pcon && con; pcon = pcon->next, con = con->next) {
|
||||
pcon->enforce = con->enforce;
|
||||
|
@ -890,7 +930,7 @@ static void copy_pose_channel_data(bPoseChannel *pchan, const bPoseChannel *chan
|
|||
/**
|
||||
* Copy the internal members of each pose channel including constraints
|
||||
* and ID-Props, used when duplicating bones in editmode.
|
||||
* (unlike copy_pose_channel_data which only).
|
||||
* (unlike copy_pose_channel_data which only does posing-related stuff).
|
||||
*
|
||||
* \note use when copying bones in editmode (on returned value from #BKE_pose_channel_verify)
|
||||
*/
|
||||
|
@ -913,6 +953,11 @@ void BKE_pose_channel_copy_data(bPoseChannel *pchan, const bPoseChannel *pchan_f
|
|||
pchan->ikstretch = pchan_from->ikstretch;
|
||||
pchan->ikrotweight = pchan_from->ikrotweight;
|
||||
pchan->iklinweight = pchan_from->iklinweight;
|
||||
|
||||
/* bbone settings (typically not animated) */
|
||||
pchan->bboneflag = pchan_from->bboneflag;
|
||||
pchan->bbone_next = pchan_from->bbone_next;
|
||||
pchan->bbone_prev = pchan_from->bbone_prev;
|
||||
|
||||
/* constraints */
|
||||
BKE_constraints_copy(&pchan->constraints, &pchan_from->constraints, true);
|
||||
|
@ -1353,8 +1398,13 @@ void BKE_pose_rest(bPose *pose)
|
|||
unit_qt(pchan->quat);
|
||||
unit_axis_angle(pchan->rotAxis, &pchan->rotAngle);
|
||||
pchan->size[0] = pchan->size[1] = pchan->size[2] = 1.0f;
|
||||
|
||||
pchan->flag &= ~(POSE_LOC | POSE_ROT | POSE_SIZE);
|
||||
|
||||
pchan->roll1 = pchan->roll2 = 0.0f;
|
||||
pchan->curveInX = pchan->curveInY = 0.0f;
|
||||
pchan->curveOutX = pchan->curveOutY = 0.0f;
|
||||
pchan->scaleIn = pchan->scaleOut = 1.0f;
|
||||
|
||||
pchan->flag &= ~(POSE_LOC | POSE_ROT | POSE_SIZE | POSE_BBONE_SHAPE);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -1389,9 +1439,19 @@ bool BKE_pose_copy_result(bPose *to, bPose *from)
|
|||
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->scaleIn = pchanfrom->scaleIn;
|
||||
pchanto->scaleOut = pchanfrom->scaleOut;
|
||||
|
||||
pchanto->rotmode = pchanfrom->rotmode;
|
||||
pchanto->flag = pchanfrom->flag;
|
||||
pchanto->protectflag = pchanfrom->protectflag;
|
||||
pchanto->bboneflag = pchanfrom->bboneflag;
|
||||
}
|
||||
}
|
||||
return true;
|
||||
|
|
|
@ -348,6 +348,12 @@ void postEditBoneDuplicate(struct ListBase *editbones, Object *ob)
|
|||
if (pchan_src->custom_tx) {
|
||||
pchan_dst->custom_tx = pchan_duplicate_map(ob->pose, name_map, pchan_src->custom_tx);
|
||||
}
|
||||
if (pchan_src->bbone_prev) {
|
||||
pchan_dst->bbone_prev = pchan_duplicate_map(ob->pose, name_map, pchan_src->bbone_prev);
|
||||
}
|
||||
if (pchan_src->bbone_next) {
|
||||
pchan_dst->bbone_next = pchan_duplicate_map(ob->pose, name_map, pchan_src->bbone_next);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue