Fix #140969: Joining armature objects that share their data fails assertion

Add a precondition check that verifies all to-be-joined armatures are
unique. If this is detected, an error is shown and the operator is
aborted.

Joining shared Armatures is non-trivial, because the corresponding
pose bones may actually have different drivers or constraints on them
(because those live on the Object ID, and not the Armature).
Duplicating any shared Armature ID could be a first step, but I am not
convinced this is always the right approach. This is why joining
shared Armatures is not supported for now. Users can choose how to
make each Armature unique, either by deselecting objects or by
duplicating their data.

Pull Request: https://projects.blender.org/blender/blender/pulls/140971
This commit is contained in:
Sybren A. Stüvel
2025-06-26 11:01:41 +02:00
parent 7e17ec5562
commit 2ce3e8c877

View File

@@ -333,6 +333,30 @@ wmOperatorStatus ED_armature_join_objects_exec(bContext *C, wmOperator *op)
return OPERATOR_CANCELLED;
}
/* Check that there are no shared Armatures, as the code below assumes that
* each to-be-joined Armature is unique. */
{
blender::Set<const bArmature *> seen_armatures;
CTX_DATA_BEGIN (C, const Object *, ob_iter, selected_editable_objects) {
if (ob_iter->type != OB_ARMATURE) {
continue;
}
const bArmature *armature = static_cast<bArmature *>(ob_iter->data);
if (seen_armatures.add(armature)) {
/* Armature pointer was added to the set, which means it wasn't seen before. */
continue;
}
BKE_reportf(op->reports,
RPT_ERROR,
"Cannot join objects that share armature data: %s",
armature->id.name + 2);
return OPERATOR_CANCELLED;
}
CTX_DATA_END;
}
/* Inverse transform for all selected armatures in this object,
* See #object_join_exec for detailed comment on why the safe version is used. */
invert_m4_m4_safe_ortho(oimat, ob_active->object_to_world().ptr());