merge 17122:17206
authorMartin Poirier <theeth@yahoo.com>
Tue, 28 Oct 2008 18:47:01 +0000 (18:47 +0000)
committerMartin Poirier <theeth@yahoo.com>
Tue, 28 Oct 2008 18:47:01 +0000 (18:47 +0000)
1  2 
source/blender/blenloader/intern/readfile.c
source/blender/src/buttons_editing.c
source/blender/src/editarmature.c

index ec26683444ebed7fd2c7380abb46552301275c85,edb9c3ff898dfe109e61c0fdaeeeb1b7a636d13c..3a9d0a6ae6a16cd611658fe33c86cf2886cb4df8
@@@ -4921,6 -4921,12 +4921,12 @@@ static void alphasort_version_246(FileD
                        ma= newlibadr(fd, lib, me->mat[mf->mat_nr]);
                        texalpha = 0;
  
+                       /* we can't read from this if it comes from a library,
+                        * because direct_link might not have happened on it,
+                        * so ma->mtex is not pointing to valid memory yet */
+                       if(ma && ma->id.lib)
+                               ma= NULL;
                        for(b=0; ma && b<MAX_MTEX; b++)
                                if(ma->mtex && ma->mtex[b] && ma->mtex[b]->mapto & MAP_ALPHA)
                                        texalpha = 1;
@@@ -7373,24 -7379,6 +7379,24 @@@ static void do_versions(FileData *fd, L
                        }
                }
        }
 +      
 +      /* sanity check for skgen
 +       * */
 +      {
 +              Scene *sce;
 +              for(sce=main->scene.first; sce; sce = sce->id.next)
 +              {
 +                      if (sce->toolsettings->skgen_subdivisions[0] == sce->toolsettings->skgen_subdivisions[1] ||
 +                              sce->toolsettings->skgen_subdivisions[0] == sce->toolsettings->skgen_subdivisions[2] ||
 +                              sce->toolsettings->skgen_subdivisions[1] == sce->toolsettings->skgen_subdivisions[2])
 +                      {
 +                                      sce->toolsettings->skgen_subdivisions[0] = SKGEN_SUB_CORRELATION;
 +                                      sce->toolsettings->skgen_subdivisions[1] = SKGEN_SUB_LENGTH;
 +                                      sce->toolsettings->skgen_subdivisions[2] = SKGEN_SUB_ANGLE;
 +                      }
 +              }
 +      }
 +      
  
        if ((main->versionfile < 245) || (main->versionfile == 245 && main->subversionfile < 2)) {
                Image *ima;
index b7561deed8e4f9549b55a3a8b58a428027efbae2,3d60e9a8eeaf90f32410b770cb4f387518b04b0c..45267f506226acf58e2c61923b3acccd4bdb59f2
  #include "butspace.h" // own module
  #include "multires.h"
  
 +#include "reeb.h"
 +
  static float editbutweight= 1.0;
  float editbutvweight= 1;
  static int actmcol= 0, acttface= 0, acttface_rnd = 0, actmcol_rnd = 0;
@@@ -4637,7 -4635,7 +4637,7 @@@ static void editing_panel_pose_bones(Ob
                        uiDefButBitI(block, TOG, BONE_NO_SCALE, B_ARM_RECALCDATA, "S",                  70,by-38,20,19, &curBone->flag, 1.0, 32.0, 0.0, 0.0, "Don't inherit scale from parent Bone");
                        uiDefButBitI(block, TOGN, BONE_NO_DEFORM, B_ARM_RECALCDATA, "Deform",   90, by-38, 80, 19, &curBone->flag, 0.0, 0.0, 0.0, 0.0, "Indicate if Bone deforms geometry");
                        uiDefButBitI(block, TOG, BONE_MULT_VG_ENV, B_ARM_RECALCDATA, "Mult",    170,by-38,80,19, &curBone->flag, 1.0, 32.0, 0.0, 0.0, "Multiply Bone Envelope with VertexGroup");
-                       uiDefButBitI(block, TOG, BONE_MULT_VG_ENV, B_ARM_RECALCDATA, "Hide",    250,by-38,80,19, &curBone->flag, 1.0, 32.0, 0.0, 0.0, "Toggles display of this bone in Edit Mode");
+                       uiDefButBitI(block, TOG, BONE_HIDDEN_P, B_ARM_RECALCDATA, "Hide",       250,by-38,80,19, &curBone->flag, 1.0, 32.0, 0.0, 0.0, "Toggles display of this bone in Edit Mode");
                        
                        /* layers */
                        uiBlockBeginAlign(block);
@@@ -4762,7 -4760,7 +4762,7 @@@ void do_vgroupbuts(unsigned short event
                        DAG_object_flush_update(G.scene, ob, OB_RECALC_DATA);
                        scrarea_queue_winredraw(curarea);
                        allqueue(REDRAWOOPS, 0);
-                       
+                       BIF_undo_push("New vertex group");
                        break;
                case B_DELVGROUP:
                        if ((G.obedit) && (G.obedit == ob)) {
                        break;
                case B_ASSIGNVGROUP:
                        assign_verts_defgroup ();
+                       DAG_object_flush_update(G.scene, ob, OB_RECALC_DATA);
                        allqueue (REDRAWVIEW3D, 1);
                        BIF_undo_push("Assign to vertex group");
                        break;
                case B_REMOVEVGROUP:
                        remove_verts_defgroup (0);
+                       DAG_object_flush_update(G.scene, ob, OB_RECALC_DATA);
                        allqueue (REDRAWVIEW3D, 1);
                        allqueue(REDRAWOOPS, 0);
                        BIF_undo_push("Remove from vertex group");
                        break;
                case B_SELVGROUP:
-                       sel_verts_defgroup(1);
+                       sel_verts_defgroup(1); /* runs countall() */
                        allqueue (REDRAWVIEW3D, 1);
                        allqueue(REDRAWOOPS, 0);
-                       countall();
+                       BIF_undo_push("Select vertex group");
                        break;
                case B_DESELVGROUP:
-                       sel_verts_defgroup(0);
-                       DAG_object_flush_update(G.scene, ob, OB_RECALC_DATA);
+                       sel_verts_defgroup(0); /* runs countall() */
                        allqueue (REDRAWVIEW3D, 1);
                        allqueue(REDRAWOOPS, 0);
-                       countall();
+                       BIF_undo_push("DeSelect vertex group");
                        break;
                case B_LINKEDVGROUP:
                        copy_linked_vgroup_channels(ob);
+                       allqueue (REDRAWVIEW3D, 1);
+                       allqueue(REDRAWOOPS, 0);
+                       BIF_undo_push("Copy vertex group to linked obdata");
                        break;
                case B_COPYVGROUP:
                        duplicate_defgroup (ob);
                        scrarea_queue_winredraw (curarea);
                        allqueue (REDRAWOOPS, 0);
+                       BIF_undo_push("Copy vertex group");
                        break;
        }
  }
@@@ -5049,9 -5052,6 +5054,9 @@@ void do_meshbuts(unsigned short event
        case B_GEN_SKELETON:
                generateSkeleton();
                break;
 +      case B_RETARGET_SKELETON:
 +              BIF_retargetArmature();
 +              break;
        }
  
        /* WATCH IT: previous events only in editmode! */
@@@ -5150,100 -5150,6 +5155,100 @@@ static void skgen_reorder(void *option
        }
  }
  
 +static void skgen_graphgen(void *arg1, void *arg2)
 +{
 +      BIF_GlobalReebGraphFromEditMesh();
 +      allqueue(REDRAWVIEW3D, 0);
 +}
 +
 +static void skgen_graphfree(void *arg1, void *arg2)
 +{
 +      BIF_GlobalReebFree();
 +      allqueue(REDRAWVIEW3D, 0);
 +}
 +
 +static void skgen_rigadjust(void *arg1, void *arg2)
 +{
 +      BIF_adjustRetarget();
 +}
 +
 +static void skgen_rigfree(void *arg1, void *arg2)
 +{
 +      BIF_freeRetarget();
 +}
 +
 +static void skgen_graph_block(uiBlock *block)
 +{
 +      uiBlockBeginAlign(block);
 +      uiDefButS(block, NUM, B_DIFF, "Resolution:",                                                    1025,150,225,19, &G.scene->toolsettings->skgen_resolution,10.0,1000.0, 0, 0,            "Specifies the resolution of the graph's embedding");
 +      uiDefButBitS(block, TOG, SKGEN_HARMONIC, B_DIFF,                "H",                    1250,150, 25,19, &G.scene->toolsettings->skgen_options, 0, 0, 0, 0,                                     "Apply harmonic smoothing to the weighting");
 +      uiDefButBitS(block, TOG, SKGEN_FILTER_INTERNAL, B_DIFF, "Filter In",    1025,130, 83,19, &G.scene->toolsettings->skgen_options, 0, 0, 0, 0,                                     "Filter internal small arcs from graph");
 +      uiDefButF(block, NUM, B_DIFF,                                                   "",                             1111,130,164,19, &G.scene->toolsettings->skgen_threshold_internal,0.0, 10.0, 10, 0,     "Specify the threshold ratio for filtering internal arcs");
 +      uiDefButBitS(block, TOG, SKGEN_FILTER_EXTERNAL, B_DIFF, "Filter Ex",    1025,110, 53,19, &G.scene->toolsettings->skgen_options, 0, 0, 0, 0,                                     "Filter external small arcs from graph");
 +      uiDefButBitS(block, TOG, SKGEN_FILTER_SMART,    B_DIFF, "Sm",                   1078,110, 30,19, &G.scene->toolsettings->skgen_options, 0, 0, 0, 0,                                     "Smart Filtering");
 +      uiDefButF(block, NUM, B_DIFF,                                                   "",                             1111,110,164,19, &G.scene->toolsettings->skgen_threshold_external,0.0, 10.0, 10, 0,     "Specify the threshold ratio for filtering external arcs");
 +      
 +      uiDefButBitS(block, TOG, SKGEN_SYMMETRY, B_DIFF,                "Symmetry",             1025, 90,125,19, &G.scene->toolsettings->skgen_options, 0, 0, 0, 0,                                     "Restore symmetries based on topology");
 +      uiDefButF(block, NUM, B_DIFF,                                                   "T:",                   1150, 90,125,19, &G.scene->toolsettings->skgen_symmetry_limit,0.0, 1.0, 10, 0,  "Specify the threshold distance for considering potential symmetric arcs");
 +      uiDefButC(block, NUM, B_DIFF,                                                   "P:",                   1025, 70, 62,19, &G.scene->toolsettings->skgen_postpro_passes, 0, 10, 10, 0,            "Specify the number of processing passes on the embeddings");
 +      uiDefButC(block, ROW, B_DIFF,                                                   "Smooth",               1087, 70, 63,19, &G.scene->toolsettings->skgen_postpro, 5.0, (float)SKGEN_SMOOTH, 0, 0, "Smooth embeddings");
 +      uiDefButC(block, ROW, B_DIFF,                                                   "Average",              1150, 70, 62,19, &G.scene->toolsettings->skgen_postpro, 5.0, (float)SKGEN_AVERAGE, 0, 0, "Average embeddings");
 +      uiDefButC(block, ROW, B_DIFF,                                                   "Sharpen",              1212, 70, 63,19, &G.scene->toolsettings->skgen_postpro, 5.0, (float)SKGEN_SHARPEN, 0, 0, "Sharpen embeddings");
 +
 +      uiBlockEndAlign(block);
 +}
 +
 +static void editing_panel_mesh_skgen_display(Object *ob, Mesh *me)
 +{
 +      uiBlock *block;
 +      uiBut *but;
 +
 +      block= uiNewBlock(&curarea->uiblocks, "editing_panel_mesh_skgen_display", UI_EMBOSS, UI_HELV, curarea->win);
 +      uiNewPanelTabbed("Mesh Tools More", "Skgen");
 +      if(uiNewPanel(curarea, block, "Graph", "Editing", 960, 0, 318, 204)==0) return;
 +      
 +      but = uiDefBut(block, BUT, B_DIFF, "Generate",                          1025,170,125,19, 0, 0, 0, 0, 0, "Generate Graph from Mesh");
 +      uiButSetFunc(but, skgen_graphgen, NULL, NULL);
 +      but = uiDefBut(block, BUT, B_DIFF, "Free",                                      1150,170,125,19, 0, 0, 0, 0, 0, "Free Graph from Mesh");
 +      uiButSetFunc(but, skgen_graphfree, NULL, NULL);
 +      
 +      skgen_graph_block(block);
 +
 +      uiBlockBeginAlign(block);
 +      uiDefButBitS(block, TOG, SKGEN_DISP_LENGTH, REDRAWVIEW3D,       "Length",                       1025, 40, 50,19, &G.scene->toolsettings->skgen_options, 0, 0, 0, 0,             "Show Length");
 +      uiDefButBitS(block, TOG, SKGEN_DISP_WEIGHT, REDRAWVIEW3D,       "Weight",                       1075, 40, 50,19, &G.scene->toolsettings->skgen_options, 0, 0, 0, 0,             "Show Weight");
 +      uiDefButBitS(block, TOG, SKGEN_DISP_EMBED, REDRAWVIEW3D,        "Embed",                        1125, 40, 50,19, &G.scene->toolsettings->skgen_options, 0, 0, 0, 0,             "Show Arc Embedings");
 +      uiDefButBitS(block, TOG, SKGEN_DISP_INDEX, REDRAWVIEW3D,        "Index",                        1175, 40, 50,19, &G.scene->toolsettings->skgen_options, 0, 0, 0, 0,             "Show Arc and Node indexes");
 +      uiDefButBitS(block, TOG, SKGEN_DISP_ORIG, REDRAWVIEW3D,         "Original",                     1225, 40, 50,19, &G.scene->toolsettings->skgen_options, 0, 0, 0, 0,             "Show Original Graph");
 +
 +      uiBlockEndAlign(block);
 +
 +      uiDefButC(block, NUM, REDRAWVIEW3D,                                             "Level:",                       1025, 20, 125,19, &G.scene->toolsettings->skgen_multi_level, 0, REEB_MAX_MULTI_LEVEL, 1, 0,"Specify the level to draw");
 +}
 +
 +static void editing_panel_mesh_skgen_retarget(Object *ob, Mesh *me)
 +{
 +      uiBlock *block;
 +      uiBut *but;
 +
 +      block= uiNewBlock(&curarea->uiblocks, "editing_panel_mesh_skgen_retarget", UI_EMBOSS, UI_HELV, curarea->win);
 +      uiNewPanelTabbed("Mesh Tools More", "Skgen");
 +      if(uiNewPanel(curarea, block, "Retarget", "Editing", 960, 0, 318, 204)==0) return;
 +      
 +      uiDefBut(block, BUT, B_RETARGET_SKELETON, "Retarget Skeleton",  1025,170,100,19, 0, 0, 0, 0, 0, "Retarget Selected Armature to this Mesh");
 +      but = uiDefBut(block, BUT, B_DIFF, "Adjust",                                    1125,170,100,19, 0, 0, 0, 0, 0, "Adjust Retarget using new weights");
 +      uiButSetFunc(but, skgen_rigadjust, NULL, NULL);
 +      but = uiDefBut(block, BUT, B_DIFF, "Free",                                              1225,170,50,19, 0, 0, 0, 0, 0, "Free Retarget structure");
 +      uiButSetFunc(but, skgen_rigfree, NULL, NULL);
 +
 +      skgen_graph_block(block);
 +
 +      uiDefButF(block, NUM, B_DIFF,                                                   "Ang:",                 1025, 40, 83,19, &G.scene->toolsettings->skgen_retarget_angle_weight, 0, 10, 1, 0,              "Angle Weight");
 +      uiDefButF(block, NUM, B_DIFF,                                                   "Len:",                 1108, 40, 83,19, &G.scene->toolsettings->skgen_retarget_length_weight, 0, 10, 1, 0,             "Length Weight");
 +      uiDefButF(block, NUM, B_DIFF,                                                   "Dist:",                1191, 40, 84,19, &G.scene->toolsettings->skgen_retarget_distance_weight, 0, 10, 1, 0,           "Distance Weight");
 +      uiDefButC(block, NUM, B_DIFF,                                                   "Method:",              1025, 20, 125,19, &G.scene->toolsettings->skgen_optimisation_method, 0, 2, 1, 0,"Optimisation Method (0: brute, 1: memoize, 2: annealing max fixed");
 +}
 +
  static void editing_panel_mesh_skgen(Object *ob, Mesh *me)
  {
        uiBlock *block;
        int i;
  
        block= uiNewBlock(&curarea->uiblocks, "editing_panel_mesh_skgen", UI_EMBOSS, UI_HELV, curarea->win);
 -      if(uiNewPanel(curarea, block, "Skeleton Generator", "Editing", 960, 0, 318, 204)==0) return;
 +      uiNewPanelTabbed("Mesh Tools More", "Skgen");
 +      if(uiNewPanel(curarea, block, "Generator", "Editing", 960, 0, 318, 204)==0) return;
        
 -      uiDefBut(block, BUT, B_GEN_SKELETON, "Generate Skeleton",                       1025,170,250,19, 0, 0, 0, 0, 0, "Generate Skeleton from Mesh");
 +      uiDefBut(block, BUT, B_GEN_SKELETON, "Generate",                        1025,170,250,19, 0, 0, 0, 0, 0, "Generate Skeleton from Mesh");
  
 -      uiBlockBeginAlign(block);
 -      uiDefButS(block, NUM, B_DIFF, "Resolution:",                                                    1025,150,250,19, &G.scene->toolsettings->skgen_resolution,10.0,1000.0, 0, 0,            "Specifies the resolution of the graph's embedding");
 -      uiDefButBitS(block, TOG, SKGEN_FILTER_INTERNAL, B_DIFF, "Filter In",    1025,130, 83,19, &G.scene->toolsettings->skgen_options, 0, 0, 0, 0,                                     "Filter internal small arcs from graph");
 -      uiDefButF(block, NUM, B_DIFF,                                                   "T:",                   1111,130,164,19, &G.scene->toolsettings->skgen_threshold_internal,0.0, 1.0, 10, 0,      "Specify the threshold ratio for filtering internal arcs");
 -      uiDefButBitS(block, TOG, SKGEN_FILTER_EXTERNAL, B_DIFF, "Filter Ex",    1025,110, 83,19, &G.scene->toolsettings->skgen_options, 0, 0, 0, 0,                                     "Filter external small arcs from graph");
 -      uiDefButF(block, NUM, B_DIFF,                                                   "T:",                   1111,110,164,19, &G.scene->toolsettings->skgen_threshold_external,0.0, 1.0, 10, 0,      "Specify the threshold ratio for filtering external arcs");
 +      skgen_graph_block(block);
  
 +      uiBlockBeginAlign(block);
        for(i = 0; i < SKGEN_SUB_TOTAL; i++)
        {
 -              int y = 90 - 20 * i;
 +              int y = 50 - 20 * i;
                
                but = uiDefIconBut(block, BUT, B_MODIFIER_RECALC, VICON_MOVE_DOWN,              1025, y, 16, 19, NULL, 0.0, 0.0, 0.0, 0.0, "Change the order the subdivisions algorithm are applied");
                uiButSetFunc(but, skgen_reorder, SET_INT_IN_POINTER(i), NULL);
                                uiDefButF(block, NUM, B_DIFF,                                                   "T:",                   1111, y,164,19, &G.scene->toolsettings->skgen_angle_limit,0.0, 90.0, 10, 0,                     "Specify the threshold angle in degrees for subdivision");
                                break;
                        case SKGEN_SUB_CORRELATION:
 -                              uiDefButBitS(block, TOG, SKGEN_CUT_CORRELATION, B_DIFF, "Correlation",  1041, y, 67,19, &G.scene->toolsettings->skgen_options, 0, 0, 0, 0,                                      "Subdivide arcs based on correlation");
 -                              uiDefButF(block, NUM, B_DIFF,                                                   "T:",                   1111, y,164,19, &G.scene->toolsettings->skgen_correlation_limit,0.0, 1.0, 0.01, 0,      "Specify the threshold correlation for subdivision");
 +                              uiDefButBitS(block, TOG, SKGEN_CUT_CORRELATION, B_DIFF, "Adaptative",   1041, y, 67,19, &G.scene->toolsettings->skgen_options, 0, 0, 0, 0,                                      "Subdivide arcs adaptatively");
 +                              uiDefButF(block, NUM, B_DIFF,                                                   "T:",                   1111, y,114,19, &G.scene->toolsettings->skgen_correlation_limit,0.0, 1.0, 0.01, 0,      "Specify the adaptive threshold for subdivision");
 +                              uiDefButBitS(block, TOG, SKGEN_STICK_TO_EMBEDDING, B_DIFF,              "E",                    1225, y, 25,19, &G.scene->toolsettings->skgen_options, 0, 0, 0, 0,                                      "Stick endpoint to embedding");
 +                              uiDefButBitS(block, TOG, SKGEN_ADAPTIVE_DISTANCE, B_DIFF,               "D",                    1250, y, 25,19, &G.scene->toolsettings->skgen_options, 0, 0, 0, 0,                                      "Adaptive distance (on) or variance(off)");
                                break;
                }
        }
  
 -      uiDefButBitS(block, TOG, SKGEN_SYMMETRY, B_DIFF,                "Symmetry",             1025, 30,125,19, &G.scene->toolsettings->skgen_options, 0, 0, 0, 0,                                     "Restore symmetries based on topology");
 -      uiDefButF(block, NUM, B_DIFF,                                                   "T:",                   1150, 30,125,19, &G.scene->toolsettings->skgen_symmetry_limit,0.0, 1.0, 10, 0,  "Specify the threshold distance for considering potential symmetric arcs");
 -      uiDefButC(block, NUM, B_DIFF,                                                   "P:",                   1025, 10, 62,19, &G.scene->toolsettings->skgen_postpro_passes, 0, 10, 10, 0,            "Specify the number of processing passes on the embeddings");
 -      uiDefButC(block, ROW, B_DIFF,                                                   "Smooth",               1087, 10, 63,19, &G.scene->toolsettings->skgen_postpro, 5.0, (float)SKGEN_SMOOTH, 0, 0, "Smooth embeddings");
 -      uiDefButC(block, ROW, B_DIFF,                                                   "Average",              1150, 10, 62,19, &G.scene->toolsettings->skgen_postpro, 5.0, (float)SKGEN_AVERAGE, 0, 0, "Average embeddings");
 -      uiDefButC(block, ROW, B_DIFF,                                                   "Sharpen",              1212, 10, 63,19, &G.scene->toolsettings->skgen_postpro, 5.0, (float)SKGEN_SHARPEN, 0, 0, "Sharpen embeddings");
        uiBlockEndAlign(block);
  }
  
@@@ -6710,11 -6623,8 +6715,11 @@@ void editing_panels(
                        editing_panel_mesh_tools1(ob, ob->data);
                        uiNewPanelTabbed("Mesh Tools 1", "Editing");
                        
 -                      if (G.rt == 42) /* hidden for now, no time for docs */
 -                              editing_panel_mesh_skgen(ob, ob->data);
 +                      #ifdef WITH_BF_REEB
 +                      editing_panel_mesh_skgen(ob, ob->data);
 +                      editing_panel_mesh_skgen_retarget(ob, ob->data);
 +                      editing_panel_mesh_skgen_display(ob, ob->data);
 +                      #endif
                        
                        editing_panel_mesh_uvautocalculation();
                        if (EM_texFaceCheck())
                editing_panel_links(ob);
                editing_panel_curve_type(ob, cu);
                editing_panel_modifiers(ob);
- //            editing_panel_shapes(ob);
+ //            editing_panel_shapes(ob); /* there are some backend things that are not ready for this yet */
                if(G.obedit) {
                        editing_panel_curve_tools(ob, cu);
                        editing_panel_curve_tools1(ob, cu);
index d94d77952248f2993c32b76f41eb68279f06289a,0b8c1339daed3614b67b9c8f6e31b1bbe8723ec0..5ddf522e4a86aa86e043c2857f0a736ca9ac3b26
@@@ -2278,7 -2278,7 +2278,7 @@@ void adduplicate_armature(void
                                        bPoseChannel *chanold, *channew;
                                        ListBase     *listold, *listnew;
                                        
-                                       chanold = verify_pose_channel (OBACT->pose, curBone->name);
+                                       chanold = verify_pose_channel(OBACT->pose, curBone->name);
                                        if (chanold) {
                                                listold = &chanold->constraints;
                                                if (listold) {
                                                                /* copy transform locks */
                                                                channew->protectflag = chanold->protectflag;
                                                                
+                                                               /* copy bone group */
+                                                               channew->agrp_index= chanold->agrp_index;
+                                                               
                                                                /* ik (dof) settings */
                                                                channew->ikflag = chanold->ikflag;
                                                                VECCOPY(channew->limitmin, chanold->limitmin);
                                                                
                                                                /* constraints */
                                                                listnew = &channew->constraints;
-                                                               copy_constraints (listnew, listold);
+                                                               copy_constraints(listnew, listold);
+                                                               
+                                                               /* custom shape */
+                                                               channew->custom= chanold->custom;
                                                        }
                                                }
                                        }
@@@ -3277,7 -3283,11 +3283,11 @@@ void switch_direction_armature (void
                EditBone *ebo, *child=NULL, *parent=NULL;
                
                /* loop over bones in chain */
-               for (ebo= chain->data; ebo; child= ebo, ebo=parent) {
+               for (ebo= chain->data; ebo; ebo= parent) {
+                       /* parent is this bone's original parent
+                        *      - we store this, as the next bone that is checked is this one
+                        *        but the value of ebo->parent may change here...
+                        */
                        parent= ebo->parent;
                        
                        /* only if selected and editable */
                                else    
                                        ebo->flag &= ~BONE_CONNECTED;
                                
-                               /* FIXME: other things that need fixing?
-                                *              i.e. roll?
+                               /* get next bones 
+                                *      - child will become the new parent of next bone
+                                */
+                               child= ebo;
+                       }
+                       else {
+                               /* not swapping this bone, however, if its 'parent' got swapped, unparent us from it 
+                                * as it will be facing in opposite direction
+                                */
+                               if ((parent) && (EBONE_VISIBLE(arm, parent) && EBONE_EDITABLE(parent))) {
+                                       ebo->parent= NULL;
+                                       ebo->flag &= ~BONE_CONNECTED;
+                               }
+                               
+                               /* get next bones
+                                *      - child will become new parent of next bone (not swapping occurred, 
+                                *        so set to NULL to prevent infinite-loop)
                                 */
+                               child= NULL;
                        }
                }
        }
@@@ -4488,7 -4514,542 +4514,7 @@@ void transform_armature_mirror_update(v
  /*************************************** SKELETON GENERATOR ******************************************/
  /*****************************************************************************************************/
  
 -/**************************************** SYMMETRY HANDLING ******************************************/
  
 -void markdownSymmetryArc(ReebArc *arc, ReebNode *node, int level);
 -
 -void mirrorAlongAxis(float v[3], float center[3], float axis[3])
 -{
 -      float dv[3], pv[3];
 -      
 -      VecSubf(dv, v, center);
 -      Projf(pv, dv, axis);
 -      VecMulf(pv, -2);
 -      VecAddf(v, v, pv);
 -}
 -
 -/* Helper structure for radial symmetry */
 -typedef struct RadialArc
 -{
 -      ReebArc *arc; 
 -      float n[3]; /* normalized vector joining the nodes of the arc */
 -} RadialArc;
 -
 -void reestablishRadialSymmetry(ReebNode *node, int depth, float axis[3])
 -{
 -      RadialArc *ring = NULL;
 -      RadialArc *unit;
 -      float limit = G.scene->toolsettings->skgen_symmetry_limit;
 -      int symmetric = 1;
 -      int count = 0;
 -      int i;
 -
 -      /* count the number of arcs in the symmetry ring */
 -      for (i = 0; node->arcs[i] != NULL; i++)
 -      {
 -              ReebArc *connectedArc = node->arcs[i];
 -              
 -              /* depth is store as a negative in flag. symmetry level is positive */
 -              if (connectedArc->flags == -depth)
 -              {
 -                      count++;
 -              }
 -      }
 -
 -      ring = MEM_callocN(sizeof(RadialArc) * count, "radial symmetry ring");
 -      unit = ring;
 -
 -      /* fill in the ring */
 -      for (unit = ring, i = 0; node->arcs[i] != NULL; i++)
 -      {
 -              ReebArc *connectedArc = node->arcs[i];
 -              
 -              /* depth is store as a negative in flag. symmetry level is positive */
 -              if (connectedArc->flags == -depth)
 -              {
 -                      ReebNode *otherNode = OTHER_NODE(connectedArc, node);
 -                      float vec[3];
 -
 -                      unit->arc = connectedArc;
 -
 -                      /* project the node to node vector on the symmetry plane */
 -                      VecSubf(unit->n, otherNode->p, node->p);
 -                      Projf(vec, unit->n, axis);
 -                      VecSubf(unit->n, unit->n, vec);
 -
 -                      Normalize(unit->n);
 -
 -                      unit++;
 -              }
 -      }
 -
 -      /* sort ring */
 -      for (i = 0; i < count - 1; i++)
 -      {
 -              float minAngle = 3; /* arbitrary high value, higher than 2, at least */
 -              int minIndex = -1;
 -              int j;
 -
 -              for (j = i + 1; j < count; j++)
 -              {
 -                      float angle = Inpf(ring[i].n, ring[j].n);
 -
 -                      /* map negative values to 1..2 */
 -                      if (angle < 0)
 -                      {
 -                              angle = 1 - angle;
 -                      }
 -
 -                      if (angle < minAngle)
 -                      {
 -                              minIndex = j;
 -                              minAngle = angle;
 -                      }
 -              }
 -
 -              /* swap if needed */
 -              if (minIndex != i + 1)
 -              {
 -                      RadialArc tmp;
 -                      tmp = ring[i + 1];
 -                      ring[i + 1] = ring[minIndex];
 -                      ring[minIndex] = tmp;
 -              }
 -      }
 -
 -      for (i = 0; i < count && symmetric; i++)
 -      {
 -              ReebNode *node1, *node2;
 -              float tangent[3];
 -              float normal[3];
 -              float p[3];
 -              int j = (i + 1) % count; /* next arc in the circular list */
 -
 -              VecAddf(tangent, ring[i].n, ring[j].n);
 -              Crossf(normal, tangent, axis);
 -              
 -              node1 = OTHER_NODE(ring[i].arc, node);
 -              node2 = OTHER_NODE(ring[j].arc, node);
 -
 -              VECCOPY(p, node2->p);
 -              mirrorAlongAxis(p, node->p, normal);
 -              
 -              /* check if it's within limit before continuing */
 -              if (VecLenf(node1->p, p) > limit)
 -              {
 -                      symmetric = 0;
 -              }
 -
 -      }
 -
 -      if (symmetric)
 -      {
 -              /* first pass, merge incrementally */
 -              for (i = 0; i < count - 1; i++)
 -              {
 -                      ReebNode *node1, *node2;
 -                      float tangent[3];
 -                      float normal[3];
 -                      int j = i + 1;
 -      
 -                      VecAddf(tangent, ring[i].n, ring[j].n);
 -                      Crossf(normal, tangent, axis);
 -                      
 -                      node1 = OTHER_NODE(ring[i].arc, node);
 -                      node2 = OTHER_NODE(ring[j].arc, node);
 -      
 -                      /* mirror first node and mix with the second */
 -                      mirrorAlongAxis(node1->p, node->p, normal);
 -                      VecLerpf(node2->p, node2->p, node1->p, 1.0f / (j + 1));
 -                      
 -                      /* Merge buckets
 -                       * there shouldn't be any null arcs here, but just to be safe 
 -                       * */
 -                      if (ring[i].arc->bcount > 0 && ring[j].arc->bcount > 0)
 -                      {
 -                              ReebArcIterator iter1, iter2;
 -                              EmbedBucket *bucket1 = NULL, *bucket2 = NULL;
 -                              
 -                              initArcIterator(&iter1, ring[i].arc, node);
 -                              initArcIterator(&iter2, ring[j].arc, node);
 -                              
 -                              bucket1 = nextBucket(&iter1);
 -                              bucket2 = nextBucket(&iter2);
 -                      
 -                              /* Make sure they both start at the same value */       
 -                              while(bucket1 && bucket1->val < bucket2->val)
 -                              {
 -                                      bucket1 = nextBucket(&iter1);
 -                              }
 -                              
 -                              while(bucket2 && bucket2->val < bucket1->val)
 -                              {
 -                                      bucket2 = nextBucket(&iter2);
 -                              }
 -              
 -              
 -                              for ( ;bucket1 && bucket2; bucket1 = nextBucket(&iter1), bucket2 = nextBucket(&iter2))
 -                              {
 -                                      bucket2->nv += bucket1->nv; /* add counts */
 -                                      
 -                                      /* mirror on axis */
 -                                      mirrorAlongAxis(bucket1->p, node->p, normal);
 -                                      /* add bucket2 in bucket1 */
 -                                      VecLerpf(bucket2->p, bucket2->p, bucket1->p, (float)bucket1->nv / (float)(bucket2->nv));
 -                              }
 -                      }
 -              }
 -              
 -              /* second pass, mirror back on previous arcs */
 -              for (i = count - 1; i > 0; i--)
 -              {
 -                      ReebNode *node1, *node2;
 -                      float tangent[3];
 -                      float normal[3];
 -                      int j = i - 1;
 -      
 -                      VecAddf(tangent, ring[i].n, ring[j].n);
 -                      Crossf(normal, tangent, axis);
 -                      
 -                      node1 = OTHER_NODE(ring[i].arc, node);
 -                      node2 = OTHER_NODE(ring[j].arc, node);
 -      
 -                      /* copy first node than mirror */
 -                      VECCOPY(node2->p, node1->p);
 -                      mirrorAlongAxis(node2->p, node->p, normal);
 -                      
 -                      /* Copy buckets
 -                       * there shouldn't be any null arcs here, but just to be safe 
 -                       * */
 -                      if (ring[i].arc->bcount > 0 && ring[j].arc->bcount > 0)
 -                      {
 -                              ReebArcIterator iter1, iter2;
 -                              EmbedBucket *bucket1 = NULL, *bucket2 = NULL;
 -                              
 -                              initArcIterator(&iter1, ring[i].arc, node);
 -                              initArcIterator(&iter2, ring[j].arc, node);
 -                              
 -                              bucket1 = nextBucket(&iter1);
 -                              bucket2 = nextBucket(&iter2);
 -                      
 -                              /* Make sure they both start at the same value */       
 -                              while(bucket1 && bucket1->val < bucket2->val)
 -                              {
 -                                      bucket1 = nextBucket(&iter1);
 -                              }
 -                              
 -                              while(bucket2 && bucket2->val < bucket1->val)
 -                              {
 -                                      bucket2 = nextBucket(&iter2);
 -                              }
 -              
 -              
 -                              for ( ;bucket1 && bucket2; bucket1 = nextBucket(&iter1), bucket2 = nextBucket(&iter2))
 -                              {
 -                                      /* copy and mirror back to bucket2 */                   
 -                                      bucket2->nv = bucket1->nv;
 -                                      VECCOPY(bucket2->p, bucket1->p);
 -                                      mirrorAlongAxis(bucket2->p, node->p, normal);
 -                              }
 -                      }
 -              }
 -      }
 -
 -      MEM_freeN(ring);
 -}
 -
 -void reestablishAxialSymmetry(ReebNode *node, int depth, float axis[3])
 -{
 -      ReebArc *arc1 = NULL;
 -      ReebArc *arc2 = NULL;
 -      ReebNode *node1 = NULL, *node2 = NULL;
 -      float limit = G.scene->toolsettings->skgen_symmetry_limit;
 -      float nor[3], vec[3], p[3];
 -      int i;
 -      
 -      for (i = 0; node->arcs[i] != NULL; i++)
 -      {
 -              ReebArc *connectedArc = node->arcs[i];
 -              
 -              /* depth is store as a negative in flag. symmetry level is positive */
 -              if (connectedArc->flags == -depth)
 -              {
 -                      if (arc1 == NULL)
 -                      {
 -                              arc1 = connectedArc;
 -                              node1 = OTHER_NODE(arc1, node);
 -                      }
 -                      else
 -                      {
 -                              arc2 = connectedArc;
 -                              node2 = OTHER_NODE(arc2, node);
 -                              break; /* Can stop now, the two arcs have been found */
 -                      }
 -              }
 -      }
 -      
 -      /* shouldn't happen, but just to be sure */
 -      if (node1 == NULL || node2 == NULL)
 -      {
 -              return;
 -      }
 -      
 -      VecSubf(p, node1->p, node->p);
 -      Crossf(vec, p, axis);
 -      Crossf(nor, vec, axis);
 -      
 -      /* mirror node2 along axis */
 -      VECCOPY(p, node2->p);
 -      mirrorAlongAxis(p, node->p, nor);
 -      
 -      /* check if it's within limit before continuing */
 -      if (VecLenf(node1->p, p) <= limit)
 -      {
 -      
 -              /* average with node1 */
 -              VecAddf(node1->p, node1->p, p);
 -              VecMulf(node1->p, 0.5f);
 -              
 -              /* mirror back on node2 */
 -              VECCOPY(node2->p, node1->p);
 -              mirrorAlongAxis(node2->p, node->p, nor);
 -              
 -              /* Merge buckets
 -               * there shouldn't be any null arcs here, but just to be safe 
 -               * */
 -              if (arc1->bcount > 0 && arc2->bcount > 0)
 -              {
 -                      ReebArcIterator iter1, iter2;
 -                      EmbedBucket *bucket1 = NULL, *bucket2 = NULL;
 -                      
 -                      initArcIterator(&iter1, arc1, node);
 -                      initArcIterator(&iter2, arc2, node);
 -                      
 -                      bucket1 = nextBucket(&iter1);
 -                      bucket2 = nextBucket(&iter2);
 -              
 -                      /* Make sure they both start at the same value */       
 -                      while(bucket1 && bucket1->val < bucket2->val)
 -                      {
 -                              bucket1 = nextBucket(&iter1);
 -                      }
 -                      
 -                      while(bucket2 && bucket2->val < bucket1->val)
 -                      {
 -                              bucket2 = nextBucket(&iter2);
 -                      }
 -      
 -      
 -                      for ( ;bucket1 && bucket2; bucket1 = nextBucket(&iter1), bucket2 = nextBucket(&iter2))
 -                      {
 -                              bucket1->nv += bucket2->nv; /* add counts */
 -                              
 -                              /* mirror on axis */
 -                              mirrorAlongAxis(bucket2->p, node->p, nor);
 -                              /* add bucket2 in bucket1 */
 -                              VecLerpf(bucket1->p, bucket1->p, bucket2->p, (float)bucket2->nv / (float)(bucket1->nv));
 -      
 -                              /* copy and mirror back to bucket2 */                   
 -                              bucket2->nv = bucket1->nv;
 -                              VECCOPY(bucket2->p, bucket1->p);
 -                              mirrorAlongAxis(bucket2->p, node->p, nor);
 -                      }
 -              }
 -      }
 -}
 -
 -void markdownSecondarySymmetry(ReebNode *node, int depth, int level)
 -{
 -      float axis[3] = {0, 0, 0};
 -      int count = 0;
 -      int i;
 -
 -      /* Only reestablish spatial symmetry if needed */
 -      if (G.scene->toolsettings->skgen_options & SKGEN_SYMMETRY)
 -      {
 -              /* count the number of branches in this symmetry group
 -               * and determinte the axis of symmetry
 -               *  */  
 -              for (i = 0; node->arcs[i] != NULL; i++)
 -              {
 -                      ReebArc *connectedArc = node->arcs[i];
 -                      
 -                      /* depth is store as a negative in flag. symmetry level is positive */
 -                      if (connectedArc->flags == -depth)
 -                      {
 -                              count++;
 -                      }
 -                      /* If arc is on the axis */
 -                      else if (connectedArc->flags == level)
 -                      {
 -                              VecAddf(axis, axis, connectedArc->v1->p);
 -                              VecSubf(axis, axis, connectedArc->v2->p);
 -                      }
 -              }
 -      
 -              Normalize(axis);
 -      
 -              /* Split between axial and radial symmetry */
 -              if (count == 2)
 -              {
 -                      reestablishAxialSymmetry(node, depth, axis);
 -              }
 -              else
 -              {
 -                      reestablishRadialSymmetry(node, depth, axis);
 -              }
 -      }
 -
 -      /* markdown secondary symetries */      
 -      for (i = 0; node->arcs[i] != NULL; i++)
 -      {
 -              ReebArc *connectedArc = node->arcs[i];
 -              
 -              if (connectedArc->flags == -depth)
 -              {
 -                      /* markdown symmetry for branches corresponding to the depth */
 -                      markdownSymmetryArc(connectedArc, node, level + 1);
 -              }
 -      }
 -}
 -
 -void markdownSymmetryArc(ReebArc *arc, ReebNode *node, int level)
 -{
 -      int i;
 -      arc->flags = level;
 -      
 -      node = OTHER_NODE(arc, node);
 -      
 -      for (i = 0; node->arcs[i] != NULL; i++)
 -      {
 -              ReebArc *connectedArc = node->arcs[i];
 -              
 -              if (connectedArc != arc)
 -              {
 -                      ReebNode *connectedNode = OTHER_NODE(connectedArc, node);
 -                      
 -                      /* symmetry level is positive value, negative values is subtree depth */
 -                      connectedArc->flags = -subtreeDepth(connectedNode, connectedArc);
 -              }
 -      }
 -
 -      arc = NULL;
 -
 -      for (i = 0; node->arcs[i] != NULL; i++)
 -      {
 -              int issymmetryAxis = 0;
 -              ReebArc *connectedArc = node->arcs[i];
 -              
 -              /* only arcs not already marked as symetric */
 -              if (connectedArc->flags < 0)
 -              {
 -                      int j;
 -                      
 -                      /* true by default */
 -                      issymmetryAxis = 1;
 -                      
 -                      for (j = 0; node->arcs[j] != NULL && issymmetryAxis == 1; j++)
 -                      {
 -                              ReebArc *otherArc = node->arcs[j];
 -                              
 -                              /* different arc, same depth */
 -                              if (otherArc != connectedArc && otherArc->flags == connectedArc->flags)
 -                              {
 -                                      /* not on the symmetry axis */
 -                                      issymmetryAxis = 0;
 -                              } 
 -                      }
 -              }
 -              
 -              /* arc could be on the symmetry axis */
 -              if (issymmetryAxis == 1)
 -              {
 -                      /* no arc as been marked previously, keep this one */
 -                      if (arc == NULL)
 -                      {
 -                              arc = connectedArc;
 -                      }
 -                      else
 -                      {
 -                              /* there can't be more than one symmetry arc */
 -                              arc = NULL;
 -                              break;
 -                      }
 -              }
 -      }
 -      
 -      /* go down the arc continuing the symmetry axis */
 -      if (arc)
 -      {
 -              markdownSymmetryArc(arc, node, level);
 -      }
 -
 -      
 -      /* secondary symmetry */
 -      for (i = 0; node->arcs[i] != NULL; i++)
 -      {
 -              ReebArc *connectedArc = node->arcs[i];
 -              
 -              /* only arcs not already marked as symetric and is not the next arc on the symmetry axis */
 -              if (connectedArc->flags < 0)
 -              {
 -                      /* subtree depth is store as a negative value in the flag */
 -                      markdownSecondarySymmetry(node, -connectedArc->flags, level);
 -              }
 -      }
 -}
 -
 -void markdownSymmetry(ReebGraph *rg)
 -{
 -      ReebNode *node;
 -      ReebArc *arc;
 -      /* only for Acyclic graphs */
 -      int cyclic = isGraphCyclic(rg);
 -      
 -      /* mark down all arcs as non-symetric */
 -      for (arc = rg->arcs.first; arc; arc = arc->next)
 -      {
 -              arc->flags = 0;
 -      }
 -      
 -      /* mark down all nodes as not on the symmetry axis */
 -      for (node = rg->nodes.first; node; node = node->next)
 -      {
 -              node->flags = 0;
 -      }
 -
 -      /* node list is sorted, so lowest node is always the head (by design) */
 -      node = rg->nodes.first;
 -      
 -      /* only work on acyclic graphs and if only one arc is incident on the first node */
 -      if (cyclic == 0 && countConnectedArcs(rg, node) == 1)
 -      {
 -              arc = node->arcs[0];
 -              
 -              markdownSymmetryArc(arc, node, 1);
 -
 -              /* mark down non-symetric arcs */
 -              for (arc = rg->arcs.first; arc; arc = arc->next)
 -              {
 -                      if (arc->flags < 0)
 -                      {
 -                              arc->flags = 0;
 -                      }
 -                      else
 -                      {
 -                              /* mark down nodes with the lowest level symmetry axis */
 -                              if (arc->v1->flags == 0 || arc->v1->flags > arc->flags)
 -                              {
 -                                      arc->v1->flags = arc->flags;
 -                              }
 -                              if (arc->v2->flags == 0 || arc->v2->flags > arc->flags)
 -                              {
 -                                      arc->v2->flags = arc->flags;
 -                              }
 -                      }
 -              }
 -      }
 -}
  
  /**************************************** SUBDIVISION ALGOS ******************************************/
  
@@@ -4553,7 -5114,7 +4579,7 @@@ EditBone * subdivideByAngle(ReebArc *ar
        return lastBone;
  }
  
 -float calcCorrelation(ReebArc *arc, int start, int end, float v0[3], float n[3])
 +float calcVariance(ReebArc *arc, int start, int end, float v0[3], float n[3])
  {
        int len = 2 + abs(end - start);
        
                /* adding start(0) and end(1) values to s_t */
                s_t += (avg_t * avg_t) + (1 - avg_t) * (1 - avg_t);
                
 -              return 1.0f - s_xyz / s_t; 
 +              return s_xyz / s_t; 
        }
        else
        {
 -              return 1.0f;
 +              return 0;
 +      }
 +}
 +
 +float calcDistance(ReebArc *arc, int start, int end, float head[3], float tail[3])
 +{
 +      ReebArcIterator iter;
 +      EmbedBucket *bucket = NULL;
 +      float max_dist = 0;
 +      
 +      /* calculate maximum distance */
 +      for (initArcIterator2(&iter, arc, start, end), bucket = nextBucket(&iter);
 +              bucket;
 +              bucket = nextBucket(&iter))
 +      {
 +              float v1[3], v2[3], c[3];
 +              float dist;
 +              
 +              VecSubf(v1, head, tail);
 +              VecSubf(v2, bucket->p, tail);
 +
 +              Crossf(c, v1, v2);
 +              
 +              dist = Inpf(c, c) / Inpf(v1, v1);
 +              
 +              max_dist = dist > max_dist ? dist : max_dist;
        }
 +      
 +      
 +      return max_dist; 
  }
  
  EditBone * subdivideByCorrelation(ReebArc *arc, ReebNode *head, ReebNode *tail)
  {
        ReebArcIterator iter;
        float n[3];
 -      float CORRELATION_THRESHOLD = G.scene->toolsettings->skgen_correlation_limit;
 +      float ADAPTIVE_THRESHOLD = G.scene->toolsettings->skgen_correlation_limit;
        EditBone *lastBone = NULL;
        
        /* init iterator to get start and end from head */
        /* Calculate overall */
        VecSubf(n, arc->buckets[iter.end].p, head->p);
        
 -      if (G.scene->toolsettings->skgen_options & SKGEN_CUT_CORRELATION && 
 -              calcCorrelation(arc, iter.start, iter.end, head->p, n) < CORRELATION_THRESHOLD)
 +      if (G.scene->toolsettings->skgen_options & SKGEN_CUT_CORRELATION)
        {
                EmbedBucket *bucket = NULL;
                EmbedBucket *previous = NULL;
                EditBone *child = NULL;
                EditBone *parent = NULL;
 +              float normal[3] = {0, 0, 0};
 +              float avg_normal[3];
 +              int total = 0;
                int boneStart = iter.start;
 -
 +              
                parent = add_editbone("Bone");
                parent->flag = BONE_SELECTED|BONE_TIPSEL|BONE_ROOTSEL;
                VECCOPY(parent->head, head->p);
                        bucket;
                        previous = bucket, bucket = nextBucket(&iter))
                {
 -                      /* Calculate normal */
 -                      VecSubf(n, bucket->p, parent->head);
 +                      float btail[3];
 +                      float value = 0;
  
 -                      if (calcCorrelation(arc, boneStart, iter.index, parent->head, n) < CORRELATION_THRESHOLD)
 +                      if (G.scene->toolsettings->skgen_options & SKGEN_STICK_TO_EMBEDDING)
                        {
 -                              VECCOPY(parent->tail, previous->p);
 +                              VECCOPY(btail, bucket->p);
 +                      }
 +                      else
 +                      {
 +                              float length;
 +                              
 +                              /* Calculate normal */
 +                              VecSubf(n, bucket->p, parent->head);
 +                              length = Normalize(n);
 +                              
 +                              total += 1;
 +                              VecAddf(normal, normal, n);
 +                              VECCOPY(avg_normal, normal);
 +                              VecMulf(avg_normal, 1.0f / total);
 +                               
 +                              VECCOPY(btail, avg_normal);
 +                              VecMulf(btail, length);
 +                              VecAddf(btail, btail, parent->head);
 +                      }
 +
 +                      if (G.scene->toolsettings->skgen_options & SKGEN_ADAPTIVE_DISTANCE)
 +                      {
 +                              value = calcDistance(arc, boneStart, iter.index, parent->head, btail);
 +                      }
 +                      else
 +                      {
 +                              float n[3];
 +                              
 +                              VecSubf(n, btail, parent->head);
 +                              value = calcVariance(arc, boneStart, iter.index, parent->head, n);
 +                      }
 +
 +                      if (value > ADAPTIVE_THRESHOLD)
 +                      {
 +                              VECCOPY(parent->tail, btail);
  
                                child = add_editbone("Bone");
                                VECCOPY(child->head, parent->tail);
                                
                                parent = child; // new child is next parent
                                boneStart = iter.index; // start from end
 +                              
 +                              normal[0] = normal[1] = normal[2] = 0;
 +                              total = 0;
                        }
                }
  
@@@ -4737,7 -5231,7 +4763,7 @@@ float arcLengthRatio(ReebArc *arc
        float embedLength = 0.0f;
        int i;
        
 -      arcLength = VecLenf(arc->v1->p, arc->v2->p);
 +      arcLength = VecLenf(arc->head->p, arc->tail->p);
        
        if (arc->bcount > 0)
        {
                        embedLength += VecLenf(arc->buckets[i - 1].p, arc->buckets[i].p);
                }
                /* Add head and tail -> embedding vectors */
 -              embedLength += VecLenf(arc->v1->p, arc->buckets[0].p);
 -              embedLength += VecLenf(arc->v2->p, arc->buckets[arc->bcount - 1].p);
 +              embedLength += VecLenf(arc->head->p, arc->buckets[0].p);
 +              embedLength += VecLenf(arc->tail->p, arc->buckets[arc->bcount - 1].p);
        }
        else
        {
@@@ -4880,6 -5374,8 +4906,6 @@@ void generateSkeletonFromReebGraph(Reeb
        {
                exit_editmode(EM_FREEDATA|EM_FREEUNDO|EM_WAITCURSOR); // freedata, and undo
        }
 -
 -      setcursor_space(SPACE_VIEW3D, CURSOR_WAIT);
        
        dst = add_object(OB_ARMATURE);
        base_init_from_view3d(BASACT, G.vd);
  
        arcBoneMap = BLI_ghash_new(BLI_ghashutil_ptrhash, BLI_ghashutil_ptrcmp);
        
 -      markdownSymmetry(rg);
 +      BLI_markdownSymmetry((BGraph*)rg, rg->nodes.first, G.scene->toolsettings->skgen_symmetry_limit);
        
        for (arc = rg->arcs.first; arc; arc = arc->next) 
        {
  
                /* Find out the direction of the arc through simple heuristics (in order of priority) :
                 * 
 -               * 1- Arcs on primary symmetry axis (flags == 1) point up (head: high weight -> tail: low weight)
 +               * 1- Arcs on primary symmetry axis (symmetry == 1) point up (head: high weight -> tail: low weight)
                 * 2- Arcs starting on a primary axis point away from it (head: node on primary axis)
                 * 3- Arcs point down (head: low weight -> tail: high weight)
                 *
 -               * Finally, the arc direction is stored in its flags: 1 (low -> high), -1 (high -> low)
 +               * Finally, the arc direction is stored in its flag: 1 (low -> high), -1 (high -> low)
                 */
  
                /* if arc is a symmetry axis, internal bones go up the tree */          
 -              if (arc->flags == 1 && arc->v2->degree != 1)
 +              if (arc->symmetry_level == 1 && arc->tail->degree != 1)
                {
 -                      head = arc->v2;
 -                      tail = arc->v1;
 +                      head = arc->tail;
 +                      tail = arc->head;
                        
 -                      arc->flags = -1; /* mark arc direction */
 +                      arc->flag = -1; /* mark arc direction */
                }
                /* Bones point AWAY from the symmetry axis */
 -              else if (arc->v1->flags == 1)
 +              else if (arc->head->symmetry_level == 1)
                {
 -                      head = arc->v1;
 -                      tail = arc->v2;
 +                      head = arc->head;
 +                      tail = arc->tail;
                        
 -                      arc->flags = 1; /* mark arc direction */
 +                      arc->flag = 1; /* mark arc direction */
                }
 -              else if (arc->v2->flags == 1)
 +              else if (arc->tail->symmetry_level == 1)
                {
 -                      head = arc->v2;
 -                      tail = arc->v1;
 +                      head = arc->tail;
 +                      tail = arc->head;
                        
 -                      arc->flags = -1; /* mark arc direction */
 +                      arc->flag = -1; /* mark arc direction */
                }
                /* otherwise, always go from low weight to high weight */
                else
                {
 -                      head = arc->v1;
 -                      tail = arc->v2;
 +                      head = arc->head;
 +                      tail = arc->tail;
                        
 -                      arc->flags = 1; /* mark arc direction */
 +                      arc->flag = 1; /* mark arc direction */
                }
                
                /* Loop over subdivision methods */     
                ReebArc *incomingArc = NULL;
                int i;
  
 -              for (i = 0; node->arcs[i] != NULL; i++)
 +              for (i = 0; i < node->degree; i++)
                {
 -                      arc = node->arcs[i];
 +                      arc = (ReebArc*)node->arcs[i];
  
                        /* if arc is incoming into the node */
 -                      if ((arc->v1 == node && arc->flags == -1) || (arc->v2 == node && arc->flags == 1))
 +                      if ((arc->head == node && arc->flag == -1) || (arc->tail == node && arc->flag == 1))
                        {
                                if (incomingArc == NULL)
                                {
                        EditBone *parentBone = BLI_ghash_lookup(arcBoneMap, incomingArc);
  
                        /* Look for outgoing arcs and parent their bones */
 -                      for (i = 0; node->arcs[i] != NULL; i++)
 +                      for (i = 0; i < node->degree; i++)
                        {
                                arc = node->arcs[i];
  
                                /* if arc is outgoing from the node */
 -                              if ((arc->v1 == node && arc->flags == 1) || (arc->v2 == node && arc->flags == -1))
 +                              if ((arc->head == node && arc->flag == 1) || (arc->tail == node && arc->flag == -1))
                                {
                                        EditBone *childBone = BLI_ghash_lookup(arcBoneMap, arc);
  
        }
        
        BLI_ghash_free(arcBoneMap, NULL, NULL);
 -
 -      setcursor_space(SPACE_VIEW3D, CURSOR_EDIT);
        
        BIF_undo_push("Generate Skeleton");
  }
  
  void generateSkeleton(void)
  {
 -      EditMesh *em = G.editMesh;
 -      ReebGraph *rg = NULL;
 -      int i;
 +      ReebGraph *reebg;
        
 -      if (em == NULL)
 -              return;
 -
        setcursor_space(SPACE_VIEW3D, CURSOR_WAIT);
 -
 -      if (weightFromDistance(em) == 0)
 -      {
 -              error("No selected vertex\n");
 -              return;
 -      }
 -              
 -      renormalizeWeight(em, 1.0f);
 -      
 -      weightToHarmonic(em);
 -      
 -#ifdef DEBUG_REEB
 -      weightToVCol(em);
 -#endif
 -      
 -      rg = generateReebGraph(em, G.scene->toolsettings->skgen_resolution);
 -
 -      verifyBuckets(rg);
        
 -      /* Remove arcs without embedding */
 -      filterNullReebGraph(rg);
 +      reebg = BIF_ReebGraphFromEditMesh();
  
 -      verifyBuckets(rg);
 +      generateSkeletonFromReebGraph(reebg);
  
 +      REEB_freeGraph(reebg);
  
 -      i = 1;
 -      /* filter until there's nothing more to do */
 -      while (i == 1)
 -      {
 -              i = 0; /* no work done yet */
 -              
 -              if (G.scene->toolsettings->skgen_options & SKGEN_FILTER_EXTERNAL)
 -              {
 -                      i |= filterExternalReebGraph(rg, G.scene->toolsettings->skgen_threshold_external * G.scene->toolsettings->skgen_resolution);
 -              }
 -      
 -              verifyBuckets(rg);
 -      
 -              if (G.scene->toolsettings->skgen_options & SKGEN_FILTER_INTERNAL)
 -              {
 -                      i |= filterInternalReebGraph(rg, G.scene->toolsettings->skgen_threshold_internal * G.scene->toolsettings->skgen_resolution);
 -              }
 -      }
 -
 -      verifyBuckets(rg);
 -
 -      repositionNodes(rg);
 -      
 -      verifyBuckets(rg);
 -
 -      /* Filtering might have created degree 2 nodes, so remove them */
 -      removeNormalNodes(rg);
 -      
 -      verifyBuckets(rg);
 -
 -      for(i = 0; i <  G.scene->toolsettings->skgen_postpro_passes; i++)
 -      {
 -              postprocessGraph(rg, G.scene->toolsettings->skgen_postpro);
 -      }
 -
 -      buildAdjacencyList(rg);
 -      
 -      sortNodes(rg);
 -      
 -      sortArcs(rg);
 -      
 -      generateSkeletonFromReebGraph(rg);
 -
 -      freeGraph(rg);
 +      setcursor_space(SPACE_VIEW3D, CURSOR_EDIT);
  }