Bugfix [#27990] Merge Bones freezes Blender

Recoded side-chain reparenting step to fix (as far as I've been able
to tell) infinite looping problems which were a bit intermittent here
using the test file. The fix here involves some tighter checks to
prevent corrupting the parenting of bones in the run of bones being
merged but also of any ancestors of those.
This commit is contained in:
Joshua Leung 2011-07-22 13:52:31 +00:00
parent 1e19f1cde1
commit 75029e1119

@ -2993,27 +2993,30 @@ static void bones_merge(Object *obedit, EditBone *start, EditBone *end, EditBone
/* TODO, copy more things to the new bone */
newbone->flag= start->flag & (BONE_HINGE|BONE_NO_DEFORM|BONE_NO_SCALE|BONE_NO_CYCLICOFFSET|BONE_NO_LOCAL_LOCATION|BONE_DONE);
/* step 2a: parent children of in-between bones to newbone */
for (chain= chains->first; chain; chain= chain->next) {
/* ick: we need to check if parent of each bone in chain is one of the bones in the chain being merged */
short found= 0;
for (ebo= chain->data; ebo; ebo= ebo->parent) {
/* step 2a: reparent any side chains which may be parented to any bone in the chain of bones to merge
* - potentially several tips for side chains leading to some tree exist...
*/
for (chain = chains->first; chain; chain = chain->next) {
/* traverse down chain until we hit the bottom or if we run into the tip of the chain of bones we're
* merging (need to stop in this case to avoid corrupting this chain too!)
*/
for (ebone = chain->data; (ebone) && (ebone != end); ebone = ebone->parent) {
short found = 0;
/* try to find which bone from the list to be removed, is the parent */
for (ebone= end; ebone; ebone= ebone->parent) {
if (ebo->parent == ebone) {
found= 1;
/* check if this bone is parented to one in the merging chain
* ! WATCHIT: must only go check until end of checking chain
*/
for (ebo = end; (ebo) && (ebo != start->parent); ebo = ebo->parent) {
/* side-chain found? --> remap parent to new bone, then we're done with this chain :) */
if (ebone->parent == ebo) {
ebone->parent = newbone;
found = 1;
break;
}
}
/* adjust this bone's parent to newbone then */
if (found) {
ebo->parent= newbone;
break;
}
}
if (found) {
/* carry on to the next tip now */
if (found)
break;
}
}
@ -3050,12 +3053,12 @@ static int armature_merge_exec (bContext *C, wmOperator *op)
LinkData *chain, *nchain;
EditBone *ebo;
armature_tag_select_mirrored(arm);
/* get chains (ends on chains) */
chains_find_tips(arm->edbo, &chains);
if (chains.first == NULL) return OPERATOR_CANCELLED;
armature_tag_select_mirrored(arm);
/* each 'chain' is the last bone in the chain (with no children) */
for (chain= chains.first; chain; chain= nchain) {
EditBone *bstart= NULL, *bend= NULL;