Revision: 38604
          
http://projects.blender.org/scm/viewvc.php?view=rev&root=bf-blender&revision=38604
Author:   aligorith
Date:     2011-07-22 13:52:31 +0000 (Fri, 22 Jul 2011)
Log Message:
-----------
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.

Modified Paths:
--------------
    branches/soc-2011-pepper/source/blender/editors/armature/editarmature.c

Modified: 
branches/soc-2011-pepper/source/blender/editors/armature/editarmature.c
===================================================================
--- branches/soc-2011-pepper/source/blender/editors/armature/editarmature.c     
2011-07-22 11:53:20 UTC (rev 38603)
+++ branches/soc-2011-pepper/source/blender/editors/armature/editarmature.c     
2011-07-22 13:52:31 UTC (rev 38604)
@@ -2993,29 +2993,32 @@
        /* 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;
+                       /* carry on to the next tip now  */
+                       if (found) 
                                break;
-                       }
                }
-               if (found) {
-                       break;
-               }
        }
        
        /* step 2b: parent child of end to newbone (child from this chain) */
@@ -3050,12 +3053,12 @@
                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;
@@ -3100,7 +3103,7 @@
                }               
                
                armature_tag_unselect(arm);
-
+               
                BLI_freelistN(&chains);
        }
        

_______________________________________________
Bf-blender-cvs mailing list
[email protected]
http://lists.blender.org/mailman/listinfo/bf-blender-cvs

Reply via email to