BMesh: optimize selection flushing
De-selecting a face would do flushing checks on each vertex 3 times, now only do once.
This commit is contained in:
@@ -70,6 +70,69 @@ static void recount_totsels(BMesh *bm)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/** \name BMesh helper functions for selection flushing.
|
||||||
|
* \{ */
|
||||||
|
|
||||||
|
static bool bm_vert_is_edge_select_any_other(BMVert *v, BMEdge *e_first)
|
||||||
|
{
|
||||||
|
BMEdge *e_iter = e_first;
|
||||||
|
|
||||||
|
/* start by stepping over the current edge */
|
||||||
|
while ((e_iter = bmesh_disk_edge_next(e_iter, v)) != e_first) {
|
||||||
|
if (BM_elem_flag_test(e_iter, BM_ELEM_SELECT)) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
#if 0
|
||||||
|
static bool bm_vert_is_edge_select_any(BMVert *v)
|
||||||
|
{
|
||||||
|
if (v->e) {
|
||||||
|
BMEdge *e_iter, *e_first;
|
||||||
|
e_iter = e_first = v->e;
|
||||||
|
do {
|
||||||
|
if (BM_elem_flag_test(e_iter, BM_ELEM_SELECT)) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
} while ((e_iter = bmesh_disk_edge_next(e_iter, v)) != e_first);
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
static bool bm_edge_is_face_select_any_other(BMLoop *l_first)
|
||||||
|
{
|
||||||
|
BMLoop *l_iter = l_first;
|
||||||
|
|
||||||
|
/* start by stepping over the current face */
|
||||||
|
while ((l_iter = l_iter->radial_next) != l_first) {
|
||||||
|
if (BM_elem_flag_test(l_iter->f, BM_ELEM_SELECT)) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
#if 0
|
||||||
|
static bool bm_edge_is_face_select_any(BMEdge *e)
|
||||||
|
{
|
||||||
|
if (e->l) {
|
||||||
|
BMLoop *l_iter, *l_first;
|
||||||
|
l_iter = l_first = e->l;
|
||||||
|
do {
|
||||||
|
if (BM_elem_flag_test(l_iter->f, BM_ELEM_SELECT)) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
} while ((l_iter = l_iter->radial_next) != l_first);
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/** \} */
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* \brief Select Mode Clean
|
* \brief Select Mode Clean
|
||||||
*
|
*
|
||||||
@@ -386,19 +449,8 @@ void BM_edge_select_set(BMesh *bm, BMEdge *e, const bool select)
|
|||||||
|
|
||||||
/* check if the vert is used by a selected edge */
|
/* check if the vert is used by a selected edge */
|
||||||
for (i = 0; i < 2; i++) {
|
for (i = 0; i < 2; i++) {
|
||||||
bool deselect = true;
|
|
||||||
BMVert *v = *((&e->v1) + i);
|
BMVert *v = *((&e->v1) + i);
|
||||||
BMEdge *e_other = e;
|
if (bm_vert_is_edge_select_any_other(v, e) == false) {
|
||||||
|
|
||||||
/* start by stepping over the current edge */
|
|
||||||
while ((e_other = bmesh_disk_edge_next(e_other, v)) != e) {
|
|
||||||
if (BM_elem_flag_test(e_other, BM_ELEM_SELECT)) {
|
|
||||||
deselect = false;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (deselect) {
|
|
||||||
BM_vert_select_set(bm, v, false);
|
BM_vert_select_set(bm, v, false);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -441,8 +493,6 @@ void BM_face_select_set(BMesh *bm, BMFace *f, const bool select)
|
|||||||
} while ((l_iter = l_iter->next) != l_first);
|
} while ((l_iter = l_iter->next) != l_first);
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
BMIter liter;
|
|
||||||
BMLoop *l;
|
|
||||||
|
|
||||||
if (BM_elem_flag_test(f, BM_ELEM_SELECT)) {
|
if (BM_elem_flag_test(f, BM_ELEM_SELECT)) {
|
||||||
BM_elem_flag_disable(f, BM_ELEM_SELECT);
|
BM_elem_flag_disable(f, BM_ELEM_SELECT);
|
||||||
@@ -450,35 +500,73 @@ void BM_face_select_set(BMesh *bm, BMFace *f, const bool select)
|
|||||||
}
|
}
|
||||||
|
|
||||||
/* flush down to edges */
|
/* flush down to edges */
|
||||||
BM_ITER_ELEM (l, &liter, f, BM_LOOPS_OF_FACE) {
|
l_iter = l_first = BM_FACE_FIRST_LOOP(f);
|
||||||
BMIter fiter;
|
do {
|
||||||
BMFace *f2;
|
/* vertex flushing is handled below */
|
||||||
BM_ITER_ELEM (f2, &fiter, l->e, BM_FACES_OF_EDGE) {
|
if (bm_edge_is_face_select_any_other(l_iter) == false) {
|
||||||
if (BM_elem_flag_test(f2, BM_ELEM_SELECT))
|
BM_edge_select_set_noflush(bm, l_iter->e, false);
|
||||||
break;
|
|
||||||
}
|
}
|
||||||
|
} while ((l_iter = l_iter->next) != l_first);
|
||||||
if (!f2) {
|
|
||||||
BM_edge_select_set(bm, l->e, false);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/* flush down to verts */
|
/* flush down to verts */
|
||||||
BM_ITER_ELEM (l, &liter, f, BM_LOOPS_OF_FACE) {
|
l_iter = l_first = BM_FACE_FIRST_LOOP(f);
|
||||||
BMIter eiter;
|
do {
|
||||||
BMEdge *e;
|
if (bm_vert_is_edge_select_any_other(l_iter->v, l_iter->e) == false) {
|
||||||
BM_ITER_ELEM (e, &eiter, l->v, BM_EDGES_OF_VERT) {
|
BM_vert_select_set(bm, l_iter->v, false);
|
||||||
if (BM_elem_flag_test(e, BM_ELEM_SELECT))
|
|
||||||
break;
|
|
||||||
}
|
}
|
||||||
|
} while ((l_iter = l_iter->next) != l_first);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
if (!e) {
|
/** \name Non flushing versions element selection.
|
||||||
BM_vert_select_set(bm, l->v, false);
|
* \{ */
|
||||||
}
|
|
||||||
|
void BM_edge_select_set_noflush(BMesh *bm, BMEdge *e, const bool select)
|
||||||
|
{
|
||||||
|
BLI_assert(e->head.htype == BM_EDGE);
|
||||||
|
|
||||||
|
if (BM_elem_flag_test(e, BM_ELEM_HIDDEN)) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (select) {
|
||||||
|
if (!BM_elem_flag_test(e, BM_ELEM_SELECT)) {
|
||||||
|
BM_elem_flag_enable(e, BM_ELEM_SELECT);
|
||||||
|
bm->totedgesel += 1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
if (BM_elem_flag_test(e, BM_ELEM_SELECT)) {
|
||||||
|
BM_elem_flag_disable(e, BM_ELEM_SELECT);
|
||||||
|
bm->totedgesel -= 1;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void BM_face_select_set_noflush(BMesh *bm, BMFace *f, const bool select)
|
||||||
|
{
|
||||||
|
BLI_assert(f->head.htype == BM_FACE);
|
||||||
|
|
||||||
|
if (BM_elem_flag_test(f, BM_ELEM_HIDDEN)) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (select) {
|
||||||
|
if (!BM_elem_flag_test(f, BM_ELEM_SELECT)) {
|
||||||
|
BM_elem_flag_enable(f, BM_ELEM_SELECT);
|
||||||
|
bm->totfacesel += 1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
if (BM_elem_flag_test(f, BM_ELEM_SELECT)) {
|
||||||
|
BM_elem_flag_disable(f, BM_ELEM_SELECT);
|
||||||
|
bm->totfacesel -= 1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/** \} */
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Select Mode Set
|
* Select Mode Set
|
||||||
*
|
*
|
||||||
|
@@ -59,6 +59,10 @@ void BM_vert_select_set(BMesh *bm, BMVert *v, const bool select);
|
|||||||
void BM_edge_select_set(BMesh *bm, BMEdge *e, const bool select);
|
void BM_edge_select_set(BMesh *bm, BMEdge *e, const bool select);
|
||||||
void BM_face_select_set(BMesh *bm, BMFace *f, const bool select);
|
void BM_face_select_set(BMesh *bm, BMFace *f, const bool select);
|
||||||
|
|
||||||
|
/* lower level functions which don't do flushing */
|
||||||
|
void BM_edge_select_set_noflush(BMesh *bm, BMEdge *e, const bool select);
|
||||||
|
void BM_face_select_set_noflush(BMesh *bm, BMFace *e, const bool select);
|
||||||
|
|
||||||
void BM_mesh_select_mode_clean_ex(BMesh *bm, const short selectmode);
|
void BM_mesh_select_mode_clean_ex(BMesh *bm, const short selectmode);
|
||||||
void BM_mesh_select_mode_clean(BMesh *bm);
|
void BM_mesh_select_mode_clean(BMesh *bm);
|
||||||
|
|
||||||
|
Reference in New Issue
Block a user