2c99599f797b51fb6a1b4b4fc49ce8fefac93a2e
[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_listbase.h"
40
41 #include "bmesh.h"
42 #include "bmesh_private.h"
43
44 #include <string.h>
45
46 /*
47  * BMESH SELECTMODE FLUSH
48  *
49  * Makes sure to flush selections 
50  * 'upwards' (ie: all verts of an edge
51  * selects the edge and so on). This 
52  * should only be called by system and not
53  * tool authors.
54  *
55 */
56
57 static void recount_totsels(BMesh *bm)
58 {
59         BMIter iter;
60         BMHeader *ele;
61         const char itypes[3] = {BM_VERTS_OF_MESH, BM_EDGES_OF_MESH, BM_FACES_OF_MESH};
62         int *tots[3];
63         int i;
64
65         /*recount tot*sel variables*/
66         bm->totvertsel = bm->totedgesel = bm->totfacesel = 0;
67         tots[0] = &bm->totvertsel;
68         tots[1] = &bm->totedgesel;
69         tots[2] = &bm->totfacesel;
70
71         for (i=0; i<3; i++) {
72                 ele = BMIter_New(&iter, bm, itypes[i], NULL);
73                 for ( ; ele; ele=BMIter_Step(&iter)) {
74                         if (BM_TestHFlag(ele, BM_SELECT)) *tots[i] += 1;
75                 }
76         }
77 }
78
79 void BM_SelectMode_Flush(BMesh *bm)
80 {
81         BMEdge *e;
82         BMLoop *l;
83         BMFace *f;
84
85         BMIter edges;
86         BMIter faces;
87
88         int totsel;
89
90         if(bm->selectmode & SCE_SELECT_VERTEX) {
91                 for(e = BMIter_New(&edges, bm, BM_EDGES_OF_MESH, bm ); e; e= BMIter_Step(&edges)) {
92                         if(BM_TestHFlag(e->v1, BM_SELECT) && BM_TestHFlag(e->v2, BM_SELECT) && !BM_TestHFlag(e, BM_HIDDEN)) {
93                                 BM_SetHFlag(e, BM_SELECT);
94                         }
95                         else {
96                                 BM_ClearHFlag(e, BM_SELECT);
97                         }
98                 }
99                 for(f = BMIter_New(&faces, bm, BM_FACES_OF_MESH, bm ); f; f= BMIter_Step(&faces)) {
100                         totsel = 0;
101                         l=(BMLoop*) bm_firstfaceloop(f);
102                         do {
103                                 if(BM_TestHFlag(l->v, BM_SELECT)) 
104                                         totsel++;
105                                 l = l->next;
106                         } while(l != bm_firstfaceloop(f));
107                         
108                         if(totsel == f->len && !BM_TestHFlag(f, BM_HIDDEN)) {
109                                 BM_SetHFlag(f, BM_SELECT);
110                         }
111                         else {
112                                 BM_ClearHFlag(f, BM_SELECT);
113                         }
114                 }
115         }
116         else if(bm->selectmode & SCE_SELECT_EDGE) {
117                 for(f = BMIter_New(&faces, bm, BM_FACES_OF_MESH, bm ); f; f= BMIter_Step(&faces)) {
118                         totsel = 0;
119                         l = bm_firstfaceloop(f);
120                         do {
121                                 if(BM_TestHFlag(&(l->e->head), BM_SELECT)) 
122                                         totsel++;
123                                 l = l->next;
124                         } while(l!=bm_firstfaceloop(f));
125                         
126                         if(totsel == f->len && !BM_TestHFlag(f, BM_HIDDEN)) {
127                                 BM_SetHFlag(f, BM_SELECT);
128                         }
129                         else {
130                                 BM_ClearHFlag(f, BM_SELECT);
131                         }
132                 }
133         }
134
135         /*Remove any deselected elements from the BMEditSelection*/
136         BM_validate_selections(bm);
137
138         recount_totsels(bm);
139 }
140
141 /*
142  * BMESH SELECT VERT
143  *
144  * Changes selection state of a single vertex 
145  * in a mesh
146  *
147 */
148
149 void BM_Select_Vert(BMesh *bm, BMVert *v, int select)
150 {
151         /* BMIter iter; */
152         /* BMEdge *e; */
153
154         if (BM_TestHFlag(v, BM_HIDDEN)) {
155                 return;
156         }
157
158         if(select) {
159                 if (!BM_TestHFlag(v, BM_SELECT)) {
160                         bm->totvertsel += 1;
161                         BM_SetHFlag(v, BM_SELECT);
162                 }
163         } else {
164                 if (BM_TestHFlag(v, BM_SELECT)) {
165                         bm->totvertsel -= 1;
166                         BM_ClearHFlag(v, BM_SELECT);
167                 }
168         }
169 }
170
171 /*
172  * BMESH SELECT EDGE
173  *
174  * Changes selection state of a single edge
175  * in a mesh.
176  *
177 */
178
179 void BM_Select_Edge(BMesh *bm, BMEdge *e, int select)
180 {
181         if (BM_TestHFlag(e, BM_HIDDEN)) {
182                 return;
183         }
184
185         if(select) {
186                 if (!BM_TestHFlag(e, BM_SELECT)) bm->totedgesel += 1;
187
188                 BM_SetHFlag(&(e->head), BM_SELECT);
189                 BM_Select(bm, e->v1, TRUE);
190                 BM_Select(bm, e->v2, TRUE);
191         }
192         else {
193                 if (BM_TestHFlag(e, BM_SELECT)) bm->totedgesel -= 1;
194                 BM_ClearHFlag(&(e->head), BM_SELECT);
195
196                 if ( bm->selectmode == SCE_SELECT_EDGE ||
197                      bm->selectmode == SCE_SELECT_FACE ||
198                      bm->selectmode == (SCE_SELECT_EDGE | SCE_SELECT_FACE))
199                 {
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]); e2; e2 = BMIter_Step(&iter)) {
210                                         if(e2 == e) {
211                                                 continue;
212                                         }
213
214                                         if (BM_TestHFlag(e2, BM_SELECT)) {
215                                                 deselect = 0;
216                                                 break;
217                                         }
218                                 }
219
220                                 if(deselect) BM_Select_Vert(bm, verts[i], FALSE);
221                         }
222                 }
223                 else {
224                         BM_Select(bm, e->v1, FALSE);
225                         BM_Select(bm, e->v2, FALSE);
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, TRUE);
255                         BM_Select_Edge(bm, l->e, TRUE);
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, FALSE);
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                                 BM_Select(bm, l->v, FALSE);
292                         }
293                 }
294         }
295 }
296
297 /*
298  * BMESH SELECTMODE SET
299  *
300  * Sets the selection mode for the bmesh
301  *
302 */
303
304 void BM_Selectmode_Set(BMesh *bm, int selectmode)
305 {
306         BMVert *v;
307         BMEdge *e;
308         BMFace *f;
309         
310         BMIter verts;
311         BMIter edges;
312         BMIter faces;
313         
314         bm->selectmode = selectmode;
315
316         if(bm->selectmode & SCE_SELECT_VERTEX) {
317                 for(e = BMIter_New(&edges, bm, BM_EDGES_OF_MESH, bm ); e; e= BMIter_Step(&edges))
318                         BM_ClearHFlag(e, 0);
319                 for(f = BMIter_New(&faces, bm, BM_FACES_OF_MESH, bm ); f; f= BMIter_Step(&faces))
320                         BM_ClearHFlag(f, 0);
321                 BM_SelectMode_Flush(bm);
322         }
323         else if(bm->selectmode & SCE_SELECT_EDGE) {
324                 for(v= BMIter_New(&verts, bm, BM_VERTS_OF_MESH, bm ); v; v= BMIter_Step(&verts))
325                         BM_ClearHFlag(v, 0);
326                 for(e= BMIter_New(&edges, bm, BM_EDGES_OF_MESH, bm ); e; e= BMIter_Step(&edges)) {
327                         if(BM_TestHFlag(&(e->head), BM_SELECT)) {
328                                 BM_Select_Edge(bm, e, TRUE);
329                         }
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, TRUE);
339                         }
340                 }
341                 BM_SelectMode_Flush(bm);
342         }
343 }
344
345
346 int BM_CountFlag(struct BMesh *bm, const char htype, const char hflag, int respecthide)
347 {
348         BMHeader *head;
349         BMIter iter;
350         int tot = 0;
351
352         if (htype & BM_VERT) {
353                 for (head = BMIter_New(&iter, bm, BM_VERTS_OF_MESH, NULL); head; head=BMIter_Step(&iter)) {
354                         if (respecthide && BM_TestHFlag(head, BM_HIDDEN)) continue;
355                         if (BM_TestHFlag(head, hflag)) tot++;
356                 }
357         }
358         if (htype & BM_EDGE) {
359                 for (head = BMIter_New(&iter, bm, BM_EDGES_OF_MESH, NULL); head; head=BMIter_Step(&iter)) {
360                         if (respecthide && BM_TestHFlag(head, BM_HIDDEN)) continue;
361                         if (BM_TestHFlag(head, hflag)) tot++;
362                 }
363         }
364         if (htype & BM_FACE) {
365                 for (head = BMIter_New(&iter, bm, BM_FACES_OF_MESH, NULL); head; head=BMIter_Step(&iter)) {
366                         if (respecthide && BM_TestHFlag(head, BM_HIDDEN)) continue;
367                         if (BM_TestHFlag(head, hflag)) tot++;
368                 }
369         }
370
371         return tot;
372 }
373
374 /*note: by design, this will not touch the editselection history stuff*/
375 void BM_Select(struct BMesh *bm, void *element, int select)
376 {
377         BMHeader *head = element;
378
379         if     (head->htype == BM_VERT) BM_Select_Vert(bm, (BMVert*)element, select);
380         else if(head->htype == BM_EDGE) BM_Select_Edge(bm, (BMEdge*)element, select);
381         else if(head->htype == BM_FACE) BM_Select_Face(bm, (BMFace*)element, select);
382 }
383
384 int BM_Selected(BMesh *UNUSED(bm), const void *element)
385 {
386         const BMHeader *head = element;
387         int selected = BM_TestHFlag(head, BM_SELECT);
388         BLI_assert(!selected || !BM_TestHFlag(head, BM_HIDDEN));
389         return selected;
390 }
391
392 /* this replaces the active flag used in uv/face mode */
393 void BM_set_actFace(BMesh *bm, BMFace *efa)
394 {
395         bm->act_face = efa;
396 }
397
398 BMFace *BM_get_actFace(BMesh *bm, int sloppy)
399 {
400         if (bm->act_face) {
401                 return bm->act_face;
402         } else if (sloppy) {
403                 BMIter iter;
404                 BMFace *f= NULL;
405                 BMEditSelection *ese;
406                 
407                 /* Find the latest non-hidden face from the BMEditSelection */
408                 ese = bm->selected.last;
409                 for (; ese; ese=ese->prev) {
410                         if(ese->htype == BM_FACE) {
411                                 f= (BMFace *)ese->data;
412                                 
413                                 if (BM_TestHFlag(f, BM_HIDDEN)) {
414                                         f= NULL;
415                                 }
416                                 else {
417                                         break;
418                                 }
419                         }
420                 }
421                 /* Last attempt: try to find any selected face */
422                 if (f==NULL) {
423                         BM_ITER(f, &iter, bm, BM_FACES_OF_MESH, NULL) {
424                                 if (BM_TestHFlag(f, BM_SELECT)) {
425                                         break;
426                                 }
427                         }
428                 }
429                 return f; /* can still be null */
430         }
431         return NULL;
432 }
433
434 /* Generic way to get data from an EditSelection type
435  * These functions were written to be used by the Modifier widget
436  * when in Rotate about active mode, but can be used anywhere.
437  *
438  * - EM_editselection_center
439  * - EM_editselection_normal
440  * - EM_editselection_plane
441 */
442 void BM_editselection_center(BMesh *bm, float r_center[3], BMEditSelection *ese)
443 {
444         if (ese->htype == BM_VERT) {
445                 BMVert *eve= ese->data;
446                 copy_v3_v3(r_center, eve->co);
447         }
448         else if (ese->htype == BM_EDGE) {
449                 BMEdge *eed= ese->data;
450                 add_v3_v3v3(r_center, eed->v1->co, eed->v2->co);
451                 mul_v3_fl(r_center, 0.5);
452         }
453         else if (ese->htype == BM_FACE) {
454                 BMFace *efa= ese->data;
455                 BM_Compute_Face_CenterBounds(bm, efa, r_center);
456         }
457 }
458
459 void BM_editselection_normal(float r_normal[3], BMEditSelection *ese)
460 {
461         if (ese->htype == BM_VERT) {
462                 BMVert *eve= ese->data;
463                 copy_v3_v3(r_normal, eve->no);
464         }
465         else if (ese->htype == BM_EDGE) {
466                 BMEdge *eed= ese->data;
467                 float plane[3]; /* need a plane to correct the normal */
468                 float vec[3]; /* temp vec storage */
469                 
470                 add_v3_v3v3(r_normal, eed->v1->no, eed->v2->no);
471                 sub_v3_v3v3(plane, eed->v2->co, eed->v1->co);
472                 
473                 /* the 2 vertex normals will be close but not at rightangles to the edge
474                 for rotate about edge we want them to be at right angles, so we need to
475                 do some extra colculation to correct the vert normals,
476                 we need the plane for this */
477                 cross_v3_v3v3(vec, r_normal, plane);
478                 cross_v3_v3v3(r_normal, plane, vec);
479                 normalize_v3(r_normal);
480                 
481         }
482         else if (ese->htype == BM_FACE) {
483                 BMFace *efa= ese->data;
484                 copy_v3_v3(r_normal, efa->no);
485         }
486 }
487
488 /* ref - editmesh_lib.cL:EM_editselection_plane() */
489
490 /* Calculate a plane that is rightangles to the edge/vert/faces normal
491 also make the plane run along an axis that is related to the geometry,
492 because this is used for the manipulators Y axis.*/
493 void BM_editselection_plane(BMesh *bm, float r_plane[3], BMEditSelection *ese)
494 {
495         if (ese->htype == BM_VERT) {
496                 BMVert *eve= ese->data;
497                 float vec[3]={0,0,0};
498                 
499                 if (ese->prev) { /*use previously selected data to make a useful vertex plane */
500                         BM_editselection_center(bm, vec, ese->prev);
501                         sub_v3_v3v3(r_plane, vec, eve->co);
502                 } else {
503                         /* make a fake  plane thats at rightangles to the normal
504                         we cant make a crossvec from a vec thats the same as the vec
505                         unlikely but possible, so make sure if the normal is (0,0,1)
506                         that vec isnt the same or in the same direction even.*/
507                         if (eve->no[0] < 0.5f)          vec[0]= 1.0f;
508                         else if (eve->no[1] < 0.5f)     vec[1]= 1.0f;
509                         else                                            vec[2]= 1.0f;
510                         cross_v3_v3v3(r_plane, eve->no, vec);
511                 }
512         }
513         else if (ese->htype == BM_EDGE) {
514                 BMEdge *eed= ese->data;
515
516                 /* the plane is simple, it runs along the edge
517                 however selecting different edges can swap the direction of the y axis.
518                 this makes it less likely for the y axis of the manipulator
519                 (running along the edge).. to flip less often.
520                 at least its more pradictable */
521                 if (eed->v2->co[1] > eed->v1->co[1]) /*check which to do first */
522                         sub_v3_v3v3(r_plane, eed->v2->co, eed->v1->co);
523                 else
524                         sub_v3_v3v3(r_plane, eed->v1->co, eed->v2->co);
525                 
526         }
527         else if (ese->htype == BM_FACE) {
528                 BMFace *efa= ese->data;
529                 float vec[3] = {0.0f, 0.0f, 0.0f};
530                 
531                 /*for now, use face normal*/
532
533                 /* make a fake plane thats at rightangles to the normal
534                 we cant make a crossvec from a vec thats the same as the vec
535                 unlikely but possible, so make sure if the normal is (0,0,1)
536                 that vec isnt the same or in the same direction even.*/
537                 if (efa->len < 3) {
538                         /* crappy fallback method */
539                         if      (efa->no[0] < 0.5f)     vec[0]= 1.0f;
540                         else if (efa->no[1] < 0.5f)     vec[1]= 1.0f;
541                         else                        vec[2]= 1.0f;
542                         cross_v3_v3v3(r_plane, efa->no, vec);
543                 }
544                 else {
545                         BMVert *verts[4]= {NULL};
546
547                         BMIter_AsArray(bm, BM_VERTS_OF_FACE, efa, (void **)verts, 4);
548
549                         if (efa->len == 4) {
550                                 float vecA[3], vecB[3];
551                                 sub_v3_v3v3(vecA, verts[3]->co, verts[2]->co);
552                                 sub_v3_v3v3(vecB, verts[0]->co, verts[1]->co);
553                                 add_v3_v3v3(r_plane, vecA, vecB);
554
555                                 sub_v3_v3v3(vecA, verts[0]->co, verts[3]->co);
556                                 sub_v3_v3v3(vecB, verts[1]->co, verts[2]->co);
557                                 add_v3_v3v3(vec, vecA, vecB);
558                                 /*use the biggest edge length*/
559                                 if (dot_v3v3(r_plane, r_plane) < dot_v3v3(vec, vec)) {
560                                         copy_v3_v3(r_plane, vec);
561                                 }
562                         }
563                         else {
564                                 /* BMESH_TODO (not urgent, use longest ngon edge for alignment) */
565
566                                 /*start with v1-2 */
567                                 sub_v3_v3v3(r_plane, verts[0]->co, verts[1]->co);
568
569                                 /*test the edge between v2-3, use if longer */
570                                 sub_v3_v3v3(vec, verts[1]->co, verts[2]->co);
571                                 if (dot_v3v3(r_plane, r_plane) < dot_v3v3(vec, vec))
572                                         copy_v3_v3(r_plane, vec);
573
574                                 /*test the edge between v1-3, use if longer */
575                                 sub_v3_v3v3(vec, verts[2]->co, verts[0]->co);
576                                 if (dot_v3v3(r_plane, r_plane) < dot_v3v3(vec, vec)) {
577                                         copy_v3_v3(r_plane, vec);
578                                 }
579                         }
580
581                 }
582         }
583         normalize_v3(r_plane);
584 }
585
586 static int BM_check_selection(BMesh *bm, void *data)
587 {
588         BMEditSelection *ese;
589         
590         for(ese = bm->selected.first; ese; ese = ese->next) {
591                 if(ese->data == data) return 1;
592         }
593         
594         return 0;
595 }
596
597 void BM_remove_selection(BMesh *bm, void *data)
598 {
599         BMEditSelection *ese;
600         for(ese=bm->selected.first; ese; ese = ese->next) {
601                 if(ese->data == data) {
602                         BLI_freelinkN(&(bm->selected),ese);
603                         break;
604                 }
605         }
606 }
607
608 void BM_clear_selection_history(BMesh *bm)
609 {
610         BLI_freelistN(&bm->selected);
611         bm->selected.first = bm->selected.last = NULL;
612 }
613
614 void BM_store_selection(BMesh *bm, void *data)
615 {
616         BMEditSelection *ese;
617         if(!BM_check_selection(bm, data)) {
618                 ese = (BMEditSelection*) MEM_callocN( sizeof(BMEditSelection), "BMEdit Selection");
619                 ese->htype = ((BMHeader*)data)->htype;
620                 ese->data = data;
621                 BLI_addtail(&(bm->selected),ese);
622         }
623 }
624
625 void BM_validate_selections(BMesh *bm)
626 {
627         BMEditSelection *ese, *nextese;
628
629         ese = bm->selected.first;
630
631         while(ese) {
632                 nextese = ese->next;
633                 if (!BM_TestHFlag(ese->data, BM_SELECT)) {
634                         BLI_freelinkN(&(bm->selected), ese);
635                 }
636                 ese = nextese;
637         }
638 }
639
640 void BM_clear_flag_all(BMesh *bm, const char hflag)
641 {
642         const char itypes[3] = {BM_VERTS_OF_MESH, BM_EDGES_OF_MESH, BM_FACES_OF_MESH};
643         BMIter iter;
644         BMHeader *ele;
645         int i;
646
647         if (hflag & BM_SELECT)
648                 BM_clear_selection_history(bm);
649
650         for (i=0; i<3; i++) {           
651                 ele = BMIter_New(&iter, bm, itypes[i], NULL);
652                 for ( ; ele; ele=BMIter_Step(&iter)) {
653                         if (hflag & BM_SELECT) BM_Select(bm, ele, FALSE);
654                         BM_ClearHFlag(ele, hflag);
655                 }
656         }
657 }
658
659
660 /***************** Mesh Hiding stuff *************/
661
662 #define SETHIDE(ele) hide ? BM_SetHFlag(ele, BM_HIDDEN) : BM_ClearHFlag(ele, BM_HIDDEN);
663
664 static void vert_flush_hide(BMesh *bm, BMVert *v)
665 {
666         BMIter iter;
667         BMEdge *e;
668         int hide = 1;
669
670         BM_ITER(e, &iter, bm, BM_EDGES_OF_VERT, v) {
671                 hide = hide && BM_TestHFlag(e, BM_HIDDEN);
672         }
673
674         SETHIDE(v);
675 }
676
677 static void edge_flush_hide(BMesh *bm, BMEdge *e)
678 {
679         BMIter iter;
680         BMFace *f;
681         int hide = 1;
682
683         BM_ITER(f, &iter, bm, BM_FACES_OF_EDGE, e) {
684                 hide = hide && BM_TestHFlag(f, BM_HIDDEN);
685         }
686
687         SETHIDE(e);
688 }
689
690 void BM_Hide_Vert(BMesh *bm, BMVert *v, int hide)
691 {
692         /*vert hiding: vert + surrounding edges and faces*/
693         BMIter iter, fiter;
694         BMEdge *e;
695         BMFace *f;
696
697         SETHIDE(v);
698
699         BM_ITER(e, &iter, bm, BM_EDGES_OF_VERT, v) {
700                 SETHIDE(e);
701
702                 BM_ITER(f, &fiter, bm, BM_FACES_OF_EDGE, e) {
703                         SETHIDE(f);
704                 }
705         }
706 }
707
708 void BM_Hide_Edge(BMesh *bm, BMEdge *e, int hide)
709 {
710         BMIter iter;
711         BMFace *f;
712         /* BMVert *v; */
713
714         /*edge hiding: faces around the edge*/
715         BM_ITER(f, &iter, bm, BM_FACES_OF_EDGE, e) {
716                 SETHIDE(f);
717         }
718         
719         SETHIDE(e);
720
721         /*hide vertices if necassary*/
722         vert_flush_hide(bm, e->v1);
723         vert_flush_hide(bm, e->v2);
724 }
725
726 void BM_Hide_Face(BMesh *bm, BMFace *f, int hide)
727 {
728         BMIter iter;
729         BMLoop *l;
730
731         /**/
732         SETHIDE(f);
733
734         BM_ITER(l, &iter, bm, BM_LOOPS_OF_FACE, f) {
735                 edge_flush_hide(bm, l->e);
736         }
737
738         BM_ITER(l, &iter, bm, BM_LOOPS_OF_FACE, f) {
739                 vert_flush_hide(bm, l->v);
740         }
741 }
742
743 void BM_Hide(BMesh *bm, void *element, int hide)
744 {
745         BMHeader *h = element;
746
747         /*Follow convention of always deselecting before
748           hiding an element*/
749         if (hide)
750                 BM_Select(bm, element, FALSE);
751
752         switch (h->htype) {
753                 case BM_VERT:
754                         BM_Hide_Vert(bm, element, hide);
755                         break;
756                 case BM_EDGE:
757                         BM_Hide_Edge(bm, element, hide);
758                         break;
759                 case BM_FACE:
760                         BM_Hide_Face(bm, element, hide);
761                         break;
762         }
763 }