diff options
author | Tomoaki Kawada <i@yvt.jp> | 2019-04-28 16:19:45 +0300 |
---|---|---|
committer | Alexander Gavrilov <angavrilov@gmail.com> | 2019-04-28 17:05:37 +0300 |
commit | 9e3246ce6e9767148e4394dc7acbec04a7d69163 (patch) | |
tree | 0145ddd31683391866bd62c93d7e00831de57bf0 /source/blender/blenkernel/intern/armature.c | |
parent | 91bb8da59fe16e711e44d8fb0ff6422277b2d742 (diff) |
Fix T63794: duplicating an armature clears B-Bones' custom handle references.
This patch fixes T63794 by updating duplicated bones' custom handle references
to point to the new armature's bones.
The problem occurs because B-Bones of a duplicated armature keep pointing to
the old armature's bones. The references are cleared upon entering Edit Mode
because there are no matching `EditBone` for such bones, and `find_ebone_link`
just returns `NULL` in such cases.
Reviewers: mont29, angavrilov
Maniphest Tasks: T63794
Differential Revision: https://developer.blender.org/D4726
Diffstat (limited to 'source/blender/blenkernel/intern/armature.c')
-rw-r--r-- | source/blender/blenkernel/intern/armature.c | 33 |
1 files changed, 33 insertions, 0 deletions
diff --git a/source/blender/blenkernel/intern/armature.c b/source/blender/blenkernel/intern/armature.c index 97238020f29..7f374c1d66e 100644 --- a/source/blender/blenkernel/intern/armature.c +++ b/source/blender/blenkernel/intern/armature.c @@ -169,6 +169,28 @@ static void copy_bonechildren(Bone *bone_dst, } } +static void copy_bonechildren_custom_handles(Bone *bone_dst, bArmature *arm_dst, GHash **bone_hash) +{ + Bone *bone_dst_child; + + /* Lazily create the name -> bone hashtable. */ + if ((bone_dst->bbone_prev || bone_dst->bbone_next) && *bone_hash == NULL) { + *bone_hash = BKE_armature_bone_from_name_map(arm_dst); + } + + if (bone_dst->bbone_prev) { + bone_dst->bbone_prev = BLI_ghash_lookup(*bone_hash, bone_dst->bbone_prev->name); + } + if (bone_dst->bbone_next) { + bone_dst->bbone_next = BLI_ghash_lookup(*bone_hash, bone_dst->bbone_next->name); + } + + for (bone_dst_child = bone_dst->childbase.first; bone_dst_child; + bone_dst_child = bone_dst_child->next) { + copy_bonechildren_custom_handles(bone_dst_child, arm_dst, bone_hash); + } +} + /** * Only copy internal data of Armature ID from source * to already allocated/initialized destination. @@ -202,6 +224,17 @@ void BKE_armature_copy_data(Main *UNUSED(bmain), arm_dst->act_bone = bone_dst_act; + /* Fix custom handle references. */ + GHash *bone_hash = NULL; /* lazily created */ + + for (bone_dst = arm_dst->bonebase.first; bone_dst; bone_dst = bone_dst->next) { + copy_bonechildren_custom_handles(bone_dst, arm_dst, &bone_hash); + } + + if (bone_hash) { + BLI_ghash_free(bone_hash, NULL, NULL); + } + arm_dst->edbo = NULL; arm_dst->act_edbone = NULL; } |