142d2f6604b10d691eaa38871c714a7f15c7c07f
[blender.git] / source / blender / bmesh / intern / bmesh_marking.c
1 /*
2  * ***** BEGIN GPL LICENSE BLOCK *****
3  *
4  * This program is free software; you can redistribute it and/or
5  * modify it under the terms of the GNU General Public License
6  * as published by the Free Software Foundation; either version 2
7  * of the License, or (at your option) any later version.
8  *
9  * This program is distributed in the hope that it will be useful,
10  * but WITHOUT ANY WARRANTY; without even the implied warranty of
11  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
12  * GNU General Public License for more details.
13  *
14  * You should have received a copy of the GNU General Public License
15  * along with this program; if not, write to the Free Software Foundation,
16  * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
17  *
18  * Contributor(s): Joseph Eagar, Geoffrey Bantle, Campbell Barton
19  *
20  * ***** END GPL LICENSE BLOCK *****
21  */
22
23 /** \file blender/bmesh/intern/bmesh_marking.c
24  *  \ingroup bmesh
25  *
26  * Selection routines for bmesh structures.
27  * This is actually all old code ripped from
28  * editmesh_lib.c and slightly modified to work
29  * for bmesh's. This also means that it has some
30  * of the same problems.... something that
31  * that should be addressed eventually.
32  */
33
34 #include "MEM_guardedalloc.h"
35
36 #include "BKE_utildefines.h"
37
38 #include "BLI_math.h"
39 #include "BLI_blenlib.h"
40 #include "BLI_array.h"
41
42 #include "bmesh.h"
43 #include "bmesh_private.h"
44
45 #include <string.h>
46
47 /*
48  * BMESH SELECTMODE FLUSH
49  *
50  * Makes sure to flush selections 
51  * 'upwards' (ie: all verts of an edge
52  * selects the edge and so on). This 
53  * should only be called by system and not
54  * tool authors.
55  *
56 */
57
58 static void recount_totsels(BMesh *bm)
59 {
60         BMIter iter;
61         BMHeader *ele;
62         int types[3] = {BM_VERTS_OF_MESH, BM_EDGES_OF_MESH, BM_FACES_OF_MESH};
63         int *tots[3];
64         int i;
65
66         /*recount tot*sel variables*/
67         bm->totvertsel = bm->totedgesel = bm->totfacesel = 0;
68         tots[0] = &bm->totvertsel;
69         tots[1] = &bm->totedgesel;
70         tots[2] = &bm->totfacesel;
71
72         for (i=0; i<3; i++) {
73                 ele = BMIter_New(&iter, bm, types[i], NULL);
74                 for ( ; ele; ele=BMIter_Step(&iter)) {
75                         if (BM_TestHFlag(ele, BM_SELECT)) *tots[i] += 1;
76                 }
77         }
78 }
79
80 void BM_SelectMode_Flush(BMesh *bm)
81 {
82         BMEdge *e;
83         BMLoop *l;
84         BMFace *f;
85
86         BMIter edges;
87         BMIter faces;
88
89         int totsel;
90
91         if(bm->selectmode & SCE_SELECT_VERTEX) {
92                 for(e = BMIter_New(&edges, bm, BM_EDGES_OF_MESH, bm ); e; e= BMIter_Step(&edges)) {
93                         if(BM_TestHFlag(e->v1, BM_SELECT) && BM_TestHFlag(e->v2, BM_SELECT) && !BM_TestHFlag(e, BM_HIDDEN)) {
94                                 BM_SetHFlag(e, BM_SELECT);
95                         }
96                         else {
97                                 BM_ClearHFlag(e, BM_SELECT);
98                         }
99                 }
100                 for(f = BMIter_New(&faces, bm, BM_FACES_OF_MESH, bm ); f; f= BMIter_Step(&faces)) {
101                         totsel = 0;
102                         l=(BMLoop*) bm_firstfaceloop(f);
103                         do{
104                                 if(BM_TestHFlag(l->v, BM_SELECT)) 
105                                         totsel++;
106                                 l = l->next;
107                         } while(l != bm_firstfaceloop(f));
108                         
109                         if(totsel == f->len && !BM_TestHFlag(f, BM_HIDDEN)) {
110                                 BM_SetHFlag(f, BM_SELECT);
111                         }
112                         else {
113                                 BM_ClearHFlag(f, BM_SELECT);
114                         }
115                 }
116         }
117         else if(bm->selectmode & SCE_SELECT_EDGE) {
118                 for(f = BMIter_New(&faces, bm, BM_FACES_OF_MESH, bm ); f; f= BMIter_Step(&faces)) {
119                         totsel = 0;
120                         l = bm_firstfaceloop(f);
121                         do{
122                                 if(BM_TestHFlag(&(l->e->head), BM_SELECT)) 
123                                         totsel++;
124                                 l = l->next;
125                         }while(l!=bm_firstfaceloop(f));
126                         
127                         if(totsel == f->len && !BM_TestHFlag(f, BM_HIDDEN)) {
128                                 BM_SetHFlag(f, BM_SELECT);
129                         }
130                         else {
131                                 BM_ClearHFlag(f, BM_SELECT);
132                         }
133                 }
134         }
135
136         /*Remove any deselected elements from the BMEditSelection*/
137         BM_validate_selections(bm);
138
139         recount_totsels(bm);
140 }
141
142 /*
143  * BMESH SELECT VERT
144  *
145  * Changes selection state of a single vertex 
146  * in a mesh
147  *
148 */
149
150 void BM_Select_Vert(BMesh *bm, BMVert *v, int select)
151 {
152         /* BMIter iter; */
153         /* BMEdge *e; */
154
155         if (BM_TestHFlag(v, BM_HIDDEN)) {
156                 return;
157         }
158
159         if(select) {
160                 if (!BM_TestHFlag(v, BM_SELECT)) {
161                         bm->totvertsel += 1;
162                         BM_SetHFlag(v, BM_SELECT);
163                 }
164         } else {
165                 if (BM_TestHFlag(v, BM_SELECT)) {
166                         bm->totvertsel -= 1;
167                         BM_ClearHFlag(v, BM_SELECT);
168                 }
169         }
170 }
171
172 /*
173  * BMESH SELECT EDGE
174  *
175  * Changes selection state of a single edge
176  * in a mesh.
177  *
178 */
179
180 void BM_Select_Edge(BMesh *bm, BMEdge *e, int select)
181 {
182         if (BM_TestHFlag(e, BM_HIDDEN)) {
183                 return;
184         }
185
186         if(select){
187                 if (!BM_TestHFlag(e, BM_SELECT)) bm->totedgesel += 1;
188
189                 BM_SetHFlag(&(e->head), BM_SELECT);
190                 BM_Select(bm, e->v1, 1);
191                 BM_Select(bm, e->v2, 1);
192         }else{ 
193                 if (BM_TestHFlag(e, BM_SELECT)) bm->totedgesel -= 1;
194                 BM_ClearHFlag(&(e->head), BM_SELECT);
195
196                 if(
197                         bm->selectmode == SCE_SELECT_EDGE ||
198                         bm->selectmode == SCE_SELECT_FACE ||
199                         bm->selectmode == (SCE_SELECT_EDGE | SCE_SELECT_FACE)){
200
201                         BMIter iter;
202                         BMVert *verts[2] = {e->v1, e->v2};
203                         BMEdge *e2;
204                         int i;
205
206                         for(i = 0; i < 2; i++){
207                                 int deselect = 1;
208
209                                 for(e2 = BMIter_New(&iter, bm, BM_EDGES_OF_VERT, verts[i]);
210                                     e2; e2 = BMIter_Step(&iter)){
211                                         if(e2 == e){
212                                                 continue;
213                                         }
214
215                                         if (BM_TestHFlag(e2, BM_SELECT)){
216                                                 deselect = 0;
217                                                 break;
218                                         }
219                                 }
220
221                                 if(deselect) BM_Select_Vert(bm, verts[i], 0);
222                         }
223                 }else{
224                         BM_Select(bm, e->v1, 0);
225                         BM_Select(bm, e->v2, 0);
226                 }
227
228         }
229 }
230
231 /*
232  *
233  * BMESH SELECT FACE
234  *
235  * Changes selection state of a single
236  * face in a mesh.
237  *
238 */
239
240 void BM_Select_Face(BMesh *bm, BMFace *f, int select)
241 {
242         BMLoop *l;
243
244         if (BM_TestHFlag(f, BM_HIDDEN)) {
245                 return;
246         }
247
248         if(select){ 
249                 if (!BM_TestHFlag(f, BM_SELECT)) bm->totfacesel += 1;
250
251                 BM_SetHFlag(&(f->head), BM_SELECT);
252                 l=(BMLoop*) bm_firstfaceloop(f);
253                 do{
254                         BM_Select_Vert(bm, l->v, 1);
255                         BM_Select_Edge(bm, l->e, 1);
256                         l = l->next;
257                 }while(l != bm_firstfaceloop(f));
258         }
259         else{ 
260                 BMIter liter;
261                 BMLoop *l;
262
263                 if (BM_TestHFlag(f, BM_SELECT)) bm->totfacesel -= 1;
264                 BM_ClearHFlag(&(f->head), BM_SELECT);
265
266                 /*flush down to edges*/
267                 BM_ITER(l, &liter, bm, BM_LOOPS_OF_FACE, f) {
268                         BMIter fiter;
269                         BMFace *f2;
270                         BM_ITER(f2, &fiter, bm, BM_FACES_OF_EDGE, l->e) {
271                                 if (BM_TestHFlag(f2, BM_SELECT))
272                                         break;
273                         }
274
275                         if (!f2)
276                         {
277                                 BM_Select(bm, l->e, 0);
278                         }
279                 }
280
281                 /*flush down to verts*/
282                 BM_ITER(l, &liter, bm, BM_LOOPS_OF_FACE, f) {
283                         BMIter eiter;
284                         BMEdge *e;
285                         BM_ITER(e, &eiter, bm, BM_EDGES_OF_VERT, l->v) {
286                                 if (BM_TestHFlag(e, BM_SELECT))
287                                         break;
288                         }
289
290                         if (!e)
291                         {
292                                 BM_Select(bm, l->v, 0);
293                         }
294                 }
295         }
296 }
297
298 /*
299  * BMESH SELECTMODE SET
300  *
301  * Sets the selection mode for the bmesh
302  *
303 */
304
305 void BM_Selectmode_Set(BMesh *bm, int selectmode)
306 {
307         BMVert *v;
308         BMEdge *e;
309         BMFace *f;
310         
311         BMIter verts;
312         BMIter edges;
313         BMIter faces;
314         
315         bm->selectmode = selectmode;
316
317         if(bm->selectmode & SCE_SELECT_VERTEX) {
318                 for(e = BMIter_New(&edges, bm, BM_EDGES_OF_MESH, bm ); e; e= BMIter_Step(&edges))
319                         BM_ClearHFlag(e, 0);
320                 for(f = BMIter_New(&faces, bm, BM_FACES_OF_MESH, bm ); f; f= BMIter_Step(&faces))
321                         BM_ClearHFlag(f, 0);
322                 BM_SelectMode_Flush(bm);
323         }
324         else if(bm->selectmode & SCE_SELECT_EDGE) {
325                 for(v= BMIter_New(&verts, bm, BM_VERTS_OF_MESH, bm ); v; v= BMIter_Step(&verts))
326                         BM_ClearHFlag(v, 0);
327                 for(e= BMIter_New(&edges, bm, BM_EDGES_OF_MESH, bm ); e; e= BMIter_Step(&edges)){
328                         if(BM_TestHFlag(&(e->head), BM_SELECT))
329                                 BM_Select_Edge(bm, e, 1);
330                 }
331                 BM_SelectMode_Flush(bm);
332         }
333         else if(bm->selectmode & SCE_SELECT_FACE) {
334                 for(e = BMIter_New(&edges, bm, BM_EDGES_OF_MESH, bm ); e; e= BMIter_Step(&edges))
335                         BM_ClearHFlag(e, 0);
336                 for(f = BMIter_New(&faces, bm, BM_FACES_OF_MESH, bm ); f; f= BMIter_Step(&faces)){
337                         if(BM_TestHFlag(&(f->head), BM_SELECT))
338                                 BM_Select_Face(bm, f, 1);
339                 }
340                 BM_SelectMode_Flush(bm);
341         }
342 }
343
344
345 int BM_CountFlag(struct BMesh *bm, const char htype, const char hflag, int respecthide)
346 {
347         BMHeader *head;
348         BMIter iter;
349         int tot = 0;
350
351         if (htype & BM_VERT) {
352                 for (head = BMIter_New(&iter, bm, BM_VERTS_OF_MESH, NULL); head; head=BMIter_Step(&iter)) {
353                         if (respecthide && BM_TestHFlag(head, BM_HIDDEN)) continue;
354                         if (BM_TestHFlag(head, hflag)) tot++;
355                 }
356         }
357         if (htype & BM_EDGE) {
358                 for (head = BMIter_New(&iter, bm, BM_EDGES_OF_MESH, NULL); head; head=BMIter_Step(&iter)) {
359                         if (respecthide && BM_TestHFlag(head, BM_HIDDEN)) continue;
360                         if (BM_TestHFlag(head, hflag)) tot++;
361                 }
362         }
363         if (htype & BM_FACE) {
364                 for (head = BMIter_New(&iter, bm, BM_FACES_OF_MESH, NULL); head; head=BMIter_Step(&iter)) {
365                         if (respecthide && BM_TestHFlag(head, BM_HIDDEN)) continue;
366                         if (BM_TestHFlag(head, hflag)) tot++;
367                 }
368         }
369
370         return tot;
371 }
372
373 /*note: by design, this will not touch the editselection history stuff*/
374 void BM_Select(struct BMesh *bm, void *element, int select)
375 {
376         BMHeader *head = element;
377
378         if     (head->htype == BM_VERT) BM_Select_Vert(bm, (BMVert*)element, select);
379         else if(head->htype == BM_EDGE) BM_Select_Edge(bm, (BMEdge*)element, select);
380         else if(head->htype == BM_FACE) BM_Select_Face(bm, (BMFace*)element, select);
381 }
382
383 int BM_Selected(BMesh *UNUSED(bm), const void *element)
384 {
385         const BMHeader *head = element;
386         int selected = BM_TestHFlag(head, BM_SELECT);
387         BLI_assert(!selected || !BM_TestHFlag(head, BM_HIDDEN));
388         return selected;
389 }
390
391 /* this replaces the active flag used in uv/face mode */
392 void BM_set_actFace(BMesh *bm, BMFace *efa)
393 {
394         bm->act_face = efa;
395 }
396
397 BMFace *BM_get_actFace(BMesh *bm, int sloppy)
398 {
399         if (bm->act_face) {
400                 return bm->act_face;
401         } else if (sloppy) {
402                 BMIter iter;
403                 BMFace *f= NULL;
404                 BMEditSelection *ese;
405                 
406                 /* Find the latest non-hidden face from the BMEditSelection */
407                 ese = bm->selected.last;
408                 for (; ese; ese=ese->prev){
409                         if(ese->htype == BM_FACE) {
410                                 f= (BMFace *)ese->data;
411                                 
412                                 if (BM_TestHFlag(f, BM_HIDDEN)) {
413                                         f= NULL;
414                                 }
415                                 else {
416                                         break;
417                                 }
418                         }
419                 }
420                 /* Last attempt: try to find any selected face */
421                 if (f==NULL) {
422                         BM_ITER(f, &iter, bm, BM_FACES_OF_MESH, NULL) {
423                                 if (BM_TestHFlag(f, BM_SELECT)) {
424                                         break;
425                                 }
426                         }
427                 }
428                 return f; /* can still be null */
429         }
430         return NULL;
431 }
432
433 /* generic way to get data from an EditSelection type 
434 These functions were written to be used by the Modifier widget when in Rotate about active mode,
435 but can be used anywhere.
436 EM_editselection_center
437 EM_editselection_normal
438 EM_editselection_plane
439 */
440 void BM_editselection_center(BMesh *bm, float *center, BMEditSelection *ese)
441 {
442         if (ese->htype == BM_VERT) {
443                 BMVert *eve= ese->data;
444                 copy_v3_v3(center, eve->co);
445         }
446         else if (ese->htype == BM_EDGE) {
447                 BMEdge *eed= ese->data;
448                 add_v3_v3v3(center, eed->v1->co, eed->v2->co);
449                 mul_v3_fl(center, 0.5);
450         }
451         else if (ese->htype == BM_FACE) {
452                 BMFace *efa= ese->data;
453                 BM_Compute_Face_Center(bm, efa, center);
454         }
455 }
456
457 void BM_editselection_normal(float *normal, BMEditSelection *ese)
458 {
459         if (ese->htype == BM_VERT) {
460                 BMVert *eve= ese->data;
461                 copy_v3_v3(normal, eve->no);
462         }
463         else if (ese->htype == BM_EDGE) {
464                 BMEdge *eed= ese->data;
465                 float plane[3]; /* need a plane to correct the normal */
466                 float vec[3]; /* temp vec storage */
467                 
468                 add_v3_v3v3(normal, eed->v1->no, eed->v2->no);
469                 sub_v3_v3v3(plane, eed->v2->co, eed->v1->co);
470                 
471                 /* the 2 vertex normals will be close but not at rightangles to the edge
472                 for rotate about edge we want them to be at right angles, so we need to
473                 do some extra colculation to correct the vert normals,
474                 we need the plane for this */
475                 cross_v3_v3v3(vec, normal, plane);
476                 cross_v3_v3v3(normal, plane, vec); 
477                 normalize_v3(normal);
478                 
479         }
480         else if (ese->htype == BM_FACE) {
481                 BMFace *efa= ese->data;
482                 copy_v3_v3(normal, efa->no);
483         }
484 }
485
486 /* Calculate a plane that is rightangles to the edge/vert/faces normal
487 also make the plane run along an axis that is related to the geometry,
488 because this is used for the manipulators Y axis.*/
489 void BM_editselection_plane(BMesh *bm, float *plane, BMEditSelection *ese)
490 {
491         if (ese->htype == BM_VERT) {
492                 BMVert *eve= ese->data;
493                 float vec[3]={0,0,0};
494                 
495                 if (ese->prev) { /*use previously selected data to make a useful vertex plane */
496                         BM_editselection_center(bm, vec, ese->prev);
497                         sub_v3_v3v3(plane, vec, eve->co);
498                 } else {
499                         /* make a fake  plane thats at rightangles to the normal
500                         we cant make a crossvec from a vec thats the same as the vec
501                         unlikely but possible, so make sure if the normal is (0,0,1)
502                         that vec isnt the same or in the same direction even.*/
503                         if (eve->no[0] < 0.5f)          vec[0]= 1.0f;
504                         else if (eve->no[1] < 0.5f)     vec[1]= 1.0f;
505                         else                                            vec[2]= 1.0f;
506                         cross_v3_v3v3(plane, eve->no, vec);
507                 }
508         }
509         else if (ese->htype == BM_EDGE) {
510                 BMEdge *eed= ese->data;
511
512                 /* the plane is simple, it runs along the edge
513                 however selecting different edges can swap the direction of the y axis.
514                 this makes it less likely for the y axis of the manipulator
515                 (running along the edge).. to flip less often.
516                 at least its more pradictable */
517                 if (eed->v2->co[1] > eed->v1->co[1]) /*check which to do first */
518                         sub_v3_v3v3(plane, eed->v2->co, eed->v1->co);
519                 else
520                         sub_v3_v3v3(plane, eed->v1->co, eed->v2->co);
521                 
522         }
523         else if (ese->htype == BM_FACE) {
524                 BMFace *efa= ese->data;
525                 float vec[3] = {0.0f, 0.0f, 0.0f};
526                 
527                 /*for now, use face normal*/
528
529                 /* make a fake plane thats at rightangles to the normal
530                 we cant make a crossvec from a vec thats the same as the vec
531                 unlikely but possible, so make sure if the normal is (0,0,1)
532                 that vec isnt the same or in the same direction even.*/
533                 if (efa->no[0] < 0.5f)          vec[0]= 1.0f;
534                 else if (efa->no[1] < 0.5f)     vec[1]= 1.0f;
535                 else                                            vec[2]= 1.0f;
536                 cross_v3_v3v3(plane, efa->no, vec);
537 #if 0 //BMESH_TODO
538
539                 if (efa->v4) { /*if its a quad- set the plane along the 2 longest edges.*/
540                         float vecA[3], vecB[3];
541                         sub_v3_v3v3(vecA, efa->v4->co, efa->v3->co);
542                         sub_v3_v3v3(vecB, efa->v1->co, efa->v2->co);
543                         add_v3_v3v3(plane, vecA, vecB);
544                         
545                         sub_v3_v3v3(vecA, efa->v1->co, efa->v4->co);
546                         sub_v3_v3v3(vecB, efa->v2->co, efa->v3->co);
547                         add_v3_v3v3(vec, vecA, vecB);                                           
548                         /*use the biggest edge length*/
549                         if (plane[0]*plane[0]+plane[1]*plane[1]+plane[2]*plane[2] < vec[0]*vec[0]+vec[1]*vec[1]+vec[2]*vec[2])
550                                 copy_v3_v3(plane, vec);
551                 } else {
552                         /*start with v1-2 */
553                         sub_v3_v3v3(plane, efa->v1->co, efa->v2->co);
554                         
555                         /*test the edge between v2-3, use if longer */
556                         sub_v3_v3v3(vec, efa->v2->co, efa->v3->co);
557                         if (plane[0]*plane[0]+plane[1]*plane[1]+plane[2]*plane[2] < vec[0]*vec[0]+vec[1]*vec[1]+vec[2]*vec[2])
558                                 copy_v3_v3(plane, vec);
559                         
560                         /*test the edge between v1-3, use if longer */
561                         sub_v3_v3v3(vec, efa->v3->co, efa->v1->co);
562                         if (plane[0]*plane[0]+plane[1]*plane[1]+plane[2]*plane[2] < vec[0]*vec[0]+vec[1]*vec[1]+vec[2]*vec[2])
563                                 copy_v3_v3(plane, vec);
564                 }
565 #endif
566         }
567         normalize_v3(plane);
568 }
569
570 static int BM_check_selection(BMesh *bm, void *data)
571 {
572         BMEditSelection *ese;
573         
574         for(ese = bm->selected.first; ese; ese = ese->next){
575                 if(ese->data == data) return 1;
576         }
577         
578         return 0;
579 }
580
581 void BM_remove_selection(BMesh *bm, void *data)
582 {
583         BMEditSelection *ese;
584         for(ese=bm->selected.first; ese; ese = ese->next){
585                 if(ese->data == data){
586                         BLI_freelinkN(&(bm->selected),ese);
587                         break;
588                 }
589         }
590 }
591
592 void BM_clear_selection_history(BMesh *bm)
593 {
594         BLI_freelistN(&bm->selected);
595         bm->selected.first = bm->selected.last = NULL;
596 }
597
598 void BM_store_selection(BMesh *bm, void *data)
599 {
600         BMEditSelection *ese;
601         if(!BM_check_selection(bm, data)){
602                 ese = (BMEditSelection*) MEM_callocN( sizeof(BMEditSelection), "BMEdit Selection");
603                 ese->htype = ((BMHeader*)data)->htype;
604                 ese->data = data;
605                 BLI_addtail(&(bm->selected),ese);
606         }
607 }
608
609 void BM_validate_selections(BMesh *bm)
610 {
611         BMEditSelection *ese, *nextese;
612
613         ese = bm->selected.first;
614
615         while(ese) {
616                 nextese = ese->next;
617                 if (!BM_TestHFlag(ese->data, BM_SELECT)) {
618                         BLI_freelinkN(&(bm->selected), ese);
619                 }
620                 ese = nextese;
621         }
622 }
623
624 void BM_clear_flag_all(BMesh *bm, const char hflag)
625 {
626         int types[3] = {BM_VERTS_OF_MESH, BM_EDGES_OF_MESH, BM_FACES_OF_MESH};
627         BMIter iter;
628         BMHeader *ele;
629         int i;
630
631         if (hflag & BM_SELECT)
632                 BM_clear_selection_history(bm);
633
634         for (i=0; i<3; i++) {           
635                 ele = BMIter_New(&iter, bm, types[i], NULL);
636                 for ( ; ele; ele=BMIter_Step(&iter)) {
637                         if (hflag & BM_SELECT) BM_Select(bm, ele, 0);
638                         BM_ClearHFlag(ele, hflag);
639                 }
640         }
641 }
642
643
644 /***************** Mesh Hiding stuff *************/
645
646 #define SETHIDE(ele) hide ? BM_SetHFlag(ele, BM_HIDDEN) : BM_ClearHFlag(ele, BM_HIDDEN);
647
648 static void vert_flush_hide(BMesh *bm, BMVert *v)
649 {
650         BMIter iter;
651         BMEdge *e;
652         int hide = 1;
653
654         BM_ITER(e, &iter, bm, BM_EDGES_OF_VERT, v) {
655                 hide = hide && BM_TestHFlag(e, BM_HIDDEN);
656         }
657
658         SETHIDE(v);
659 }
660
661 static void edge_flush_hide(BMesh *bm, BMEdge *e)
662 {
663         BMIter iter;
664         BMFace *f;
665         int hide = 1;
666
667         BM_ITER(f, &iter, bm, BM_FACES_OF_EDGE, e) {
668                 hide = hide && BM_TestHFlag(f, BM_HIDDEN);
669         }
670
671         SETHIDE(e);
672 }
673
674 void BM_Hide_Vert(BMesh *bm, BMVert *v, int hide)
675 {
676         /*vert hiding: vert + surrounding edges and faces*/
677         BMIter iter, fiter;
678         BMEdge *e;
679         BMFace *f;
680
681         SETHIDE(v);
682
683         BM_ITER(e, &iter, bm, BM_EDGES_OF_VERT, v) {
684                 SETHIDE(e);
685
686                 BM_ITER(f, &fiter, bm, BM_FACES_OF_EDGE, e) {
687                         SETHIDE(f);
688                 }
689         }
690 }
691
692 void BM_Hide_Edge(BMesh *bm, BMEdge *e, int hide)
693 {
694         BMIter iter;
695         BMFace *f;
696         /* BMVert *v; */
697
698         /*edge hiding: faces around the edge*/
699         BM_ITER(f, &iter, bm, BM_FACES_OF_EDGE, e) {
700                 SETHIDE(f);
701         }
702         
703         SETHIDE(e);
704
705         /*hide vertices if necassary*/
706         vert_flush_hide(bm, e->v1);
707         vert_flush_hide(bm, e->v2);
708 }
709
710 void BM_Hide_Face(BMesh *bm, BMFace *f, int hide)
711 {
712         BMIter iter;
713         BMLoop *l;
714
715         /**/
716         SETHIDE(f);
717
718         BM_ITER(l, &iter, bm, BM_LOOPS_OF_FACE, f) {
719                 edge_flush_hide(bm, l->e);
720         }
721
722         BM_ITER(l, &iter, bm, BM_LOOPS_OF_FACE, f) {
723                 vert_flush_hide(bm, l->v);
724         }
725 }
726
727 void BM_Hide(BMesh *bm, void *element, int hide)
728 {
729         BMHeader *h = element;
730
731         /*Follow convention of always deselecting before
732           hiding an element*/
733         if (hide)
734                 BM_Select(bm, element, 0);
735
736         switch (h->htype) {
737                 case BM_VERT:
738                         BM_Hide_Vert(bm, element, hide);
739                         break;
740                 case BM_EDGE:
741                         BM_Hide_Edge(bm, element, hide);
742                         break;
743                 case BM_FACE:
744                         BM_Hide_Face(bm, element, hide);
745                         break;
746         }
747 }