4 * ***** BEGIN GPL/BL DUAL LICENSE BLOCK *****
6 * This program is free software; you can redistribute it and/or
7 * modify it under the terms of the GNU General Public License
8 * as published by the Free Software Foundation; either version 2
9 * of the License, or (at your option) any later version. The Blender
10 * Foundation also sells licenses for use in proprietary software under
11 * the Blender License. See http://www.blender.org/BL/ for information
14 * This program is distributed in the hope that it will be useful,
15 * but WITHOUT ANY WARRANTY; without even the implied warranty of
16 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17 * GNU General Public License for more details.
19 * You should have received a copy of the GNU General Public License
20 * along with this program; if not, write to the Free Software Foundation,
21 * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
23 * The Original Code is Copyright (C) 2004 by NaN Holding BV.
24 * All rights reserved.
26 * The Original Code is: all of this file.
28 * Contributor(s): none yet.
30 * ***** END GPL/BL DUAL LICENSE BLOCK *****
35 editmesh_mods.c, UI level access, no geometry changes
43 #include "MEM_guardedalloc.h"
45 #include "MTC_matrixops.h"
47 #include "DNA_mesh_types.h"
48 #include "DNA_material_types.h"
49 #include "DNA_meshdata_types.h"
50 #include "DNA_modifier_types.h"
51 #include "DNA_object_types.h"
52 #include "DNA_texture_types.h"
53 #include "DNA_scene_types.h"
54 #include "DNA_screen_types.h"
55 #include "DNA_space_types.h"
56 #include "DNA_view3d_types.h"
58 #include "BLI_blenlib.h"
59 #include "BLI_arithb.h"
60 #include "BLI_editVert.h"
63 #include "BKE_displist.h"
64 #include "BKE_depsgraph.h"
65 #include "BKE_DerivedMesh.h"
66 #include "BKE_customdata.h"
67 #include "BKE_global.h"
69 #include "BKE_material.h"
70 #include "BKE_texture.h"
71 #include "BKE_utildefines.h"
74 #include "BKE_verse.h"
77 #include "BIF_editmesh.h"
78 #include "BIF_resources.h"
80 #include "BIF_glutil.h"
81 #include "BIF_graphics.h"
82 #include "BIF_interface.h"
83 #include "BIF_meshtools.h"
84 #include "BIF_mywindow.h"
85 #include "BIF_resources.h"
86 #include "BIF_screen.h"
87 #include "BIF_space.h"
88 #include "BIF_toolbox.h"
89 #include "BIF_editsima.h"
92 #include "BIF_verse.h"
95 #include "BDR_drawobject.h"
96 #include "BDR_editobject.h"
98 #include "BSE_drawview.h"
100 #include "BSE_view.h"
102 #include "IMB_imbuf_types.h"
103 #include "IMB_imbuf.h"
105 #include "RE_render_ext.h" /* externtex */
107 #include "multires.h"
108 #include "mydevice.h"
111 #include "editmesh.h"
114 /* ****************************** MIRROR **************** */
116 void EM_select_mirrored(void)
118 if(G.scene->selectmode & SCE_SELECT_VERTEX) {
119 EditMesh *em = G.editMesh;
122 for(eve= em->verts.first; eve; eve= eve->next) {
123 if(eve->f & SELECT) {
124 v1= editmesh_get_x_mirror_vert(G.obedit, eve->co);
134 /* ****************************** SELECTION ROUTINES **************** */
136 unsigned int em_solidoffs=0, em_wireoffs=0, em_vertoffs=0; /* set in drawobject.c ... for colorindices */
138 /* facilities for border select and circle select */
139 static char *selbuf= NULL;
141 /* opengl doesn't support concave... */
142 static void draw_triangulated(short mcords[][2], short tot)
144 ListBase lb={NULL, NULL};
150 dl= MEM_callocN(sizeof(DispList), "poly disp");
154 dl->verts= fp= MEM_callocN(tot*3*sizeof(float), "poly verts");
155 BLI_addtail(&lb, dl);
157 for(a=0; a<tot; a++, fp+=3) {
158 fp[0]= (float)mcords[a][0];
159 fp[1]= (float)mcords[a][1];
163 filldisplist(&lb, &lb);
166 dl= lb.first; /* filldisplist adds in head of list */
167 if(dl->type==DL_INDEX3) {
173 glBegin(GL_TRIANGLES);
175 glVertex3fv(fp+3*index[0]);
176 glVertex3fv(fp+3*index[1]);
177 glVertex3fv(fp+3*index[2]);
187 /* reads rect, and builds selection array for quick lookup */
188 /* returns if all is OK */
189 int EM_init_backbuf_border(short xmin, short ymin, short xmax, short ymax)
195 if(G.obedit==NULL || G.vd->drawtype<OB_SOLID || (G.vd->flag & V3D_ZBUF_SELECT)==0) return 0;
196 if(em_vertoffs==0) return 0;
198 buf= read_backbuf(xmin, ymin, xmax, ymax);
199 if(buf==NULL) return 0;
203 /* build selection lookup */
204 selbuf= MEM_callocN(em_vertoffs+1, "selbuf");
206 a= (xmax-xmin+1)*(ymax-ymin+1);
208 if(*dr>0 && *dr<=em_vertoffs)
216 int EM_check_backbuf(unsigned int index)
218 if(selbuf==NULL) return 1;
219 if(index>0 && index<=em_vertoffs)
220 return selbuf[index];
224 void EM_free_backbuf(void)
226 if(selbuf) MEM_freeN(selbuf);
230 /* mcords is a polygon mask
232 - draw with black in backbuffer,
233 - grab again and compare
236 int EM_mask_init_backbuf_border(short mcords[][2], short tot, short xmin, short ymin, short xmax, short ymax)
238 unsigned int *dr, *drm;
239 struct ImBuf *buf, *bufmask;
242 /* method in use for face selecting too */
244 if(FACESEL_PAINT_TEST);
247 else if(G.vd->drawtype<OB_SOLID || (G.vd->flag & V3D_ZBUF_SELECT)==0) return 0;
249 if(em_vertoffs==0) return 0;
251 buf= read_backbuf(xmin, ymin, xmax, ymax);
252 if(buf==NULL) return 0;
258 glDrawBuffer(GL_AUX0);
260 glDisable(GL_DEPTH_TEST);
265 /* yah, opengl doesn't do concave... tsk! */
266 draw_triangulated(mcords, tot);
268 glBegin(GL_LINE_LOOP); /* for zero sized masks, lines */
269 for(a=0; a<tot; a++) glVertex2s(mcords[a][0], mcords[a][1]);
273 glFinish(); /* to be sure readpixels sees mask */
275 glDrawBuffer(GL_BACK);
278 bufmask= read_backbuf(xmin, ymin, xmax, ymax);
280 if(bufmask==NULL) return 0; /* only when mem alloc fails, go crash somewhere else! */
282 /* build selection lookup */
283 selbuf= MEM_callocN(em_vertoffs+1, "selbuf");
285 a= (xmax-xmin+1)*(ymax-ymin+1);
287 if(*dr>0 && *dr<=em_vertoffs && *drm==0) selbuf[*dr]= 1;
291 IMB_freeImBuf(bufmask);
296 /* circle shaped sample area */
297 int EM_init_backbuf_circle(short xs, short ys, short rads)
301 short xmin, ymin, xmax, ymax, xc, yc;
304 /* method in use for face selecting too */
306 if(FACESEL_PAINT_TEST);
309 else if(G.vd->drawtype<OB_SOLID || (G.vd->flag & V3D_ZBUF_SELECT)==0) return 0;
310 if(em_vertoffs==0) return 0;
312 xmin= xs-rads; xmax= xs+rads;
313 ymin= ys-rads; ymax= ys+rads;
314 buf= read_backbuf(xmin, ymin, xmax, ymax);
315 if(buf==NULL) return 0;
319 /* build selection lookup */
320 selbuf= MEM_callocN(em_vertoffs+1, "selbuf");
322 for(yc= -rads; yc<=rads; yc++) {
323 for(xc= -rads; xc<=rads; xc++, dr++) {
324 if(xc*xc + yc*yc < radsq) {
325 if(*dr>0 && *dr<=em_vertoffs) selbuf[*dr]= 1;
335 static void findnearestvert__doClosest(void *userData, EditVert *eve, int x, int y, int index)
337 struct { short mval[2], pass, select, strict; int dist, lastIndex, closestIndex; EditVert *closest; } *data = userData;
340 if (index<=data->lastIndex)
343 if (index>data->lastIndex)
348 int temp = abs(data->mval[0] - x) + abs(data->mval[1]- y);
349 if ((eve->f&1) == data->select) {
350 if (data->strict == 1)
356 if (temp<data->dist) {
359 data->closestIndex = index;
367 static unsigned int findnearestvert__backbufIndextest(unsigned int index){
368 EditVert *eve = BLI_findlink(&G.editMesh->verts, index-1);
369 if(eve && (eve->f & SELECT)) return 0;
375 * dist (in/out): minimal distance to the nearest and at the end, actual distance
376 * sel: selection bias
377 * if SELECT, selected vertice are given a 5 pixel bias to make them farter than unselect verts
378 * if 0, unselected vertice are given the bias
379 * strict: if 1, the vertice corresponding to the sel parameter are ignored and not just biased
381 EditVert *findnearestvert(int *dist, short sel, short strict)
385 getmouseco_areawin(mval);
386 if(G.vd->drawtype>OB_WIRE && (G.vd->flag & V3D_ZBUF_SELECT)){
391 if(strict) index = sample_backbuf_rect(mval, 50, em_wireoffs, 0xFFFFFF, &distance, strict, findnearestvert__backbufIndextest);
392 else index = sample_backbuf_rect(mval, 50, em_wireoffs, 0xFFFFFF, &distance, 0, NULL);
394 eve = BLI_findlink(&G.editMesh->verts, index-1);
396 if(eve && distance < *dist) {
405 struct { short mval[2], pass, select, strict; int dist, lastIndex, closestIndex; EditVert *closest; } data;
406 static int lastSelectedIndex=0;
407 static EditVert *lastSelected=NULL;
409 if (lastSelected && BLI_findlink(&G.editMesh->verts, lastSelectedIndex)!=lastSelected) {
410 lastSelectedIndex = 0;
414 data.lastIndex = lastSelectedIndex;
415 data.mval[0] = mval[0];
416 data.mval[1] = mval[1];
419 data.strict = strict;
421 data.closestIndex = 0;
424 mesh_foreachScreenVert(findnearestvert__doClosest, &data, 1);
428 mesh_foreachScreenVert(findnearestvert__doClosest, &data, 1);
432 lastSelected = data.closest;
433 lastSelectedIndex = data.closestIndex;
439 /* returns labda for closest distance v1 to line-piece v2-v3 */
440 static float labda_PdistVL2Dfl( float *v1, float *v2, float *v3)
446 len= rc[0]*rc[0]+ rc[1]*rc[1];
450 return ( rc[0]*(v1[0]-v2[0]) + rc[1]*(v1[1]-v2[1]) )/len;
453 /* note; uses G.vd, so needs active 3d window */
454 static void findnearestedge__doClosest(void *userData, EditEdge *eed, int x0, int y0, int x1, int y1, int index)
456 struct { float mval[2]; int dist; EditEdge *closest; } *data = userData;
465 distance= PdistVL2Dfl(data->mval, v1, v2);
467 if(eed->f & SELECT) distance+=5;
468 if(distance < data->dist) {
469 if(G.vd->flag & V3D_CLIPPING) {
470 float labda= labda_PdistVL2Dfl(data->mval, v1, v2);
473 vec[0]= eed->v1->co[0] + labda*(eed->v2->co[0] - eed->v1->co[0]);
474 vec[1]= eed->v1->co[1] + labda*(eed->v2->co[1] - eed->v1->co[1]);
475 vec[2]= eed->v1->co[2] + labda*(eed->v2->co[2] - eed->v1->co[2]);
476 Mat4MulVecfl(G.obedit->obmat, vec);
478 if(view3d_test_clipping(G.vd, vec)==0) {
479 data->dist = distance;
484 data->dist = distance;
489 EditEdge *findnearestedge(int *dist)
493 getmouseco_areawin(mval);
495 if(G.vd->drawtype>OB_WIRE && (G.vd->flag & V3D_ZBUF_SELECT)) {
497 unsigned int index = sample_backbuf_rect(mval, 50, em_solidoffs, em_wireoffs, &distance,0, NULL);
498 EditEdge *eed = BLI_findlink(&G.editMesh->edges, index-1);
500 if (eed && distance<*dist) {
508 struct { float mval[2]; int dist; EditEdge *closest; } data;
510 data.mval[0] = mval[0];
511 data.mval[1] = mval[1];
515 mesh_foreachScreenEdge(findnearestedge__doClosest, &data, 2);
522 static void findnearestface__getDistance(void *userData, EditFace *efa, int x, int y, int index)
524 struct { short mval[2]; int dist; EditFace *toFace; } *data = userData;
526 if (efa==data->toFace) {
527 int temp = abs(data->mval[0]-x) + abs(data->mval[1]-y);
533 static void findnearestface__doClosest(void *userData, EditFace *efa, int x, int y, int index)
535 struct { short mval[2], pass; int dist, lastIndex, closestIndex; EditFace *closest; } *data = userData;
538 if (index<=data->lastIndex)
541 if (index>data->lastIndex)
546 int temp = abs(data->mval[0]-x) + abs(data->mval[1]-y);
548 if (temp<data->dist) {
551 data->closestIndex = index;
555 static EditFace *findnearestface(int *dist)
559 getmouseco_areawin(mval);
561 if(G.vd->drawtype>OB_WIRE && (G.vd->flag & V3D_ZBUF_SELECT)) {
562 unsigned int index = sample_backbuf(mval[0], mval[1]);
563 EditFace *efa = BLI_findlink(&G.editMesh->faces, index-1);
566 struct { short mval[2]; int dist; EditFace *toFace; } data;
568 data.mval[0] = mval[0];
569 data.mval[1] = mval[1];
570 data.dist = 0x7FFF; /* largest short */
573 mesh_foreachScreenFace(findnearestface__getDistance, &data);
575 if(G.scene->selectmode == SCE_SELECT_FACE || data.dist<*dist) { /* only faces, no dist check */
584 struct { short mval[2], pass; int dist, lastIndex, closestIndex; EditFace *closest; } data;
585 static int lastSelectedIndex=0;
586 static EditFace *lastSelected=NULL;
588 if (lastSelected && BLI_findlink(&G.editMesh->faces, lastSelectedIndex)!=lastSelected) {
589 lastSelectedIndex = 0;
593 data.lastIndex = lastSelectedIndex;
594 data.mval[0] = mval[0];
595 data.mval[1] = mval[1];
598 data.closestIndex = 0;
601 mesh_foreachScreenFace(findnearestface__doClosest, &data);
605 mesh_foreachScreenFace(findnearestface__doClosest, &data);
609 lastSelected = data.closest;
610 lastSelectedIndex = data.closestIndex;
616 /* for interactivity, frontbuffer draw in current window */
617 static void draw_dm_mapped_vert__mapFunc(void *theVert, int index, float *co, float *no_f, short *no_s)
619 if (EM_get_vert_for_index(index)==theVert) {
623 static void draw_dm_mapped_vert(DerivedMesh *dm, EditVert *eve)
625 EM_init_index_arrays(1, 0, 0);
627 dm->foreachMappedVert(dm, draw_dm_mapped_vert__mapFunc, eve);
629 EM_free_index_arrays();
632 static int draw_dm_mapped_edge__setDrawOptions(void *theEdge, int index)
634 return EM_get_edge_for_index(index)==theEdge;
636 static void draw_dm_mapped_edge(DerivedMesh *dm, EditEdge *eed)
638 EM_init_index_arrays(0, 1, 0);
639 dm->drawMappedEdges(dm, draw_dm_mapped_edge__setDrawOptions, eed);
640 EM_free_index_arrays();
643 static void draw_dm_mapped_face_center__mapFunc(void *theFace, int index, float *cent, float *no)
645 if (EM_get_face_for_index(index)==theFace) {
649 static void draw_dm_mapped_face_center(DerivedMesh *dm, EditFace *efa)
651 EM_init_index_arrays(0, 0, 1);
653 dm->foreachMappedFaceCenter(dm, draw_dm_mapped_face_center__mapFunc, efa);
655 EM_free_index_arrays();
658 static void unified_select_draw(EditVert *eve, EditEdge *eed, EditFace *efa)
660 DerivedMesh *dm = editmesh_get_derived_cage(CD_MASK_BAREMESH);
662 glDrawBuffer(GL_FRONT);
666 if(G.vd->flag & V3D_CLIPPING)
667 view3d_set_clipping(G.vd);
670 mymultmatrix(G.obedit->obmat);
674 if(G.scene->selectmode & SCE_SELECT_VERTEX) {
675 glPointSize(BIF_GetThemeValuef(TH_VERTEX_SIZE));
677 if(efa->f & SELECT) BIF_ThemeColor(TH_VERTEX_SELECT);
678 else BIF_ThemeColor(TH_VERTEX);
681 bglVertex3fv(efa->v1->co);
682 bglVertex3fv(efa->v2->co);
683 bglVertex3fv(efa->v3->co);
684 if(efa->v4) bglVertex3fv(efa->v4->co);
688 if(G.scene->selectmode & (SCE_SELECT_EDGE|SCE_SELECT_FACE)) {
690 BIF_ThemeColor((efa->f & SELECT)?TH_EDGE_SELECT:TH_WIRE);
692 draw_dm_mapped_edge(dm, efa->e1);
693 draw_dm_mapped_edge(dm, efa->e2);
694 draw_dm_mapped_edge(dm, efa->e3);
696 draw_dm_mapped_edge(dm, efa->e4);
701 if(G.scene->selectmode & SCE_SELECT_FACE && (G.vd->drawtype!=OB_TEXTURE)) {
703 glPointSize(BIF_GetThemeValuef(TH_FACEDOT_SIZE));
704 BIF_ThemeColor((efa->f & SELECT)?TH_FACE_DOT:TH_WIRE);
706 draw_dm_mapped_face_center(dm, efa);
712 if(G.scene->selectmode & (SCE_SELECT_EDGE|SCE_SELECT_FACE)) {
713 BIF_ThemeColor((eed->f & SELECT)?TH_EDGE_SELECT:TH_WIRE);
715 draw_dm_mapped_edge(dm, eed);
717 if(G.scene->selectmode & SCE_SELECT_VERTEX) {
718 glPointSize(BIF_GetThemeValuef(TH_VERTEX_SIZE));
720 BIF_ThemeColor((eed->f & SELECT)?TH_VERTEX_SELECT:TH_VERTEX);
722 draw_dm_mapped_vert(dm, eed->v1);
723 draw_dm_mapped_vert(dm, eed->v2);
727 if(G.scene->selectmode & SCE_SELECT_VERTEX) {
728 glPointSize(BIF_GetThemeValuef(TH_VERTEX_SIZE));
730 BIF_ThemeColor((eve->f & SELECT)?TH_VERTEX_SELECT:TH_VERTEX);
732 draw_dm_mapped_vert(dm, eve);
740 glDrawBuffer(GL_BACK);
742 if(G.vd->flag & V3D_CLIPPING)
743 view3d_clr_clipping();
745 /* signal that frontbuf differs from back */
746 curarea->win_swap= WIN_FRONT_OK;
752 /* best distance based on screen coords.
753 use g.scene->selectmode to define how to use
754 selected vertices and edges get disadvantage
755 return 1 if found one
757 static int unified_findnearest(EditVert **eve, EditEdge **eed, EditFace **efa)
765 if(G.scene->selectmode & SCE_SELECT_VERTEX)
766 *eve= findnearestvert(&dist, SELECT, 0);
767 if(G.scene->selectmode & SCE_SELECT_FACE)
768 *efa= findnearestface(&dist);
770 dist-= 20; /* since edges select lines, we give dots advantage of 20 pix */
771 if(G.scene->selectmode & SCE_SELECT_EDGE)
772 *eed= findnearestedge(&dist);
774 /* return only one of 3 pointers, for frontbuffer redraws */
776 *efa= NULL; *eve= NULL;
782 return (*eve || *eed || *efa);
785 /* this as a way to compare the ares, perim of 2 faces thay will scale to different sizes
786 *0.5 so smaller faces arnt ALWAYS selected with a thresh of 1.0 */
787 #define SCALE_CMP(a,b) ((a+a*thresh >= b) && (a-(a*thresh*0.5) <= b))
789 /* **************** GROUP SELECTS ************** */
790 /* selects new faces/edges/verts based on the
794 mode 1: same material
797 mode 4: same perimeter
799 mode 6: same co-planer
801 int facegroup_select(short mode)
803 EditMesh *em = G.editMesh;
804 EditFace *efa, *base_efa=NULL;
805 unsigned int selcount=0; /*count how many new faces we select*/
807 /*deselcount, count how many deselected faces are left, so we can bail out early
808 also means that if there are no deselected faces, we can avoid a lot of looping */
809 unsigned int deselcount=0;
812 float thresh=G.scene->toolsettings->select_thresh;
814 for(efa= em->faces.first; efa; efa= efa->next) {
816 if (efa->f & SELECT) {
821 deselcount++; /* a deselected face we may select later */
826 if (!ok || !deselcount) /* no data selected OR no more data to select */
829 /*if mode is 3 then record face areas, 4 record perimeter */
831 for(efa= em->faces.first; efa; efa= efa->next) {
832 efa->tmp.fp= EM_face_area(efa);
834 } else if (mode==4) {
835 for(efa= em->faces.first; efa; efa= efa->next) {
836 efa->tmp.fp= EM_face_perimeter(efa);
840 for(base_efa= em->faces.first; base_efa; base_efa= base_efa->next) {
841 if (base_efa->f1) { /* This was one of the faces originaly selected */
842 if (mode==1) { /* same material */
843 for(efa= em->faces.first; efa; efa= efa->next) {
845 !(efa->f & SELECT) &&
847 base_efa->mat_nr == efa->mat_nr
849 EM_select_face(efa, 1);
852 if (!deselcount) /*have we selected all posible faces?, if so return*/
856 } else if (mode==2) { /* same image */
857 MTFace *tf, *base_tf;
859 base_tf = (MTFace*)CustomData_em_get(&em->fdata, base_efa->data,
865 for(efa= em->faces.first; efa; efa= efa->next) {
866 if (!(efa->f & SELECT) && !efa->h) {
867 tf = (MTFace*)CustomData_em_get(&em->fdata, efa->data,
870 if(base_tf->tpage == tf->tpage) {
871 EM_select_face(efa, 1);
874 if (!deselcount) /*have we selected all posible faces?, if so return*/
879 } else if (mode==3 || mode==4) { /* same area OR same perimeter, both use the same temp var */
880 for(efa= em->faces.first; efa; efa= efa->next) {
882 (!(efa->f & SELECT) && !efa->h) &&
883 SCALE_CMP(base_efa->tmp.fp, efa->tmp.fp)
885 EM_select_face(efa, 1);
888 if (!deselcount) /*have we selected all posible faces?, if so return*/
892 } else if (mode==5) { /* same normal */
894 for(efa= em->faces.first; efa; efa= efa->next) {
895 if (!(efa->f & SELECT) && !efa->h) {
896 angle= VecAngle2(base_efa->n, efa->n);
897 if (angle/180.0<=thresh) {
898 EM_select_face(efa, 1);
901 if (!deselcount) /*have we selected all posible faces?, if so return*/
906 } else if (mode==6) { /* same planer */
907 float angle, base_dot, dot;
908 base_dot= Inpf(base_efa->cent, base_efa->n);
909 for(efa= em->faces.first; efa; efa= efa->next) {
910 if (!(efa->f & SELECT) && !efa->h) {
911 angle= VecAngle2(base_efa->n, efa->n);
912 if (angle/180.0<=thresh) {
913 dot=Inpf(efa->cent, base_efa->n);
914 if (fabs(base_dot-dot) <= thresh) {
915 EM_select_face(efa, 1);
918 if (!deselcount) /*have we selected all posible faces?, if so return*/
926 } /* end base_efa loop */
934 mode 2: same direction
935 mode 3: same number of face users
936 mode 4: similar face angles.
937 mode 5: similar crease
939 mode 7: similar sharp
942 /* this function is only used by edgegroup_select's edge angle */
946 int edgegroup_select(short mode)
948 EditMesh *em = G.editMesh;
949 EditEdge *eed, *base_eed=NULL;
950 unsigned int selcount=0; /* count how many new edges we select*/
952 /*count how many visible selected edges there are,
953 so we can return when there are none left */
954 unsigned int deselcount=0;
957 float thresh=G.scene->toolsettings->select_thresh;
959 for(eed= em->edges.first; eed; eed= eed->next) {
961 if (eed->f & SELECT) {
968 /* set all eed->tmp.l to 0 we use it later.
969 for counting face users*/
971 eed->f2=0; /* only for mode 4, edge animations */
975 if (!ok || !deselcount) /* no data selected OR no more data to select*/
978 if (mode==1) { /*store length*/
979 for(eed= em->edges.first; eed; eed= eed->next) {
980 if (!eed->h) /* dont calc data for hidden edges*/
981 eed->tmp.fp= VecLenf(eed->v1->co, eed->v2->co);
983 } else if (mode==3) { /*store face users*/
985 /* cound how many faces each edge uses use tmp->l */
986 for(efa= em->faces.first; efa; efa= efa->next) {
990 if (efa->e4) efa->e4->tmp.l++;
992 } else if (mode==4) { /*store edge angles */
995 /* cound how many faces each edge uses use tmp.l */
996 for(efa= em->faces.first; efa; efa= efa->next) {
997 /* here we use the edges temp data to assign a face
998 if a face has alredy been assigned (eed->f2==1)
999 we calculate the angle between the current face and
1000 the edges previously found face.
1001 store the angle in eed->tmp.fp (loosing the face eed->tmp.f)
1002 but tagging eed->f2==2, so we know not to look at it again.
1003 This only works for edges that connect to 2 faces. but its good enough
1006 /* se we can loop through face edges*/
1010 if (j==1) eed= efa->e2;
1011 else if (j==2) eed= efa->e3;
1016 } /* done looping */
1018 if (!eed->h) { /* dont calc data for hidden edges*/
1021 else if (eed->f2==0) /* first access, assign the face */
1023 else if (eed->f2==1) /* second, we assign the angle*/
1024 eed->tmp.fp= VecAngle2(eed->tmp.f->n, efa->n)/180;
1025 eed->f2++; /* f2==0 no face assigned. f2==1 one face found. f2==2 angle calculated.*/
1032 for(base_eed= em->edges.first; base_eed; base_eed= base_eed->next) {
1034 if (mode==1) { /* same length */
1035 for(eed= em->edges.first; eed; eed= eed->next) {
1037 !(eed->f & SELECT) &&
1039 SCALE_CMP(base_eed->tmp.fp, eed->tmp.fp)
1041 EM_select_edge(eed, 1);
1044 if (!deselcount) /*have we selected all posible faces?, if so return*/
1048 } else if (mode==2) { /* same direction */
1049 float base_dir[3], dir[3], angle;
1050 VecSubf(base_dir, base_eed->v1->co, base_eed->v2->co);
1051 for(eed= em->edges.first; eed; eed= eed->next) {
1052 if (!(eed->f & SELECT) && !eed->h) {
1053 VecSubf(dir, eed->v1->co, eed->v2->co);
1054 angle= VecAngle2(base_dir, dir);
1056 if (angle>90) /* use the smallest angle between the edges */
1057 angle= fabs(angle-180.0f);
1059 if (angle/90.0<=thresh) {
1060 EM_select_edge(eed, 1);
1063 if (!deselcount) /*have we selected all posible faces?, if so return*/
1068 } else if (mode==3) { /* face users */
1069 for(eed= em->edges.first; eed; eed= eed->next) {
1071 !(eed->f & SELECT) &&
1073 base_eed->tmp.l==eed->tmp.l
1075 EM_select_edge(eed, 1);
1078 if (!deselcount) /*have we selected all posible faces?, if so return*/
1082 } else if (mode==4 && base_eed->f2==2) { /* edge angles, f2==2 means the edge has an angle. */
1083 for(eed= em->edges.first; eed; eed= eed->next) {
1085 !(eed->f & SELECT) &&
1088 (fabs(base_eed->tmp.fp-eed->tmp.fp)<=thresh)
1090 EM_select_edge(eed, 1);
1093 if (!deselcount) /*have we selected all posible faces?, if so return*/
1097 } else if (mode==5) { /* edge crease */
1098 for(eed= em->edges.first; eed; eed= eed->next) {
1100 !(eed->f & SELECT) &&
1102 (fabs(base_eed->crease-eed->crease) <= thresh)
1104 EM_select_edge(eed, 1);
1107 if (!deselcount) /*have we selected all posible faces?, if so return*/
1111 } else if (mode==6) { /* edge seam */
1112 for(eed= em->edges.first; eed; eed= eed->next) {
1114 !(eed->f & SELECT) &&
1116 (eed->seam == base_eed->seam)
1118 EM_select_edge(eed, 1);
1121 if (!deselcount) /*have we selected all posible faces?, if so return*/
1125 } else if (mode==7) { /* edge sharp */
1126 for(eed= em->edges.first; eed; eed= eed->next) {
1128 !(eed->f & SELECT) &&
1130 (eed->sharp == base_eed->sharp)
1132 EM_select_edge(eed, 1);
1135 if (!deselcount) /*have we selected all posible faces?, if so return*/
1149 mode 2: same number of face users
1150 mode 3: same vertex groups
1152 int vertgroup_select(short mode)
1154 EditMesh *em = G.editMesh;
1155 EditVert *eve, *base_eve=NULL;
1157 unsigned int selcount=0; /* count how many new edges we select*/
1159 /*count how many visible selected edges there are,
1160 so we can return when there are none left */
1161 unsigned int deselcount=0;
1164 float thresh=G.scene->toolsettings->select_thresh;
1166 for(eve= em->verts.first; eve; eve= eve->next) {
1168 if (eve->f & SELECT) {
1175 /* set all eve->tmp.l to 0 we use them later.*/
1181 if (!ok || !deselcount) /* no data selected OR no more data to select*/
1185 if (mode==2) { /* store face users */
1188 /* count how many faces each edge uses use tmp->l */
1189 for(efa= em->faces.first; efa; efa= efa->next) {
1193 if (efa->v4) efa->v4->tmp.l++;
1198 for(base_eve= em->verts.first; base_eve; base_eve= base_eve->next) {
1201 if (mode==1) { /* same normal */
1203 for(eve= em->verts.first; eve; eve= eve->next) {
1204 if (!(eve->f & SELECT) && !eve->h) {
1205 angle= VecAngle2(base_eve->no, eve->no);
1206 if (angle/180.0<=thresh) {
1210 if (!deselcount) /*have we selected all posible faces?, if so return*/
1215 } else if (mode==2) { /* face users */
1216 for(eve= em->verts.first; eve; eve= eve->next) {
1218 !(eve->f & SELECT) &&
1220 base_eve->tmp.l==eve->tmp.l
1225 if (!deselcount) /*have we selected all posible faces?, if so return*/
1229 } else if (mode==3) { /* vertex groups */
1230 MDeformVert *dvert, *base_dvert;
1231 short i, j; /* weight index */
1233 base_dvert= CustomData_em_get(&em->vdata, base_eve->data,
1236 if (!base_dvert || base_dvert->totweight == 0)
1239 for(eve= em->verts.first; eve; eve= eve->next) {
1240 dvert= CustomData_em_get(&em->vdata, eve->data,
1243 if (dvert && !(eve->f & SELECT) && !eve->h && dvert->totweight) {
1244 /* do the extra check for selection in the following if, so were not
1245 checking verts that may be alredy selected */
1246 for (i=0; base_dvert->totweight >i && !(eve->f & SELECT); i++) {
1247 for (j=0; dvert->totweight >j; j++) {
1248 if (base_dvert->dw[i].def_nr==dvert->dw[j].def_nr) {
1252 if (!deselcount) /*have we selected all posible faces?, if so return*/
1262 } /* end basevert loop */
1266 /* EditMode menu triggered from space.c by pressing Shift+G
1267 handles face/edge vert context and
1268 facegroup_select/edgegroup_select/vertgroup_select do all the work
1271 void select_mesh_group_menu()
1274 int selcount, first_item=1, multi=0;
1275 char str[512] = "Select Similar "; /* total max length is 404 at the moment */
1277 if (!ELEM3(G.scene->selectmode, SCE_SELECT_VERTEX, SCE_SELECT_EDGE, SCE_SELECT_FACE)) {
1281 if(G.scene->selectmode & SCE_SELECT_VERTEX) {
1282 if (multi) strcat(str, "%t|Vertices%x-1|");
1283 else strcat(str, "Vertices %t|");
1284 strcat(str, " Normal %x1| Face Users %x2| Shared Vertex Groups%x3");
1288 if(G.scene->selectmode & SCE_SELECT_EDGE) {
1290 if (first_item) strcat(str, "%t|Edges%x-1|");
1291 else strcat(str, "|%l|Edges%x-1|");
1292 } else strcat(str, "Edges %t|");
1294 strcat(str, " Length %x10| Direction %x20| Face Users%x30| Face Angle%x40| Crease%x50| Seam%x60| Sharp%x70");
1298 if(G.scene->selectmode & SCE_SELECT_FACE) {
1300 strcat(str, "|%l|Faces%x-1|");
1301 } else strcat(str, "Faces %t|");
1302 strcat(str, " Material %x100| Image %x200| Area %x300| Perimeter %x400| Normal %x500| Co-Planar %x600");
1310 selcount= vertgroup_select(ret);
1311 if (selcount) { /* update if data was selected */
1312 EM_select_flush(); /* so that selected verts, go onto select faces */
1313 G.totvertsel += selcount;
1314 allqueue(REDRAWVIEW3D, 0);
1315 if (EM_texFaceCheck())
1316 allqueue(REDRAWIMAGE, 0);
1317 BIF_undo_push("Select Similar Vertices");
1323 selcount= edgegroup_select(ret/10);
1325 if (selcount) { /* update if data was selected */
1326 /*EM_select_flush();*/ /* dont use because it can end up selecting more edges and is not usefull*/
1327 G.totedgesel+=selcount;
1328 allqueue(REDRAWVIEW3D, 0);
1329 if (EM_texFaceCheck())
1330 allqueue(REDRAWIMAGE, 0);
1331 BIF_undo_push("Select Similar Edges");
1337 selcount= facegroup_select(ret/100);
1338 if (selcount) { /* update if data was selected */
1339 G.totfacesel+=selcount;
1340 allqueue(REDRAWVIEW3D, 0);
1341 if (EM_texFaceCheck())
1342 allqueue(REDRAWIMAGE, 0);
1343 BIF_undo_push("Select Similar Faces");
1349 int mesh_layers_menu_charlen(CustomData *data, int type)
1352 /* see if there is a duplicate */
1353 for(i=0; i<data->totlayer; i++) {
1354 if((&data->layers[i])->type == type) {
1355 /* we could count the chars here but we'll just assumeme each
1356 * is 32 chars with some room for the menu text - 40 should be fine */
1363 /* this function adds menu text into an existing string.
1364 * this string's size should be allocated with mesh_layers_menu_charlen */
1365 void mesh_layers_menu_concat(CustomData *data, int type, char *str) {
1368 CustomDataLayer *layer;
1370 /* see if there is a duplicate */
1371 for(i=0; i<data->totlayer; i++) {
1372 layer = &data->layers[i];
1373 if(layer->type == type) {
1374 str_pt += sprintf(str_pt, "%s%%x%d|", layer->name, count);
1380 int mesh_layers_menu(CustomData *data, int type) {
1384 str_pt = str = MEM_mallocN(mesh_layers_menu_charlen(data, type) + 18, "layer menu");
1387 str_pt += sprintf(str_pt, "Layers%%t|");
1389 mesh_layers_menu_concat(data, type, str_pt);
1396 /* ctrl+c in mesh editmode */
1397 void mesh_copy_menu(void)
1399 EditMesh *em = G.editMesh;
1401 short ret, change=0;
1405 ese = em->selected.last;
1409 if(ese->type == EDITVERT) {
1410 /*EditVert *ev, *ev_act = (EditVert*)ese->data;
1412 } else if(ese->type == EDITEDGE) {
1413 EditEdge *eed, *eed_act = (EditEdge*)ese->data;
1414 float vec[3], vec_mid[3], eed_len, eed_len_act;
1416 ret= pupmenu("Copy Active Edge to Selected%t|Crease%x1|Length%x2");
1419 eed_len_act = VecLenf(eed_act->v1->co, eed_act->v2->co);
1422 case 1: /* copy crease */
1423 for(eed=em->edges.first; eed; eed=eed->next) {
1424 if (eed->f & SELECT && eed != eed_act && eed->crease != eed_act->crease) {
1425 eed->crease = eed_act->crease;
1431 case 2: /* copy length */
1433 for(eed=em->edges.first; eed; eed=eed->next) {
1434 if (eed->f & SELECT && eed != eed_act) {
1436 eed_len = VecLenf(eed->v1->co, eed->v2->co);
1438 if (eed_len == eed_len_act) continue;
1439 /* if this edge is zero length we cont do anything with it*/
1440 if (eed_len == 0.0f) continue;
1441 if (eed_len_act == 0.0f) {
1442 VecAddf(vec_mid, eed->v1->co, eed->v2->co);
1443 VecMulf(vec_mid, 0.5);
1444 VECCOPY(eed->v1->co, vec_mid);
1445 VECCOPY(eed->v2->co, vec_mid);
1447 /* copy the edge length */
1448 VecAddf(vec_mid, eed->v1->co, eed->v2->co);
1449 VecMulf(vec_mid, 0.5);
1452 VecSubf(vec, eed->v1->co, vec_mid);
1453 VecMulf(vec, eed_len_act/eed_len);
1454 VecAddf(eed->v1->co, vec, vec_mid);
1457 VecSubf(vec, eed->v2->co, vec_mid);
1458 VecMulf(vec, eed_len_act/eed_len);
1459 VecAddf(eed->v2->co, vec, vec_mid);
1466 recalc_editnormals();
1472 } else if(ese->type == EDITFACE) {
1473 EditFace *efa, *efa_act = (EditFace*)ese->data;
1474 MTFace *tf, *tf_act;
1475 MCol *mcol, *mcol_act;
1478 "Copy Face Selected%t|"
1479 "Active Material%x1|Active Image%x2|Active UV Coords%x3|"
1480 "Active Mode%x4|Active Transp%x5|Active Vertex Colors%x6|%l|"
1482 "TexFace UVs from layer%x7|"
1483 "TexFace Images from layer%x8|"
1484 "TexFace All from layer%x9|"
1485 "Vertex Colors from layer%x10");
1489 tf_act = CustomData_em_get(&em->fdata, efa_act->data, CD_MTFACE);
1490 mcol_act = CustomData_em_get(&em->fdata, efa_act->data, CD_MCOL);
1493 case 1: /* copy material */
1494 for(efa=em->faces.first; efa; efa=efa->next) {
1495 if (efa->f & SELECT && efa->mat_nr != efa_act->mat_nr) {
1496 efa->mat_nr = efa_act->mat_nr;
1501 case 2: /* copy image */
1503 error("mesh has no uv/image layers");
1506 for(efa=em->faces.first; efa; efa=efa->next) {
1507 if (efa->f & SELECT && efa != efa_act) {
1508 tf = CustomData_em_get(&em->fdata, efa->data, CD_MTFACE);
1509 if (tf_act->tpage) {
1510 tf->tpage = tf_act->tpage;
1514 tf->mode &= ~TF_TEX;
1516 tf->tile= tf_act->tile;
1522 case 3: /* copy UV's */
1524 error("mesh has no uv/image layers");
1527 for(efa=em->faces.first; efa; efa=efa->next) {
1528 if (efa->f & SELECT && efa != efa_act) {
1529 tf = CustomData_em_get(&em->fdata, efa->data, CD_MTFACE);
1530 memcpy(tf->uv, tf_act->uv, sizeof(tf->uv));
1535 case 4: /* mode's */
1537 error("mesh has no uv/image layers");
1540 for(efa=em->faces.first; efa; efa=efa->next) {
1541 if (efa->f & SELECT && efa != efa_act) {
1542 tf = CustomData_em_get(&em->fdata, efa->data, CD_MTFACE);
1543 tf->mode= tf_act->mode;
1548 case 5: /* copy transp's */
1550 error("mesh has no uv/image layers");
1553 for(efa=em->faces.first; efa; efa=efa->next) {
1554 if (efa->f & SELECT && efa != efa_act) {
1555 tf = CustomData_em_get(&em->fdata, efa->data, CD_MTFACE);
1556 tf->transp= tf_act->transp;
1562 case 6: /* copy vcols's */
1564 error("mesh has no color layers");
1567 /* guess the 4th color if needs be */
1571 /* guess the othe vale, we may need to use it
1573 * Modifying the 4th value of the mcol is ok here since its not seen
1576 val = ((float)(mcol_act->r + (mcol_act+1)->r + (mcol_act+2)->r)) / 3; CLAMP(val, 0, 255);
1577 (mcol_act+3)->r = (char)val;
1579 val = ((float)(mcol_act->g + (mcol_act+1)->g + (mcol_act+2)->g)) / 3; CLAMP(val, 0, 255);
1580 (mcol_act+3)->g = (char)val;
1582 val = ((float)(mcol_act->b + (mcol_act+1)->b + (mcol_act+2)->b)) / 3; CLAMP(val, 0, 255);
1583 (mcol_act+3)->b = (char)val;
1587 for(efa=em->faces.first; efa; efa=efa->next) {
1588 if (efa->f & SELECT && efa != efa_act) {
1589 /* TODO - make copy from tri to quad guess the 4th vert */
1590 mcol = CustomData_em_get(&em->fdata, efa->data, CD_MCOL);
1591 memcpy(mcol, mcol_act, sizeof(MCol)*4);
1600 /* copy from layer */
1605 error("mesh has no uv/image layers");
1607 } else if (CustomData_number_of_layers(&em->fdata, CD_MTFACE)<2) {
1608 error("mesh does not have multiple uv/image layers");
1611 int layer_orig_idx, layer_idx;
1613 layer_idx = mesh_layers_menu(&em->fdata, CD_MTFACE);
1614 if (layer_idx<0) return;
1616 /* warning, have not updated mesh pointers however this is not needed since we swicth back */
1617 layer_orig_idx = CustomData_get_active_layer(&em->fdata, CD_MTFACE);
1618 if (layer_idx==layer_orig_idx)
1621 /* get the tfaces */
1622 CustomData_set_layer_active(&em->fdata, CD_MTFACE, (int)layer_idx);
1623 /* store the tfaces in our temp */
1624 for(efa=em->faces.first; efa; efa=efa->next) {
1625 if (efa->f & SELECT) {
1626 efa->tmp.p = CustomData_em_get(&em->fdata, efa->data, CD_MTFACE);
1629 CustomData_set_layer_active(&em->fdata, CD_MTFACE, layer_orig_idx);
1633 case 10: /* select vcol layers - make sure this stays in sync with above code */
1635 error("mesh has no color layers");
1637 } else if (CustomData_number_of_layers(&em->fdata, CD_MCOL)<2) {
1638 error("mesh does not have multiple color layers");
1641 int layer_orig_idx, layer_idx;
1643 layer_idx = mesh_layers_menu(&em->fdata, CD_MCOL);
1644 if (layer_idx<0) return;
1646 /* warning, have not updated mesh pointers however this is not needed since we swicth back */
1647 layer_orig_idx = CustomData_get_active_layer(&em->fdata, CD_MCOL);
1648 if (layer_idx==layer_orig_idx)
1651 /* get the tfaces */
1652 CustomData_set_layer_active(&em->fdata, CD_MCOL, (int)layer_idx);
1653 /* store the tfaces in our temp */
1654 for(efa=em->faces.first; efa; efa=efa->next) {
1655 if (efa->f & SELECT) {
1656 efa->tmp.p = CustomData_em_get(&em->fdata, efa->data, CD_MCOL);
1659 CustomData_set_layer_active(&em->fdata, CD_MCOL, layer_orig_idx);
1665 /* layer copy only - sanity checks done above */
1667 case 7: /* copy UV's only */
1668 for(efa=em->faces.first; efa; efa=efa->next) {
1669 if (efa->f & SELECT) {
1670 tf_act = (MTFace *)efa->tmp.p; /* not active but easier to use this way */
1671 tf = CustomData_em_get(&em->fdata, efa->data, CD_MTFACE);
1672 memcpy(tf->uv, tf_act->uv, sizeof(tf->uv));
1677 case 8: /* copy image settings only */
1678 for(efa=em->faces.first; efa; efa=efa->next) {
1679 if (efa->f & SELECT) {
1680 tf_act = (MTFace *)efa->tmp.p; /* not active but easier to use this way */
1681 tf = CustomData_em_get(&em->fdata, efa->data, CD_MTFACE);
1682 if (tf_act->tpage) {
1683 tf->tpage = tf_act->tpage;
1687 tf->mode &= ~TF_TEX;
1689 tf->tile= tf_act->tile;
1694 case 9: /* copy all tface info */
1695 for(efa=em->faces.first; efa; efa=efa->next) {
1696 if (efa->f & SELECT) {
1697 tf_act = (MTFace *)efa->tmp.p; /* not active but easier to use this way */
1698 tf = CustomData_em_get(&em->fdata, efa->data, CD_MTFACE);
1699 memcpy(tf->uv, ((MTFace *)efa->tmp.p)->uv, sizeof(tf->uv));
1700 tf->tpage = tf_act->tpage;
1701 tf->mode = tf_act->mode;
1702 tf->transp = tf_act->transp;
1708 for(efa=em->faces.first; efa; efa=efa->next) {
1709 if (efa->f & SELECT) {
1710 mcol_act = (MCol *)efa->tmp.p;
1711 mcol = CustomData_em_get(&em->fdata, efa->data, CD_MCOL);
1712 memcpy(mcol, mcol_act, sizeof(MCol)*4);
1722 DAG_object_flush_update(G.scene, G.obedit, OB_RECALC_DATA);
1723 allqueue(REDRAWVIEW3D, 0);
1724 allqueue(REDRAWBUTSEDIT, 0);
1726 if(ese->type == EDITVERT) BIF_undo_push("Copy Vert Attribute");
1727 else if (ese->type == EDITEDGE) BIF_undo_push("Copy Edge Attribute");
1728 else if (ese->type == EDITFACE) BIF_undo_push("Copy Face Attribute");
1734 /* **************** LOOP SELECTS *************** */
1736 /* selects quads in loop direction of indicated edge */
1737 /* only flush over edges with valence <= 2 */
1738 void faceloop_select(EditEdge *startedge, int select)
1740 EditMesh *em = G.editMesh;
1745 /* in eed->f1 we put the valence (amount of faces in edge) */
1746 /* in eed->f2 we put tagged flag as correct loop */
1747 /* in efa->f1 we put tagged flag as correct to select */
1749 for(eed= em->edges.first; eed; eed= eed->next) {
1753 for(efa= em->faces.first; efa; efa= efa->next) {
1759 if(efa->e4) efa->e4->f1++;
1763 /* tag startedge OK*/
1769 for(efa= em->faces.first; efa; efa= efa->next) {
1770 if(efa->e4 && efa->f1==0) { /* not done quad */
1771 if(efa->e1->f1<=2 && efa->e2->f1<=2 && efa->e3->f1<=2 && efa->e4->f1<=2) { /* valence ok */
1773 /* if edge tagged, select opposing edge and mark face ok */
1779 else if(efa->e2->f2) {
1799 /* (de)select the faces */
1801 for(efa= em->faces.first; efa; efa= efa->next) {
1802 if(efa->f1) EM_select_face(efa, select);
1808 /* helper for edgeloop_select, checks for eed->f2 tag in faces */
1809 static int edge_not_in_tagged_face(EditEdge *eed)
1811 EditMesh *em = G.editMesh;
1814 for(efa= em->faces.first; efa; efa= efa->next) {
1816 if(efa->e1==eed || efa->e2==eed || efa->e3==eed || efa->e4==eed) { /* edge is in face */
1817 if(efa->e1->f2 || efa->e2->f2 || efa->e3->f2 || (efa->e4 && efa->e4->f2)) { /* face is tagged */
1826 /* selects or deselects edges that:
1827 - if edges has 2 faces:
1828 - has vertices with valence of 4
1829 - not shares face with previous edge
1830 - if edge has 1 face:
1831 - has vertices with valence 4
1832 - not shares face with previous edge
1833 - but also only 1 face
1835 - has vertices with valence 2
1837 static void edgeloop_select(EditEdge *starteed, int select)
1839 EditMesh *em = G.editMesh;
1845 /* in f1 we put the valence (amount of edges in a vertex, or faces in edge) */
1846 /* in eed->f2 and efa->f1 we put tagged flag as correct loop */
1847 for(eve= em->verts.first; eve; eve= eve->next) {
1851 for(eed= em->edges.first; eed; eed= eed->next) {
1854 if((eed->h & 1)==0) { /* fgon edges add to valence too */
1855 eed->v1->f1++; eed->v2->f1++;
1858 for(efa= em->faces.first; efa; efa= efa->next) {
1864 if(efa->e4) efa->e4->f1++;
1868 /* looped edges & vertices get tagged f2 */
1870 if(starteed->v1->f1<5) starteed->v1->f2= 1;
1871 if(starteed->v2->f1<5) starteed->v2->f2= 1;
1872 /* sorry, first edge isnt even ok */
1873 if(starteed->v1->f2==0 && starteed->v2->f2==0) looking= 0;
1878 /* find correct valence edges which are not tagged yet, but connect to tagged one */
1879 for(eed= em->edges.first; eed; eed= eed->next) {
1880 if(eed->h==0 && eed->f2==0) { /* edge not hidden, not tagged */
1881 if( (eed->v1->f1<5 && eed->v1->f2) || (eed->v2->f1<5 && eed->v2->f2)) { /* valence of vertex OK, and is tagged */
1882 /* new edge is not allowed to be in face with tagged edge */
1883 if(edge_not_in_tagged_face(eed)) {
1884 if(eed->f1==starteed->f1) { /* same amount of faces */
1887 if(eed->v2->f1<5) eed->v2->f2= 1;
1888 if(eed->v1->f1<5) eed->v1->f2= 1;
1895 /* and we do the select */
1896 for(eed= em->edges.first; eed; eed= eed->next) {
1897 if(eed->f2) EM_select_edge(eed, select);
1902 Almostly exactly the same code as faceloop select
1904 static void edgering_select(EditEdge *startedge, int select){
1905 EditMesh *em = G.editMesh;
1910 /* in eed->f1 we put the valence (amount of faces in edge) */
1911 /* in eed->f2 we put tagged flag as correct loop */
1912 /* in efa->f1 we put tagged flag as correct to select */
1914 for(eed= em->edges.first; eed; eed= eed->next) {
1918 for(efa= em->faces.first; efa; efa= efa->next) {
1924 if(efa->e4) efa->e4->f1++;
1928 /* tag startedge OK */
1934 for(efa= em->faces.first; efa; efa= efa->next) {
1935 if(efa->e4 && efa->f1==0 && !efa->h) { /* not done quad */
1936 if(efa->e1->f1<=2 && efa->e2->f1<=2 && efa->e3->f1<=2 && efa->e4->f1<=2) { /* valence ok */
1938 /* if edge tagged, select opposing edge and mark face ok */
1944 else if(efa->e2->f2) {
1964 /* (de)select the edges */
1965 for(eed= em->edges.first; eed; eed= eed->next) {
1966 if(eed->f2) EM_select_edge(eed, select);
1970 void loop_multiselect(int looptype)
1974 int edindex, edfirstcount;
1976 /*edarray = MEM_mallocN(sizeof(*edarray)*G.totedgesel,"edge array");*/
1977 edarray = MEM_mallocN(sizeof(EditEdge*)*G.totedgesel,"edge array");
1979 edfirstcount = G.totedgesel;
1981 for(eed=G.editMesh->edges.first; eed; eed=eed->next){
1983 edarray[edindex] = eed;
1989 for(edindex = 0; edindex < edfirstcount; edindex +=1){
1990 eed = edarray[edindex];
1991 edgering_select(eed,SELECT);
1994 EM_selectmode_flush();
1995 BIF_undo_push("Edge Ring Multi-Select");
1998 for(edindex = 0; edindex < edfirstcount; edindex +=1){
1999 eed = edarray[edindex];
2000 edgeloop_select(eed,SELECT);
2003 EM_selectmode_flush();
2004 BIF_undo_push("Edge Loop Multi-Select");
2007 allqueue(REDRAWVIEW3D,0);
2008 if (EM_texFaceCheck())
2009 allqueue(REDRAWIMAGE, 0);
2012 /* ***************** MAIN MOUSE SELECTION ************** */
2014 /* just to have the functions nice together */
2015 static void mouse_mesh_loop(void)
2021 eed= findnearestedge(&dist);
2024 if((G.qual & LR_SHIFTKEY)==0) EM_clear_flag_all(SELECT);
2026 if((eed->f & SELECT)==0) select=1;
2027 else if(G.qual & LR_SHIFTKEY) select=0;
2029 if(G.scene->selectmode & SCE_SELECT_FACE) {
2030 faceloop_select(eed, select);
2032 else if(G.scene->selectmode & SCE_SELECT_EDGE) {
2033 if(G.qual == (LR_CTRLKEY | LR_ALTKEY) || G.qual == (LR_CTRLKEY | LR_ALTKEY |LR_SHIFTKEY))
2034 edgering_select(eed, select);
2035 else if(G.qual & LR_ALTKEY)
2036 edgeloop_select(eed, select);
2038 else if(G.scene->selectmode & SCE_SELECT_VERTEX) {
2039 if(G.qual == (LR_CTRLKEY | LR_ALTKEY) || G.qual == (LR_CTRLKEY | LR_ALTKEY |LR_SHIFTKEY))
2040 edgering_select(eed, select);
2041 else if(G.qual & LR_ALTKEY)
2042 edgeloop_select(eed, select);
2045 /* frontbuffer draw of last selected only */
2046 unified_select_draw(NULL, eed, NULL);
2048 EM_selectmode_flush();
2050 allqueue(REDRAWVIEW3D, 0);
2051 if (EM_texFaceCheck())
2052 allqueue(REDRAWIMAGE, 0);
2057 /* here actual select happens */
2058 void mouse_mesh(void)
2064 if(G.qual & LR_ALTKEY) mouse_mesh_loop();
2065 else if(unified_findnearest(&eve, &eed, &efa)) {
2067 if((G.qual & LR_SHIFTKEY)==0) EM_clear_flag_all(SELECT);
2071 if( (efa->f & SELECT)==0 ) {
2072 EM_store_selection(efa, EDITFACE);
2073 EM_select_face_fgon(efa, 1);
2075 else if(G.qual & LR_SHIFTKEY) {
2076 EM_remove_selection(efa, EDITFACE);
2077 EM_select_face_fgon(efa, 0);
2081 if((eed->f & SELECT)==0) {
2082 EM_store_selection(eed, EDITEDGE);
2083 EM_select_edge(eed, 1);
2085 else if(G.qual & LR_SHIFTKEY) {
2086 EM_remove_selection(eed, EDITEDGE);
2087 EM_select_edge(eed, 0);
2091 if((eve->f & SELECT)==0) {
2093 EM_store_selection(eve, EDITVERT);
2095 else if(G.qual & LR_SHIFTKEY){
2096 EM_remove_selection(eve, EDITVERT);
2101 /* frontbuffer draw of last selected only */
2102 unified_select_draw(eve, eed, efa);
2104 EM_selectmode_flush();
2107 allqueue(REDRAWVIEW3D, 0);
2108 if (EM_texFaceCheck()) {
2109 allqueue(REDRAWIMAGE, 0);
2110 allqueue(REDRAWBUTSEDIT, 0); /* for the texture face panel */
2114 rightmouse_transform();
2118 void selectconnected_mesh_all(void)
2120 EditMesh *em = G.editMesh;
2123 short done=1, toggle=0;
2125 if(em->edges.first==0) return;
2131 if(toggle & 1) eed= em->edges.first;
2132 else eed= em->edges.last;
2138 if(v1->f & SELECT) {
2139 if( (v2->f & SELECT)==0 ) {
2144 else if(v2->f & SELECT) {
2145 if( (v1->f & SELECT)==0 ) {
2151 if(toggle & 1) eed= eed->next;
2152 else eed= eed->prev;
2156 /* now use vertex select flag to select rest */
2161 allqueue(REDRAWVIEW3D, 0);
2162 if (EM_texFaceCheck())
2163 allqueue(REDRAWIMAGE, 0);
2164 BIF_undo_push("Select Connected (All)");
2167 void selectconnected_mesh(void)
2169 EditMesh *em = G.editMesh;
2170 EditVert *eve, *v1, *v2;
2173 short done=1, sel, toggle=0;
2175 if(em->edges.first==0) return;
2177 if( unified_findnearest(&eve, &eed, &efa)==0 ) {
2178 error("Nothing indicated ");
2183 if(G.qual & LR_SHIFTKEY) sel=0;
2185 /* clear test flags */
2186 for(v1= em->verts.first; v1; v1= v1->next) v1->f1= 0;
2188 /* start vertex/face/edge */
2190 else if(eed) eed->v1->f1= eed->v2->f1= 1;
2191 else efa->v1->f1= efa->v2->f1= efa->v3->f1= 1;
2193 /* set flag f1 if affected */
2198 if(toggle & 1) eed= em->edges.first;
2199 else eed= em->edges.last;
2206 if(v1->f1 && v2->f1==0) {
2210 else if(v1->f1==0 && v2->f1) {
2216 if(toggle & 1) eed= eed->next;
2217 else eed= eed->prev;
2221 /* now use vertex f1 flag to select/deselect */
2222 for(eed= em->edges.first; eed; eed= eed->next) {
2223 if(eed->v1->f1 && eed->v2->f1)
2224 EM_select_edge(eed, sel);
2226 for(efa= em->faces.first; efa; efa= efa->next) {
2227 if(efa->v1->f1 && efa->v2->f1 && efa->v3->f1 && (efa->v4==NULL || efa->v4->f1))
2228 EM_select_face(efa, sel);
2230 /* no flush needed, connected geometry is done */
2234 allqueue(REDRAWVIEW3D, 0);
2235 if (EM_texFaceCheck())
2236 allqueue(REDRAWIMAGE, 0);
2238 BIF_undo_push("Select Linked");
2242 /* for use with selectconnected_delimit_mesh only! */
2243 #define is_edge_delimit_ok(eed) ((eed->tmp.l == 1) && (eed->seam==0))
2244 #define is_face_tag(efa) is_edge_delimit_ok(efa->e1) || is_edge_delimit_ok(efa->e2) || is_edge_delimit_ok(efa->e3) || (efa->v4 && is_edge_delimit_ok(efa->e4))
2246 #define face_tag(efa)\
2247 if(efa->v4) efa->tmp.l= efa->e1->tmp.l= efa->e2->tmp.l= efa->e3->tmp.l= efa->e4->tmp.l= 1;\
2248 else efa->tmp.l= efa->e1->tmp.l= efa->e2->tmp.l= efa->e3->tmp.l= 1;
2250 /* all - 1) use all faces for extending the selection 2) only use the mouse face
2251 * sel - 1) select 0) deselect
2253 static void selectconnected_delimit_mesh__internal(short all, short sel)
2255 EditMesh *em = G.editMesh;
2257 short done=1, change=0;
2260 if(em->faces.first==0) return;
2262 /* flag all edges as off*/
2263 for(eed= em->edges.first; eed; eed= eed->next)
2267 for(efa= em->faces.first; efa; efa= efa->next) {
2268 if (efa->f & SELECT) {
2275 EditFace *efa_mouse = findnearestface(&dist);
2278 error("Nothing indicated ");
2282 for(efa= em->faces.first; efa; efa= efa->next) {
2285 efa_mouse->tmp.l = 1;
2286 face_tag(efa_mouse);
2291 /* simple algo - select all faces that have a selected edge
2292 * this intern selects the edge, repeat until nothing is left to do */
2293 for(efa= em->faces.first; efa; efa= efa->next) {
2294 if ((efa->tmp.l == 0) && (!efa->h)) {
2295 if (is_face_tag(efa)) {
2303 for(efa= em->faces.first; efa; efa= efa->next) {
2306 if (!(efa->f & SELECT)) {
2307 EM_select_face(efa, 1);
2311 if (efa->f & SELECT) {
2312 EM_select_face(efa, 0);
2322 if (!sel) /* make sure de-selecting faces didnt de-select the verts/edges connected to selected faces, this is common with boundries */
2323 for(efa= em->faces.first; efa; efa= efa->next)
2324 if (efa->f & SELECT)
2325 EM_select_face(efa, 1);
2329 allqueue(REDRAWVIEW3D, 0);
2330 if (EM_texFaceCheck())
2331 allqueue(REDRAWIMAGE, 0);
2333 BIF_undo_push("Select Linked Delimeted");
2337 #undef is_edge_delimit_ok
2341 void selectconnected_delimit_mesh(void)
2343 selectconnected_delimit_mesh__internal(0, ((G.qual & LR_SHIFTKEY)==0));
2345 void selectconnected_delimit_mesh_all(void)
2347 selectconnected_delimit_mesh__internal(1, 1);
2351 /* swap is 0 or 1, if 1 it hides not selected */
2352 void hide_mesh(int swap)
2354 EditMesh *em = G.editMesh;
2360 if(G.obedit==0) return;
2362 /* hide happens on least dominant select mode, and flushes up, not down! (helps preventing errors in subsurf) */
2363 /* - vertex hidden, always means edge is hidden too
2364 - edge hidden, always means face is hidden too
2365 - face hidden, only set face hide
2366 - then only flush back down what's absolute hidden
2368 if(G.scene->selectmode & SCE_SELECT_VERTEX) {
2369 for(eve= em->verts.first; eve; eve= eve->next) {
2370 if((eve->f & SELECT)!=swap) {
2376 for(eed= em->edges.first; eed; eed= eed->next) {
2377 if(eed->v1->h || eed->v2->h) {
2383 for(efa= em->faces.first; efa; efa= efa->next) {
2384 if(efa->e1->h & 1 || efa->e2->h & 1 || efa->e3->h & 1 || (efa->e4 && efa->e4->h & 1)) {
2390 else if(G.scene->selectmode & SCE_SELECT_EDGE) {
2392 for(eed= em->edges.first; eed; eed= eed->next) {
2393 if((eed->f & SELECT)!=swap) {
2395 EM_select_edge(eed, 0);
2399 for(efa= em->faces.first; efa; efa= efa->next) {
2400 if(efa->e1->h & 1 || efa->e2->h & 1 || efa->e3->h & 1 || (efa->e4 && efa->e4->h & 1)) {
2408 for(efa= em->faces.first; efa; efa= efa->next) {
2409 if((efa->f & SELECT)!=swap) {
2411 EM_select_face(efa, 0);
2416 /* flush down, only whats 100% hidden */
2417 for(eve= em->verts.first; eve; eve= eve->next) eve->f1= 0;
2418 for(eed= em->edges.first; eed; eed= eed->next) eed->f1= 0;
2420 if(G.scene->selectmode & SCE_SELECT_FACE) {
2421 for(efa= em->faces.first; efa; efa= efa->next) {
2422 if(efa->h) a= 1; else a= 2;
2426 if(efa->e4) efa->e4->f1 |= a;
2430 if(G.scene->selectmode >= SCE_SELECT_EDGE) {
2431 for(eed= em->edges.first; eed; eed= eed->next) {
2432 if(eed->f1==1) eed->h |= 1;
2433 if(eed->h & 1) a= 1; else a= 2;
2439 if(G.scene->selectmode >= SCE_SELECT_VERTEX) {
2440 for(eve= em->verts.first; eve; eve= eve->next) {
2441 if(eve->f1==1) eve->h= 1;
2445 G.totedgesel= G.totfacesel= G.totvertsel= 0;
2446 allqueue(REDRAWVIEW3D, 0);
2447 if(EM_texFaceCheck())
2448 allqueue(REDRAWIMAGE, 0);
2449 DAG_object_flush_update(G.scene, G.obedit, OB_RECALC_DATA);
2450 BIF_undo_push("Hide");
2454 void reveal_mesh(void)
2456 EditMesh *em = G.editMesh;
2461 if(G.obedit==0) return;
2463 for(eve= em->verts.first; eve; eve= eve->next) {
2469 for(eed= em->edges.first; eed; eed= eed->next) {
2472 if(G.scene->selectmode & SCE_SELECT_VERTEX);
2473 else EM_select_edge(eed, 1);
2476 for(efa= em->faces.first; efa; efa= efa->next) {
2479 if(G.scene->selectmode & (SCE_SELECT_EDGE|SCE_SELECT_VERTEX));
2480 else EM_select_face(efa, 1);
2484 EM_fgon_flags(); /* redo flags and indices for fgons */
2485 EM_selectmode_flush();
2488 allqueue(REDRAWVIEW3D, 0);
2489 if (EM_texFaceCheck())
2490 allqueue(REDRAWIMAGE, 0);
2491 DAG_object_flush_update(G.scene, G.obedit, OB_RECALC_DATA);
2492 BIF_undo_push("Reveal");
2495 void hide_tface_uv(int swap)
2497 EditMesh *em = G.editMesh;
2501 if( is_uv_tface_editing_allowed()==0 ) return;
2503 /* call the mesh function if we are in mesh sync sel */
2504 if (G.sima->flag & SI_SYNC_UVSEL) {
2510 for (efa= em->faces.first; efa; efa= efa->next) {
2511 if(efa->f & SELECT) {
2512 tface= CustomData_em_get(&em->fdata, efa->data, CD_MTFACE);
2513 if((tface->flag & (TF_SEL1|TF_SEL2|TF_SEL3))==0) {
2515 EM_select_face(efa, 0);
2516 else if(!(tface->flag & TF_SEL4))
2517 EM_select_face(efa, 0);
2522 for (efa= em->faces.first; efa; efa= efa->next) {
2523 if(efa->f & SELECT) {
2524 tface= CustomData_em_get(&em->fdata, efa->data, CD_MTFACE);
2525 if(tface->flag & (TF_SEL1|TF_SEL2|TF_SEL3))
2526 EM_select_face(efa, 0);
2527 else if(efa->v4 && tface->flag & TF_SEL4)
2528 EM_select_face(efa, 0);
2533 /*deselects too many but ok for now*/
2534 EM_deselect_flush();
2535 EM_validate_selections();
2537 BIF_undo_push("Hide UV");
2539 object_tface_flags_changed(OBACT, 0);
2542 void reveal_tface_uv(void)
2544 EditMesh *em = G.editMesh;
2548 if( is_uv_tface_editing_allowed()==0 ) return;
2550 /* call the mesh function if we are in mesh sync sel */
2551 if (G.sima->flag & SI_SYNC_UVSEL) {
2556 for (efa= em->faces.first; efa; efa= efa->next) {
2558 if (!(efa->f & SELECT)) {
2559 EM_select_face(efa, 1);
2560 tface= CustomData_em_get(&em->fdata, efa->data, CD_MTFACE);
2561 tface->flag |= (TF_SEL1|TF_SEL2|TF_SEL3|TF_SEL4);
2566 EM_selectmode_flush();
2568 BIF_undo_push("Reveal UV");
2570 object_tface_flags_changed(OBACT, 0);
2573 void select_faces_by_numverts(int numverts)
2575 EditMesh *em = G.editMesh;
2578 /* Selects trias/qiads or isolated verts, and edges that do not have 2 neighboring
2582 /* for loose vertices/edges, we first select all, loop below will deselect */
2584 EM_set_flag_all(SELECT);
2585 else if(G.scene->selectmode!=SCE_SELECT_FACE) {
2586 error("Only works in face selection mode");
2590 for(efa= em->faces.first; efa; efa= efa->next) {
2592 EM_select_face(efa, (numverts==4) );
2595 EM_select_face(efa, (numverts==3) );
2600 addqueue(curarea->win, REDRAW, 0);
2601 if (EM_texFaceCheck())
2602 allqueue(REDRAWIMAGE, 0);
2605 BIF_undo_push("Select Triangles");
2606 else if (numverts==4)
2607 BIF_undo_push("Select Quads");
2609 BIF_undo_push("Select non-Triangles/Quads");
2612 void select_sharp_edges(void)
2614 /* Find edges that have exactly two neighboring faces,
2615 * check the angle between those faces, and if angle is
2616 * small enough, select the edge
2618 EditMesh *em = G.editMesh;
2623 long edgecount = 0, i;
2624 static short sharpness = 135;
2627 if(G.scene->selectmode==SCE_SELECT_FACE) {
2628 error("Doesn't work in face selection mode");
2632 if(button(&sharpness,0, 180,"Max Angle:")==0) return;
2633 /* if faces are at angle 'sharpness', then the face normals
2634 * are at angle 180.0 - 'sharpness' (convert to radians too)
2636 fsharpness = ((180.0 - sharpness) * M_PI) / 180.0;
2639 /* count edges, use tmp.l */
2640 eed= em->edges.first;
2648 /* for each edge, we want a pointer to two adjacent faces */
2649 efa1 = MEM_callocN(edgecount*sizeof(EditFace *),
2650 "pairs of edit face pointers");
2651 efa2 = MEM_callocN(edgecount*sizeof(EditFace *),
2652 "pairs of edit face pointers");
2654 #define face_table_edge(eed) { \
2659 /* invalidate, edge has more than two neighbors */ \
2672 /* find the adjacent faces of each edge, we want only two */
2673 efa= em->faces.first;
2675 face_table_edge(efa->e1);
2676 face_table_edge(efa->e2);
2677 face_table_edge(efa->e3);
2679 face_table_edge(efa->e4);
2684 #undef face_table_edge
2686 eed = em->edges.first;
2690 /* edge has two or less neighboring faces */
2691 if ( (efa1[i]) && (efa2[i]) ) {
2692 /* edge has exactly two neighboring faces, check angle */
2694 angle = saacos(efa1[i]->n[0]*efa2[i]->n[0] +
2695 efa1[i]->n[1]*efa2[i]->n[1] +
2696 efa1[i]->n[2]*efa2[i]->n[2]);
2697 if (fabs(angle) >= fsharpness)
2698 EM_select_edge(eed, 1);
2709 addqueue(curarea->win, REDRAW, 0);
2710 if (EM_texFaceCheck())
2711 allqueue(REDRAWIMAGE, 0);
2713 BIF_undo_push("Select Sharp Edges");
2716 void select_linked_flat_faces(void)
2718 /* Find faces that are linked to selected faces that are
2719 * relatively flat (angle between faces is higher than
2722 EditMesh *em = G.editMesh;
2727 long edgecount = 0, i, faceselcount=0, faceselcountold=0;
2728 static short sharpness = 135;
2731 if(G.scene->selectmode!=SCE_SELECT_FACE) {
2732 error("Only works in face selection mode");
2736 if(button(&sharpness,0, 180,"Min Angle:")==0) return;
2737 /* if faces are at angle 'sharpness', then the face normals
2738 * are at angle 180.0 - 'sharpness' (convert to radians too)
2740 fsharpness = ((180.0 - sharpness) * M_PI) / 180.0;
2743 /* count edges, use tmp.l */
2744 eed= em->edges.first;
2752 /* for each edge, we want a pointer to two adjacent faces */
2753 efa1 = MEM_callocN(edgecount*sizeof(EditFace *),
2754 "pairs of edit face pointers");
2755 efa2 = MEM_callocN(edgecount*sizeof(EditFace *),
2756 "pairs of edit face pointers");
2758 #define face_table_edge(eed) { \
2763 /* invalidate, edge has more than two neighbors */ \
2776 /* find the adjacent faces of each edge, we want only two */
2777 efa= em->faces.first;
2779 face_table_edge(efa->e1);
2780 face_table_edge(efa->e2);
2781 face_table_edge(efa->e3);
2783 face_table_edge(efa->e4);
2786 /* while were at it, count the selected faces */
2787 if (efa->f & SELECT) ++faceselcount;
2792 #undef face_table_edge
2794 eed= em->edges.first;
2798 /* edge has two or less neighboring faces */
2799 if ( (efa1[i]) && (efa2[i]) ) {
2800 /* edge has exactly two neighboring faces, check angle */
2802 angle = saacos(efa1[i]->n[0]*efa2[i]->n[0] +
2803 efa1[i]->n[1]*efa2[i]->n[1] +
2804 efa1[i]->n[2]*efa2[i]->n[2]);
2805 /* invalidate: edge too sharp */
2806 if (fabs(angle) >= fsharpness)
2810 /* invalidate: less than two neighbors */
2818 #define select_flat_neighbor(eed) { \
2821 if (! (efa1[i]->f & SELECT) ) { \
2822 EM_select_face(efa1[i], 1); \
2825 if (! (efa2[i]->f & SELECT) ) { \
2826 EM_select_face(efa2[i], 1); \
2832 while (faceselcount != faceselcountold) {
2833 faceselcountold = faceselcount;
2835 efa= em->faces.first;
2837 if (efa->f & SELECT) {
2838 select_flat_neighbor(efa->e1);
2839 select_flat_neighbor(efa->e2);
2840 select_flat_neighbor(efa->e3);
2842 select_flat_neighbor(efa->e4);
2849 #undef select_flat_neighbor
2855 addqueue(curarea->win, REDRAW, 0);
2856 if (EM_texFaceCheck())
2857 allqueue(REDRAWIMAGE, 0);
2858 BIF_undo_push("Select Linked Flat Faces");
2861 void select_non_manifold(void)
2863 EditMesh *em = G.editMesh;
2868 /* Selects isolated verts, and edges that do not have 2 neighboring
2872 if(G.scene->selectmode==SCE_SELECT_FACE) {
2873 error("Doesn't work in face selection mode");
2877 eve= em->verts.first;
2879 /* this will count how many edges are connected
2885 eed= em->edges.first;
2887 /* this will count how many faces are connected to
2890 /* increase edge count for verts */
2896 efa= em->faces.first;
2898 /* increase face count for edges */
2907 /* select verts that are attached to an edge that does not
2908 * have 2 neighboring faces */
2909 eed= em->edges.first;
2911 if (eed->h==0 && eed->f1 != 2) {
2912 EM_select_edge(eed, 1);
2917 /* select isolated verts */
2918 eve= em->verts.first;
2921 if (!eve->h) eve->f |= SELECT;
2927 addqueue(curarea->win, REDRAW, 0);
2928 if (EM_texFaceCheck())
2929 allqueue(REDRAWIMAGE, 0);
2930 BIF_undo_push("Select Non Manifold");
2933 void selectswap_mesh(void) /* UI level */
2935 EditMesh *em = G.editMesh;
2940 if(G.scene->selectmode & SCE_SELECT_VERTEX) {
2942 for(eve= em->verts.first; eve; eve= eve->next) {
2944 if(eve->f & SELECT) eve->f &= ~SELECT;
2945 else eve->f|= SELECT;
2949 else if(G.scene->selectmode & SCE_SELECT_EDGE) {
2950 for(eed= em->edges.first; eed; eed= eed->next) {
2952 EM_select_edge(eed, !(eed->f & SELECT));
2957 for(efa= em->faces.first; efa; efa= efa->next) {
2959 EM_select_face(efa, !(efa->f & SELECT));
2964 EM_selectmode_flush();
2967 allqueue(REDRAWVIEW3D, 0);
2968 if (EM_texFaceCheck())
2969 allqueue(REDRAWIMAGE, 0);
2971 BIF_undo_push("Select Swap");
2975 void deselectall_mesh(void) /* this toggles!!!, UI level */
2978 if(G.obedit->lay & G.vd->lay) {
2980 if( EM_nvertices_selected() ) {
2981 EM_clear_flag_all(SELECT);
2982 BIF_undo_push("Deselect All");
2985 EM_set_flag_all(SELECT);
2986 BIF_undo_push("Select All");
2991 if (EM_texFaceCheck())
2992 allqueue(REDRAWIMAGE, 0);
2994 allqueue(REDRAWVIEW3D, 0);
2998 void select_more(void)