Three new selection techniques in mesh edit mode, two of which are
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?
This commit is contained in:
@@ -154,6 +154,11 @@ void undo_pop_mesh(int steps);
|
|||||||
void undo_redo_mesh(void);
|
void undo_redo_mesh(void);
|
||||||
void undo_clear_mesh(void);
|
void undo_clear_mesh(void);
|
||||||
void undo_menu_mesh(void);
|
void undo_menu_mesh(void);
|
||||||
|
|
||||||
|
/* Stuff */
|
||||||
|
void select_non_manifold(void);
|
||||||
|
void select_more(void);
|
||||||
|
void select_less(void);
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
|||||||
@@ -8532,3 +8532,180 @@ void bevel_menu()
|
|||||||
righthandfaces(1);
|
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);
|
||||||
|
}
|
||||||
|
|||||||
@@ -583,6 +583,15 @@ void do_view3d_select_meshmenu(void *arg, int event)
|
|||||||
case 6: /* select Faceloop */
|
case 6: /* select Faceloop */
|
||||||
loop('s');
|
loop('s');
|
||||||
break;
|
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);
|
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, "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, "");
|
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, "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, "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, "");
|
uiDefIconTextBut(block, BUTM, 1, ICON_BLANK1, "Linked Vertices|Ctrl L", 0, yco-=20, menuwidth, 19, NULL, 0.0, 0.0, 1, 4, "");
|
||||||
|
|||||||
@@ -1144,6 +1144,9 @@ void winqreadview3dspace(ScrArea *sa, void *spacedata, BWinEvent *evt)
|
|||||||
else if((G.qual==0)) {
|
else if((G.qual==0)) {
|
||||||
mirrormenu();
|
mirrormenu();
|
||||||
}
|
}
|
||||||
|
if(G.qual & (LR_SHIFTKEY | LR_ALTKEY | LR_CTRLKEY)) {
|
||||||
|
if(G.obedit->type==OB_MESH) select_non_manifold();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
else if((G.qual==0)){
|
else if((G.qual==0)){
|
||||||
movetolayer();
|
movetolayer();
|
||||||
@@ -1440,11 +1443,30 @@ void winqreadview3dspace(ScrArea *sa, void *spacedata, BWinEvent *evt)
|
|||||||
|
|
||||||
case PAD0: case PAD1: case PAD2: case PAD3: case PAD4:
|
case PAD0: case PAD1: case PAD2: case PAD3: case PAD4:
|
||||||
case PAD5: case PAD6: case PAD7: case PAD8: case PAD9:
|
case PAD5: case PAD6: case PAD7: case PAD8: case PAD9:
|
||||||
case PADMINUS: case PADPLUSKEY: case PADENTER:
|
case PADENTER:
|
||||||
persptoetsen(event);
|
persptoetsen(event);
|
||||||
doredraw= 1;
|
doredraw= 1;
|
||||||
break;
|
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:
|
case ESCKEY:
|
||||||
if(G.qual==0) {
|
if(G.qual==0) {
|
||||||
if (G.vd->flag & V3D_DISPIMAGE) {
|
if (G.vd->flag & V3D_DISPIMAGE) {
|
||||||
|
|||||||
@@ -1584,6 +1584,10 @@ static TBitem tb_mesh_select[]= {
|
|||||||
{ 0, "SEPR", 0, NULL},
|
{ 0, "SEPR", 0, NULL},
|
||||||
{ 0, "Face Loop|Shift R", 6, NULL},
|
{ 0, "Face Loop|Shift R", 6, NULL},
|
||||||
{ 0, "Linked Vertices|Ctrl L", 4, 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}};
|
{ -1, "", 0, do_view3d_select_meshmenu}};
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user