From ec664be2d751c5cf66c197a99da0d0cf3e3dfd09 Mon Sep 17 00:00:00 2001 From: Campbell Barton Date: Sat, 25 Mar 2006 06:32:39 +0000 Subject: [PATCH] Added select group edges (Length/Direction/FaceUsers) Added VecAngle2 - needed for grouping by normal and planer faces. Made select face & edge group ignore hidden faces. fixed a bug where hiding faces didnt update G.tot*sel --- source/blender/blenlib/BLI_arithb.h | 6 ++ source/blender/blenlib/intern/arithb.c | 16 ++- source/blender/src/editmesh_mods.c | 138 ++++++++++++++++++++----- 3 files changed, 134 insertions(+), 26 deletions(-) diff --git a/source/blender/blenlib/BLI_arithb.h b/source/blender/blenlib/BLI_arithb.h index fcb72f7d8f0..feb5af6b9e4 100644 --- a/source/blender/blenlib/BLI_arithb.h +++ b/source/blender/blenlib/BLI_arithb.h @@ -634,6 +634,12 @@ VecAngle3( float *v3 ); + float +VecAngle2( + float *v1, + float *v2 +); + void i_lookat( float vx, float vy, diff --git a/source/blender/blenlib/intern/arithb.c b/source/blender/blenlib/intern/arithb.c index 0734efba7f7..bbf2f88134c 100644 --- a/source/blender/blenlib/intern/arithb.c +++ b/source/blender/blenlib/intern/arithb.c @@ -2304,7 +2304,7 @@ void VecRotToQuat( float *vec, float phi, float *quat) } } -/* Return the angle in degrees between vecs 1-2 and 2-3 */ +/* Return the angle in degrees between vecs 1-2 and 2-3 in degrees */ float VecAngle3( float *v1, float *v2, float *v3) { float vec1[3], vec2[3]; @@ -2313,8 +2313,18 @@ float VecAngle3( float *v1, float *v2, float *v3) VecSubf(vec2, v2, v3); Normalise(vec1); Normalise(vec2); - /* 180.0/M_PI is 57.2957795131f*/ - return saacos(vec1[0]*vec2[0] + vec1[1]*vec2[1] + vec1[2]*vec2[2]) * 57.2957795131f; + return saacos(vec1[0]*vec2[0] + vec1[1]*vec2[1] + vec1[2]*vec2[2]) * 180.0/M_PI; +} + +/* Return the angle in degrees between vecs 1-2 and 2-3 */ +float VecAngle2( float *v1, float *v2) +{ + float vec1[3], vec2[3]; + VecCopyf(vec1, v1); + VecCopyf(vec2, v2); + Normalise(vec1); + Normalise(vec2); + return saacos(vec1[0]*vec2[0] + vec1[1]*vec2[1] + vec1[2]*vec2[2]) * 180.0/M_PI; } diff --git a/source/blender/src/editmesh_mods.c b/source/blender/src/editmesh_mods.c index 5bc8d3d9cbe..815f943954c 100644 --- a/source/blender/src/editmesh_mods.c +++ b/source/blender/src/editmesh_mods.c @@ -747,8 +747,8 @@ static int unified_findnearest(EditVert **eve, EditEdge **eed, EditFace **efa) /* **************** GROUP SELECTS ************** */ /* selects new faces/edges/verts based on the existing selection - mode 1 is same material - mode 2 is same image + mode 1: same material + mode 2: same image mode 3: same area mode 4: same perimeter mode 5: same normal @@ -757,40 +757,43 @@ static int unified_findnearest(EditVert **eve, EditEdge **eed, EditFace **efa) void facegroup_select(short mode) { EditMesh *em = G.editMesh; - EditFace *efa, *base_efa; - short change=0; - float thresh=G.scene->toolsettings->doublimit; + EditFace *efa, *base_efa=NULL; + short selcount=0; + float thresh=G.scene->toolsettings->doublimit; /* todo. better var for this */ for(efa= em->faces.first; efa; efa= efa->next) { - if (efa->f & SELECT) { + if (efa->f & SELECT && !efa->h) { base_efa= efa; break; } } + if (!base_efa) + return; + if (mode==1) { /* same material */ for(efa= em->faces.first; efa; efa= efa->next) { - if (!(efa->f & SELECT) && base_efa->mat_nr == efa->mat_nr) { + if (!(efa->f & SELECT) && !efa->h && base_efa->mat_nr == efa->mat_nr) { EM_select_face(efa, 1); - change=1; + selcount++; } } } else if (mode==2) { /* same image */ for(efa= em->faces.first; efa; efa= efa->next) { - if (!(efa->f & SELECT) && base_efa->tf.tpage == efa->tf.tpage) { + if (!(efa->f & SELECT) && !efa->h && base_efa->tf.tpage == efa->tf.tpage) { EM_select_face(efa, 1); - change=1; + selcount++; } } } else if (mode==3) { /* same area */ float area, base_area; base_area= EM_face_area(base_efa); for(efa= em->faces.first; efa; efa= efa->next) { - if (!(efa->f & SELECT)) { + if (!(efa->f & SELECT) && !efa->h) { area= EM_face_area(efa); if (fabs(area-base_area)<=thresh) { EM_select_face(efa, 1); - change=1; + selcount++; } } } @@ -798,22 +801,22 @@ void facegroup_select(short mode) float perimeter, base_perimeter; base_perimeter= EM_face_perimeter(base_efa); for(efa= em->faces.first; efa; efa= efa->next) { - if (!(efa->f & SELECT)) { + if (!(efa->f & SELECT) && !efa->h) { perimeter= EM_face_perimeter(efa); if (fabs(perimeter-base_perimeter)<=thresh) { EM_select_face(efa, 1); - change=1; + selcount++; } } } } else if (mode==5) { /* same normal */ float angle; for(efa= em->faces.first; efa; efa= efa->next) { - if (!(efa->f & SELECT)) { - angle= saacos(base_efa->n[0]*efa->n[0] + base_efa->n[1]*efa->n[1] + base_efa->n[2]*efa->n[2]) * 57.2957795131; /*180.0/M_PI*/ + if (!(efa->f & SELECT) && !efa->h) { + angle= VecAngle2(base_efa->n, efa->n); if (angle<=thresh) { EM_select_face(efa, 1); - change=1; + selcount++; } } } @@ -821,13 +824,13 @@ void facegroup_select(short mode) float angle, base_dot, dot; base_dot= base_efa->cent[0]*base_efa->n[0] + base_efa->cent[1]*base_efa->n[1] + base_efa->cent[2]*base_efa->n[2]; for(efa= em->faces.first; efa; efa= efa->next) { - if (!(efa->f & SELECT)) { - angle= saacos(base_efa->n[0]*efa->n[0] + base_efa->n[1]*efa->n[1] + base_efa->n[2]*efa->n[2]) * 57.2957795131; /*180.0/M_PI*/ + if (!(efa->f & SELECT) && !efa->h) { + angle= VecAngle2(base_efa->n, efa->n); if (angle<=thresh) { dot= efa->cent[0]*base_efa->n[0] + efa->cent[1]*base_efa->n[1] + efa->cent[2]*base_efa->n[2]; if (fabs(base_dot-dot) <= thresh) { EM_select_face(efa, 1); - change=1; + selcount++; } } } @@ -835,12 +838,98 @@ void facegroup_select(short mode) } - if (change) { + if (selcount) { + G.totfacesel+=selcount; allqueue(REDRAWVIEW3D, 0); BIF_undo_push("Select Grouped Faces"); } } + +/* selects new faces/edges/verts based on the + existing selection + mode 1: same length + mode 2: same direction + mode 3: same number of face users +*/ +void edgegroup_select(short mode) +{ + EditMesh *em = G.editMesh; + EditEdge *eed, *base_eed=NULL; + short selcount=0; + float thresh=G.scene->toolsettings->doublimit; /* todo. better var for this */ + if (mode==3) { /* set all eed->tmp.l to 0 we use them later.*/ + for(eed= em->edges.first; eed; eed= eed->next) { + if (eed->f & SELECT && !eed->h) { + base_eed= eed; + } + eed->tmp.l=0; + } + } else { + for(eed= em->edges.first; eed; eed= eed->next) { + if (eed->f & SELECT && !eed->h) { + base_eed= eed; + break; + } + } + } + + if (!base_eed) + return; + + if (mode==1) { /* same length */ + float base_length= VecLenf(base_eed->v1->co, base_eed->v2->co); + for(eed= em->edges.first; eed; eed= eed->next) { + if (!(eed->f & SELECT) && !eed->h && ( fabs(base_length-VecLenf(eed->v1->co, eed->v2->co)) <= thresh ) ) { + EM_select_edge(eed, 1); + selcount++; + } + } + } else if (mode==2) { /* same direction */ + float base_dir[3], dir[3], angle; + VecSubf(base_dir, base_eed->v1->co, base_eed->v2->co); + for(eed= em->edges.first; eed; eed= eed->next) { + if (!(eed->f & SELECT) && !eed->h) { + VecSubf(dir, eed->v1->co, eed->v2->co); + angle= VecAngle2(base_dir, dir); + + if (angle>90) /* use the smallest angle between the edges */ + angle= fabs(angle-180.0f); + + if (angle<=thresh) { + EM_select_edge(eed, 1); + selcount++; + } + } + } + } else if (mode==3) { /* face users */ + EditFace *efa; + + /* cound how many faces each edge uses use tmp->l */ + for(efa= em->faces.first; efa; efa= efa->next) { + efa->e1->tmp.l++; + efa->e2->tmp.l++; + efa->e3->tmp.l++; + if (efa->e4) efa->e4->tmp.l++; + } + + for(eed= em->edges.first; eed; eed= eed->next) { + if ((!(eed->f & SELECT) && !eed->h) && (base_eed->tmp.l==eed->tmp.l)) { + EM_select_edge(eed, 1); + selcount++; + } + } + } + + if (selcount) { + G.totedgesel+=selcount; + allqueue(REDRAWVIEW3D, 0); + BIF_undo_push("Select Grouped Faces"); + } +} + + + void select_mesh_group_menu() { short ret; @@ -851,7 +940,9 @@ void select_mesh_group_menu() facegroup_select(ret); } else if(G.scene->selectmode & SCE_SELECT_EDGE) { - /**/ + ret= pupmenu("Select Grouped Edges (by Same)%t|Length %x1|Direction %x2|Face Users%x3"); + if (ret<1) return; + edgegroup_select(ret); } else if(G.scene->selectmode & SCE_SELECT_VERTEX) { /**/ } @@ -1447,7 +1538,8 @@ void hide_mesh(int swap) if(eve->f1==1) eve->h= 1; } } - + + G.totedgesel= G.totfacesel= G.totvertsel= 0; allqueue(REDRAWVIEW3D, 0); DAG_object_flush_update(G.scene, G.obedit, OB_RECALC_DATA); BIF_undo_push("Hide");