2 * ***** BEGIN GPL LICENSE BLOCK *****
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.
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.
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.
18 * Contributor(s): Joseph Eagar, Geoffrey Bantle, Campbell Barton
20 * ***** END GPL LICENSE BLOCK *****
23 /** \file blender/bmesh/intern/bmesh_marking.c
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.
34 #include "MEM_guardedalloc.h"
36 #include "DNA_scene_types.h"
39 #include "BLI_listbase.h"
43 static void recount_totsels(BMesh *bm)
47 const char iter_types[3] = {BM_VERTS_OF_MESH,
53 /* recount (tot * sel) variables */
54 bm->totvertsel = bm->totedgesel = bm->totfacesel = 0;
55 tots[0] = &bm->totvertsel;
56 tots[1] = &bm->totedgesel;
57 tots[2] = &bm->totfacesel;
59 for (i = 0; i < 3; i++) {
60 ele = BM_iter_new(&iter, bm, iter_types[i], NULL);
61 for ( ; ele; ele = BM_iter_step(&iter)) {
62 if (BM_elem_flag_test(ele, BM_ELEM_SELECT)) *tots[i] += 1;
68 * \brief Select Mode Flush
70 * Makes sure to flush selections 'upwards'
71 * (ie: all verts of an edge selects the edge and so on).
72 * This should only be called by system and not tool authors.
74 void BM_mesh_select_mode_flush(BMesh *bm)
86 if (bm->selectmode & SCE_SELECT_VERTEX) {
87 BM_ITER_MESH (e, &eiter, bm, BM_EDGES_OF_MESH) {
88 if (BM_elem_flag_test(e->v1, BM_ELEM_SELECT) &&
89 BM_elem_flag_test(e->v2, BM_ELEM_SELECT) &&
90 !BM_elem_flag_test(e, BM_ELEM_HIDDEN))
92 BM_elem_flag_enable(e, BM_ELEM_SELECT);
95 BM_elem_flag_disable(e, BM_ELEM_SELECT);
98 BM_ITER_MESH (f, &fiter, bm, BM_FACES_OF_MESH) {
100 if (!BM_elem_flag_test(f, BM_ELEM_HIDDEN)) {
101 l_iter = l_first = BM_FACE_FIRST_LOOP(f);
103 if (!BM_elem_flag_test(l_iter->v, BM_ELEM_SELECT)) {
107 } while ((l_iter = l_iter->next) != l_first);
113 BM_elem_flag_set(f, BM_ELEM_SELECT, ok);
116 else if (bm->selectmode & SCE_SELECT_EDGE) {
117 BM_ITER_MESH (f, &fiter, bm, BM_FACES_OF_MESH) {
119 if (!BM_elem_flag_test(f, BM_ELEM_HIDDEN)) {
120 l_iter = l_first = BM_FACE_FIRST_LOOP(f);
122 if (!BM_elem_flag_test(l_iter->e, BM_ELEM_SELECT)) {
126 } while ((l_iter = l_iter->next) != l_first);
132 BM_elem_flag_set(f, BM_ELEM_SELECT, ok);
136 /* Remove any deselected elements from the BMEditSelection */
137 BM_select_history_validate(bm);
143 * mode independent flushing up/down
145 void BM_mesh_deselect_flush(BMesh *bm)
157 BM_ITER_MESH (e, &eiter, bm, BM_EDGES_OF_MESH) {
158 if (!(BM_elem_flag_test(e->v1, BM_ELEM_SELECT) &&
159 BM_elem_flag_test(e->v2, BM_ELEM_SELECT) &&
160 !BM_elem_flag_test(e, BM_ELEM_HIDDEN)))
162 BM_elem_flag_disable(e, BM_ELEM_SELECT);
166 BM_ITER_MESH (f, &fiter, bm, BM_FACES_OF_MESH) {
168 if (!BM_elem_flag_test(f, BM_ELEM_HIDDEN)) {
169 l_iter = l_first = BM_FACE_FIRST_LOOP(f);
171 if (!BM_elem_flag_test(l_iter->v, BM_ELEM_SELECT)) {
175 } while ((l_iter = l_iter->next) != l_first);
182 BM_elem_flag_disable(f, BM_ELEM_SELECT);
186 /* Remove any deselected elements from the BMEditSelection */
187 BM_select_history_validate(bm);
194 * mode independent flushing up/down
196 void BM_mesh_select_flush(BMesh *bm)
208 BM_ITER_MESH (e, &eiter, bm, BM_EDGES_OF_MESH) {
209 if (BM_elem_flag_test(e->v1, BM_ELEM_SELECT) &&
210 BM_elem_flag_test(e->v2, BM_ELEM_SELECT) &&
211 !BM_elem_flag_test(e, BM_ELEM_HIDDEN))
213 BM_elem_flag_enable(e, BM_ELEM_SELECT);
217 BM_ITER_MESH (f, &fiter, bm, BM_FACES_OF_MESH) {
219 if (!BM_elem_flag_test(f, BM_ELEM_HIDDEN)) {
220 l_iter = l_first = BM_FACE_FIRST_LOOP(f);
222 if (!BM_elem_flag_test(l_iter->v, BM_ELEM_SELECT)) {
226 } while ((l_iter = l_iter->next) != l_first);
233 BM_elem_flag_enable(f, BM_ELEM_SELECT);
243 * Changes selection state of a single vertex
246 void BM_vert_select_set(BMesh *bm, BMVert *v, int select)
248 BLI_assert(v->head.htype == BM_VERT);
250 if (BM_elem_flag_test(v, BM_ELEM_HIDDEN)) {
255 if (!BM_elem_flag_test(v, BM_ELEM_SELECT)) {
257 BM_elem_flag_enable(v, BM_ELEM_SELECT);
261 if (BM_elem_flag_test(v, BM_ELEM_SELECT)) {
263 BM_elem_flag_disable(v, BM_ELEM_SELECT);
271 * Changes selection state of a single edge in a mesh.
273 void BM_edge_select_set(BMesh *bm, BMEdge *e, int select)
275 BLI_assert(e->head.htype == BM_EDGE);
277 if (BM_elem_flag_test(e, BM_ELEM_HIDDEN)) {
282 if (!BM_elem_flag_test(e, BM_ELEM_SELECT)) bm->totedgesel += 1;
284 BM_elem_flag_enable(e, BM_ELEM_SELECT);
285 BM_vert_select_set(bm, e->v1, TRUE);
286 BM_vert_select_set(bm, e->v2, TRUE);
289 if (BM_elem_flag_test(e, BM_ELEM_SELECT)) bm->totedgesel -= 1;
290 BM_elem_flag_disable(e, BM_ELEM_SELECT);
292 if (bm->selectmode == SCE_SELECT_EDGE ||
293 bm->selectmode == SCE_SELECT_FACE ||
294 bm->selectmode == (SCE_SELECT_EDGE | SCE_SELECT_FACE))
298 BMVert *verts[2] = {e->v1, e->v2};
302 for (i = 0; i < 2; i++) {
305 for (e2 = BM_iter_new(&iter, bm, BM_EDGES_OF_VERT, verts[i]); e2; e2 = BM_iter_step(&iter)) {
310 if (BM_elem_flag_test(e2, BM_ELEM_SELECT)) {
317 BM_vert_select_set(bm, verts[i], FALSE);
322 BM_vert_select_set(bm, e->v1, FALSE);
323 BM_vert_select_set(bm, e->v2, FALSE);
332 * Changes selection state of a single
335 void BM_face_select_set(BMesh *bm, BMFace *f, int select)
340 BLI_assert(f->head.htype == BM_FACE);
342 if (BM_elem_flag_test(f, BM_ELEM_HIDDEN)) {
347 if (!BM_elem_flag_test(f, BM_ELEM_SELECT)) {
351 BM_elem_flag_enable(f, BM_ELEM_SELECT);
352 l_iter = l_first = BM_FACE_FIRST_LOOP(f);
354 BM_vert_select_set(bm, l_iter->v, TRUE);
355 BM_edge_select_set(bm, l_iter->e, TRUE);
356 } while ((l_iter = l_iter->next) != l_first);
362 if (BM_elem_flag_test(f, BM_ELEM_SELECT)) bm->totfacesel -= 1;
363 BM_elem_flag_disable(f, BM_ELEM_SELECT);
365 /* flush down to edges */
366 BM_ITER_ELEM (l, &liter, f, BM_LOOPS_OF_FACE) {
369 BM_ITER_ELEM (f2, &fiter, l->e, BM_FACES_OF_EDGE) {
370 if (BM_elem_flag_test(f2, BM_ELEM_SELECT))
375 BM_edge_select_set(bm, l->e, FALSE);
379 /* flush down to verts */
380 BM_ITER_ELEM (l, &liter, f, BM_LOOPS_OF_FACE) {
383 BM_ITER_ELEM (e, &eiter, l->v, BM_EDGES_OF_VERT) {
384 if (BM_elem_flag_test(e, BM_ELEM_SELECT))
389 BM_vert_select_set(bm, l->v, FALSE);
398 * Sets the selection mode for the bmesh,
399 * updating the selection state.
401 void BM_mesh_select_mode_set(BMesh *bm, int selectmode)
406 bm->selectmode = selectmode;
408 if (bm->selectmode & SCE_SELECT_VERTEX) {
409 /* disabled because selection flushing handles these */
411 BM_ITER_MESH (ele, &iter, bm, BM_EDGES_OF_MESH) {
412 BM_elem_flag_disable(ele, BM_ELEM_SELECT);
414 BM_ITER_MESH (ele, &iter, bm, BM_FACES_OF_MESH) {
415 BM_elem_flag_disable(ele, BM_ELEM_SELECT);
418 BM_mesh_select_mode_flush(bm);
420 else if (bm->selectmode & SCE_SELECT_EDGE) {
421 /* disabled because selection flushing handles these */
423 BM_ITER_MESH (ele, &iter, bm, BM_VERTS_OF_MESH) {
424 BM_elem_flag_disable(ele, BM_ELEM_SELECT);
428 BM_ITER_MESH (ele, &iter, bm, BM_EDGES_OF_MESH) {
429 if (BM_elem_flag_test(ele, BM_ELEM_SELECT)) {
430 BM_edge_select_set(bm, (BMEdge *)ele, TRUE);
433 BM_mesh_select_mode_flush(bm);
435 else if (bm->selectmode & SCE_SELECT_FACE) {
436 /* disabled because selection flushing handles these */
438 BM_ITER_MESH (ele, &iter, bm, BM_EDGES_OF_MESH) {
439 BM_elem_flag_disable(ele, BM_ELEM_SELECT);
442 BM_ITER_MESH (ele, &iter, bm, BM_FACES_OF_MESH) {
443 if (BM_elem_flag_test(ele, BM_ELEM_SELECT)) {
444 BM_face_select_set(bm, (BMFace *)ele, TRUE);
447 BM_mesh_select_mode_flush(bm);
452 * counts number of elements with flag enabled/disabled
454 static int bm_mesh_flag_count(BMesh *bm, const char htype, const char hflag,
455 const short respecthide, const short test_for_enabled)
461 BLI_assert(ELEM(TRUE, FALSE, test_for_enabled));
463 if (htype & BM_VERT) {
464 for (ele = BM_iter_new(&iter, bm, BM_VERTS_OF_MESH, NULL); ele; ele = BM_iter_step(&iter)) {
465 if (respecthide && BM_elem_flag_test(ele, BM_ELEM_HIDDEN)) continue;
466 if (BM_elem_flag_test_bool(ele, hflag) == test_for_enabled) tot++;
469 if (htype & BM_EDGE) {
470 for (ele = BM_iter_new(&iter, bm, BM_EDGES_OF_MESH, NULL); ele; ele = BM_iter_step(&iter)) {
471 if (respecthide && BM_elem_flag_test(ele, BM_ELEM_HIDDEN)) continue;
472 if (BM_elem_flag_test_bool(ele, hflag) == test_for_enabled) tot++;
475 if (htype & BM_FACE) {
476 for (ele = BM_iter_new(&iter, bm, BM_FACES_OF_MESH, NULL); ele; ele = BM_iter_step(&iter)) {
477 if (respecthide && BM_elem_flag_test(ele, BM_ELEM_HIDDEN)) continue;
478 if (BM_elem_flag_test_bool(ele, hflag) == test_for_enabled) tot++;
485 int BM_mesh_elem_hflag_count_enabled(BMesh *bm, const char htype, const char hflag, int respecthide)
487 return bm_mesh_flag_count(bm, htype, hflag, respecthide, TRUE);
490 int BM_mesh_elem_hflag_count_disabled(BMesh *bm, const char htype, const char hflag, int respecthide)
492 return bm_mesh_flag_count(bm, htype, hflag, respecthide, FALSE);
496 * \note use BM_elem_flag_test(ele, BM_ELEM_SELECT) to test selection
497 * \note by design, this will not touch the editselection history stuff
499 void _bm_elem_select_set(BMesh *bm, BMHeader *head, int select)
501 switch (head->htype) {
503 BM_vert_select_set(bm, (BMVert *)head, select);
506 BM_edge_select_set(bm, (BMEdge *)head, select);
509 BM_face_select_set(bm, (BMFace *)head, select);
517 /* this replaces the active flag used in uv/face mode */
518 void BM_active_face_set(BMesh *bm, BMFace *efa)
523 BMFace *BM_active_face_get(BMesh *bm, int sloppy)
531 BMEditSelection *ese;
533 /* Find the latest non-hidden face from the BMEditSelection */
534 ese = bm->selected.last;
535 for ( ; ese; ese = ese->prev) {
536 if (ese->htype == BM_FACE) {
537 f = (BMFace *)ese->ele;
539 if (BM_elem_flag_test(f, BM_ELEM_HIDDEN)) {
547 /* Last attempt: try to find any selected face */
549 BM_ITER_MESH (f, &iter, bm, BM_FACES_OF_MESH) {
550 if (BM_elem_flag_test(f, BM_ELEM_SELECT)) {
555 return f; /* can still be null */
561 * Generic way to get data from an EditSelection type
562 * These functions were written to be used by the Modifier widget
563 * when in Rotate about active mode, but can be used anywhere.
565 * - #EM_editselection_center
566 * - #EM_editselection_normal
567 * - #EM_editselection_plane
569 void BM_editselection_center(float r_center[3], BMEditSelection *ese)
571 if (ese->htype == BM_VERT) {
572 BMVert *eve = (BMVert *)ese->ele;
573 copy_v3_v3(r_center, eve->co);
575 else if (ese->htype == BM_EDGE) {
576 BMEdge *eed = (BMEdge *)ese->ele;
577 add_v3_v3v3(r_center, eed->v1->co, eed->v2->co);
578 mul_v3_fl(r_center, 0.5);
580 else if (ese->htype == BM_FACE) {
581 BMFace *efa = (BMFace *)ese->ele;
582 BM_face_calc_center_bounds(efa, r_center);
586 void BM_editselection_normal(float r_normal[3], BMEditSelection *ese)
588 if (ese->htype == BM_VERT) {
589 BMVert *eve = (BMVert *)ese->ele;
590 copy_v3_v3(r_normal, eve->no);
592 else if (ese->htype == BM_EDGE) {
593 BMEdge *eed = (BMEdge *)ese->ele;
594 float plane[3]; /* need a plane to correct the normal */
595 float vec[3]; /* temp vec storage */
597 add_v3_v3v3(r_normal, eed->v1->no, eed->v2->no);
598 sub_v3_v3v3(plane, eed->v2->co, eed->v1->co);
600 /* the 2 vertex normals will be close but not at rightangles to the edge
601 * for rotate about edge we want them to be at right angles, so we need to
602 * do some extra colculation to correct the vert normals,
603 * we need the plane for this */
604 cross_v3_v3v3(vec, r_normal, plane);
605 cross_v3_v3v3(r_normal, plane, vec);
606 normalize_v3(r_normal);
609 else if (ese->htype == BM_FACE) {
610 BMFace *efa = (BMFace *)ese->ele;
611 copy_v3_v3(r_normal, efa->no);
615 /* ref - editmesh_lib.cL:EM_editselection_plane() */
617 /* Calculate a plane that is rightangles to the edge/vert/faces normal
618 * also make the plane run along an axis that is related to the geometry,
619 * because this is used for the manipulators Y axis. */
620 void BM_editselection_plane(BMesh *bm, float r_plane[3], BMEditSelection *ese)
622 if (ese->htype == BM_VERT) {
623 BMVert *eve = (BMVert *)ese->ele;
624 float vec[3] = {0.0f, 0.0f, 0.0f};
626 if (ese->prev) { /* use previously selected data to make a useful vertex plane */
627 BM_editselection_center(vec, ese->prev);
628 sub_v3_v3v3(r_plane, vec, eve->co);
631 /* make a fake plane thats at rightangles to the normal
632 * we cant make a crossvec from a vec thats the same as the vec
633 * unlikely but possible, so make sure if the normal is (0, 0, 1)
634 * that vec isn't the same or in the same direction even. */
635 if (eve->no[0] < 0.5f) vec[0] = 1.0f;
636 else if (eve->no[1] < 0.5f) vec[1] = 1.0f;
638 cross_v3_v3v3(r_plane, eve->no, vec);
641 else if (ese->htype == BM_EDGE) {
642 BMEdge *eed = (BMEdge *)ese->ele;
644 /* the plane is simple, it runs along the edge
645 * however selecting different edges can swap the direction of the y axis.
646 * this makes it less likely for the y axis of the manipulator
647 * (running along the edge).. to flip less often.
648 * at least its more predictable */
649 if (eed->v2->co[1] > eed->v1->co[1]) { /* check which to do first */
650 sub_v3_v3v3(r_plane, eed->v2->co, eed->v1->co);
653 sub_v3_v3v3(r_plane, eed->v1->co, eed->v2->co);
657 else if (ese->htype == BM_FACE) {
658 BMFace *efa = (BMFace *)ese->ele;
659 float vec[3] = {0.0f, 0.0f, 0.0f};
661 /* for now, use face normal */
663 /* make a fake plane thats at rightangles to the normal
664 * we cant make a crossvec from a vec thats the same as the vec
665 * unlikely but possible, so make sure if the normal is (0, 0, 1)
666 * that vec isn't the same or in the same direction even. */
668 /* crappy fallback method */
669 if (efa->no[0] < 0.5f) vec[0] = 1.0f;
670 else if (efa->no[1] < 0.5f) vec[1] = 1.0f;
672 cross_v3_v3v3(r_plane, efa->no, vec);
675 BMVert *verts[4] = {NULL};
677 BM_iter_as_array(bm, BM_VERTS_OF_FACE, efa, (void **)verts, 4);
680 float vecA[3], vecB[3];
681 sub_v3_v3v3(vecA, verts[3]->co, verts[2]->co);
682 sub_v3_v3v3(vecB, verts[0]->co, verts[1]->co);
683 add_v3_v3v3(r_plane, vecA, vecB);
685 sub_v3_v3v3(vecA, verts[0]->co, verts[3]->co);
686 sub_v3_v3v3(vecB, verts[1]->co, verts[2]->co);
687 add_v3_v3v3(vec, vecA, vecB);
688 /* use the biggest edge length */
689 if (dot_v3v3(r_plane, r_plane) < dot_v3v3(vec, vec)) {
690 copy_v3_v3(r_plane, vec);
694 /* BMESH_TODO (not urgent, use longest ngon edge for alignment) */
696 /* start with v1-2 */
697 sub_v3_v3v3(r_plane, verts[0]->co, verts[1]->co);
699 /* test the edge between v2-3, use if longer */
700 sub_v3_v3v3(vec, verts[1]->co, verts[2]->co);
701 if (dot_v3v3(r_plane, r_plane) < dot_v3v3(vec, vec))
702 copy_v3_v3(r_plane, vec);
704 /* test the edge between v1-3, use if longer */
705 sub_v3_v3v3(vec, verts[2]->co, verts[0]->co);
706 if (dot_v3v3(r_plane, r_plane) < dot_v3v3(vec, vec)) {
707 copy_v3_v3(r_plane, vec);
713 normalize_v3(r_plane);
716 int BM_select_history_check(BMesh *bm, const BMElem *ele)
718 BMEditSelection *ese;
720 for (ese = bm->selected.first; ese; ese = ese->next) {
721 if (ese->ele == ele) {
729 int BM_select_history_remove(BMesh *bm, BMElem *ele)
731 BMEditSelection *ese;
732 for (ese = bm->selected.first; ese; ese = ese->next) {
733 if (ese->ele == ele) {
734 BLI_freelinkN(&(bm->selected), ese);
742 void BM_select_history_clear(BMesh *bm)
744 BLI_freelistN(&bm->selected);
745 bm->selected.first = bm->selected.last = NULL;
748 void BM_select_history_store_notest(BMesh *bm, BMElem *ele)
750 BMEditSelection *ese = (BMEditSelection *) MEM_callocN(sizeof(BMEditSelection), "BMEdit Selection");
751 ese->htype = ((BMHeader *)ele)->htype;
753 BLI_addtail(&(bm->selected), ese);
756 void BM_select_history_store(BMesh *bm, BMElem *ele)
758 if (!BM_select_history_check(bm, ele)) {
759 BM_select_history_store_notest(bm, ele);
763 void BM_select_history_validate(BMesh *bm)
765 BMEditSelection *ese, *nextese;
767 ese = bm->selected.first;
771 if (!BM_elem_flag_test(ese->ele, BM_ELEM_SELECT)) {
772 BLI_freelinkN(&(bm->selected), ese);
778 void BM_mesh_elem_hflag_disable_test(BMesh *bm, const char htype, const char hflag,
779 int respecthide, const char hflag_test)
781 const char iter_types[3] = {BM_VERTS_OF_MESH,
785 const char flag_types[3] = {BM_VERT, BM_EDGE, BM_FACE};
791 if (hflag & BM_ELEM_SELECT) {
792 BM_select_history_clear(bm);
795 if ((htype == (BM_VERT | BM_EDGE | BM_FACE)) &&
796 (hflag == BM_ELEM_SELECT) &&
797 (respecthide == FALSE) &&
800 /* fast path for deselect all, avoid topology loops
801 * since we know all will be de-selected anyway. */
802 for (i = 0; i < 3; i++) {
803 ele = BM_iter_new(&iter, bm, iter_types[i], NULL);
804 for ( ; ele; ele = BM_iter_step(&iter)) {
805 BM_elem_flag_disable(ele, BM_ELEM_SELECT);
808 bm->totvertsel = bm->totedgesel = bm->totfacesel = 0;
811 for (i = 0; i < 3; i++) {
812 if (htype & flag_types[i]) {
813 ele = BM_iter_new(&iter, bm, iter_types[i], NULL);
814 for ( ; ele; ele = BM_iter_step(&iter)) {
816 if (respecthide && BM_elem_flag_test(ele, BM_ELEM_HIDDEN)) {
819 if (hflag_test && !BM_elem_flag_test(ele, hflag_test)) {
823 if (hflag & BM_ELEM_SELECT) {
824 BM_elem_select_set(bm, ele, FALSE);
826 BM_elem_flag_disable(ele, hflag);
833 void BM_mesh_elem_hflag_enable_test(BMesh *bm, const char htype, const char hflag,
834 int respecthide, const char hflag_test)
836 const char iter_types[3] = {BM_VERTS_OF_MESH,
840 const char flag_types[3] = {BM_VERT, BM_EDGE, BM_FACE};
842 /* use the nosel version when setting so under no
843 * condition may a hidden face become selected.
844 * Applying other flags to hidden faces is OK. */
845 const char hflag_nosel = hflag & ~BM_ELEM_SELECT;
851 if (hflag & BM_ELEM_SELECT) {
852 BM_select_history_clear(bm);
855 /* note, better not attempt a fast path for selection as done with de-select
856 * because hidden geometry and different selection modes can give different results,
857 * we could of course check for no hiddent faces and then use quicker method but its not worth it. */
859 for (i = 0; i < 3; i++) {
860 if (htype & flag_types[i]) {
861 ele = BM_iter_new(&iter, bm, iter_types[i], NULL);
862 for ( ; ele; ele = BM_iter_step(&iter)) {
864 if (respecthide && BM_elem_flag_test(ele, BM_ELEM_HIDDEN)) {
867 if (hflag_test && !BM_elem_flag_test(ele, hflag_test)) {
871 if (hflag & BM_ELEM_SELECT) {
872 BM_elem_select_set(bm, ele, TRUE);
874 BM_elem_flag_enable(ele, hflag_nosel);
880 void BM_mesh_elem_hflag_disable_all(BMesh *bm, const char htype, const char hflag,
883 /* call with 0 hflag_test */
884 BM_mesh_elem_hflag_disable_test(bm, htype, hflag, respecthide, 0);
887 void BM_mesh_elem_hflag_enable_all(BMesh *bm, const char htype, const char hflag,
890 /* call with 0 hflag_test */
891 BM_mesh_elem_hflag_enable_test(bm, htype, hflag, respecthide, 0);
894 /***************** Mesh Hiding stuff *********** */
896 static void vert_flush_hide_set(BMVert *v)
902 BM_ITER_ELEM (e, &iter, v, BM_EDGES_OF_VERT) {
903 hide = hide && BM_elem_flag_test(e, BM_ELEM_HIDDEN);
906 BM_elem_flag_set(v, BM_ELEM_HIDDEN, hide);
909 static void edge_flush_hide(BMEdge *e)
915 BM_ITER_ELEM (f, &iter, e, BM_FACES_OF_EDGE) {
916 hide = hide && BM_elem_flag_test(f, BM_ELEM_HIDDEN);
919 BM_elem_flag_set(e, BM_ELEM_HIDDEN, hide);
922 void BM_vert_hide_set(BMVert *v, int hide)
924 /* vert hiding: vert + surrounding edges and faces */
929 BM_elem_flag_set(v, BM_ELEM_HIDDEN, hide);
931 BM_ITER_ELEM (e, &iter, v, BM_EDGES_OF_VERT) {
932 BM_elem_flag_set(e, BM_ELEM_HIDDEN, hide);
934 BM_ITER_ELEM (f, &fiter, e, BM_FACES_OF_EDGE) {
935 BM_elem_flag_set(f, BM_ELEM_HIDDEN, hide);
940 void BM_edge_hide_set(BMEdge *e, int hide)
946 /* edge hiding: faces around the edge */
947 BM_ITER_ELEM (f, &iter, e, BM_FACES_OF_EDGE) {
948 BM_elem_flag_set(f, BM_ELEM_HIDDEN, hide);
951 BM_elem_flag_set(e, BM_ELEM_HIDDEN, hide);
953 /* hide vertices if necessary */
954 vert_flush_hide_set(e->v1);
955 vert_flush_hide_set(e->v2);
958 void BM_face_hide_set(BMFace *f, int hide)
963 BM_elem_flag_set(f, BM_ELEM_HIDDEN, hide);
965 BM_ITER_ELEM (l, &iter, f, BM_LOOPS_OF_FACE) {
966 edge_flush_hide(l->e);
969 BM_ITER_ELEM (l, &iter, f, BM_LOOPS_OF_FACE) {
970 vert_flush_hide_set(l->v);
974 void _bm_elem_hide_set(BMesh *bm, BMHeader *head, int hide)
976 /* Follow convention of always deselecting before
977 * hiding an element */
978 switch (head->htype) {
980 if (hide) BM_vert_select_set(bm, (BMVert *)head, FALSE);
981 BM_vert_hide_set((BMVert *)head, hide);
984 if (hide) BM_edge_select_set(bm, (BMEdge *)head, FALSE);
985 BM_edge_hide_set((BMEdge *)head, hide);
988 if (hide) BM_face_select_set(bm, (BMFace *)head, FALSE);
989 BM_face_hide_set((BMFace *)head, hide);