Fix T59627: missing COW update tags when joining armatures.

Objects that had constraints or drivers referring to the
joined armatures weren't tagged, and thus evaluated copies
ended up with old bad pointers.
This commit is contained in:
Alexander Gavrilov 2019-05-11 17:53:17 +03:00
parent 5f84e2d732
commit 0e09075e39

@ -66,10 +66,16 @@
/* *************************************** Join *************************************** */
/* NOTE: no operator define here as this is exported to the Object-level operator */
static void joined_armature_fix_links_constraints(
Object *tarArm, Object *srcArm, bPoseChannel *pchan, EditBone *curbone, ListBase *lb)
static void joined_armature_fix_links_constraints(Main *bmain,
Object *ob,
Object *tarArm,
Object *srcArm,
bPoseChannel *pchan,
EditBone *curbone,
ListBase *lb)
{
bConstraint *con;
bool changed = false;
for (con = lb->first; con; con = con->next) {
const bConstraintTypeInfo *cti = BKE_constraint_typeinfo_get(con);
@ -84,10 +90,12 @@ static void joined_armature_fix_links_constraints(
if (ct->tar == srcArm) {
if (ct->subtarget[0] == '\0') {
ct->tar = tarArm;
changed = true;
}
else if (STREQ(ct->subtarget, pchan->name)) {
ct->tar = tarArm;
BLI_strncpy(ct->subtarget, curbone->name, sizeof(ct->subtarget));
changed = true;
}
}
}
@ -104,13 +112,21 @@ static void joined_armature_fix_links_constraints(
if (data->act) {
BKE_action_fix_paths_rename(
&tarArm->id, data->act, "pose.bones[", pchan->name, curbone->name, 0, 0, false);
DEG_id_tag_update_ex(bmain, &data->act->id, ID_RECALC_COPY_ON_WRITE);
}
}
}
if (changed) {
DEG_id_tag_update_ex(bmain, &ob->id, ID_RECALC_COPY_ON_WRITE);
}
}
/* userdata for joined_armature_fix_animdata_cb() */
typedef struct tJoinArmature_AdtFixData {
Main *bmain;
Object *srcArm;
Object *tarArm;
@ -129,6 +145,7 @@ static void joined_armature_fix_animdata_cb(ID *id, FCurve *fcu, void *user_data
ID *dst_id = &afd->tarArm->id;
GHashIterator gh_iter;
bool changed = false;
/* Fix paths - If this is the target object, it will have some "dirty" paths */
if ((id == src_id) && strstr(fcu->rna_path, "pose.bones[")) {
@ -142,6 +159,8 @@ static void joined_armature_fix_animdata_cb(ID *id, FCurve *fcu, void *user_data
fcu->rna_path = BKE_animsys_fix_rna_path_rename(
id, fcu->rna_path, "pose.bones", old_name, new_name, 0, 0, false);
changed = true;
/* we don't want to apply a second remapping on this driver now,
* so stop trying names, but keep fixing drivers
*/
@ -163,6 +182,8 @@ static void joined_armature_fix_animdata_cb(ID *id, FCurve *fcu, void *user_data
if (dtar->id == src_id) {
dtar->id = dst_id;
changed = true;
/* also check on the subtarget...
* XXX: We duplicate the logic from drivers_path_rename_fix() here, with our own
* little twists so that we know that it isn't going to clobber the wrong data
@ -193,6 +214,10 @@ static void joined_armature_fix_animdata_cb(ID *id, FCurve *fcu, void *user_data
DRIVER_TARGETS_LOOPER_END;
}
}
if (changed) {
DEG_id_tag_update_ex(afd->bmain, id, ID_RECALC_COPY_ON_WRITE);
}
}
/* Helper function for armature joining - link fixing */
@ -210,13 +235,14 @@ static void joined_armature_fix_links(
pose = ob->pose;
for (pchant = pose->chanbase.first; pchant; pchant = pchant->next) {
joined_armature_fix_links_constraints(
tarArm, srcArm, pchan, curbone, &pchant->constraints);
bmain, ob, tarArm, srcArm, pchan, curbone, &pchant->constraints);
}
}
/* fix object-level constraints */
if (ob != srcArm) {
joined_armature_fix_links_constraints(tarArm, srcArm, pchan, curbone, &ob->constraints);
joined_armature_fix_links_constraints(
bmain, ob, tarArm, srcArm, pchan, curbone, &ob->constraints);
}
/* See if an object is parented to this armature */
@ -231,6 +257,8 @@ static void joined_armature_fix_links(
/* make tar armature be new parent */
ob->parent = tarArm;
DEG_id_tag_update_ex(bmain, &ob->id, ID_RECALC_COPY_ON_WRITE);
}
}
}
@ -286,6 +314,7 @@ int join_armature_exec(bContext *C, wmOperator *op)
BLI_assert(ob_active->data != ob_iter->data);
/* init callback data for fixing up AnimData links later */
afd.bmain = bmain;
afd.srcArm = ob_iter;
afd.tarArm = ob_active;
afd.names_map = BLI_ghash_str_new("join_armature_adt_fix");