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 "BKE_utildefines.h"
39 #include "BLI_listbase.h"
42 #include "bmesh_private.h"
47 * BMESH SELECTMODE FLUSH
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
57 static void recount_totsels(BMesh *bm)
61 const char iter_types[3] = {BM_VERTS_OF_MESH,
67 /* recount (tot * sel) variables */
68 bm->totvertsel = bm->totedgesel = bm->totfacesel = 0;
69 tots[0] = &bm->totvertsel;
70 tots[1] = &bm->totedgesel;
71 tots[2] = &bm->totfacesel;
73 for (i = 0; i < 3; i++) {
74 ele = BMIter_New(&iter, bm, iter_types[i], NULL);
75 for ( ; ele; ele = BMIter_Step(&iter)) {
76 if (BM_TestHFlag(ele, BM_SELECT)) *tots[i] += 1;
81 void BM_SelectMode_Flush(BMesh *bm)
93 if (bm->selectmode & SCE_SELECT_VERTEX) {
94 for (e = BMIter_New(&edges, bm, BM_EDGES_OF_MESH, bm); e; e = BMIter_Step(&edges)) {
95 if (BM_TestHFlag(e->v1, BM_SELECT) && BM_TestHFlag(e->v2, BM_SELECT) && !BM_TestHFlag(e, BM_HIDDEN)) {
96 BM_SetHFlag(e, BM_SELECT);
99 BM_ClearHFlag(e, BM_SELECT);
102 for (f = BMIter_New(&faces, bm, BM_FACES_OF_MESH, bm); f; f = BMIter_Step(&faces)) {
104 l_iter = l_first = BM_FACE_FIRST_LOOP(f);
106 if (BM_TestHFlag(l_iter->v, BM_SELECT)) {
109 } while ((l_iter = l_iter->next) != l_first);
111 if (totsel == f->len && !BM_TestHFlag(f, BM_HIDDEN)) {
112 BM_SetHFlag(f, BM_SELECT);
115 BM_ClearHFlag(f, BM_SELECT);
119 else if (bm->selectmode & SCE_SELECT_EDGE) {
120 for (f = BMIter_New(&faces, bm, BM_FACES_OF_MESH, bm); f; f = BMIter_Step(&faces)) {
122 l_iter = l_first = BM_FACE_FIRST_LOOP(f);
124 if (BM_TestHFlag(&(l_iter->e->head), BM_SELECT)) {
127 } while ((l_iter = l_iter->next) != l_first);
129 if (totsel == f->len && !BM_TestHFlag(f, BM_HIDDEN)) {
130 BM_SetHFlag(f, BM_SELECT);
133 BM_ClearHFlag(f, BM_SELECT);
138 /* Remove any deselected elements from the BMEditSelection */
139 BM_validate_selections(bm);
147 * Changes selection state of a single vertex
152 void BM_Select_Vert(BMesh *bm, BMVert *v, int select)
157 if (BM_TestHFlag(v, BM_HIDDEN)) {
162 if (!BM_TestHFlag(v, BM_SELECT)) {
164 BM_SetHFlag(v, BM_SELECT);
168 if (BM_TestHFlag(v, BM_SELECT)) {
170 BM_ClearHFlag(v, BM_SELECT);
178 * Changes selection state of a single edge
183 void BM_Select_Edge(BMesh *bm, BMEdge *e, int select)
185 if (BM_TestHFlag(e, BM_HIDDEN)) {
190 if (!BM_TestHFlag(e, BM_SELECT)) bm->totedgesel += 1;
192 BM_SetHFlag(&(e->head), BM_SELECT);
193 BM_Select(bm, e->v1, TRUE);
194 BM_Select(bm, e->v2, TRUE);
197 if (BM_TestHFlag(e, BM_SELECT)) bm->totedgesel -= 1;
198 BM_ClearHFlag(&(e->head), BM_SELECT);
200 if ( bm->selectmode == SCE_SELECT_EDGE ||
201 bm->selectmode == SCE_SELECT_FACE ||
202 bm->selectmode == (SCE_SELECT_EDGE | SCE_SELECT_FACE))
206 BMVert *verts[2] = {e->v1, e->v2};
210 for (i = 0; i < 2; i++) {
213 for (e2 = BMIter_New(&iter, bm, BM_EDGES_OF_VERT, verts[i]); e2; e2 = BMIter_Step(&iter)) {
218 if (BM_TestHFlag(e2, BM_SELECT)) {
224 if (deselect) BM_Select_Vert(bm, verts[i], FALSE);
228 BM_Select(bm, e->v1, FALSE);
229 BM_Select(bm, e->v2, FALSE);
239 * Changes selection state of a single
244 void BM_Select_Face(BMesh *bm, BMFace *f, int select)
249 if (BM_TestHFlag(f, BM_HIDDEN)) {
254 if (!BM_TestHFlag(f, BM_SELECT)) bm->totfacesel += 1;
256 BM_SetHFlag(&(f->head), BM_SELECT);
257 l_iter = l_first = BM_FACE_FIRST_LOOP(f);
259 BM_Select_Vert(bm, l_iter->v, TRUE);
260 BM_Select_Edge(bm, l_iter->e, TRUE);
261 } while ((l_iter = l_iter->next) != l_first);
267 if (BM_TestHFlag(f, BM_SELECT)) bm->totfacesel -= 1;
268 BM_ClearHFlag(&(f->head), BM_SELECT);
270 /* flush down to edges */
271 BM_ITER(l, &liter, bm, BM_LOOPS_OF_FACE, f) {
274 BM_ITER(f2, &fiter, bm, BM_FACES_OF_EDGE, l->e) {
275 if (BM_TestHFlag(f2, BM_SELECT))
281 BM_Select(bm, l->e, FALSE);
285 /* flush down to verts */
286 BM_ITER(l, &liter, bm, BM_LOOPS_OF_FACE, f) {
289 BM_ITER(e, &eiter, bm, BM_EDGES_OF_VERT, l->v) {
290 if (BM_TestHFlag(e, BM_SELECT))
295 BM_Select(bm, l->v, FALSE);
302 * BMESH SELECTMODE SET
304 * Sets the selection mode for the bmesh
308 void BM_Selectmode_Set(BMesh *bm, int selectmode)
318 bm->selectmode = selectmode;
320 if (bm->selectmode & SCE_SELECT_VERTEX) {
321 for (e = BMIter_New(&edges, bm, BM_EDGES_OF_MESH, bm); e; e = BMIter_Step(&edges))
323 for (f = BMIter_New(&faces, bm, BM_FACES_OF_MESH, bm); f; f = BMIter_Step(&faces))
325 BM_SelectMode_Flush(bm);
327 else if (bm->selectmode & SCE_SELECT_EDGE) {
328 for (v = BMIter_New(&verts, bm, BM_VERTS_OF_MESH, bm); v; v = BMIter_Step(&verts))
330 for (e = BMIter_New(&edges, bm, BM_EDGES_OF_MESH, bm); e; e = BMIter_Step(&edges)) {
331 if (BM_TestHFlag(&(e->head), BM_SELECT)) {
332 BM_Select_Edge(bm, e, TRUE);
335 BM_SelectMode_Flush(bm);
337 else if (bm->selectmode & SCE_SELECT_FACE) {
338 for (e = BMIter_New(&edges, bm, BM_EDGES_OF_MESH, bm); e; e = BMIter_Step(&edges))
340 for (f = BMIter_New(&faces, bm, BM_FACES_OF_MESH, bm); f; f = BMIter_Step(&faces)) {
341 if (BM_TestHFlag(&(f->head), BM_SELECT)) {
342 BM_Select_Face(bm, f, TRUE);
345 BM_SelectMode_Flush(bm);
350 int BM_CountFlag(struct BMesh *bm, const char htype, const char hflag, int respecthide)
356 if (htype & BM_VERT) {
357 for (head = BMIter_New(&iter, bm, BM_VERTS_OF_MESH, NULL); head; head = BMIter_Step(&iter)) {
358 if (respecthide && BM_TestHFlag(head, BM_HIDDEN)) continue;
359 if (BM_TestHFlag(head, hflag)) tot++;
362 if (htype & BM_EDGE) {
363 for (head = BMIter_New(&iter, bm, BM_EDGES_OF_MESH, NULL); head; head = BMIter_Step(&iter)) {
364 if (respecthide && BM_TestHFlag(head, BM_HIDDEN)) continue;
365 if (BM_TestHFlag(head, hflag)) tot++;
368 if (htype & BM_FACE) {
369 for (head = BMIter_New(&iter, bm, BM_FACES_OF_MESH, NULL); head; head = BMIter_Step(&iter)) {
370 if (respecthide && BM_TestHFlag(head, BM_HIDDEN)) continue;
371 if (BM_TestHFlag(head, hflag)) tot++;
378 /* note: by design, this will not touch the editselection history stuff */
379 void BM_Select(struct BMesh *bm, void *element, int select)
381 BMHeader *head = element;
383 if (head->htype == BM_VERT) BM_Select_Vert(bm, (BMVert *)element, select);
384 else if (head->htype == BM_EDGE) BM_Select_Edge(bm, (BMEdge *)element, select);
385 else if (head->htype == BM_FACE) BM_Select_Face(bm, (BMFace *)element, select);
388 int BM_Selected(BMesh *UNUSED(bm), const void *element)
390 const BMHeader *head = element;
391 int selected = BM_TestHFlag(head, BM_SELECT);
392 BLI_assert(!selected || !BM_TestHFlag(head, BM_HIDDEN));
396 /* this replaces the active flag used in uv/face mode */
397 void BM_set_actFace(BMesh *bm, BMFace *efa)
402 BMFace *BM_get_actFace(BMesh *bm, int sloppy)
410 BMEditSelection *ese;
412 /* Find the latest non-hidden face from the BMEditSelection */
413 ese = bm->selected.last;
414 for ( ; ese; ese = ese->prev) {
415 if (ese->htype == BM_FACE) {
416 f = (BMFace *)ese->data;
418 if (BM_TestHFlag(f, BM_HIDDEN)) {
426 /* Last attempt: try to find any selected face */
428 BM_ITER(f, &iter, bm, BM_FACES_OF_MESH, NULL) {
429 if (BM_TestHFlag(f, BM_SELECT)) {
434 return f; /* can still be null */
439 /* Generic way to get data from an EditSelection type
440 * These functions were written to be used by the Modifier widget
441 * when in Rotate about active mode, but can be used anywhere.
443 * - EM_editselection_center
444 * - EM_editselection_normal
445 * - EM_editselection_plane
447 void BM_editselection_center(BMesh *bm, float r_center[3], BMEditSelection *ese)
449 if (ese->htype == BM_VERT) {
450 BMVert *eve = ese->data;
451 copy_v3_v3(r_center, eve->co);
453 else if (ese->htype == BM_EDGE) {
454 BMEdge *eed = ese->data;
455 add_v3_v3v3(r_center, eed->v1->co, eed->v2->co);
456 mul_v3_fl(r_center, 0.5);
458 else if (ese->htype == BM_FACE) {
459 BMFace *efa = ese->data;
460 BM_Compute_Face_CenterBounds(bm, efa, r_center);
464 void BM_editselection_normal(float r_normal[3], BMEditSelection *ese)
466 if (ese->htype == BM_VERT) {
467 BMVert *eve = ese->data;
468 copy_v3_v3(r_normal, eve->no);
470 else if (ese->htype == BM_EDGE) {
471 BMEdge *eed = ese->data;
472 float plane[3]; /* need a plane to correct the normal */
473 float vec[3]; /* temp vec storage */
475 add_v3_v3v3(r_normal, eed->v1->no, eed->v2->no);
476 sub_v3_v3v3(plane, eed->v2->co, eed->v1->co);
478 /* the 2 vertex normals will be close but not at rightangles to the edge
479 * for rotate about edge we want them to be at right angles, so we need to
480 * do some extra colculation to correct the vert normals,
481 * we need the plane for this */
482 cross_v3_v3v3(vec, r_normal, plane);
483 cross_v3_v3v3(r_normal, plane, vec);
484 normalize_v3(r_normal);
487 else if (ese->htype == BM_FACE) {
488 BMFace *efa = ese->data;
489 copy_v3_v3(r_normal, efa->no);
493 /* ref - editmesh_lib.cL:EM_editselection_plane() */
495 /* Calculate a plane that is rightangles to the edge/vert/faces normal
496 * also make the plane run along an axis that is related to the geometry,
497 * because this is used for the manipulators Y axis. */
498 void BM_editselection_plane(BMesh *bm, float r_plane[3], BMEditSelection *ese)
500 if (ese->htype == BM_VERT) {
501 BMVert *eve = ese->data;
502 float vec[3] = {0.0f, 0.0f, 0.0f};
504 if (ese->prev) { /* use previously selected data to make a useful vertex plane */
505 BM_editselection_center(bm, vec, ese->prev);
506 sub_v3_v3v3(r_plane, vec, eve->co);
509 /* make a fake plane thats at rightangles to the normal
510 * we cant make a crossvec from a vec thats the same as the vec
511 * unlikely but possible, so make sure if the normal is (0, 0, 1)
512 * that vec isnt the same or in the same direction even. */
513 if (eve->no[0] < 0.5f) vec[0] = 1.0f;
514 else if (eve->no[1] < 0.5f) vec[1] = 1.0f;
516 cross_v3_v3v3(r_plane, eve->no, vec);
519 else if (ese->htype == BM_EDGE) {
520 BMEdge *eed = ese->data;
522 /* the plane is simple, it runs along the edge
523 * however selecting different edges can swap the direction of the y axis.
524 * this makes it less likely for the y axis of the manipulator
525 * (running along the edge).. to flip less often.
526 * at least its more pradictable */
527 if (eed->v2->co[1] > eed->v1->co[1]) { /* check which to do first */
528 sub_v3_v3v3(r_plane, eed->v2->co, eed->v1->co);
531 sub_v3_v3v3(r_plane, eed->v1->co, eed->v2->co);
535 else if (ese->htype == BM_FACE) {
536 BMFace *efa = ese->data;
537 float vec[3] = {0.0f, 0.0f, 0.0f};
539 /* for now, use face normal */
541 /* make a fake plane thats at rightangles to the normal
542 * we cant make a crossvec from a vec thats the same as the vec
543 * unlikely but possible, so make sure if the normal is (0, 0, 1)
544 * that vec isnt the same or in the same direction even. */
546 /* crappy fallback method */
547 if (efa->no[0] < 0.5f) vec[0] = 1.0f;
548 else if (efa->no[1] < 0.5f) vec[1] = 1.0f;
550 cross_v3_v3v3(r_plane, efa->no, vec);
553 BMVert *verts[4] = {NULL};
555 BMIter_AsArray(bm, BM_VERTS_OF_FACE, efa, (void **)verts, 4);
558 float vecA[3], vecB[3];
559 sub_v3_v3v3(vecA, verts[3]->co, verts[2]->co);
560 sub_v3_v3v3(vecB, verts[0]->co, verts[1]->co);
561 add_v3_v3v3(r_plane, vecA, vecB);
563 sub_v3_v3v3(vecA, verts[0]->co, verts[3]->co);
564 sub_v3_v3v3(vecB, verts[1]->co, verts[2]->co);
565 add_v3_v3v3(vec, vecA, vecB);
566 /* use the biggest edge length */
567 if (dot_v3v3(r_plane, r_plane) < dot_v3v3(vec, vec)) {
568 copy_v3_v3(r_plane, vec);
572 /* BMESH_TODO (not urgent, use longest ngon edge for alignment) */
574 /* start with v1-2 */
575 sub_v3_v3v3(r_plane, verts[0]->co, verts[1]->co);
577 /* test the edge between v2-3, use if longer */
578 sub_v3_v3v3(vec, verts[1]->co, verts[2]->co);
579 if (dot_v3v3(r_plane, r_plane) < dot_v3v3(vec, vec))
580 copy_v3_v3(r_plane, vec);
582 /* test the edge between v1-3, use if longer */
583 sub_v3_v3v3(vec, verts[2]->co, verts[0]->co);
584 if (dot_v3v3(r_plane, r_plane) < dot_v3v3(vec, vec)) {
585 copy_v3_v3(r_plane, vec);
591 normalize_v3(r_plane);
594 static int BM_check_selection(BMesh *bm, void *data)
596 BMEditSelection *ese;
598 for (ese = bm->selected.first; ese; ese = ese->next) {
599 if (ese->data == data) {
607 void BM_remove_selection(BMesh *bm, void *data)
609 BMEditSelection *ese;
610 for (ese = bm->selected.first; ese; ese = ese->next) {
611 if (ese->data == data) {
612 BLI_freelinkN(&(bm->selected), ese);
618 void BM_clear_selection_history(BMesh *bm)
620 BLI_freelistN(&bm->selected);
621 bm->selected.first = bm->selected.last = NULL;
624 void BM_store_selection(BMesh *bm, void *data)
626 BMEditSelection *ese;
627 if (!BM_check_selection(bm, data)) {
628 ese = (BMEditSelection *) MEM_callocN(sizeof(BMEditSelection), "BMEdit Selection");
629 ese->htype = ((BMHeader *)data)->htype;
631 BLI_addtail(&(bm->selected), ese);
635 void BM_validate_selections(BMesh *bm)
637 BMEditSelection *ese, *nextese;
639 ese = bm->selected.first;
643 if (!BM_TestHFlag(ese->data, BM_SELECT)) {
644 BLI_freelinkN(&(bm->selected), ese);
650 void BM_clear_flag_all(BMesh *bm, const char hflag)
652 const char iter_types[3] = {BM_VERTS_OF_MESH,
659 if (hflag & BM_SELECT) {
660 BM_clear_selection_history(bm);
663 for (i = 0; i < 3; i++) {
664 ele = BMIter_New(&iter, bm, iter_types[i], NULL);
665 for ( ; ele; ele = BMIter_Step(&iter)) {
666 if (hflag & BM_SELECT) BM_Select(bm, ele, FALSE);
667 BM_ClearHFlag(ele, hflag);
673 /***************** Mesh Hiding stuff *********** */
675 #define SETHIDE(ele) hide ? BM_SetHFlag(ele, BM_HIDDEN) : BM_ClearHFlag(ele, BM_HIDDEN);
677 static void vert_flush_hide(BMesh *bm, BMVert *v)
683 BM_ITER(e, &iter, bm, BM_EDGES_OF_VERT, v) {
684 hide = hide && BM_TestHFlag(e, BM_HIDDEN);
690 static void edge_flush_hide(BMesh *bm, BMEdge *e)
696 BM_ITER(f, &iter, bm, BM_FACES_OF_EDGE, e) {
697 hide = hide && BM_TestHFlag(f, BM_HIDDEN);
703 void BM_Hide_Vert(BMesh *bm, BMVert *v, int hide)
705 /* vert hiding: vert + surrounding edges and faces */
712 BM_ITER(e, &iter, bm, BM_EDGES_OF_VERT, v) {
715 BM_ITER(f, &fiter, bm, BM_FACES_OF_EDGE, e) {
721 void BM_Hide_Edge(BMesh *bm, BMEdge *e, int hide)
727 /* edge hiding: faces around the edge */
728 BM_ITER(f, &iter, bm, BM_FACES_OF_EDGE, e) {
734 /* hide vertices if necassary */
735 vert_flush_hide(bm, e->v1);
736 vert_flush_hide(bm, e->v2);
739 void BM_Hide_Face(BMesh *bm, BMFace *f, int hide)
746 BM_ITER(l, &iter, bm, BM_LOOPS_OF_FACE, f) {
747 edge_flush_hide(bm, l->e);
750 BM_ITER(l, &iter, bm, BM_LOOPS_OF_FACE, f) {
751 vert_flush_hide(bm, l->v);
755 void BM_Hide(BMesh *bm, void *element, int hide)
757 BMHeader *h = element;
759 /* Follow convention of always deselecting before
760 * hiding an element */
762 BM_Select(bm, element, FALSE);
767 BM_Hide_Vert(bm, element, hide);
770 BM_Hide_Edge(bm, element, hide);
773 BM_Hide_Face(bm, element, hide);