Welcome to mirror list, hosted at ThFree Co, Russian Federation.

git.blender.org/blender.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
Diffstat (limited to 'source/blender/bmesh/intern/bmesh_marking.c')
-rw-r--r--source/blender/bmesh/intern/bmesh_marking.c747
1 files changed, 747 insertions, 0 deletions
diff --git a/source/blender/bmesh/intern/bmesh_marking.c b/source/blender/bmesh/intern/bmesh_marking.c
new file mode 100644
index 00000000000..81e7bcb1b9d
--- /dev/null
+++ b/source/blender/bmesh/intern/bmesh_marking.c
@@ -0,0 +1,747 @@
+/*
+ * ***** BEGIN GPL LICENSE BLOCK *****
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ * Contributor(s): Joseph Eagar, Geoffrey Bantle, Campbell Barton
+ *
+ * ***** END GPL LICENSE BLOCK *****
+ */
+
+/** \file blender/bmesh/intern/bmesh_marking.c
+ * \ingroup bmesh
+ *
+ * Selection routines for bmesh structures.
+ * This is actually all old code ripped from
+ * editmesh_lib.c and slightly modified to work
+ * for bmesh's. This also means that it has some
+ * of the same problems.... something that
+ * that should be addressed eventually.
+ */
+
+#include "MEM_guardedalloc.h"
+
+#include "BKE_utildefines.h"
+
+#include "BLI_math.h"
+#include "BLI_blenlib.h"
+#include "BLI_array.h"
+
+#include "bmesh.h"
+#include "bmesh_private.h"
+
+#include <string.h>
+
+/*
+ * BMESH SELECTMODE FLUSH
+ *
+ * Makes sure to flush selections
+ * 'upwards' (ie: all verts of an edge
+ * selects the edge and so on). This
+ * should only be called by system and not
+ * tool authors.
+ *
+*/
+
+static void recount_totsels(BMesh *bm)
+{
+ BMIter iter;
+ BMHeader *ele;
+ int types[3] = {BM_VERTS_OF_MESH, BM_EDGES_OF_MESH, BM_FACES_OF_MESH};
+ int *tots[3];
+ int i;
+
+ /*recount tot*sel variables*/
+ bm->totvertsel = bm->totedgesel = bm->totfacesel = 0;
+ tots[0] = &bm->totvertsel;
+ tots[1] = &bm->totedgesel;
+ tots[2] = &bm->totfacesel;
+
+ for (i=0; i<3; i++) {
+ ele = BMIter_New(&iter, bm, types[i], NULL);
+ for ( ; ele; ele=BMIter_Step(&iter)) {
+ if (BM_TestHFlag(ele, BM_SELECT)) *tots[i] += 1;
+ }
+ }
+}
+
+void BM_SelectMode_Flush(BMesh *bm)
+{
+ BMEdge *e;
+ BMLoop *l;
+ BMFace *f;
+
+ BMIter edges;
+ BMIter faces;
+
+ int totsel;
+
+ if(bm->selectmode & SCE_SELECT_VERTEX) {
+ for(e = BMIter_New(&edges, bm, BM_EDGES_OF_MESH, bm ); e; e= BMIter_Step(&edges)) {
+ if(BM_TestHFlag(e->v1, BM_SELECT) && BM_TestHFlag(e->v2, BM_SELECT) && !BM_TestHFlag(e, BM_HIDDEN)) {
+ BM_SetHFlag(e, BM_SELECT);
+ }
+ else {
+ BM_ClearHFlag(e, BM_SELECT);
+ }
+ }
+ for(f = BMIter_New(&faces, bm, BM_FACES_OF_MESH, bm ); f; f= BMIter_Step(&faces)) {
+ totsel = 0;
+ l=(BMLoop*) bm_firstfaceloop(f);
+ do{
+ if(BM_TestHFlag(l->v, BM_SELECT))
+ totsel++;
+ l = l->next;
+ } while(l != bm_firstfaceloop(f));
+
+ if(totsel == f->len && !BM_TestHFlag(f, BM_HIDDEN)) {
+ BM_SetHFlag(f, BM_SELECT);
+ }
+ else {
+ BM_ClearHFlag(f, BM_SELECT);
+ }
+ }
+ }
+ else if(bm->selectmode & SCE_SELECT_EDGE) {
+ for(f = BMIter_New(&faces, bm, BM_FACES_OF_MESH, bm ); f; f= BMIter_Step(&faces)) {
+ totsel = 0;
+ l = bm_firstfaceloop(f);
+ do{
+ if(BM_TestHFlag(&(l->e->head), BM_SELECT))
+ totsel++;
+ l = l->next;
+ }while(l!=bm_firstfaceloop(f));
+
+ if(totsel == f->len && !BM_TestHFlag(f, BM_HIDDEN)) {
+ BM_SetHFlag(f, BM_SELECT);
+ }
+ else {
+ BM_ClearHFlag(f, BM_SELECT);
+ }
+ }
+ }
+
+ /*Remove any deselected elements from the BMEditSelection*/
+ BM_validate_selections(bm);
+
+ recount_totsels(bm);
+}
+
+/*
+ * BMESH SELECT VERT
+ *
+ * Changes selection state of a single vertex
+ * in a mesh
+ *
+*/
+
+void BM_Select_Vert(BMesh *bm, BMVert *v, int select)
+{
+ /* BMIter iter; */
+ /* BMEdge *e; */
+
+ if (BM_TestHFlag(v, BM_HIDDEN)) {
+ return;
+ }
+
+ if(select) {
+ if (!BM_TestHFlag(v, BM_SELECT)) {
+ bm->totvertsel += 1;
+ BM_SetHFlag(v, BM_SELECT);
+ }
+ } else {
+ if (BM_TestHFlag(v, BM_SELECT)) {
+ bm->totvertsel -= 1;
+ BM_ClearHFlag(v, BM_SELECT);
+ }
+ }
+}
+
+/*
+ * BMESH SELECT EDGE
+ *
+ * Changes selection state of a single edge
+ * in a mesh.
+ *
+*/
+
+void BM_Select_Edge(BMesh *bm, BMEdge *e, int select)
+{
+ if (BM_TestHFlag(e, BM_HIDDEN)) {
+ return;
+ }
+
+ if(select){
+ if (!BM_TestHFlag(e, BM_SELECT)) bm->totedgesel += 1;
+
+ BM_SetHFlag(&(e->head), BM_SELECT);
+ BM_Select(bm, e->v1, 1);
+ BM_Select(bm, e->v2, 1);
+ }else{
+ if (BM_TestHFlag(e, BM_SELECT)) bm->totedgesel -= 1;
+ BM_ClearHFlag(&(e->head), BM_SELECT);
+
+ if(
+ bm->selectmode == SCE_SELECT_EDGE ||
+ bm->selectmode == SCE_SELECT_FACE ||
+ bm->selectmode == (SCE_SELECT_EDGE | SCE_SELECT_FACE)){
+
+ BMIter iter;
+ BMVert *verts[2] = {e->v1, e->v2};
+ BMEdge *e2;
+ int i;
+
+ for(i = 0; i < 2; i++){
+ int deselect = 1;
+
+ for(e2 = BMIter_New(&iter, bm, BM_EDGES_OF_VERT, verts[i]);
+ e2; e2 = BMIter_Step(&iter)){
+ if(e2 == e){
+ continue;
+ }
+
+ if (BM_TestHFlag(e2, BM_SELECT)){
+ deselect = 0;
+ break;
+ }
+ }
+
+ if(deselect) BM_Select_Vert(bm, verts[i], 0);
+ }
+ }else{
+ BM_Select(bm, e->v1, 0);
+ BM_Select(bm, e->v2, 0);
+ }
+
+ }
+}
+
+/*
+ *
+ * BMESH SELECT FACE
+ *
+ * Changes selection state of a single
+ * face in a mesh.
+ *
+*/
+
+void BM_Select_Face(BMesh *bm, BMFace *f, int select)
+{
+ BMLoop *l;
+
+ if (BM_TestHFlag(f, BM_HIDDEN)) {
+ return;
+ }
+
+ if(select){
+ if (!BM_TestHFlag(f, BM_SELECT)) bm->totfacesel += 1;
+
+ BM_SetHFlag(&(f->head), BM_SELECT);
+ l=(BMLoop*) bm_firstfaceloop(f);
+ do{
+ BM_Select_Vert(bm, l->v, 1);
+ BM_Select_Edge(bm, l->e, 1);
+ l = l->next;
+ }while(l != bm_firstfaceloop(f));
+ }
+ else{
+ BMIter liter;
+ BMLoop *l;
+
+ if (BM_TestHFlag(f, BM_SELECT)) bm->totfacesel -= 1;
+ BM_ClearHFlag(&(f->head), BM_SELECT);
+
+ /*flush down to edges*/
+ BM_ITER(l, &liter, bm, BM_LOOPS_OF_FACE, f) {
+ BMIter fiter;
+ BMFace *f2;
+ BM_ITER(f2, &fiter, bm, BM_FACES_OF_EDGE, l->e) {
+ if (BM_TestHFlag(f2, BM_SELECT))
+ break;
+ }
+
+ if (!f2)
+ {
+ BM_Select(bm, l->e, 0);
+ }
+ }
+
+ /*flush down to verts*/
+ BM_ITER(l, &liter, bm, BM_LOOPS_OF_FACE, f) {
+ BMIter eiter;
+ BMEdge *e;
+ BM_ITER(e, &eiter, bm, BM_EDGES_OF_VERT, l->v) {
+ if (BM_TestHFlag(e, BM_SELECT))
+ break;
+ }
+
+ if (!e)
+ {
+ BM_Select(bm, l->v, 0);
+ }
+ }
+ }
+}
+
+/*
+ * BMESH SELECTMODE SET
+ *
+ * Sets the selection mode for the bmesh
+ *
+*/
+
+void BM_Selectmode_Set(BMesh *bm, int selectmode)
+{
+ BMVert *v;
+ BMEdge *e;
+ BMFace *f;
+
+ BMIter verts;
+ BMIter edges;
+ BMIter faces;
+
+ bm->selectmode = selectmode;
+
+ if(bm->selectmode & SCE_SELECT_VERTEX) {
+ for(e = BMIter_New(&edges, bm, BM_EDGES_OF_MESH, bm ); e; e= BMIter_Step(&edges))
+ BM_ClearHFlag(e, 0);
+ for(f = BMIter_New(&faces, bm, BM_FACES_OF_MESH, bm ); f; f= BMIter_Step(&faces))
+ BM_ClearHFlag(f, 0);
+ BM_SelectMode_Flush(bm);
+ }
+ else if(bm->selectmode & SCE_SELECT_EDGE) {
+ for(v= BMIter_New(&verts, bm, BM_VERTS_OF_MESH, bm ); v; v= BMIter_Step(&verts))
+ BM_ClearHFlag(v, 0);
+ for(e= BMIter_New(&edges, bm, BM_EDGES_OF_MESH, bm ); e; e= BMIter_Step(&edges)){
+ if(BM_TestHFlag(&(e->head), BM_SELECT))
+ BM_Select_Edge(bm, e, 1);
+ }
+ BM_SelectMode_Flush(bm);
+ }
+ else if(bm->selectmode & SCE_SELECT_FACE) {
+ for(e = BMIter_New(&edges, bm, BM_EDGES_OF_MESH, bm ); e; e= BMIter_Step(&edges))
+ BM_ClearHFlag(e, 0);
+ for(f = BMIter_New(&faces, bm, BM_FACES_OF_MESH, bm ); f; f= BMIter_Step(&faces)){
+ if(BM_TestHFlag(&(f->head), BM_SELECT))
+ BM_Select_Face(bm, f, 1);
+ }
+ BM_SelectMode_Flush(bm);
+ }
+}
+
+
+int BM_CountFlag(struct BMesh *bm, const char htype, const char hflag, int respecthide)
+{
+ BMHeader *head;
+ BMIter iter;
+ int tot = 0;
+
+ if (htype & BM_VERT) {
+ for (head = BMIter_New(&iter, bm, BM_VERTS_OF_MESH, NULL); head; head=BMIter_Step(&iter)) {
+ if (respecthide && BM_TestHFlag(head, BM_HIDDEN)) continue;
+ if (BM_TestHFlag(head, hflag)) tot++;
+ }
+ }
+ if (htype & BM_EDGE) {
+ for (head = BMIter_New(&iter, bm, BM_EDGES_OF_MESH, NULL); head; head=BMIter_Step(&iter)) {
+ if (respecthide && BM_TestHFlag(head, BM_HIDDEN)) continue;
+ if (BM_TestHFlag(head, hflag)) tot++;
+ }
+ }
+ if (htype & BM_FACE) {
+ for (head = BMIter_New(&iter, bm, BM_FACES_OF_MESH, NULL); head; head=BMIter_Step(&iter)) {
+ if (respecthide && BM_TestHFlag(head, BM_HIDDEN)) continue;
+ if (BM_TestHFlag(head, hflag)) tot++;
+ }
+ }
+
+ return tot;
+}
+
+/*note: by design, this will not touch the editselection history stuff*/
+void BM_Select(struct BMesh *bm, void *element, int select)
+{
+ BMHeader *head = element;
+
+ if (head->htype == BM_VERT) BM_Select_Vert(bm, (BMVert*)element, select);
+ else if(head->htype == BM_EDGE) BM_Select_Edge(bm, (BMEdge*)element, select);
+ else if(head->htype == BM_FACE) BM_Select_Face(bm, (BMFace*)element, select);
+}
+
+int BM_Selected(BMesh *UNUSED(bm), const void *element)
+{
+ const BMHeader *head = element;
+ int selected = BM_TestHFlag(head, BM_SELECT);
+ BLI_assert(!selected || !BM_TestHFlag(head, BM_HIDDEN));
+ return selected;
+}
+
+/* this replaces the active flag used in uv/face mode */
+void BM_set_actFace(BMesh *bm, BMFace *efa)
+{
+ bm->act_face = efa;
+}
+
+BMFace *BM_get_actFace(BMesh *bm, int sloppy)
+{
+ if (bm->act_face) {
+ return bm->act_face;
+ } else if (sloppy) {
+ BMIter iter;
+ BMFace *f= NULL;
+ BMEditSelection *ese;
+
+ /* Find the latest non-hidden face from the BMEditSelection */
+ ese = bm->selected.last;
+ for (; ese; ese=ese->prev){
+ if(ese->htype == BM_FACE) {
+ f= (BMFace *)ese->data;
+
+ if (BM_TestHFlag(f, BM_HIDDEN)) {
+ f= NULL;
+ }
+ else {
+ break;
+ }
+ }
+ }
+ /* Last attempt: try to find any selected face */
+ if (f==NULL) {
+ BM_ITER(f, &iter, bm, BM_FACES_OF_MESH, NULL) {
+ if (BM_TestHFlag(f, BM_SELECT)) {
+ break;
+ }
+ }
+ }
+ return f; /* can still be null */
+ }
+ return NULL;
+}
+
+/* generic way to get data from an EditSelection type
+These functions were written to be used by the Modifier widget when in Rotate about active mode,
+but can be used anywhere.
+EM_editselection_center
+EM_editselection_normal
+EM_editselection_plane
+*/
+void BM_editselection_center(BMesh *bm, float *center, BMEditSelection *ese)
+{
+ if (ese->htype == BM_VERT) {
+ BMVert *eve= ese->data;
+ copy_v3_v3(center, eve->co);
+ }
+ else if (ese->htype == BM_EDGE) {
+ BMEdge *eed= ese->data;
+ add_v3_v3v3(center, eed->v1->co, eed->v2->co);
+ mul_v3_fl(center, 0.5);
+ }
+ else if (ese->htype == BM_FACE) {
+ BMFace *efa= ese->data;
+ BM_Compute_Face_CenterBounds(bm, efa, center);
+ }
+}
+
+void BM_editselection_normal(float *normal, BMEditSelection *ese)
+{
+ if (ese->htype == BM_VERT) {
+ BMVert *eve= ese->data;
+ copy_v3_v3(normal, eve->no);
+ }
+ else if (ese->htype == BM_EDGE) {
+ BMEdge *eed= ese->data;
+ float plane[3]; /* need a plane to correct the normal */
+ float vec[3]; /* temp vec storage */
+
+ add_v3_v3v3(normal, eed->v1->no, eed->v2->no);
+ sub_v3_v3v3(plane, eed->v2->co, eed->v1->co);
+
+ /* the 2 vertex normals will be close but not at rightangles to the edge
+ for rotate about edge we want them to be at right angles, so we need to
+ do some extra colculation to correct the vert normals,
+ we need the plane for this */
+ cross_v3_v3v3(vec, normal, plane);
+ cross_v3_v3v3(normal, plane, vec);
+ normalize_v3(normal);
+
+ }
+ else if (ese->htype == BM_FACE) {
+ BMFace *efa= ese->data;
+ copy_v3_v3(normal, efa->no);
+ }
+}
+
+/* Calculate a plane that is rightangles to the edge/vert/faces normal
+also make the plane run along an axis that is related to the geometry,
+because this is used for the manipulators Y axis.*/
+void BM_editselection_plane(BMesh *bm, float *plane, BMEditSelection *ese)
+{
+ if (ese->htype == BM_VERT) {
+ BMVert *eve= ese->data;
+ float vec[3]={0,0,0};
+
+ if (ese->prev) { /*use previously selected data to make a useful vertex plane */
+ BM_editselection_center(bm, vec, ese->prev);
+ sub_v3_v3v3(plane, vec, eve->co);
+ } else {
+ /* make a fake plane thats at rightangles to the normal
+ we cant make a crossvec from a vec thats the same as the vec
+ unlikely but possible, so make sure if the normal is (0,0,1)
+ that vec isnt the same or in the same direction even.*/
+ if (eve->no[0] < 0.5f) vec[0]= 1.0f;
+ else if (eve->no[1] < 0.5f) vec[1]= 1.0f;
+ else vec[2]= 1.0f;
+ cross_v3_v3v3(plane, eve->no, vec);
+ }
+ }
+ else if (ese->htype == BM_EDGE) {
+ BMEdge *eed= ese->data;
+
+ /* the plane is simple, it runs along the edge
+ however selecting different edges can swap the direction of the y axis.
+ this makes it less likely for the y axis of the manipulator
+ (running along the edge).. to flip less often.
+ at least its more pradictable */
+ if (eed->v2->co[1] > eed->v1->co[1]) /*check which to do first */
+ sub_v3_v3v3(plane, eed->v2->co, eed->v1->co);
+ else
+ sub_v3_v3v3(plane, eed->v1->co, eed->v2->co);
+
+ }
+ else if (ese->htype == BM_FACE) {
+ BMFace *efa= ese->data;
+ float vec[3] = {0.0f, 0.0f, 0.0f};
+
+ /*for now, use face normal*/
+
+ /* make a fake plane thats at rightangles to the normal
+ we cant make a crossvec from a vec thats the same as the vec
+ unlikely but possible, so make sure if the normal is (0,0,1)
+ that vec isnt the same or in the same direction even.*/
+ if (efa->no[0] < 0.5f) vec[0]= 1.0f;
+ else if (efa->no[1] < 0.5f) vec[1]= 1.0f;
+ else vec[2]= 1.0f;
+ cross_v3_v3v3(plane, efa->no, vec);
+#if 0 //BMESH_TODO
+
+ if (efa->v4) { /*if its a quad- set the plane along the 2 longest edges.*/
+ float vecA[3], vecB[3];
+ sub_v3_v3v3(vecA, efa->v4->co, efa->v3->co);
+ sub_v3_v3v3(vecB, efa->v1->co, efa->v2->co);
+ add_v3_v3v3(plane, vecA, vecB);
+
+ sub_v3_v3v3(vecA, efa->v1->co, efa->v4->co);
+ sub_v3_v3v3(vecB, efa->v2->co, efa->v3->co);
+ add_v3_v3v3(vec, vecA, vecB);
+ /*use the biggest edge length*/
+ 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])
+ copy_v3_v3(plane, vec);
+ } else {
+ /*start with v1-2 */
+ sub_v3_v3v3(plane, efa->v1->co, efa->v2->co);
+
+ /*test the edge between v2-3, use if longer */
+ sub_v3_v3v3(vec, efa->v2->co, efa->v3->co);
+ 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])
+ copy_v3_v3(plane, vec);
+
+ /*test the edge between v1-3, use if longer */
+ sub_v3_v3v3(vec, efa->v3->co, efa->v1->co);
+ 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])
+ copy_v3_v3(plane, vec);
+ }
+#endif
+ }
+ normalize_v3(plane);
+}
+
+static int BM_check_selection(BMesh *bm, void *data)
+{
+ BMEditSelection *ese;
+
+ for(ese = bm->selected.first; ese; ese = ese->next){
+ if(ese->data == data) return 1;
+ }
+
+ return 0;
+}
+
+void BM_remove_selection(BMesh *bm, void *data)
+{
+ BMEditSelection *ese;
+ for(ese=bm->selected.first; ese; ese = ese->next){
+ if(ese->data == data){
+ BLI_freelinkN(&(bm->selected),ese);
+ break;
+ }
+ }
+}
+
+void BM_clear_selection_history(BMesh *bm)
+{
+ BLI_freelistN(&bm->selected);
+ bm->selected.first = bm->selected.last = NULL;
+}
+
+void BM_store_selection(BMesh *bm, void *data)
+{
+ BMEditSelection *ese;
+ if(!BM_check_selection(bm, data)){
+ ese = (BMEditSelection*) MEM_callocN( sizeof(BMEditSelection), "BMEdit Selection");
+ ese->htype = ((BMHeader*)data)->htype;
+ ese->data = data;
+ BLI_addtail(&(bm->selected),ese);
+ }
+}
+
+void BM_validate_selections(BMesh *bm)
+{
+ BMEditSelection *ese, *nextese;
+
+ ese = bm->selected.first;
+
+ while(ese) {
+ nextese = ese->next;
+ if (!BM_TestHFlag(ese->data, BM_SELECT)) {
+ BLI_freelinkN(&(bm->selected), ese);
+ }
+ ese = nextese;
+ }
+}
+
+void BM_clear_flag_all(BMesh *bm, const char hflag)
+{
+ int types[3] = {BM_VERTS_OF_MESH, BM_EDGES_OF_MESH, BM_FACES_OF_MESH};
+ BMIter iter;
+ BMHeader *ele;
+ int i;
+
+ if (hflag & BM_SELECT)
+ BM_clear_selection_history(bm);
+
+ for (i=0; i<3; i++) {
+ ele = BMIter_New(&iter, bm, types[i], NULL);
+ for ( ; ele; ele=BMIter_Step(&iter)) {
+ if (hflag & BM_SELECT) BM_Select(bm, ele, 0);
+ BM_ClearHFlag(ele, hflag);
+ }
+ }
+}
+
+
+/***************** Mesh Hiding stuff *************/
+
+#define SETHIDE(ele) hide ? BM_SetHFlag(ele, BM_HIDDEN) : BM_ClearHFlag(ele, BM_HIDDEN);
+
+static void vert_flush_hide(BMesh *bm, BMVert *v)
+{
+ BMIter iter;
+ BMEdge *e;
+ int hide = 1;
+
+ BM_ITER(e, &iter, bm, BM_EDGES_OF_VERT, v) {
+ hide = hide && BM_TestHFlag(e, BM_HIDDEN);
+ }
+
+ SETHIDE(v);
+}
+
+static void edge_flush_hide(BMesh *bm, BMEdge *e)
+{
+ BMIter iter;
+ BMFace *f;
+ int hide = 1;
+
+ BM_ITER(f, &iter, bm, BM_FACES_OF_EDGE, e) {
+ hide = hide && BM_TestHFlag(f, BM_HIDDEN);
+ }
+
+ SETHIDE(e);
+}
+
+void BM_Hide_Vert(BMesh *bm, BMVert *v, int hide)
+{
+ /*vert hiding: vert + surrounding edges and faces*/
+ BMIter iter, fiter;
+ BMEdge *e;
+ BMFace *f;
+
+ SETHIDE(v);
+
+ BM_ITER(e, &iter, bm, BM_EDGES_OF_VERT, v) {
+ SETHIDE(e);
+
+ BM_ITER(f, &fiter, bm, BM_FACES_OF_EDGE, e) {
+ SETHIDE(f);
+ }
+ }
+}
+
+void BM_Hide_Edge(BMesh *bm, BMEdge *e, int hide)
+{
+ BMIter iter;
+ BMFace *f;
+ /* BMVert *v; */
+
+ /*edge hiding: faces around the edge*/
+ BM_ITER(f, &iter, bm, BM_FACES_OF_EDGE, e) {
+ SETHIDE(f);
+ }
+
+ SETHIDE(e);
+
+ /*hide vertices if necassary*/
+ vert_flush_hide(bm, e->v1);
+ vert_flush_hide(bm, e->v2);
+}
+
+void BM_Hide_Face(BMesh *bm, BMFace *f, int hide)
+{
+ BMIter iter;
+ BMLoop *l;
+
+ /**/
+ SETHIDE(f);
+
+ BM_ITER(l, &iter, bm, BM_LOOPS_OF_FACE, f) {
+ edge_flush_hide(bm, l->e);
+ }
+
+ BM_ITER(l, &iter, bm, BM_LOOPS_OF_FACE, f) {
+ vert_flush_hide(bm, l->v);
+ }
+}
+
+void BM_Hide(BMesh *bm, void *element, int hide)
+{
+ BMHeader *h = element;
+
+ /*Follow convention of always deselecting before
+ hiding an element*/
+ if (hide)
+ BM_Select(bm, element, 0);
+
+ switch (h->htype) {
+ case BM_VERT:
+ BM_Hide_Vert(bm, element, hide);
+ break;
+ case BM_EDGE:
+ BM_Hide_Edge(bm, element, hide);
+ break;
+ case BM_FACE:
+ BM_Hide_Face(bm, element, hide);
+ break;
+ }
+}