Three new selection techniques in mesh edit mode, two of which are
authorChris Want <cwant@ualberta.ca>
Sat, 3 Jan 2004 06:01:16 +0000 (06:01 +0000)
committerChris Want <cwant@ualberta.ca>
Sat, 3 Jan 2004 06:01:16 +0000 (06:01 +0000)
controversial:

* "Select non-manifold geometry" via ctrl-alt-shift-M, or through
  the menu or toolbox. Great for troubleshooting weirdness on a
  subsurf, or for preparing a mesh for decimation or for rapid
  prototyping.

* "Select more" via ctrl-PADPLUS, or through the menu or toolbox.
  If a selected vert shares an edge with an unselected vert, the
  unselected one gets selected too. Similar to PADPLUS in wings3d.
  This is controversial because maybe it would be more useful to
  select all of the verts that share a face (instead of just an
  edge) with a selected vert -- what do *you* think?

* "Select less" via ctrl-PADMINUS, or through the menu or toolbox.
  If a selected vert shares an edge with an unselected vert, the
  selected one gets unselected too. Similar to PADMINUS in wings3d.
  Also, selected non-manifold geometry becomes unselected. This is
  controversial because of the non-manifold stuff ... is it needed?
  What do *you* think?

source/blender/include/BIF_editmesh.h
source/blender/src/editmesh.c
source/blender/src/header_view3d.c
source/blender/src/space.c
source/blender/src/toolbox.c

index 63e8a8ce12782a56911f5449512254b027af3024..0850551907c84bd0bd8105ef32ecc123df6dd24b 100644 (file)
@@ -154,6 +154,11 @@ void undo_pop_mesh(int steps);
 void undo_redo_mesh(void);
 void undo_clear_mesh(void);
 void undo_menu_mesh(void);
+
+/* Stuff */
+void select_non_manifold(void);
+void select_more(void);
+void select_less(void);
+
 #endif
 
index 53e8a0a80f0157160c17cdf89c22a81fb415d3d7..6f6dbaf00e7f64df4e019f7fb3b7a4c589a3e597 100644 (file)
@@ -8532,3 +8532,180 @@ void bevel_menu()
                righthandfaces(1);
        }
 }
+
+void select_non_manifold(void)
+{
+       EditVert *eve;
+       EditEdge *eed;
+       EditVlak *evl;
+
+       /* Selects isolated verts, and edges that do not have 2 neighboring
+        * faces
+        */
+
+
+       eve= G.edve.first;
+       while(eve) {
+               /* this will count how many edges are connected
+                * to this vert */
+               eve->f1= 0;
+               eve= eve->next;
+       }
+
+       eed= G.eded.first;
+       while(eed) {
+               /* this will count how many faces are connected to
+                * this edge */
+               eed->f1= 0;
+               /* increase edge count for verts */
+               ++eed->v1->f1;
+               ++eed->v2->f1;
+               eed= eed->next;
+       }
+
+       evl= G.edvl.first;
+       while(evl) {
+               /* increase face count for edges */
+               ++evl->e1->f1;
+               ++evl->e2->f1;
+               ++evl->e3->f1;
+               if (evl->e4)
+                       ++evl->e4->f1;                  
+               evl= evl->next;
+       }
+
+       /* select verts that are attached to an edge that does not
+        * have 2 neighboring faces */
+       eed= G.eded.first;
+       while(eed) {
+               if (eed->f1 != 2) {
+                       eed->v1->f |= 1;
+                       eed->v2->f |= 1;
+               }
+               eed= eed->next;
+       }
+
+       /* select isolated verts */
+       eve= G.edve.first;
+       while(eve) {
+               if (eve->f1 == 0) {
+                       eve->f |= 1;
+               }
+               eve= eve->next;
+       }
+       addqueue(curarea->win,  REDRAW, 0);
+
+}
+
+void select_more(void)
+{
+       EditVert *eve;
+       EditEdge *eed;
+
+       eve= G.edve.first;
+       while(eve) {
+               eve->f1 = 0;
+               eve= eve->next;
+       }
+
+       eed= G.eded.first;
+       while(eed) {
+               if (eed->v1->f & 1)
+                       eed->v2->f1 = 1;
+               if (eed->v2->f & 1)
+                       eed->v1->f1 = 1;
+
+               eed= eed->next;
+       }
+
+       eve= G.edve.first;
+       while(eve) {
+               if (eve->f1 == 1)
+                       eve->f |= 1;
+
+               eve= eve->next;
+       }
+
+       addqueue(curarea->win,  REDRAW, 0);
+}
+
+void select_less(void)
+{
+       EditVert *eve;
+       EditEdge *eed;
+       EditVlak *evl;
+
+       /* eve->f1 & 1 => isolated   */
+       /* eve->f1 & 2 => on an edge */
+       /* eve->f1 & 4 => shares edge with a deselected vert */ 
+       /* eve->f1 & 8 => at most one neighbor */ 
+
+       eve= G.edve.first;
+       while(eve) {
+               /* assume vert is isolated unless proven otherwise, */
+               /* assume at most one neighbor too */
+               eve->f1 = 1 | 8;
+
+               eve= eve->next;
+       }
+
+       eed= G.eded.first;
+       while(eed) {
+               /* this will count how many faces are connected to
+                * this edge */
+               eed->f1= 0;
+
+               /* if vert wasn't isolated, it now has more than one neighbor */
+               if (~eed->v1->f1 & 1) eed->v1->f1 &= ~8;
+               if (~eed->v2->f1 & 1) eed->v2->f1 &= ~8;
+
+               /* verts on edge are clearly not isolated */
+               eed->v1->f1 &= ~1;
+               eed->v2->f1 &= ~1;
+
+               /* if one of the verts on the edge is deselected, 
+                * deselect the other */
+               if (~eed->v1->f & 1)
+                       eed->v2->f1 |= 4;
+               if (~eed->v2->f & 1)
+                       eed->v1->f1 |= 4;
+
+               eed= eed->next;
+       }
+
+       evl= G.edvl.first;
+       while(evl) {
+               /* increase face count for edges */
+               ++evl->e1->f1;
+               ++evl->e2->f1;
+               ++evl->e3->f1;
+               if (evl->e4)
+                       ++evl->e4->f1;                  
+
+               evl= evl->next;
+       }
+
+       eed= G.eded.first;
+       while(eed) {
+               /* if the edge has only one neighboring face, then
+                * deselect attached verts */
+               if (eed->f1 == 1) {
+                       eed->v1->f1 |= 2;
+                       eed->v2->f1 |= 2;
+               }
+
+               eed= eed->next;
+       }
+
+       /* deselect verts */
+       eve= G.edve.first;
+       while(eve) {
+               if (eve->f1) {
+                       eve->f &= ~1;
+               }
+
+               eve= eve->next;
+       }
+
+       allqueue(REDRAWVIEW3D, 0);
+}
index 229a3d7986b47941342be11053ef73432d1411e4..c16231ea09a6cbb1b6c20896a61a78bb5823d043 100644 (file)
@@ -583,6 +583,15 @@ void do_view3d_select_meshmenu(void *arg, int event)
                case 6: /* select Faceloop */
                        loop('s');
                        break;
+               case 7: /* select more */
+                       select_more();
+                       break;
+               case 8: /* select less */
+                       select_less();
+                       break;
+               case 9: /* select less */
+                       select_non_manifold();
+                       break;
        }
        allqueue(REDRAWVIEW3D, 0);
 }
@@ -603,8 +612,20 @@ static uiBlock *view3d_select_meshmenu(void *arg_unused)
        uiDefIconTextBut(block, BUTM, 1, ICON_BLANK1, "Select/Deselect All|A",                          0, yco-=20, menuwidth, 19, NULL, 0.0, 0.0, 1, 2, "");
        uiDefIconTextBut(block, BUTM, 1, ICON_BLANK1, "Inverse",                                0, yco-=20, menuwidth, 19, NULL, 0.0, 0.0, 1, 3, "");
        
-       uiDefBut(block, SEPR, 0, "",                            0, yco-=6, menuwidth, 6, NULL, 0.0, 0.0, 0, 0, "");
-       
+       uiDefBut(block, SEPR, 0, "", 0, yco-=6, 
+                        menuwidth, 6, NULL, 0.0, 0.0, 0, 0, "");
+
+       uiDefIconTextBut(block, BUTM, 1, ICON_BLANK1, "More|Ctrl NumPad +",
+                                        0, yco-=20, menuwidth, 19, NULL, 0.0, 0.0, 1, 7, "");
+       uiDefIconTextBut(block, BUTM, 1, ICON_BLANK1, "Less|Ctrl NumPad -",
+                                        0, yco-=20, menuwidth, 19, NULL, 0.0, 0.0, 1, 8, "");
+       uiDefIconTextBut(block, BUTM, 1, ICON_BLANK1, 
+                                        "Non-manifold|Shift Ctrl Alt M", 
+                                        0, yco-=20, menuwidth, 19, NULL, 0.0, 0.0, 1, 9, "");
+
+       uiDefBut(block, SEPR, 0, "", 0, yco-=6, 
+                        menuwidth, 6, NULL, 0.0, 0.0, 0, 0, "");
+
        uiDefIconTextBut(block, BUTM, 1, ICON_BLANK1, "Faceloop|Shift R",                               0, yco-=20, menuwidth, 19, NULL, 0.0, 0.0, 1, 6, "");
 //     uiDefIconTextBut(block, BUTM, 1, ICON_BLANK1, "Random Vertices...",                             0, yco-=20, menuwidth, 19, NULL, 0.0, 0.0, 1, 5, "");
        uiDefIconTextBut(block, BUTM, 1, ICON_BLANK1, "Linked Vertices|Ctrl L",                         0, yco-=20, menuwidth, 19, NULL, 0.0, 0.0, 1, 4, "");
index 54c11d1594ce84fb48ec3da410acef477e450e00..0a4c814ae74329a0d2a860b6e25e29fa6f831413 100644 (file)
@@ -1144,6 +1144,9 @@ void winqreadview3dspace(ScrArea *sa, void *spacedata, BWinEvent *evt)
                                        else if((G.qual==0)) {
                                                mirrormenu();
                                        }
+                                       if(G.qual & (LR_SHIFTKEY | LR_ALTKEY | LR_CTRLKEY)) {
+                                               if(G.obedit->type==OB_MESH) select_non_manifold();
+                                       }
                                }
                                else if((G.qual==0)){
                                     movetolayer();
@@ -1440,11 +1443,30 @@ void winqreadview3dspace(ScrArea *sa, void *spacedata, BWinEvent *evt)
                                
                        case PAD0: case PAD1: case PAD2: case PAD3: case PAD4:
                        case PAD5: case PAD6: case PAD7: case PAD8: case PAD9:
-                       case PADMINUS: case PADPLUSKEY: case PADENTER:
+                       case PADENTER:
                                persptoetsen(event);
                                doredraw= 1;
                                break;
-                       
+                       case PADMINUS:
+                               if ( (G.qual==LR_CTRLKEY)
+                                        && (G.obedit) && (G.obedit->type==OB_MESH) )
+                                       select_less();
+                               else {
+                                       persptoetsen(event);
+                                       doredraw= 1;
+                               }
+                               break;
+
+                       case PADPLUSKEY:
+                               if ( (G.qual==LR_CTRLKEY)
+                                        && (G.obedit) && (G.obedit->type==OB_MESH) )
+                                       select_more();
+                               else {
+                                       persptoetsen(event);
+                                       doredraw= 1;
+                               }
+                               break;
+
                        case ESCKEY:
                                if(G.qual==0) {
                                        if (G.vd->flag & V3D_DISPIMAGE) {
index 8e0710ea9f57cf82bed3d0e4d78c48c379847c6f..b4471cac26cb2457886e043da59ff11a3ea1bffe 100644 (file)
@@ -1584,6 +1584,10 @@ static TBitem tb_mesh_select[]= {
 {      0, "SEPR",                              0, NULL},
 {      0, "Face Loop|Shift R", 6, NULL},
 {      0, "Linked Vertices|Ctrl L", 4, NULL},
+{   0, "SEPR",                          0, NULL},
+{   0, "More|Ctrl Numpad +",            7, NULL},
+{   0, "Less|Ctrl Numpad -",            8, NULL},
+{   0, "Non-manifold|Shift Ctrl Alt M", 9, NULL},
 {  -1, "",                     0, do_view3d_select_meshmenu}};