Mesh edit option 'AutoMerge' - access from the mesh menu, basically runs remove doubl...
authorCampbell Barton <ideasman42@gmail.com>
Thu, 18 Oct 2007 21:47:55 +0000 (21:47 +0000)
committerCampbell Barton <ideasman42@gmail.com>
Thu, 18 Oct 2007 21:47:55 +0000 (21:47 +0000)
unselected verts into selected verts, so it wont merge verts your not editing.

source/blender/include/BIF_editmesh.h
source/blender/include/editmesh.h
source/blender/makesdna/DNA_scene_types.h
source/blender/python/api2_2x/Mesh.c
source/blender/src/buttons_editing.c
source/blender/src/editmesh_add.c
source/blender/src/editmesh_mods.c
source/blender/src/editmesh_tools.c
source/blender/src/editobject.c
source/blender/src/header_view3d.c
source/blender/src/transform_conversions.c

index 7ad3fd480a3b4c4bf9c6a9f6d37e98754015d861..42d581ee758aeac0c2ec66de90105ac55515e839 100644 (file)
@@ -206,7 +206,7 @@ extern short sharesFace(struct EditEdge* e1, struct EditEdge* e2);
 #define SUBDIV_SELECT_LOOPCUT 3
 
 extern void convert_to_triface(int direction);
-extern int removedoublesflag(short flag, float limit);
+extern int removedoublesflag(short flag, short automerge, float limit);
 extern void xsortvert_flag(int flag);
 extern void hashvert_flag(int flag);
 
index ba96dff5aca71b5599a20a39e972c55d64573c24..1b2d91e22b80a156f0cc24183401a372efbbcc05 100644 (file)
@@ -90,6 +90,7 @@ extern int convex(float *v1, float *v2, float *v3, float *v4);
 
 /* ******************* editmesh_mods.c */
 extern EditEdge *findnearestedge(int *dist);
+extern void EM_automerge(int update);
 
 /**
  * findnearestvert
index 51ec3a9e1335029e9cd719cb61865e75eec135d6..2ba5ef5437c5c0b2d9cdefc9a5280ad69c33cde6 100644 (file)
@@ -418,8 +418,10 @@ typedef struct Scene {
        float editbutsize;                      /* size of normals */
        short selectmode;
        short proportional, prop_mode;
+       short automerge, pad5, pad6, pad7;
        
        short use_nodes;
+       
        struct bNodeTree *nodetree;     
        
        void *ed;                                                               /* sequence editor data is allocated here */
index 659ecd79d8186cf30f8d31260a9c97fd434b1bbe..494a1250728b0750852793d29bc4eced1b3f154d 100644 (file)
@@ -3526,7 +3526,7 @@ static PyObject *MEdgeSeq_collapse( BPy_MEdgeSeq * self, PyObject *args )
        basact = BASACT;
        BASACT = base;
        
-       removedoublesflag( 1, 0.0 );
+       removedoublesflag( 1, 0, 0.0 );
        /* make mesh's object active, enter mesh edit mode */
        G.obedit = object;
        
@@ -7214,7 +7214,7 @@ static PyObject *Mesh_Tools( BPy_Mesh * self, int type, void **args )
                esubdivideflag( 1, 0.0, *((int *)args[0]), 1, 0 );
                break;
        case MESH_TOOL_REMDOUB:
-               result = removedoublesflag( 1, *((float *)args[0]) );
+               result = removedoublesflag( 1, 0, *((float *)args[0]) );
 
                attr = PyInt_FromLong( result );
                if( !attr )
index c389c2ddc7e5bb29d87b8376f8aef741f8336918..86d518f54672d4aea532993c12b883f7ee96b3e4 100644 (file)
@@ -4226,7 +4226,7 @@ void do_meshbuts(unsigned short event)
                G.f -= G_DISABLE_OK;
                break;
        case B_REMDOUB:
-               count= removedoublesflag(1, G.scene->toolsettings->doublimit);
+               count= removedoublesflag(1, 1, G.scene->toolsettings->doublimit);
                notice("Removed: %d", count);
                if (count) { /* only undo and redraw if an action is taken */
                        countall ();
index 49913b345edf9ca86943b7269e33e5bd21b7a941..ccd8b58c47e3d1cf096ae1fb5f219a313e341085 100644 (file)
@@ -960,7 +960,7 @@ void make_prim(int type, float imat[3][3], int tot, int seg,
                        rotateflag(2, v1->co, cmat);
                }
 
-               removedoublesflag(4, 0.0001);
+               removedoublesflag(4, 0, 0.0001);
 
                /* and now do imat */
                eve= em->verts.first;
index a8c71824ef19df9d0ff75deff08f8c50775c095b..a0c864de0167f4174141976184f90b422ee3b541 100644 (file)
@@ -131,6 +131,18 @@ void EM_select_mirrored(void)
        }
 }
 
+void EM_automerge(int update) {
+       if  (G.scene->automerge) {
+               if (G.obedit && G.obedit->type==OB_MESH) {
+                       if (removedoublesflag(1, 1, G.scene->toolsettings->doublimit)) {
+                               if (update) {
+                                       DAG_object_flush_update(G.scene, G.obedit, OB_RECALC_DATA);
+                               }
+                       }
+               }
+       }
+}
+
 /* ****************************** SELECTION ROUTINES **************** */
 
 unsigned int em_solidoffs=0, em_wireoffs=0, em_vertoffs=0;     /* set in drawobject.c ... for colorindices */
@@ -3331,7 +3343,7 @@ void Vertex_Menu() {
        switch(ret)
        {
                case 1:
-                       notice("Removed %d Vertices", removedoublesflag(1, G.scene->toolsettings->doublimit));
+                       notice("Removed %d Vertices", removedoublesflag(1, 0, G.scene->toolsettings->doublimit));
                        BIF_undo_push("Remove Doubles");
                        break;
                case 2: 
index 2afac79be1d6688ff244cff2467b8539701f7b28..56db0ea70169774f0dac11af3abc7338cf4aa04b 100644 (file)
@@ -195,8 +195,15 @@ void convert_to_triface(int direction)
        
 }
 
-int removedoublesflag(short flag, float limit)         /* return amount */
+int removedoublesflag(short flag, short automerge, float limit)                /* return amount */
 {
+       /*
+               flag -  Test with vert->flags
+               weld -  Alternative operation, merge unselected into selected.
+                               Used for "Auto Weld" mode. warning.
+               limit - Quick manhattan distance between verts.
+       */
+       
        EditMesh *em = G.editMesh;
        /* all verts with (flag & 'flag') are being evaluated */
        EditVert *eve, *v1, *nextve;
@@ -209,12 +216,15 @@ int removedoublesflag(short flag, float limit)            /* return amount */
        
        if(multires_test()) return 0;
 
+       
        /* flag 128 is cleared, count */
+
+       /* Normal non weld operation */
        eve= em->verts.first;
        amount= 0;
        while(eve) {
                eve->f &= ~128;
-               if(eve->h==0 && (eve->f & flag)) amount++;
+               if(eve->h==0 && (automerge || (eve->f & flag))) amount++;
                eve= eve->next;
        }
        if(amount==0) return 0;
@@ -223,7 +233,7 @@ int removedoublesflag(short flag, float limit)              /* return amount */
        sb= sortblock= MEM_mallocN(sizeof(xvertsort)*amount,"sortremovedoub");
        eve= em->verts.first;
        while(eve) {
-               if(eve->h==0 && (eve->f & flag)) {
+               if(eve->h==0 && (automerge || (eve->f & flag))) {
                        sb->x= eve->co[0]+eve->co[1]+eve->co[2];
                        sb->v1= eve;
                        sb++;
@@ -232,44 +242,72 @@ int removedoublesflag(short flag, float limit)            /* return amount */
        }
        qsort(sortblock, amount, sizeof(xvertsort), vergxco);
 
+       
        /* test for doubles */
-       sb= sortblock;
-       for(a=0; a<amount; a++) {
-               eve= sb->v1;
-               if( (eve->f & 128)==0 ) {
-                       sb1= sb+1;
-                       for(b=a+1; b<amount; b++) {
-                               /* first test: simpel dist */
-                               dist= sb1->x - sb->x;
-                               if(dist > limit) break;
-                               
-                               /* second test: is vertex allowed */
-                               v1= sb1->v1;
-                               if( (v1->f & 128)==0 ) {
+       sb= sortblock;  
+       if (automerge) {
+               for(a=0; a<amount; a++, sb++) {
+                       eve= sb->v1;
+                       if( (eve->f & 128)==0 ) {
+                               sb1= sb+1;
+                               for(b=a+1; b<amount && (eve->f & 128)==0; b++, sb1++) {
+                                       if(sb1->x - sb->x > limit) break;
                                        
-                                       dist= (float)fabs(v1->co[0]-eve->co[0]);
-                                       if(dist<=limit) {
-                                               dist= (float)fabs(v1->co[1]-eve->co[1]);
-                                               if(dist<=limit) {
-                                                       dist= (float)fabs(v1->co[2]-eve->co[2]);
-                                                       if(dist<=limit) {
+                                       /* when welding, only allow selected-> unselected*/
+                                       v1= sb1->v1;
+                                       if( (v1->f & 128)==0 ) {
+                                               if ((eve->f & flag)==0 && (v1->f & flag)==1) {
+                                                       if(     (float)fabs(v1->co[0]-eve->co[0])<=limit && 
+                                                               (float)fabs(v1->co[1]-eve->co[1])<=limit &&
+                                                               (float)fabs(v1->co[2]-eve->co[2])<=limit)
+                                                       {       /* unique bit */
+                                                               eve->f|= 128;
+                                                               eve->tmp.v = v1;
+                                                       }
+                                               } else if(      (eve->f & flag)==1 && (v1->f & flag)==0 ) {
+                                                       if(     (float)fabs(v1->co[0]-eve->co[0])<=limit && 
+                                                               (float)fabs(v1->co[1]-eve->co[1])<=limit &&
+                                                               (float)fabs(v1->co[2]-eve->co[2])<=limit)
+                                                       {       /* unique bit */
                                                                v1->f|= 128;
                                                                v1->tmp.v = eve;
                                                        }
                                                }
                                        }
                                }
-                               sb1++;
                        }
                }
-               sb++;
+       } else {
+               for(a=0; a<amount; a++, sb++) {
+                       eve= sb->v1;
+                       if( (eve->f & 128)==0 ) {
+                               sb1= sb+1;
+                               for(b=a+1; b<amount; b++, sb1++) {
+                                       /* first test: simpel dist */
+                                       if(sb1->x - sb->x > limit) break;
+                                       v1= sb1->v1;
+                                       
+                                       /* second test: is vertex allowed */
+                                       if( (v1->f & 128)==0 ) {
+                                               if(     (float)fabs(v1->co[0]-eve->co[0])<=limit && 
+                                                       (float)fabs(v1->co[1]-eve->co[1])<=limit &&
+                                                       (float)fabs(v1->co[2]-eve->co[2])<=limit)
+                                               {
+                                                       v1->f|= 128;
+                                                       v1->tmp.v = eve;
+                                               }
+                                       }
+                               }
+                       }
+               }
        }
        MEM_freeN(sortblock);
-
-       for(eve = em->verts.first; eve; eve=eve->next)
-               if((eve->f & flag) && (eve->f & 128))
-                       EM_data_interp_from_verts(eve, eve->tmp.v, eve->tmp.v, 0.5f);
-
+       
+       if (!automerge)
+               for(eve = em->verts.first; eve; eve=eve->next)
+                       if((eve->f & flag) && (eve->f & 128))
+                               EM_data_interp_from_verts(eve, eve->tmp.v, eve->tmp.v, 0.5f);
+       
        /* test edges and insert again */
        eed= em->edges.first;
        while(eed) {
@@ -445,7 +483,7 @@ int removedoublesflag(short flag, float limit)              /* return amount */
        eve= (struct EditVert *)em->verts.first;
        while(eve) {
                nextve= eve->next;
-               if(eve->f & flag) {
+               if(automerge || eve->f & flag) {
                        if(eve->f & 128) {
                                a++;
                                BLI_remlink(&em->verts, eve);
@@ -4023,7 +4061,7 @@ static void bevel_mesh(float bsize, int allfaces)
 
        waitcursor(1);
 
-       removedoublesflag(1, limit);
+       removedoublesflag(1, 0, limit);
 
        /* tag all original faces */
        efa= em->faces.first;
@@ -4378,7 +4416,7 @@ static void bevel_mesh(float bsize, int allfaces)
        allqueue(REDRAWVIEW3D, 0);
        DAG_object_flush_update(G.scene, G.obedit, OB_RECALC_DATA);
        
-       removedoublesflag(1, limit);
+       removedoublesflag(1, 0, limit);
 
        /* flush selected vertices to edges/faces */
        EM_select_flush();
@@ -4531,7 +4569,7 @@ int EdgeLoopDelete(void) {
                return 0;
        }
        select_more();
-       removedoublesflag(1,0.001);
+       removedoublesflag(1,0, 0.001);
        EM_select_flush();
        DAG_object_flush_update(G.scene, G.obedit, OB_RECALC_DATA);
        return 1;
@@ -5079,6 +5117,8 @@ int EdgeSlide(short immediate, float imperc)
        }
        
        force_draw(0);
+       
+       EM_automerge(0);
        DAG_object_flush_update(G.scene, G.obedit, OB_RECALC_DATA);
        scrarea_queue_winredraw(curarea);                
        
@@ -6113,7 +6153,7 @@ int collapseEdges(void)
                
        }
        freecollections(&allcollections);
-       removedoublesflag(1, MERGELIMIT);
+       removedoublesflag(1, 0, MERGELIMIT);
        /*get rid of this!*/
        countall();
        DAG_object_flush_update(G.scene, G.obedit, OB_RECALC_DATA);
@@ -6157,7 +6197,7 @@ int merge_firstlast(int first, int uvmerge)
        }
        
        countall();
-       return removedoublesflag(1,MERGELIMIT);
+       return removedoublesflag(1, 0, MERGELIMIT);
 }
 
 int merge_target(int target, int uvmerge)
@@ -6180,7 +6220,7 @@ int merge_target(int target, int uvmerge)
        countall();
        DAG_object_flush_update(G.scene, G.obedit, OB_RECALC_DATA);
        allqueue(REDRAWVIEW3D, 0);
-       return removedoublesflag(1,MERGELIMIT);
+       return removedoublesflag(1, 0, MERGELIMIT);
        
 }
 #undef MERGELIMIT
index 33b6dbfe664aa43cf69857a5221edfd3fa57762c..6d63e0ad2306b3998ded09f3e76b16bf897461f6 100644 (file)
@@ -2424,12 +2424,12 @@ void special_editmenu(void)
                        esubdivideflag(1, fac, G.scene->toolsettings->editbutflag | B_SMOOTH, 1, 0);
                        BIF_undo_push("Subdivide Smooth");
                        break;          
-                       
+
                case 4:
                        mergemenu();
                        break;
                case 5:
-                       notice("Removed %d Vertices", removedoublesflag(1, G.scene->toolsettings->doublimit));
+                       notice("Removed %d Vertices", removedoublesflag(1, 1, G.scene->toolsettings->doublimit));
                        BIF_undo_push("Remove Doubles");
                        break;
                case 6:
index 105ac97f3359ff299572468a4d88456f0570f025..d64f8a8d1694936180c6e64b7049a31bcda0756e 100644 (file)
@@ -2536,7 +2536,7 @@ void do_view3d_edit_mesh_verticesmenu(void *arg, int event)
                make_parent();
                break;
        case 1: /* remove doubles */
-               count= removedoublesflag(1, G.scene->toolsettings->doublimit);
+               count= removedoublesflag(1, 0, G.scene->toolsettings->doublimit);
                notice("Removed: %d", count);
                if (count) { /* only undo and redraw if an action is taken */
                        DAG_object_flush_update(G.scene, G.obedit, OB_RECALC_DATA);
@@ -2978,8 +2978,12 @@ static void do_view3d_edit_meshmenu(void *arg, int event)
                if(G.scene->proportional) G.scene->proportional= 0;
                else G.scene->proportional= 1;
                break;
+       case 13: /* automerge edit (toggle) */
+               if(G.scene->automerge) G.scene->automerge= 0;
+               else G.scene->automerge= 1;
+               break;
 #ifdef WITH_VERSE
-       case 13:
+       case 14:
                if(session_list.first != session_list.last) session = session_menu();
                else session = session_list.first;
                if(session) b_verse_push_object(session, G.obedit);
@@ -3001,7 +3005,7 @@ static uiBlock *view3d_edit_meshmenu(void *arg_unused)
 #ifdef WITH_VERSE
        if((session_list.first != NULL) && (!G.obedit->vnode)) {
                uiDefIconTextBut(block, BUTM, 1, ICON_BLANK1, "Share at Verse Server",
-                               0, yco-=20, menuwidth, 19, NULL, 0.0, 0.0, 1, 13, "");
+                               0, yco-=20, menuwidth, 19, NULL, 0.0, 0.0, 1, 14, "");
                uiDefBut(block, SEPR, 0, "", 0, yco-=6, menuwidth, 6, NULL, 0.0, 0.0, 0, 0, "");
        }
 #endif
@@ -3037,6 +3041,8 @@ static uiBlock *view3d_edit_meshmenu(void *arg_unused)
        
        uiDefBut(block, SEPR, 0, "",                            0, yco-=6, menuwidth, 6, NULL, 0.0, 0.0, 0, 0, "");
                
+       
+       
        if(G.scene->proportional) {
                uiDefIconTextBut(block, BUTM, 1, ICON_CHECKBOX_HLT, "Proportional Editing|O", 0, yco-=20, menuwidth, 19, NULL, 0.0, 0.0, 1, 12, "");
        } else {
@@ -3046,6 +3052,14 @@ static uiBlock *view3d_edit_meshmenu(void *arg_unused)
        
        uiDefBut(block, SEPR, 0, "",                            0, yco-=6, menuwidth, 6, NULL, 0.0, 0.0, 0, 0, "");
        
+       if(G.scene->automerge) {
+               uiDefIconTextBut(block, BUTM, 1, ICON_CHECKBOX_HLT, "AutoMarge Editing", 0, yco-=20, menuwidth, 19, NULL, 0.0, 0.0, 1, 13, "");
+       } else {
+               uiDefIconTextBut(block, BUTM, 1, ICON_CHECKBOX_DEHLT, "AutoMarge Editing", 0, yco-=20, menuwidth, 19, NULL, 0.0, 0.0, 1, 13, "");
+       }
+       
+       uiDefBut(block, SEPR, 0, "",                            0, yco-=6, menuwidth, 6, NULL, 0.0, 0.0, 0, 0, "");
+       
        uiDefIconTextBlockBut(block, view3d_edit_mesh_showhidemenu, NULL, ICON_RIGHTARROW_THIN, "Show/Hide Vertices", 0, yco-=20, 120, 19, "");
 
        uiDefBut(block, SEPR, 0, "",                            0, yco-=6, menuwidth, 6, NULL, 0.0, 0.0, 0, 0, "");
index 7cb4c9b38c49f7036b4d46a573ba4fff4d26ee6a..3e1f08c82a3ba3162dc09591f5af9229265945ae 100644 (file)
 #include "BLI_blenlib.h"
 #include "BLI_editVert.h"
 
+#include "editmesh.h"
+
 #include "blendef.h"
 
 #include "mydevice.h"
@@ -2732,7 +2734,10 @@ void special_aftertrans_update(TransInfo *t)
        Base *base;
        short redrawipo=0, resetslowpar=1;
        int cancelled= (t->state == TRANS_CANCEL);
-               
+       
+       if (t->spacetype==SPACE_VIEW3D)
+               EM_automerge(1);
+       
        if(t->spacetype == SPACE_ACTION) {
                void *data;
                short datatype;