Anim: copy bone collection parenting and visibility in armature join.

When joining armatures, make sure to preserve parenting relations
of bone collections. Also, copy and update the visibility flags.

Pull Request: https://projects.blender.org/blender/blender/pulls/117406
This commit is contained in:
Alexander Gavrilov 2024-01-22 15:55:39 +01:00 committed by Alexander Gavrilov
parent 18b5b0812b
commit c478235985

@ -258,6 +258,50 @@ static void joined_armature_fix_links(
}
}
static BoneCollection *join_armature_remap_collection(
const bArmature *src_arm,
const int src_index,
bArmature *dest_arm,
blender::Map<std::string, BoneCollection *> &bone_collection_by_name)
{
using namespace blender::animrig;
const BoneCollection *bcoll = src_arm->collection_array[src_index];
/* Check if already remapped. */
BoneCollection *mapped = bone_collection_by_name.lookup_default(bcoll->name, nullptr);
if (mapped) {
return mapped;
}
/* Remap the parent collection if necessary. */
const int src_parent_index = armature_bonecoll_find_parent_index(src_arm, src_index);
int parent_index = -1;
if (src_parent_index >= 0) {
BoneCollection *mapped_parent = join_armature_remap_collection(
src_arm, src_parent_index, dest_arm, bone_collection_by_name);
if (mapped_parent) {
parent_index = armature_bonecoll_find_index(dest_arm, mapped_parent);
}
}
/* Create the new collection instance. */
BoneCollection *new_bcoll = ANIM_armature_bonecoll_new(dest_arm, bcoll->name, parent_index);
/* Copy collection visibility. */
new_bcoll->flags = bcoll->flags;
/* Copy custom properties. */
if (bcoll->prop) {
new_bcoll->prop = IDP_CopyProperty_ex(bcoll->prop, 0);
}
bone_collection_by_name.add(bcoll->name, new_bcoll);
return new_bcoll;
}
int ED_armature_join_objects_exec(bContext *C, wmOperator *op)
{
Main *bmain = CTX_data_main(C);
@ -331,24 +375,12 @@ int ED_armature_join_objects_exec(bContext *C, wmOperator *op)
/* Make a list of edit-bones in current armature */
ED_armature_to_edit(curarm);
/* Move new bone collections, and store their remapping info.
* TODO: armatures can potentially have multiple users, so these should
* actually be copied, not moved. However, the armature join code is
* already broken in that situation. When that gets fixed, this should
* also get fixed. Note that copying the collections should include
* copying their custom properties. (Nathan Vegdahl) */
for (BoneCollection *bcoll : curarm->collections_span()) {
BoneCollection *mapped = bone_collection_by_name.lookup_default(bcoll->name, nullptr);
if (!mapped) {
BoneCollection *new_bcoll = ANIM_armature_bonecoll_new(arm, bcoll->name);
if (bcoll->prop) {
new_bcoll->prop = IDP_CopyProperty_ex(bcoll->prop, 0);
}
bone_collection_by_name.add(bcoll->name, new_bcoll);
mapped = new_bcoll;
}
/* Copy new bone collections, and store their remapping info. */
for (int i = 0; i < curarm->collection_array_num; i++) {
BoneCollection *mapped = join_armature_remap_collection(
curarm, i, arm, bone_collection_by_name);
bone_collection_remap.add(bcoll, mapped);
bone_collection_remap.add(curarm->collection_array[i], mapped);
}
/* Get Pose of current armature */
@ -469,6 +501,9 @@ int ED_armature_join_objects_exec(bContext *C, wmOperator *op)
ED_armature_from_edit(bmain, arm);
ED_armature_edit_free(arm);
/* Make sure to recompute bone collection visibility. */
ANIM_armature_runtime_refresh(arm);
DEG_id_tag_update(&scene->id, ID_RECALC_SELECT);
WM_event_add_notifier(C, NC_SCENE | ND_OB_ACTIVE, scene);
WM_event_add_notifier(C, NC_SCENE | ND_LAYER_CONTENT, scene);