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/editors/mesh/editmesh_select.c')
-rw-r--r--source/blender/editors/mesh/editmesh_select.c7811
1 files changed, 3956 insertions, 3855 deletions
diff --git a/source/blender/editors/mesh/editmesh_select.c b/source/blender/editors/mesh/editmesh_select.c
index 8b75b511319..94886266d24 100644
--- a/source/blender/editors/mesh/editmesh_select.c
+++ b/source/blender/editors/mesh/editmesh_select.c
@@ -67,7 +67,7 @@
#include "DEG_depsgraph.h"
#include "DEG_depsgraph_query.h"
-#include "mesh_intern.h" /* own include */
+#include "mesh_intern.h" /* own include */
/* use bmesh operator flags for a few operators */
#define BMO_ELE_TAG 1
@@ -77,94 +77,92 @@
* \{ */
void EDBM_select_mirrored(
- BMEditMesh *em, const int axis, const bool extend,
- int *r_totmirr, int *r_totfail)
+ BMEditMesh *em, const int axis, const bool extend, int *r_totmirr, int *r_totfail)
{
- Mesh *me = (Mesh *)em->ob->data;
- BMesh *bm = em->bm;
- BMIter iter;
- int totmirr = 0;
- int totfail = 0;
- bool use_topology = (me && (me->editflag & ME_EDIT_MIRROR_TOPO));
-
- *r_totmirr = *r_totfail = 0;
-
- /* select -> tag */
- if (bm->selectmode & SCE_SELECT_VERTEX) {
- BMVert *v;
- BM_ITER_MESH (v, &iter, bm, BM_VERTS_OF_MESH) {
- BM_elem_flag_set(v, BM_ELEM_TAG, BM_elem_flag_test(v, BM_ELEM_SELECT));
- }
- }
- else if (em->selectmode & SCE_SELECT_EDGE) {
- BMEdge *e;
- BM_ITER_MESH (e, &iter, bm, BM_EDGES_OF_MESH) {
- BM_elem_flag_set(e, BM_ELEM_TAG, BM_elem_flag_test(e, BM_ELEM_SELECT));
- }
- }
- else {
- BMFace *f;
- BM_ITER_MESH (f, &iter, bm, BM_FACES_OF_MESH) {
- BM_elem_flag_set(f, BM_ELEM_TAG, BM_elem_flag_test(f, BM_ELEM_SELECT));
- }
- }
-
- EDBM_verts_mirror_cache_begin(em, axis, true, true, use_topology);
-
- if (!extend)
- EDBM_flag_disable_all(em, BM_ELEM_SELECT);
-
-
- if (bm->selectmode & SCE_SELECT_VERTEX) {
- BMVert *v;
- BM_ITER_MESH (v, &iter, bm, BM_VERTS_OF_MESH) {
- if (!BM_elem_flag_test(v, BM_ELEM_HIDDEN) && BM_elem_flag_test(v, BM_ELEM_TAG)) {
- BMVert *v_mirr = EDBM_verts_mirror_get(em, v);
- if (v_mirr && !BM_elem_flag_test(v_mirr, BM_ELEM_HIDDEN)) {
- BM_vert_select_set(bm, v_mirr, true);
- totmirr++;
- }
- else {
- totfail++;
- }
- }
- }
- }
- else if (em->selectmode & SCE_SELECT_EDGE) {
- BMEdge *e;
- BM_ITER_MESH (e, &iter, bm, BM_EDGES_OF_MESH) {
- if (!BM_elem_flag_test(e, BM_ELEM_HIDDEN) && BM_elem_flag_test(e, BM_ELEM_TAG)) {
- BMEdge *e_mirr = EDBM_verts_mirror_get_edge(em, e);
- if (e_mirr && !BM_elem_flag_test(e_mirr, BM_ELEM_HIDDEN)) {
- BM_edge_select_set(bm, e_mirr, true);
- totmirr++;
- }
- else {
- totfail++;
- }
- }
- }
- }
- else {
- BMFace *f;
- BM_ITER_MESH (f, &iter, bm, BM_FACES_OF_MESH) {
- if (!BM_elem_flag_test(f, BM_ELEM_HIDDEN) && BM_elem_flag_test(f, BM_ELEM_TAG)) {
- BMFace *f_mirr = EDBM_verts_mirror_get_face(em, f);
- if (f_mirr && !BM_elem_flag_test(f_mirr, BM_ELEM_HIDDEN)) {
- BM_face_select_set(bm, f_mirr, true);
- totmirr++;
- }
- else {
- totfail++;
- }
- }
- }
- }
-
- EDBM_verts_mirror_cache_end(em);
-
- *r_totmirr = totmirr;
- *r_totfail = totfail;
+ Mesh *me = (Mesh *)em->ob->data;
+ BMesh *bm = em->bm;
+ BMIter iter;
+ int totmirr = 0;
+ int totfail = 0;
+ bool use_topology = (me && (me->editflag & ME_EDIT_MIRROR_TOPO));
+
+ *r_totmirr = *r_totfail = 0;
+
+ /* select -> tag */
+ if (bm->selectmode & SCE_SELECT_VERTEX) {
+ BMVert *v;
+ BM_ITER_MESH (v, &iter, bm, BM_VERTS_OF_MESH) {
+ BM_elem_flag_set(v, BM_ELEM_TAG, BM_elem_flag_test(v, BM_ELEM_SELECT));
+ }
+ }
+ else if (em->selectmode & SCE_SELECT_EDGE) {
+ BMEdge *e;
+ BM_ITER_MESH (e, &iter, bm, BM_EDGES_OF_MESH) {
+ BM_elem_flag_set(e, BM_ELEM_TAG, BM_elem_flag_test(e, BM_ELEM_SELECT));
+ }
+ }
+ else {
+ BMFace *f;
+ BM_ITER_MESH (f, &iter, bm, BM_FACES_OF_MESH) {
+ BM_elem_flag_set(f, BM_ELEM_TAG, BM_elem_flag_test(f, BM_ELEM_SELECT));
+ }
+ }
+
+ EDBM_verts_mirror_cache_begin(em, axis, true, true, use_topology);
+
+ if (!extend)
+ EDBM_flag_disable_all(em, BM_ELEM_SELECT);
+
+ if (bm->selectmode & SCE_SELECT_VERTEX) {
+ BMVert *v;
+ BM_ITER_MESH (v, &iter, bm, BM_VERTS_OF_MESH) {
+ if (!BM_elem_flag_test(v, BM_ELEM_HIDDEN) && BM_elem_flag_test(v, BM_ELEM_TAG)) {
+ BMVert *v_mirr = EDBM_verts_mirror_get(em, v);
+ if (v_mirr && !BM_elem_flag_test(v_mirr, BM_ELEM_HIDDEN)) {
+ BM_vert_select_set(bm, v_mirr, true);
+ totmirr++;
+ }
+ else {
+ totfail++;
+ }
+ }
+ }
+ }
+ else if (em->selectmode & SCE_SELECT_EDGE) {
+ BMEdge *e;
+ BM_ITER_MESH (e, &iter, bm, BM_EDGES_OF_MESH) {
+ if (!BM_elem_flag_test(e, BM_ELEM_HIDDEN) && BM_elem_flag_test(e, BM_ELEM_TAG)) {
+ BMEdge *e_mirr = EDBM_verts_mirror_get_edge(em, e);
+ if (e_mirr && !BM_elem_flag_test(e_mirr, BM_ELEM_HIDDEN)) {
+ BM_edge_select_set(bm, e_mirr, true);
+ totmirr++;
+ }
+ else {
+ totfail++;
+ }
+ }
+ }
+ }
+ else {
+ BMFace *f;
+ BM_ITER_MESH (f, &iter, bm, BM_FACES_OF_MESH) {
+ if (!BM_elem_flag_test(f, BM_ELEM_HIDDEN) && BM_elem_flag_test(f, BM_ELEM_TAG)) {
+ BMFace *f_mirr = EDBM_verts_mirror_get_face(em, f);
+ if (f_mirr && !BM_elem_flag_test(f_mirr, BM_ELEM_HIDDEN)) {
+ BM_face_select_set(bm, f_mirr, true);
+ totmirr++;
+ }
+ else {
+ totfail++;
+ }
+ }
+ }
+ }
+
+ EDBM_verts_mirror_cache_end(em);
+
+ *r_totmirr = totmirr;
+ *r_totfail = totfail;
}
/** \} */
@@ -177,17 +175,18 @@ void EDBM_select_mirrored(
void EDBM_automerge(Scene *scene, Object *obedit, bool update, const char hflag)
{
- bool ok;
- BMEditMesh *em = BKE_editmesh_from_object(obedit);
-
- ok = BMO_op_callf(
- em->bm, BMO_FLAG_DEFAULTS,
- "automerge verts=%hv dist=%f",
- hflag, scene->toolsettings->doublimit);
-
- if (LIKELY(ok) && update) {
- EDBM_update_generic(em, true, true);
- }
+ bool ok;
+ BMEditMesh *em = BKE_editmesh_from_object(obedit);
+
+ ok = BMO_op_callf(em->bm,
+ BMO_FLAG_DEFAULTS,
+ "automerge verts=%hv dist=%f",
+ hflag,
+ scene->toolsettings->doublimit);
+
+ if (LIKELY(ok) && update) {
+ EDBM_update_generic(em, true, true);
+ }
}
/** \} */
@@ -204,173 +203,175 @@ static BLI_bitmap *selbuf = NULL;
static BLI_bitmap *edbm_backbuf_alloc(const int size)
{
- return BLI_BITMAP_NEW(size, "selbuf");
+ return BLI_BITMAP_NEW(size, "selbuf");
}
/* reads rect, and builds selection array for quick lookup */
/* returns if all is OK */
-bool EDBM_backbuf_border_init(
- ViewContext *vc, short xmin,
- short ymin, short xmax, short ymax)
+bool EDBM_backbuf_border_init(ViewContext *vc, short xmin, short ymin, short xmax, short ymax)
{
- uint *buf, *dr, buf_len;
-
- if (vc->obedit == NULL || XRAY_FLAG_ENABLED(vc->v3d)) {
- return false;
- }
-
- buf = ED_view3d_select_id_read(vc, xmin, ymin, xmax, ymax, &buf_len);
- if ((buf == NULL) || (bm_vertoffs == 0)) {
- return false;
- }
-
- dr = buf;
-
- /* build selection lookup */
- selbuf = edbm_backbuf_alloc(bm_vertoffs + 1);
-
- while (buf_len--) {
- if (*dr > 0 && *dr <= bm_vertoffs) {
- BLI_BITMAP_ENABLE(selbuf, *dr);
- }
- dr++;
- }
- MEM_freeN(buf);
- return true;
+ uint *buf, *dr, buf_len;
+
+ if (vc->obedit == NULL || XRAY_FLAG_ENABLED(vc->v3d)) {
+ return false;
+ }
+
+ buf = ED_view3d_select_id_read(vc, xmin, ymin, xmax, ymax, &buf_len);
+ if ((buf == NULL) || (bm_vertoffs == 0)) {
+ return false;
+ }
+
+ dr = buf;
+
+ /* build selection lookup */
+ selbuf = edbm_backbuf_alloc(bm_vertoffs + 1);
+
+ while (buf_len--) {
+ if (*dr > 0 && *dr <= bm_vertoffs) {
+ BLI_BITMAP_ENABLE(selbuf, *dr);
+ }
+ dr++;
+ }
+ MEM_freeN(buf);
+ return true;
}
bool EDBM_backbuf_check(unsigned int index)
{
- /* odd logic, if selbuf is NULL we assume no zbuf-selection is enabled
- * and just ignore the depth buffer, this is error prone since its possible
- * code doesn't set the depth buffer by accident, but leave for now. - Campbell */
- if (selbuf == NULL)
- return true;
+ /* odd logic, if selbuf is NULL we assume no zbuf-selection is enabled
+ * and just ignore the depth buffer, this is error prone since its possible
+ * code doesn't set the depth buffer by accident, but leave for now. - Campbell */
+ if (selbuf == NULL)
+ return true;
- if (index > 0 && index <= bm_vertoffs)
- return BLI_BITMAP_TEST_BOOL(selbuf, index);
+ if (index > 0 && index <= bm_vertoffs)
+ return BLI_BITMAP_TEST_BOOL(selbuf, index);
- return false;
+ return false;
}
void EDBM_backbuf_free(void)
{
- if (selbuf) MEM_freeN(selbuf);
- selbuf = NULL;
+ if (selbuf)
+ MEM_freeN(selbuf);
+ selbuf = NULL;
}
struct LassoMaskData {
- unsigned int *px;
- int width;
+ unsigned int *px;
+ int width;
};
static void edbm_mask_lasso_px_cb(int x, int x_end, int y, void *user_data)
{
- struct LassoMaskData *data = user_data;
- unsigned int *px = &data->px[(y * data->width) + x];
- do {
- *px = true;
- px++;
- } while (++x != x_end);
+ struct LassoMaskData *data = user_data;
+ unsigned int *px = &data->px[(y * data->width) + x];
+ do {
+ *px = true;
+ px++;
+ } while (++x != x_end);
}
-
/* mcords is a polygon mask
* - grab backbuffer,
* - draw with black in backbuffer,
* - grab again and compare
* returns 'OK'
*/
-bool EDBM_backbuf_border_mask_init(ViewContext *vc, const int mcords[][2], short tot, short xmin, short ymin, short xmax, short ymax)
+bool EDBM_backbuf_border_mask_init(ViewContext *vc,
+ const int mcords[][2],
+ short tot,
+ short xmin,
+ short ymin,
+ short xmax,
+ short ymax)
{
- uint *buf, *dr, *dr_mask, *dr_mask_arr, buf_len;
- struct LassoMaskData lasso_mask_data;
-
- /* method in use for face selecting too */
- if (vc->obedit == NULL) {
- if (!BKE_paint_select_elem_test(vc->obact)) {
- return false;
- }
- }
- else if (XRAY_FLAG_ENABLED(vc->v3d)) {
- return false;
- }
-
- buf = ED_view3d_select_id_read(vc, xmin, ymin, xmax, ymax, &buf_len);
- if ((buf == NULL) || (bm_vertoffs == 0)) {
- return false;
- }
-
- dr = buf;
-
- dr_mask = dr_mask_arr = MEM_callocN(sizeof(*dr_mask) * buf_len, __func__);
- lasso_mask_data.px = dr_mask;
- lasso_mask_data.width = (xmax - xmin) + 1;
-
- BLI_bitmap_draw_2d_poly_v2i_n(
- xmin, ymin, xmax + 1, ymax + 1,
- mcords, tot,
- edbm_mask_lasso_px_cb, &lasso_mask_data);
-
- /* build selection lookup */
- selbuf = edbm_backbuf_alloc(bm_vertoffs + 1);
-
- while (buf_len--) {
- if (*dr > 0 && *dr <= bm_vertoffs && *dr_mask == true) {
- BLI_BITMAP_ENABLE(selbuf, *dr);
- }
- dr++; dr_mask++;
- }
- MEM_freeN(buf);
- MEM_freeN(dr_mask_arr);
-
- return true;
+ uint *buf, *dr, *dr_mask, *dr_mask_arr, buf_len;
+ struct LassoMaskData lasso_mask_data;
+
+ /* method in use for face selecting too */
+ if (vc->obedit == NULL) {
+ if (!BKE_paint_select_elem_test(vc->obact)) {
+ return false;
+ }
+ }
+ else if (XRAY_FLAG_ENABLED(vc->v3d)) {
+ return false;
+ }
+
+ buf = ED_view3d_select_id_read(vc, xmin, ymin, xmax, ymax, &buf_len);
+ if ((buf == NULL) || (bm_vertoffs == 0)) {
+ return false;
+ }
+
+ dr = buf;
+
+ dr_mask = dr_mask_arr = MEM_callocN(sizeof(*dr_mask) * buf_len, __func__);
+ lasso_mask_data.px = dr_mask;
+ lasso_mask_data.width = (xmax - xmin) + 1;
+
+ BLI_bitmap_draw_2d_poly_v2i_n(
+ xmin, ymin, xmax + 1, ymax + 1, mcords, tot, edbm_mask_lasso_px_cb, &lasso_mask_data);
+
+ /* build selection lookup */
+ selbuf = edbm_backbuf_alloc(bm_vertoffs + 1);
+
+ while (buf_len--) {
+ if (*dr > 0 && *dr <= bm_vertoffs && *dr_mask == true) {
+ BLI_BITMAP_ENABLE(selbuf, *dr);
+ }
+ dr++;
+ dr_mask++;
+ }
+ MEM_freeN(buf);
+ MEM_freeN(dr_mask_arr);
+
+ return true;
}
/* circle shaped sample area */
-bool EDBM_backbuf_circle_init(
- ViewContext *vc,
- short xs, short ys, short rads)
+bool EDBM_backbuf_circle_init(ViewContext *vc, short xs, short ys, short rads)
{
- uint *buf, *dr;
- short xmin, ymin, xmax, ymax, xc, yc;
- int radsq;
-
- /* method in use for face selecting too */
- if (vc->obedit == NULL) {
- if (!BKE_paint_select_elem_test(vc->obact)) {
- return false;
- }
- }
- else if (XRAY_FLAG_ENABLED(vc->v3d)) {
- return false;
- }
-
- xmin = xs - rads; xmax = xs + rads;
- ymin = ys - rads; ymax = ys + rads;
- buf = ED_view3d_select_id_read(vc, xmin, ymin, xmax, ymax, NULL);
- if ((buf == NULL) || (bm_vertoffs == 0)) {
- return false;
- }
-
- dr = buf;
-
- /* build selection lookup */
- selbuf = edbm_backbuf_alloc(bm_vertoffs + 1);
- radsq = rads * rads;
- for (yc = -rads; yc <= rads; yc++) {
- for (xc = -rads; xc <= rads; xc++, dr++) {
- if (xc * xc + yc * yc < radsq) {
- if (*dr > 0 && *dr <= bm_vertoffs) {
- BLI_BITMAP_ENABLE(selbuf, *dr);
- }
- }
- }
- }
-
- MEM_freeN(buf);
- return true;
-
+ uint *buf, *dr;
+ short xmin, ymin, xmax, ymax, xc, yc;
+ int radsq;
+
+ /* method in use for face selecting too */
+ if (vc->obedit == NULL) {
+ if (!BKE_paint_select_elem_test(vc->obact)) {
+ return false;
+ }
+ }
+ else if (XRAY_FLAG_ENABLED(vc->v3d)) {
+ return false;
+ }
+
+ xmin = xs - rads;
+ xmax = xs + rads;
+ ymin = ys - rads;
+ ymax = ys + rads;
+ buf = ED_view3d_select_id_read(vc, xmin, ymin, xmax, ymax, NULL);
+ if ((buf == NULL) || (bm_vertoffs == 0)) {
+ return false;
+ }
+
+ dr = buf;
+
+ /* build selection lookup */
+ selbuf = edbm_backbuf_alloc(bm_vertoffs + 1);
+ radsq = rads * rads;
+ for (yc = -rads; yc <= rads; yc++) {
+ for (xc = -rads; xc <= rads; xc++, dr++) {
+ if (xc * xc + yc * yc < radsq) {
+ if (*dr > 0 && *dr <= bm_vertoffs) {
+ BLI_BITMAP_ENABLE(selbuf, *dr);
+ }
+ }
+ }
+ }
+
+ MEM_freeN(buf);
+ return true;
}
/** \} */
@@ -387,66 +388,69 @@ bool EDBM_backbuf_circle_init(
* \{ */
#define FAKE_SELECT_MODE_BEGIN(vc, fake_select_mode, select_mode, select_mode_required) \
- short select_mode = select_mode_required; \
- bool fake_select_mode = (select_mode & (vc)->scene->toolsettings->selectmode) == 0; \
- if (fake_select_mode) { \
- (vc)->v3d->flag |= V3D_INVALID_BACKBUF; \
- } ((void)0)
+ short select_mode = select_mode_required; \
+ bool fake_select_mode = (select_mode & (vc)->scene->toolsettings->selectmode) == 0; \
+ if (fake_select_mode) { \
+ (vc)->v3d->flag |= V3D_INVALID_BACKBUF; \
+ } \
+ ((void)0)
#define FAKE_SELECT_MODE_END(vc, fake_select_mode) \
- if (fake_select_mode) { \
- (vc)->v3d->flag |= V3D_INVALID_BACKBUF; \
- } ((void)0)
+ if (fake_select_mode) { \
+ (vc)->v3d->flag |= V3D_INVALID_BACKBUF; \
+ } \
+ ((void)0)
#define FIND_NEAR_SELECT_BIAS 5
#define FIND_NEAR_CYCLE_THRESHOLD_MIN 3
struct NearestVertUserData_Hit {
- float dist;
- float dist_bias;
- int index;
- BMVert *vert;
+ float dist;
+ float dist_bias;
+ int index;
+ BMVert *vert;
};
struct NearestVertUserData {
- float mval_fl[2];
- bool use_select_bias;
- bool use_cycle;
- int cycle_index_prev;
+ float mval_fl[2];
+ bool use_select_bias;
+ bool use_cycle;
+ int cycle_index_prev;
- struct NearestVertUserData_Hit hit;
- struct NearestVertUserData_Hit hit_cycle;
+ struct NearestVertUserData_Hit hit;
+ struct NearestVertUserData_Hit hit_cycle;
};
-static void findnearestvert__doClosest(void *userData, BMVert *eve, const float screen_co[2], int index)
+static void findnearestvert__doClosest(void *userData,
+ BMVert *eve,
+ const float screen_co[2],
+ int index)
{
- struct NearestVertUserData *data = userData;
- float dist_test, dist_test_bias;
-
- dist_test = dist_test_bias = len_manhattan_v2v2(data->mval_fl, screen_co);
-
- if (data->use_select_bias && BM_elem_flag_test(eve, BM_ELEM_SELECT)) {
- dist_test_bias += FIND_NEAR_SELECT_BIAS;
- }
-
- if (dist_test_bias < data->hit.dist_bias) {
- data->hit.dist_bias = dist_test_bias;
- data->hit.dist = dist_test;
- data->hit.index = index;
- data->hit.vert = eve;
- }
-
- if (data->use_cycle) {
- if ((data->hit_cycle.vert == NULL) &&
- (index > data->cycle_index_prev) &&
- (dist_test_bias < FIND_NEAR_CYCLE_THRESHOLD_MIN))
- {
- data->hit_cycle.dist_bias = dist_test_bias;
- data->hit_cycle.dist = dist_test;
- data->hit_cycle.index = index;
- data->hit_cycle.vert = eve;
- }
- }
+ struct NearestVertUserData *data = userData;
+ float dist_test, dist_test_bias;
+
+ dist_test = dist_test_bias = len_manhattan_v2v2(data->mval_fl, screen_co);
+
+ if (data->use_select_bias && BM_elem_flag_test(eve, BM_ELEM_SELECT)) {
+ dist_test_bias += FIND_NEAR_SELECT_BIAS;
+ }
+
+ if (dist_test_bias < data->hit.dist_bias) {
+ data->hit.dist_bias = dist_test_bias;
+ data->hit.dist = dist_test;
+ data->hit.index = index;
+ data->hit.vert = eve;
+ }
+
+ if (data->use_cycle) {
+ if ((data->hit_cycle.vert == NULL) && (index > data->cycle_index_prev) &&
+ (dist_test_bias < FIND_NEAR_CYCLE_THRESHOLD_MIN)) {
+ data->hit_cycle.dist_bias = dist_test_bias;
+ data->hit_cycle.dist = dist_test;
+ data->hit_cycle.index = index;
+ data->hit_cycle.vert = eve;
+ }
+ }
}
/**
@@ -458,618 +462,632 @@ static void findnearestvert__doClosest(void *userData, BMVert *eve, const float
* - When false, unselected vertices are given the bias.
* \param use_cycle: Cycle over elements within #FIND_NEAR_CYCLE_THRESHOLD_MIN in order of index.
*/
-BMVert *EDBM_vert_find_nearest_ex(
- ViewContext *vc, float *r_dist,
- const bool use_select_bias, bool use_cycle)
+BMVert *EDBM_vert_find_nearest_ex(ViewContext *vc,
+ float *r_dist,
+ const bool use_select_bias,
+ bool use_cycle)
{
- BMesh *bm = vc->em->bm;
-
- if (!XRAY_FLAG_ENABLED(vc->v3d)) {
- uint dist_px = (uint)ED_view3d_backbuf_sample_size_clamp(vc->ar, *r_dist);
- unsigned int index;
- BMVert *eve;
-
- /* No afterqueue (yet), so we check it now, otherwise the bm_xxxofs indices are bad. */
- {
- FAKE_SELECT_MODE_BEGIN(vc, fake_select_mode, select_mode, SCE_SELECT_VERTEX);
- ED_view3d_select_id_validate_with_select_mode(vc, select_mode);
-
- index = ED_view3d_select_id_read_nearest(vc, vc->mval, bm_wireoffs, 0xFFFFFF, &dist_px);
- eve = index ? BM_vert_at_index_find_or_table(bm, index - 1) : NULL;
-
- FAKE_SELECT_MODE_END(vc, fake_select_mode);
- }
-
- if (eve) {
- if (dist_px < *r_dist) {
- *r_dist = dist_px;
- return eve;
- }
- }
- return NULL;
- }
- else {
- struct NearestVertUserData data = {{0}};
- const struct NearestVertUserData_Hit *hit;
- const eV3DProjTest clip_flag = V3D_PROJ_TEST_CLIP_DEFAULT;
-
- static int prev_select_index = 0;
- static const BMVert *prev_select_elem = NULL;
-
- if ((use_cycle == false) ||
- (prev_select_elem && (prev_select_elem != BM_vert_at_index_find_or_table(bm, prev_select_index))))
- {
- prev_select_index = 0;
- prev_select_elem = NULL;
- }
-
- data.mval_fl[0] = vc->mval[0];
- data.mval_fl[1] = vc->mval[1];
- data.use_select_bias = use_select_bias;
- data.use_cycle = use_cycle;
- data.hit.dist = data.hit_cycle.dist = \
- data.hit.dist_bias = data.hit_cycle.dist_bias = *r_dist;
- data.cycle_index_prev = prev_select_index;
-
- ED_view3d_init_mats_rv3d(vc->obedit, vc->rv3d);
- mesh_foreachScreenVert(vc, findnearestvert__doClosest, &data, clip_flag);
-
- hit = (data.use_cycle && data.hit_cycle.vert) ? &data.hit_cycle : &data.hit;
- *r_dist = hit->dist;
-
- prev_select_elem = hit->vert;
- prev_select_index = hit->index;
-
- return hit->vert;
- }
+ BMesh *bm = vc->em->bm;
+
+ if (!XRAY_FLAG_ENABLED(vc->v3d)) {
+ uint dist_px = (uint)ED_view3d_backbuf_sample_size_clamp(vc->ar, *r_dist);
+ unsigned int index;
+ BMVert *eve;
+
+ /* No afterqueue (yet), so we check it now, otherwise the bm_xxxofs indices are bad. */
+ {
+ FAKE_SELECT_MODE_BEGIN (vc, fake_select_mode, select_mode, SCE_SELECT_VERTEX)
+ ;
+ ED_view3d_select_id_validate_with_select_mode(vc, select_mode);
+
+ index = ED_view3d_select_id_read_nearest(vc, vc->mval, bm_wireoffs, 0xFFFFFF, &dist_px);
+ eve = index ? BM_vert_at_index_find_or_table(bm, index - 1) : NULL;
+
+ FAKE_SELECT_MODE_END(vc, fake_select_mode);
+ }
+
+ if (eve) {
+ if (dist_px < *r_dist) {
+ *r_dist = dist_px;
+ return eve;
+ }
+ }
+ return NULL;
+ }
+ else {
+ struct NearestVertUserData data = {{0}};
+ const struct NearestVertUserData_Hit *hit;
+ const eV3DProjTest clip_flag = V3D_PROJ_TEST_CLIP_DEFAULT;
+
+ static int prev_select_index = 0;
+ static const BMVert *prev_select_elem = NULL;
+
+ if ((use_cycle == false) ||
+ (prev_select_elem &&
+ (prev_select_elem != BM_vert_at_index_find_or_table(bm, prev_select_index)))) {
+ prev_select_index = 0;
+ prev_select_elem = NULL;
+ }
+
+ data.mval_fl[0] = vc->mval[0];
+ data.mval_fl[1] = vc->mval[1];
+ data.use_select_bias = use_select_bias;
+ data.use_cycle = use_cycle;
+ data.hit.dist = data.hit_cycle.dist = data.hit.dist_bias = data.hit_cycle.dist_bias = *r_dist;
+ data.cycle_index_prev = prev_select_index;
+
+ ED_view3d_init_mats_rv3d(vc->obedit, vc->rv3d);
+ mesh_foreachScreenVert(vc, findnearestvert__doClosest, &data, clip_flag);
+
+ hit = (data.use_cycle && data.hit_cycle.vert) ? &data.hit_cycle : &data.hit;
+ *r_dist = hit->dist;
+
+ prev_select_elem = hit->vert;
+ prev_select_index = hit->index;
+
+ return hit->vert;
+ }
}
BMVert *EDBM_vert_find_nearest(ViewContext *vc, float *r_dist)
{
- return EDBM_vert_find_nearest_ex(vc, r_dist, false, false);
+ return EDBM_vert_find_nearest_ex(vc, r_dist, false, false);
}
/* find the distance to the edge we already have */
struct NearestEdgeUserData_ZBuf {
- float mval_fl[2];
- float dist;
- const BMEdge *edge_test;
+ float mval_fl[2];
+ float dist;
+ const BMEdge *edge_test;
};
-static void find_nearest_edge_center__doZBuf(
- void *userData, BMEdge *eed,
- const float screen_co_a[2], const float screen_co_b[2],
- int UNUSED(index))
+static void find_nearest_edge_center__doZBuf(void *userData,
+ BMEdge *eed,
+ const float screen_co_a[2],
+ const float screen_co_b[2],
+ int UNUSED(index))
{
- struct NearestEdgeUserData_ZBuf *data = userData;
+ struct NearestEdgeUserData_ZBuf *data = userData;
- if (eed == data->edge_test) {
- float dist_test;
- float screen_co_mid[2];
+ if (eed == data->edge_test) {
+ float dist_test;
+ float screen_co_mid[2];
- mid_v2_v2v2(screen_co_mid, screen_co_a, screen_co_b);
- dist_test = len_manhattan_v2v2(data->mval_fl, screen_co_mid);
+ mid_v2_v2v2(screen_co_mid, screen_co_a, screen_co_b);
+ dist_test = len_manhattan_v2v2(data->mval_fl, screen_co_mid);
- if (dist_test < data->dist) {
- data->dist = dist_test;
- }
- }
+ if (dist_test < data->dist) {
+ data->dist = dist_test;
+ }
+ }
}
struct NearestEdgeUserData_Hit {
- float dist;
- float dist_bias;
- int index;
- BMEdge *edge;
-
- /* edges only, un-biased manhatten distance to which ever edge we pick
- * (not used for choosing) */
- float dist_center;
+ float dist;
+ float dist_bias;
+ int index;
+ BMEdge *edge;
+
+ /* edges only, un-biased manhatten distance to which ever edge we pick
+ * (not used for choosing) */
+ float dist_center;
};
struct NearestEdgeUserData {
- ViewContext vc;
- float mval_fl[2];
- bool use_select_bias;
- bool use_cycle;
- int cycle_index_prev;
-
- struct NearestEdgeUserData_Hit hit;
- struct NearestEdgeUserData_Hit hit_cycle;
+ ViewContext vc;
+ float mval_fl[2];
+ bool use_select_bias;
+ bool use_cycle;
+ int cycle_index_prev;
+
+ struct NearestEdgeUserData_Hit hit;
+ struct NearestEdgeUserData_Hit hit_cycle;
};
/* note; uses v3d, so needs active 3d window */
static void find_nearest_edge__doClosest(
- void *userData, BMEdge *eed,
- const float screen_co_a[2], const float screen_co_b[2],
- int index)
+ void *userData, BMEdge *eed, const float screen_co_a[2], const float screen_co_b[2], int index)
{
- struct NearestEdgeUserData *data = userData;
- float dist_test, dist_test_bias;
-
- float fac = line_point_factor_v2(data->mval_fl, screen_co_a, screen_co_b);
- float screen_co[2];
-
- if (fac <= 0.0f) {
- fac = 0.0f;
- copy_v2_v2(screen_co, screen_co_a);
- }
- else if (fac >= 1.0f) {
- fac = 1.0f;
- copy_v2_v2(screen_co, screen_co_b);
- }
- else {
- interp_v2_v2v2(screen_co, screen_co_a, screen_co_b, fac);
- }
-
- dist_test = dist_test_bias = len_manhattan_v2v2(data->mval_fl, screen_co);
-
- if (data->use_select_bias && BM_elem_flag_test(eed, BM_ELEM_SELECT)) {
- dist_test_bias += FIND_NEAR_SELECT_BIAS;
- }
-
- if (data->vc.rv3d->rflag & RV3D_CLIPPING) {
- float vec[3];
-
- interp_v3_v3v3(vec, eed->v1->co, eed->v2->co, fac);
- if (ED_view3d_clipping_test(data->vc.rv3d, vec, true)) {
- return;
- }
- }
-
- if (dist_test_bias < data->hit.dist_bias) {
- float screen_co_mid[2];
-
- data->hit.dist_bias = dist_test_bias;
- data->hit.dist = dist_test;
- data->hit.index = index;
- data->hit.edge = eed;
-
- mid_v2_v2v2(screen_co_mid, screen_co_a, screen_co_b);
- data->hit.dist_center = len_manhattan_v2v2(data->mval_fl, screen_co_mid);
- }
-
- if (data->use_cycle) {
- if ((data->hit_cycle.edge == NULL) &&
- (index > data->cycle_index_prev) &&
- (dist_test_bias < FIND_NEAR_CYCLE_THRESHOLD_MIN))
- {
- float screen_co_mid[2];
-
- data->hit_cycle.dist_bias = dist_test_bias;
- data->hit_cycle.dist = dist_test;
- data->hit_cycle.index = index;
- data->hit_cycle.edge = eed;
-
- mid_v2_v2v2(screen_co_mid, screen_co_a, screen_co_b);
- data->hit_cycle.dist_center = len_manhattan_v2v2(data->mval_fl, screen_co_mid);
- }
- }
+ struct NearestEdgeUserData *data = userData;
+ float dist_test, dist_test_bias;
+
+ float fac = line_point_factor_v2(data->mval_fl, screen_co_a, screen_co_b);
+ float screen_co[2];
+
+ if (fac <= 0.0f) {
+ fac = 0.0f;
+ copy_v2_v2(screen_co, screen_co_a);
+ }
+ else if (fac >= 1.0f) {
+ fac = 1.0f;
+ copy_v2_v2(screen_co, screen_co_b);
+ }
+ else {
+ interp_v2_v2v2(screen_co, screen_co_a, screen_co_b, fac);
+ }
+
+ dist_test = dist_test_bias = len_manhattan_v2v2(data->mval_fl, screen_co);
+
+ if (data->use_select_bias && BM_elem_flag_test(eed, BM_ELEM_SELECT)) {
+ dist_test_bias += FIND_NEAR_SELECT_BIAS;
+ }
+
+ if (data->vc.rv3d->rflag & RV3D_CLIPPING) {
+ float vec[3];
+
+ interp_v3_v3v3(vec, eed->v1->co, eed->v2->co, fac);
+ if (ED_view3d_clipping_test(data->vc.rv3d, vec, true)) {
+ return;
+ }
+ }
+
+ if (dist_test_bias < data->hit.dist_bias) {
+ float screen_co_mid[2];
+
+ data->hit.dist_bias = dist_test_bias;
+ data->hit.dist = dist_test;
+ data->hit.index = index;
+ data->hit.edge = eed;
+
+ mid_v2_v2v2(screen_co_mid, screen_co_a, screen_co_b);
+ data->hit.dist_center = len_manhattan_v2v2(data->mval_fl, screen_co_mid);
+ }
+
+ if (data->use_cycle) {
+ if ((data->hit_cycle.edge == NULL) && (index > data->cycle_index_prev) &&
+ (dist_test_bias < FIND_NEAR_CYCLE_THRESHOLD_MIN)) {
+ float screen_co_mid[2];
+
+ data->hit_cycle.dist_bias = dist_test_bias;
+ data->hit_cycle.dist = dist_test;
+ data->hit_cycle.index = index;
+ data->hit_cycle.edge = eed;
+
+ mid_v2_v2v2(screen_co_mid, screen_co_a, screen_co_b);
+ data->hit_cycle.dist_center = len_manhattan_v2v2(data->mval_fl, screen_co_mid);
+ }
+ }
}
-BMEdge *EDBM_edge_find_nearest_ex(
- ViewContext *vc, float *r_dist,
- float *r_dist_center,
- const bool use_select_bias, const bool use_cycle,
- BMEdge **r_eed_zbuf)
+BMEdge *EDBM_edge_find_nearest_ex(ViewContext *vc,
+ float *r_dist,
+ float *r_dist_center,
+ const bool use_select_bias,
+ const bool use_cycle,
+ BMEdge **r_eed_zbuf)
{
- BMesh *bm = vc->em->bm;
-
- if (!XRAY_FLAG_ENABLED(vc->v3d)) {
- uint dist_px = (uint)ED_view3d_backbuf_sample_size_clamp(vc->ar, *r_dist);
- unsigned int index;
- BMEdge *eed;
-
- /* No afterqueue (yet), so we check it now, otherwise the bm_xxxofs indices are bad. */
- {
- FAKE_SELECT_MODE_BEGIN(vc, fake_select_mode, select_mode, SCE_SELECT_EDGE);
- ED_view3d_select_id_validate_with_select_mode(vc, select_mode);
-
- index = ED_view3d_select_id_read_nearest(vc, vc->mval, bm_solidoffs, bm_wireoffs, &dist_px);
- eed = index ? BM_edge_at_index_find_or_table(bm, index - 1) : NULL;
-
- FAKE_SELECT_MODE_END(vc, fake_select_mode);
- }
-
- if (r_eed_zbuf) {
- *r_eed_zbuf = eed;
- }
-
- /* exception for faces (verts don't need this) */
- if (r_dist_center && eed) {
- struct NearestEdgeUserData_ZBuf data;
-
- data.mval_fl[0] = vc->mval[0];
- data.mval_fl[1] = vc->mval[1];
- data.dist = FLT_MAX;
- data.edge_test = eed;
-
- ED_view3d_init_mats_rv3d(vc->obedit, vc->rv3d);
-
- mesh_foreachScreenEdge(vc, find_nearest_edge_center__doZBuf, &data, V3D_PROJ_TEST_CLIP_DEFAULT);
-
- *r_dist_center = data.dist;
- }
- /* end exception */
-
- if (eed) {
- if (dist_px < *r_dist) {
- *r_dist = dist_px;
- return eed;
- }
- }
- return NULL;
- }
- else {
- struct NearestEdgeUserData data = {{0}};
- const struct NearestEdgeUserData_Hit *hit;
- /* interpolate along the edge before doing a clipping plane test */
- const eV3DProjTest clip_flag = V3D_PROJ_TEST_CLIP_DEFAULT & ~V3D_PROJ_TEST_CLIP_BB;
-
- static int prev_select_index = 0;
- static const BMEdge *prev_select_elem = NULL;
-
- if ((use_cycle == false) ||
- (prev_select_elem && (prev_select_elem != BM_edge_at_index_find_or_table(bm, prev_select_index))))
- {
- prev_select_index = 0;
- prev_select_elem = NULL;
- }
-
- data.vc = *vc;
- data.mval_fl[0] = vc->mval[0];
- data.mval_fl[1] = vc->mval[1];
- data.use_select_bias = use_select_bias;
- data.use_cycle = use_cycle;
- data.hit.dist = data.hit_cycle.dist = \
- data.hit.dist_bias = data.hit_cycle.dist_bias = *r_dist;
- data.cycle_index_prev = prev_select_index;
-
- ED_view3d_init_mats_rv3d(vc->obedit, vc->rv3d);
- mesh_foreachScreenEdge(vc, find_nearest_edge__doClosest, &data, clip_flag);
-
- hit = (data.use_cycle && data.hit_cycle.edge) ? &data.hit_cycle : &data.hit;
- *r_dist = hit->dist;
- if (r_dist_center) {
- *r_dist_center = hit->dist_center;
- }
-
- prev_select_elem = hit->edge;
- prev_select_index = hit->index;
-
- return hit->edge;
- }
+ BMesh *bm = vc->em->bm;
+
+ if (!XRAY_FLAG_ENABLED(vc->v3d)) {
+ uint dist_px = (uint)ED_view3d_backbuf_sample_size_clamp(vc->ar, *r_dist);
+ unsigned int index;
+ BMEdge *eed;
+
+ /* No afterqueue (yet), so we check it now, otherwise the bm_xxxofs indices are bad. */
+ {
+ FAKE_SELECT_MODE_BEGIN (vc, fake_select_mode, select_mode, SCE_SELECT_EDGE)
+ ;
+ ED_view3d_select_id_validate_with_select_mode(vc, select_mode);
+
+ index = ED_view3d_select_id_read_nearest(vc, vc->mval, bm_solidoffs, bm_wireoffs, &dist_px);
+ eed = index ? BM_edge_at_index_find_or_table(bm, index - 1) : NULL;
+
+ FAKE_SELECT_MODE_END(vc, fake_select_mode);
+ }
+
+ if (r_eed_zbuf) {
+ *r_eed_zbuf = eed;
+ }
+
+ /* exception for faces (verts don't need this) */
+ if (r_dist_center && eed) {
+ struct NearestEdgeUserData_ZBuf data;
+
+ data.mval_fl[0] = vc->mval[0];
+ data.mval_fl[1] = vc->mval[1];
+ data.dist = FLT_MAX;
+ data.edge_test = eed;
+
+ ED_view3d_init_mats_rv3d(vc->obedit, vc->rv3d);
+
+ mesh_foreachScreenEdge(
+ vc, find_nearest_edge_center__doZBuf, &data, V3D_PROJ_TEST_CLIP_DEFAULT);
+
+ *r_dist_center = data.dist;
+ }
+ /* end exception */
+
+ if (eed) {
+ if (dist_px < *r_dist) {
+ *r_dist = dist_px;
+ return eed;
+ }
+ }
+ return NULL;
+ }
+ else {
+ struct NearestEdgeUserData data = {{0}};
+ const struct NearestEdgeUserData_Hit *hit;
+ /* interpolate along the edge before doing a clipping plane test */
+ const eV3DProjTest clip_flag = V3D_PROJ_TEST_CLIP_DEFAULT & ~V3D_PROJ_TEST_CLIP_BB;
+
+ static int prev_select_index = 0;
+ static const BMEdge *prev_select_elem = NULL;
+
+ if ((use_cycle == false) ||
+ (prev_select_elem &&
+ (prev_select_elem != BM_edge_at_index_find_or_table(bm, prev_select_index)))) {
+ prev_select_index = 0;
+ prev_select_elem = NULL;
+ }
+
+ data.vc = *vc;
+ data.mval_fl[0] = vc->mval[0];
+ data.mval_fl[1] = vc->mval[1];
+ data.use_select_bias = use_select_bias;
+ data.use_cycle = use_cycle;
+ data.hit.dist = data.hit_cycle.dist = data.hit.dist_bias = data.hit_cycle.dist_bias = *r_dist;
+ data.cycle_index_prev = prev_select_index;
+
+ ED_view3d_init_mats_rv3d(vc->obedit, vc->rv3d);
+ mesh_foreachScreenEdge(vc, find_nearest_edge__doClosest, &data, clip_flag);
+
+ hit = (data.use_cycle && data.hit_cycle.edge) ? &data.hit_cycle : &data.hit;
+ *r_dist = hit->dist;
+ if (r_dist_center) {
+ *r_dist_center = hit->dist_center;
+ }
+
+ prev_select_elem = hit->edge;
+ prev_select_index = hit->index;
+
+ return hit->edge;
+ }
}
-BMEdge *EDBM_edge_find_nearest(
- ViewContext *vc, float *r_dist)
+BMEdge *EDBM_edge_find_nearest(ViewContext *vc, float *r_dist)
{
- return EDBM_edge_find_nearest_ex(vc, r_dist, NULL, false, false, NULL);
+ return EDBM_edge_find_nearest_ex(vc, r_dist, NULL, false, false, NULL);
}
/* find the distance to the face we already have */
struct NearestFaceUserData_ZBuf {
- float mval_fl[2];
- float dist;
- const BMFace *face_test;
+ float mval_fl[2];
+ float dist;
+ const BMFace *face_test;
};
-static void find_nearest_face_center__doZBuf(void *userData, BMFace *efa, const float screen_co[2], int UNUSED(index))
+static void find_nearest_face_center__doZBuf(void *userData,
+ BMFace *efa,
+ const float screen_co[2],
+ int UNUSED(index))
{
- struct NearestFaceUserData_ZBuf *data = userData;
+ struct NearestFaceUserData_ZBuf *data = userData;
- if (efa == data->face_test) {
- const float dist_test = len_manhattan_v2v2(data->mval_fl, screen_co);
+ if (efa == data->face_test) {
+ const float dist_test = len_manhattan_v2v2(data->mval_fl, screen_co);
- if (dist_test < data->dist) {
- data->dist = dist_test;
- }
- }
+ if (dist_test < data->dist) {
+ data->dist = dist_test;
+ }
+ }
}
-
struct NearestFaceUserData_Hit {
- float dist;
- float dist_bias;
- int index;
- BMFace *face;
+ float dist;
+ float dist_bias;
+ int index;
+ BMFace *face;
};
struct NearestFaceUserData {
- float mval_fl[2];
- bool use_select_bias;
- bool use_cycle;
- int cycle_index_prev;
+ float mval_fl[2];
+ bool use_select_bias;
+ bool use_cycle;
+ int cycle_index_prev;
- struct NearestFaceUserData_Hit hit;
- struct NearestFaceUserData_Hit hit_cycle;
+ struct NearestFaceUserData_Hit hit;
+ struct NearestFaceUserData_Hit hit_cycle;
};
-static void findnearestface__doClosest(void *userData, BMFace *efa, const float screen_co[2], int index)
+static void findnearestface__doClosest(void *userData,
+ BMFace *efa,
+ const float screen_co[2],
+ int index)
{
- struct NearestFaceUserData *data = userData;
- float dist_test, dist_test_bias;
-
- dist_test = dist_test_bias = len_manhattan_v2v2(data->mval_fl, screen_co);
-
- if (data->use_select_bias && BM_elem_flag_test(efa, BM_ELEM_SELECT)) {
- dist_test_bias += FIND_NEAR_SELECT_BIAS;
- }
-
- if (dist_test_bias < data->hit.dist_bias) {
- data->hit.dist_bias = dist_test_bias;
- data->hit.dist = dist_test;
- data->hit.index = index;
- data->hit.face = efa;
- }
-
- if (data->use_cycle) {
- if ((data->hit_cycle.face == NULL) &&
- (index > data->cycle_index_prev) &&
- (dist_test_bias < FIND_NEAR_CYCLE_THRESHOLD_MIN))
- {
- data->hit_cycle.dist_bias = dist_test_bias;
- data->hit_cycle.dist = dist_test;
- data->hit_cycle.index = index;
- data->hit_cycle.face = efa;
- }
- }
+ struct NearestFaceUserData *data = userData;
+ float dist_test, dist_test_bias;
+
+ dist_test = dist_test_bias = len_manhattan_v2v2(data->mval_fl, screen_co);
+
+ if (data->use_select_bias && BM_elem_flag_test(efa, BM_ELEM_SELECT)) {
+ dist_test_bias += FIND_NEAR_SELECT_BIAS;
+ }
+
+ if (dist_test_bias < data->hit.dist_bias) {
+ data->hit.dist_bias = dist_test_bias;
+ data->hit.dist = dist_test;
+ data->hit.index = index;
+ data->hit.face = efa;
+ }
+
+ if (data->use_cycle) {
+ if ((data->hit_cycle.face == NULL) && (index > data->cycle_index_prev) &&
+ (dist_test_bias < FIND_NEAR_CYCLE_THRESHOLD_MIN)) {
+ data->hit_cycle.dist_bias = dist_test_bias;
+ data->hit_cycle.dist = dist_test;
+ data->hit_cycle.index = index;
+ data->hit_cycle.face = efa;
+ }
+ }
}
-
-BMFace *EDBM_face_find_nearest_ex(
- ViewContext *vc, float *r_dist,
- float *r_dist_center,
- const bool use_select_bias, const bool use_cycle,
- BMFace **r_efa_zbuf)
+BMFace *EDBM_face_find_nearest_ex(ViewContext *vc,
+ float *r_dist,
+ float *r_dist_center,
+ const bool use_select_bias,
+ const bool use_cycle,
+ BMFace **r_efa_zbuf)
{
- BMesh *bm = vc->em->bm;
-
- if (!XRAY_FLAG_ENABLED(vc->v3d)) {
- float dist_test = 0.0f;
- unsigned int index;
- BMFace *efa;
-
- {
- FAKE_SELECT_MODE_BEGIN(vc, fake_select_mode, select_mode, SCE_SELECT_FACE);
- ED_view3d_select_id_validate_with_select_mode(vc, select_mode);
-
- index = ED_view3d_select_id_sample(vc, vc->mval[0], vc->mval[1]);
- efa = index ? BM_face_at_index_find_or_table(bm, index - 1) : NULL;
-
- FAKE_SELECT_MODE_END(vc, fake_select_mode);
- }
-
- if (r_efa_zbuf) {
- *r_efa_zbuf = efa;
- }
-
- /* exception for faces (verts don't need this) */
- if (r_dist_center && efa) {
- struct NearestFaceUserData_ZBuf data;
-
- data.mval_fl[0] = vc->mval[0];
- data.mval_fl[1] = vc->mval[1];
- data.dist = FLT_MAX;
- data.face_test = efa;
-
- ED_view3d_init_mats_rv3d(vc->obedit, vc->rv3d);
-
- mesh_foreachScreenFace(vc, find_nearest_face_center__doZBuf, &data, V3D_PROJ_TEST_CLIP_DEFAULT);
-
- *r_dist_center = data.dist;
- }
- /* end exception */
-
- if (efa) {
- if (dist_test < *r_dist) {
- *r_dist = dist_test;
- return efa;
- }
- }
- return NULL;
- }
- else {
- struct NearestFaceUserData data = {{0}};
- const struct NearestFaceUserData_Hit *hit;
- const eV3DProjTest clip_flag = V3D_PROJ_TEST_CLIP_DEFAULT;
-
- static int prev_select_index = 0;
- static const BMFace *prev_select_elem = NULL;
-
- if ((use_cycle == false) ||
- (prev_select_elem && (prev_select_elem != BM_face_at_index_find_or_table(bm, prev_select_index))))
- {
- prev_select_index = 0;
- prev_select_elem = NULL;
- }
-
- data.mval_fl[0] = vc->mval[0];
- data.mval_fl[1] = vc->mval[1];
- data.use_select_bias = use_select_bias;
- data.use_cycle = use_cycle;
- data.hit.dist = data.hit_cycle.dist = \
- data.hit.dist_bias = data.hit_cycle.dist_bias = *r_dist;
- data.cycle_index_prev = prev_select_index;
-
- ED_view3d_init_mats_rv3d(vc->obedit, vc->rv3d);
- mesh_foreachScreenFace(vc, findnearestface__doClosest, &data, clip_flag);
-
- hit = (data.use_cycle && data.hit_cycle.face) ? &data.hit_cycle : &data.hit;
- *r_dist = hit->dist;
- if (r_dist_center) {
- *r_dist_center = hit->dist;
- }
-
- prev_select_elem = hit->face;
- prev_select_index = hit->index;
-
- return hit->face;
- }
+ BMesh *bm = vc->em->bm;
+
+ if (!XRAY_FLAG_ENABLED(vc->v3d)) {
+ float dist_test = 0.0f;
+ unsigned int index;
+ BMFace *efa;
+
+ {
+ FAKE_SELECT_MODE_BEGIN (vc, fake_select_mode, select_mode, SCE_SELECT_FACE)
+ ;
+ ED_view3d_select_id_validate_with_select_mode(vc, select_mode);
+
+ index = ED_view3d_select_id_sample(vc, vc->mval[0], vc->mval[1]);
+ efa = index ? BM_face_at_index_find_or_table(bm, index - 1) : NULL;
+
+ FAKE_SELECT_MODE_END(vc, fake_select_mode);
+ }
+
+ if (r_efa_zbuf) {
+ *r_efa_zbuf = efa;
+ }
+
+ /* exception for faces (verts don't need this) */
+ if (r_dist_center && efa) {
+ struct NearestFaceUserData_ZBuf data;
+
+ data.mval_fl[0] = vc->mval[0];
+ data.mval_fl[1] = vc->mval[1];
+ data.dist = FLT_MAX;
+ data.face_test = efa;
+
+ ED_view3d_init_mats_rv3d(vc->obedit, vc->rv3d);
+
+ mesh_foreachScreenFace(
+ vc, find_nearest_face_center__doZBuf, &data, V3D_PROJ_TEST_CLIP_DEFAULT);
+
+ *r_dist_center = data.dist;
+ }
+ /* end exception */
+
+ if (efa) {
+ if (dist_test < *r_dist) {
+ *r_dist = dist_test;
+ return efa;
+ }
+ }
+ return NULL;
+ }
+ else {
+ struct NearestFaceUserData data = {{0}};
+ const struct NearestFaceUserData_Hit *hit;
+ const eV3DProjTest clip_flag = V3D_PROJ_TEST_CLIP_DEFAULT;
+
+ static int prev_select_index = 0;
+ static const BMFace *prev_select_elem = NULL;
+
+ if ((use_cycle == false) ||
+ (prev_select_elem &&
+ (prev_select_elem != BM_face_at_index_find_or_table(bm, prev_select_index)))) {
+ prev_select_index = 0;
+ prev_select_elem = NULL;
+ }
+
+ data.mval_fl[0] = vc->mval[0];
+ data.mval_fl[1] = vc->mval[1];
+ data.use_select_bias = use_select_bias;
+ data.use_cycle = use_cycle;
+ data.hit.dist = data.hit_cycle.dist = data.hit.dist_bias = data.hit_cycle.dist_bias = *r_dist;
+ data.cycle_index_prev = prev_select_index;
+
+ ED_view3d_init_mats_rv3d(vc->obedit, vc->rv3d);
+ mesh_foreachScreenFace(vc, findnearestface__doClosest, &data, clip_flag);
+
+ hit = (data.use_cycle && data.hit_cycle.face) ? &data.hit_cycle : &data.hit;
+ *r_dist = hit->dist;
+ if (r_dist_center) {
+ *r_dist_center = hit->dist;
+ }
+
+ prev_select_elem = hit->face;
+ prev_select_index = hit->index;
+
+ return hit->face;
+ }
}
BMFace *EDBM_face_find_nearest(ViewContext *vc, float *r_dist)
{
- return EDBM_face_find_nearest_ex(vc, r_dist, NULL, false, false, NULL);
+ return EDBM_face_find_nearest_ex(vc, r_dist, NULL, false, false, NULL);
}
#undef FIND_NEAR_SELECT_BIAS
#undef FIND_NEAR_CYCLE_THRESHOLD_MIN
-
/* best distance based on screen coords.
* use em->selectmode to define how to use
* selected vertices and edges get disadvantage
* return 1 if found one
*/
-static bool unified_findnearest(
- ViewContext *vc, Base **bases, const uint bases_len,
- int *r_base_index, BMVert **r_eve, BMEdge **r_eed, BMFace **r_efa)
+static bool unified_findnearest(ViewContext *vc,
+ Base **bases,
+ const uint bases_len,
+ int *r_base_index,
+ BMVert **r_eve,
+ BMEdge **r_eed,
+ BMFace **r_efa)
{
- BMEditMesh *em = vc->em;
- static short mval_prev[2] = {-1, -1};
- /* only cycle while the mouse remains still */
- const bool use_cycle = ((mval_prev[0] == vc->mval[0]) && (mval_prev[1] == vc->mval[1]));
- const float dist_init = ED_view3d_select_dist_px();
- /* since edges select lines, we give dots advantage of ~20 pix */
- const float dist_margin = (dist_init / 2);
- float dist = dist_init;
-
- struct {
- struct {
- BMVert *ele;
- int base_index;
- } v;
- struct {
- BMEdge *ele;
- int base_index;
- } e, e_zbuf;
- struct {
- BMFace *ele;
- int base_index;
- } f, f_zbuf;
- } hit = {{NULL}};
-
- /* TODO(campbell): perform selection as one pass
- * instead of many smaller passes (which doesn't work for zbuf occlusion). */
-
- /* no afterqueue (yet), so we check it now, otherwise the em_xxxofs indices are bad */
-
- if ((dist > 0.0f) && em->selectmode & SCE_SELECT_FACE) {
- float dist_center = 0.0f;
- float *dist_center_p = (em->selectmode & (SCE_SELECT_EDGE | SCE_SELECT_VERTEX)) ? &dist_center : NULL;
-
- for (uint base_index = 0; base_index < bases_len; base_index++) {
- Base *base_iter = bases[base_index];
- Object *obedit = base_iter->object;
- ED_view3d_viewcontext_init_object(vc, obedit);
- BLI_assert(vc->em->selectmode == em->selectmode);
- BMFace *efa_zbuf = NULL;
- BMFace *efa_test = EDBM_face_find_nearest_ex(vc, &dist, dist_center_p, true, use_cycle, &efa_zbuf);
- if (efa_test && dist_center_p) {
- dist = min_ff(dist_margin, dist_center);
- }
- if (efa_test) {
- hit.f.base_index = base_index;
- hit.f.ele = efa_test;
- }
- if (efa_zbuf) {
- hit.f_zbuf.base_index = base_index;
- hit.f_zbuf.ele = efa_zbuf;
- }
- } /* bases */
- }
-
- if ((dist > 0.0f) && (em->selectmode & SCE_SELECT_EDGE)) {
- float dist_center = 0.0f;
- float *dist_center_p = (em->selectmode & SCE_SELECT_VERTEX) ? &dist_center : NULL;
-
- for (uint base_index = 0; base_index < bases_len; base_index++) {
- Base *base_iter = bases[base_index];
- Object *obedit = base_iter->object;
- ED_view3d_viewcontext_init_object(vc, obedit);
- BMEdge *eed_zbuf = NULL;
- BMEdge *eed_test = EDBM_edge_find_nearest_ex(vc, &dist, dist_center_p, true, use_cycle, &eed_zbuf);
- if (eed_test && dist_center_p) {
- dist = min_ff(dist_margin, dist_center);
- }
- if (eed_test) {
- hit.e.base_index = base_index;
- hit.e.ele = eed_test;
- }
- if (eed_zbuf) {
- hit.e_zbuf.base_index = base_index;
- hit.e_zbuf.ele = eed_zbuf;
- }
- } /* bases */
- }
-
- if ((dist > 0.0f) && em->selectmode & SCE_SELECT_VERTEX) {
- for (uint base_index = 0; base_index < bases_len; base_index++) {
- Base *base_iter = bases[base_index];
- Object *obedit = base_iter->object;
- ED_view3d_viewcontext_init_object(vc, obedit);
- BMVert *eve_test = EDBM_vert_find_nearest_ex(vc, &dist, true, use_cycle);
- if (eve_test) {
- hit.v.base_index = base_index;
- hit.v.ele = eve_test;
- }
- } /* bases */
- }
-
- /* return only one of 3 pointers, for frontbuffer redraws */
- if (hit.v.ele) {
- hit.f.ele = NULL;
- hit.e.ele = NULL;
- }
- else if (hit.e.ele) {
- hit.f.ele = NULL;
- }
-
- /* there may be a face under the cursor, who's center if too far away
- * use this if all else fails, it makes sense to select this */
- if ((hit.v.ele || hit.e.ele || hit.f.ele) == 0) {
- if (hit.e_zbuf.ele) {
- hit.e.base_index = hit.e_zbuf.base_index;
- hit.e.ele = hit.e_zbuf.ele;
- }
- else if (hit.f_zbuf.ele) {
- hit.f.base_index = hit.f_zbuf.base_index;
- hit.f.ele = hit.f_zbuf.ele;
- }
- }
-
- mval_prev[0] = vc->mval[0];
- mval_prev[1] = vc->mval[1];
-
- /* Only one element type will be non-null. */
- BLI_assert(((hit.v.ele != NULL) + (hit.e.ele != NULL) + (hit.f.ele != NULL)) <= 1);
-
- if (hit.v.ele) {
- *r_base_index = hit.v.base_index;
- }
- if (hit.e.ele) {
- *r_base_index = hit.e.base_index;
- }
- if (hit.f.ele) {
- *r_base_index = hit.f.base_index;
- }
-
- *r_eve = hit.v.ele;
- *r_eed = hit.e.ele;
- *r_efa = hit.f.ele;
-
- return (hit.v.ele || hit.e.ele || hit.f.ele);
+ BMEditMesh *em = vc->em;
+ static short mval_prev[2] = {-1, -1};
+ /* only cycle while the mouse remains still */
+ const bool use_cycle = ((mval_prev[0] == vc->mval[0]) && (mval_prev[1] == vc->mval[1]));
+ const float dist_init = ED_view3d_select_dist_px();
+ /* since edges select lines, we give dots advantage of ~20 pix */
+ const float dist_margin = (dist_init / 2);
+ float dist = dist_init;
+
+ struct {
+ struct {
+ BMVert *ele;
+ int base_index;
+ } v;
+ struct {
+ BMEdge *ele;
+ int base_index;
+ } e, e_zbuf;
+ struct {
+ BMFace *ele;
+ int base_index;
+ } f, f_zbuf;
+ } hit = {{NULL}};
+
+ /* TODO(campbell): perform selection as one pass
+ * instead of many smaller passes (which doesn't work for zbuf occlusion). */
+
+ /* no afterqueue (yet), so we check it now, otherwise the em_xxxofs indices are bad */
+
+ if ((dist > 0.0f) && em->selectmode & SCE_SELECT_FACE) {
+ float dist_center = 0.0f;
+ float *dist_center_p = (em->selectmode & (SCE_SELECT_EDGE | SCE_SELECT_VERTEX)) ?
+ &dist_center :
+ NULL;
+
+ for (uint base_index = 0; base_index < bases_len; base_index++) {
+ Base *base_iter = bases[base_index];
+ Object *obedit = base_iter->object;
+ ED_view3d_viewcontext_init_object(vc, obedit);
+ BLI_assert(vc->em->selectmode == em->selectmode);
+ BMFace *efa_zbuf = NULL;
+ BMFace *efa_test = EDBM_face_find_nearest_ex(
+ vc, &dist, dist_center_p, true, use_cycle, &efa_zbuf);
+ if (efa_test && dist_center_p) {
+ dist = min_ff(dist_margin, dist_center);
+ }
+ if (efa_test) {
+ hit.f.base_index = base_index;
+ hit.f.ele = efa_test;
+ }
+ if (efa_zbuf) {
+ hit.f_zbuf.base_index = base_index;
+ hit.f_zbuf.ele = efa_zbuf;
+ }
+ } /* bases */
+ }
+
+ if ((dist > 0.0f) && (em->selectmode & SCE_SELECT_EDGE)) {
+ float dist_center = 0.0f;
+ float *dist_center_p = (em->selectmode & SCE_SELECT_VERTEX) ? &dist_center : NULL;
+
+ for (uint base_index = 0; base_index < bases_len; base_index++) {
+ Base *base_iter = bases[base_index];
+ Object *obedit = base_iter->object;
+ ED_view3d_viewcontext_init_object(vc, obedit);
+ BMEdge *eed_zbuf = NULL;
+ BMEdge *eed_test = EDBM_edge_find_nearest_ex(
+ vc, &dist, dist_center_p, true, use_cycle, &eed_zbuf);
+ if (eed_test && dist_center_p) {
+ dist = min_ff(dist_margin, dist_center);
+ }
+ if (eed_test) {
+ hit.e.base_index = base_index;
+ hit.e.ele = eed_test;
+ }
+ if (eed_zbuf) {
+ hit.e_zbuf.base_index = base_index;
+ hit.e_zbuf.ele = eed_zbuf;
+ }
+ } /* bases */
+ }
+
+ if ((dist > 0.0f) && em->selectmode & SCE_SELECT_VERTEX) {
+ for (uint base_index = 0; base_index < bases_len; base_index++) {
+ Base *base_iter = bases[base_index];
+ Object *obedit = base_iter->object;
+ ED_view3d_viewcontext_init_object(vc, obedit);
+ BMVert *eve_test = EDBM_vert_find_nearest_ex(vc, &dist, true, use_cycle);
+ if (eve_test) {
+ hit.v.base_index = base_index;
+ hit.v.ele = eve_test;
+ }
+ } /* bases */
+ }
+
+ /* return only one of 3 pointers, for frontbuffer redraws */
+ if (hit.v.ele) {
+ hit.f.ele = NULL;
+ hit.e.ele = NULL;
+ }
+ else if (hit.e.ele) {
+ hit.f.ele = NULL;
+ }
+
+ /* there may be a face under the cursor, who's center if too far away
+ * use this if all else fails, it makes sense to select this */
+ if ((hit.v.ele || hit.e.ele || hit.f.ele) == 0) {
+ if (hit.e_zbuf.ele) {
+ hit.e.base_index = hit.e_zbuf.base_index;
+ hit.e.ele = hit.e_zbuf.ele;
+ }
+ else if (hit.f_zbuf.ele) {
+ hit.f.base_index = hit.f_zbuf.base_index;
+ hit.f.ele = hit.f_zbuf.ele;
+ }
+ }
+
+ mval_prev[0] = vc->mval[0];
+ mval_prev[1] = vc->mval[1];
+
+ /* Only one element type will be non-null. */
+ BLI_assert(((hit.v.ele != NULL) + (hit.e.ele != NULL) + (hit.f.ele != NULL)) <= 1);
+
+ if (hit.v.ele) {
+ *r_base_index = hit.v.base_index;
+ }
+ if (hit.e.ele) {
+ *r_base_index = hit.e.base_index;
+ }
+ if (hit.f.ele) {
+ *r_base_index = hit.f.base_index;
+ }
+
+ *r_eve = hit.v.ele;
+ *r_eed = hit.e.ele;
+ *r_efa = hit.f.ele;
+
+ return (hit.v.ele || hit.e.ele || hit.f.ele);
}
#undef FAKE_SELECT_MODE_BEGIN
#undef FAKE_SELECT_MODE_END
-bool EDBM_unified_findnearest(
- ViewContext *vc, Base **bases, const uint bases_len,
- int *r_base_index, BMVert **r_eve, BMEdge **r_eed, BMFace **r_efa)
+bool EDBM_unified_findnearest(ViewContext *vc,
+ Base **bases,
+ const uint bases_len,
+ int *r_base_index,
+ BMVert **r_eve,
+ BMEdge **r_eed,
+ BMFace **r_efa)
{
- return unified_findnearest(vc, bases, bases_len, r_base_index, r_eve, r_eed, r_efa);
+ return unified_findnearest(vc, bases, bases_len, r_base_index, r_eve, r_eed, r_efa);
}
/** \} */
@@ -1081,205 +1099,202 @@ bool EDBM_unified_findnearest(
* currently used for poly-build.
* \{ */
-bool EDBM_unified_findnearest_from_raycast(
- ViewContext *vc,
- Base **bases, const uint bases_len,
- bool use_boundary,
- int *r_base_index,
- struct BMVert **r_eve,
- struct BMEdge **r_eed,
- struct BMFace **r_efa)
+bool EDBM_unified_findnearest_from_raycast(ViewContext *vc,
+ Base **bases,
+ const uint bases_len,
+ bool use_boundary,
+ int *r_base_index,
+ struct BMVert **r_eve,
+ struct BMEdge **r_eed,
+ struct BMFace **r_efa)
{
- const float mval_fl[2] = {UNPACK2(vc->mval)};
- float ray_origin[3], ray_direction[3];
-
- struct {
- uint base_index;
- BMElem *ele;
- } best = {0, NULL};
-
- if (ED_view3d_win_to_ray_clipped(
- vc->depsgraph,
- vc->ar, vc->v3d, mval_fl,
- ray_origin, ray_direction, true))
- {
- float dist_sq_best = FLT_MAX;
-
- const bool use_vert = (r_eve != NULL);
- const bool use_edge = (r_eed != NULL);
- const bool use_face = (r_efa != NULL);
-
- for (uint base_index = 0; base_index < bases_len; base_index++) {
- Base *base_iter = bases[base_index];
- Object *obedit = base_iter->object;
-
- BMEditMesh *em = BKE_editmesh_from_object(obedit);
- BMesh *bm = em->bm;
- float imat3[3][3];
-
- ED_view3d_viewcontext_init_object(vc, obedit);
- copy_m3_m4(imat3, obedit->obmat);
- invert_m3(imat3);
-
- const float (*coords)[3] = NULL;
- {
- Mesh *me_eval = (Mesh *)DEG_get_evaluated_id(vc->depsgraph, obedit->data);
- if (me_eval->runtime.edit_data) {
- coords = me_eval->runtime.edit_data->vertexCos;
- }
- }
-
- if (coords != NULL) {
- BM_mesh_elem_index_ensure(bm, BM_VERT);
- }
-
- if (use_boundary && (use_vert || use_edge)) {
- BMEdge *e;
- BMIter eiter;
- BM_ITER_MESH (e, &eiter, bm, BM_EDGES_OF_MESH) {
- if ((BM_elem_flag_test(e, BM_ELEM_HIDDEN) == false) &&
- (BM_edge_is_boundary(e)))
- {
- if (use_vert) {
- for (uint j = 0; j < 2; j++) {
- BMVert *v = *((&e->v1) + j);
- float point[3];
- mul_v3_m4v3(point, obedit->obmat, coords ? coords[BM_elem_index_get(v)] : v->co);
- const float dist_sq_test = dist_squared_to_ray_v3_normalized(
- ray_origin, ray_direction, point);
- if (dist_sq_test < dist_sq_best) {
- dist_sq_best = dist_sq_test;
- best.base_index = base_index;
- best.ele = (BMElem *)v;
- }
- }
- }
-
- if (use_edge) {
- float point[3];
+ const float mval_fl[2] = {UNPACK2(vc->mval)};
+ float ray_origin[3], ray_direction[3];
+
+ struct {
+ uint base_index;
+ BMElem *ele;
+ } best = {0, NULL};
+
+ if (ED_view3d_win_to_ray_clipped(
+ vc->depsgraph, vc->ar, vc->v3d, mval_fl, ray_origin, ray_direction, true)) {
+ float dist_sq_best = FLT_MAX;
+
+ const bool use_vert = (r_eve != NULL);
+ const bool use_edge = (r_eed != NULL);
+ const bool use_face = (r_efa != NULL);
+
+ for (uint base_index = 0; base_index < bases_len; base_index++) {
+ Base *base_iter = bases[base_index];
+ Object *obedit = base_iter->object;
+
+ BMEditMesh *em = BKE_editmesh_from_object(obedit);
+ BMesh *bm = em->bm;
+ float imat3[3][3];
+
+ ED_view3d_viewcontext_init_object(vc, obedit);
+ copy_m3_m4(imat3, obedit->obmat);
+ invert_m3(imat3);
+
+ const float(*coords)[3] = NULL;
+ {
+ Mesh *me_eval = (Mesh *)DEG_get_evaluated_id(vc->depsgraph, obedit->data);
+ if (me_eval->runtime.edit_data) {
+ coords = me_eval->runtime.edit_data->vertexCos;
+ }
+ }
+
+ if (coords != NULL) {
+ BM_mesh_elem_index_ensure(bm, BM_VERT);
+ }
+
+ if (use_boundary && (use_vert || use_edge)) {
+ BMEdge *e;
+ BMIter eiter;
+ BM_ITER_MESH (e, &eiter, bm, BM_EDGES_OF_MESH) {
+ if ((BM_elem_flag_test(e, BM_ELEM_HIDDEN) == false) && (BM_edge_is_boundary(e))) {
+ if (use_vert) {
+ for (uint j = 0; j < 2; j++) {
+ BMVert *v = *((&e->v1) + j);
+ float point[3];
+ mul_v3_m4v3(point, obedit->obmat, coords ? coords[BM_elem_index_get(v)] : v->co);
+ const float dist_sq_test = dist_squared_to_ray_v3_normalized(
+ ray_origin, ray_direction, point);
+ if (dist_sq_test < dist_sq_best) {
+ dist_sq_best = dist_sq_test;
+ best.base_index = base_index;
+ best.ele = (BMElem *)v;
+ }
+ }
+ }
+
+ if (use_edge) {
+ float point[3];
#if 0
- const float dist_sq_test = dist_squared_ray_to_seg_v3(
- ray_origin, ray_direction,
- e->v1->co, e->v2->co,
- point, &depth);
+ const float dist_sq_test = dist_squared_ray_to_seg_v3(
+ ray_origin, ray_direction,
+ e->v1->co, e->v2->co,
+ point, &depth);
#else
- if (coords) {
- mid_v3_v3v3(point, coords[BM_elem_index_get(e->v1)], coords[BM_elem_index_get(e->v2)]);
- }
- else {
- mid_v3_v3v3(point, e->v1->co, e->v2->co);
- }
- mul_m4_v3(obedit->obmat, point);
- const float dist_sq_test = dist_squared_to_ray_v3_normalized(
- ray_origin, ray_direction, point);
- if (dist_sq_test < dist_sq_best) {
- dist_sq_best = dist_sq_test;
- best.base_index = base_index;
- best.ele = (BMElem *)e;
- }
+ if (coords) {
+ mid_v3_v3v3(
+ point, coords[BM_elem_index_get(e->v1)], coords[BM_elem_index_get(e->v2)]);
+ }
+ else {
+ mid_v3_v3v3(point, e->v1->co, e->v2->co);
+ }
+ mul_m4_v3(obedit->obmat, point);
+ const float dist_sq_test = dist_squared_to_ray_v3_normalized(
+ ray_origin, ray_direction, point);
+ if (dist_sq_test < dist_sq_best) {
+ dist_sq_best = dist_sq_test;
+ best.base_index = base_index;
+ best.ele = (BMElem *)e;
+ }
#endif
- }
- }
- }
- }
- else {
- /* Non boundary case. */
- if (use_vert) {
- BMVert *v;
- BMIter viter;
- BM_ITER_MESH (v, &viter, bm, BM_VERTS_OF_MESH) {
- if (BM_elem_flag_test(v, BM_ELEM_HIDDEN) == false) {
- float point[3];
- mul_v3_m4v3(point, obedit->obmat, v->co);
- const float dist_sq_test = dist_squared_to_ray_v3_normalized(
- ray_origin, ray_direction, v->co);
- if (dist_sq_test < dist_sq_best) {
- dist_sq_best = dist_sq_test;
- best.base_index = base_index;
- best.ele = (BMElem *)v;
- }
- }
- }
- }
- if (use_edge) {
- BMEdge *e;
- BMIter eiter;
- BM_ITER_MESH (e, &eiter, bm, BM_EDGES_OF_MESH) {
- if (BM_elem_flag_test(e, BM_ELEM_HIDDEN) == false) {
- float point[3];
- if (coords) {
- mid_v3_v3v3(point, coords[BM_elem_index_get(e->v1)], coords[BM_elem_index_get(e->v2)]);
- }
- else {
- mid_v3_v3v3(point, e->v1->co, e->v2->co);
- }
- mul_m4_v3(obedit->obmat, point);
- const float dist_sq_test = dist_squared_to_ray_v3_normalized(
- ray_origin, ray_direction, point);
- if (dist_sq_test < dist_sq_best) {
- dist_sq_best = dist_sq_test;
- best.base_index = base_index;
- best.ele = (BMElem *)e;
- }
- }
- }
- }
- }
-
- if (use_face) {
- BMFace *f;
- BMIter fiter;
- BM_ITER_MESH (f, &fiter, bm, BM_FACES_OF_MESH) {
- if (BM_elem_flag_test(f, BM_ELEM_HIDDEN) == false) {
- float point[3];
- if (coords) {
- BM_face_calc_center_median_vcos(bm, f, point, coords);
- }
- else {
- BM_face_calc_center_median(f, point);
- }
- mul_m4_v3(obedit->obmat, point);
- const float dist_sq_test = dist_squared_to_ray_v3_normalized(
- ray_origin, ray_direction, point);
- if (dist_sq_test < dist_sq_best) {
- dist_sq_best = dist_sq_test;
- best.base_index = base_index;
- best.ele = (BMElem *)f;
- }
- }
- }
- }
- }
- }
-
- *r_base_index = best.base_index;
- if (r_eve) {
- *r_eve = NULL;
- }
- if (r_eed) {
- *r_eed = NULL;
- }
- if (r_efa) {
- *r_efa = NULL;
- }
-
- if (best.ele) {
- switch (best.ele->head.htype) {
- case BM_VERT:
- *r_eve = (BMVert *)best.ele;
- break;
- case BM_EDGE:
- *r_eed = (BMEdge *)best.ele;
- break;
- case BM_FACE:
- *r_efa = (BMFace *)best.ele;
- break;
- default:
- BLI_assert(0);
- }
- }
- return (best.ele != NULL);
+ }
+ }
+ }
+ }
+ else {
+ /* Non boundary case. */
+ if (use_vert) {
+ BMVert *v;
+ BMIter viter;
+ BM_ITER_MESH (v, &viter, bm, BM_VERTS_OF_MESH) {
+ if (BM_elem_flag_test(v, BM_ELEM_HIDDEN) == false) {
+ float point[3];
+ mul_v3_m4v3(point, obedit->obmat, v->co);
+ const float dist_sq_test = dist_squared_to_ray_v3_normalized(
+ ray_origin, ray_direction, v->co);
+ if (dist_sq_test < dist_sq_best) {
+ dist_sq_best = dist_sq_test;
+ best.base_index = base_index;
+ best.ele = (BMElem *)v;
+ }
+ }
+ }
+ }
+ if (use_edge) {
+ BMEdge *e;
+ BMIter eiter;
+ BM_ITER_MESH (e, &eiter, bm, BM_EDGES_OF_MESH) {
+ if (BM_elem_flag_test(e, BM_ELEM_HIDDEN) == false) {
+ float point[3];
+ if (coords) {
+ mid_v3_v3v3(
+ point, coords[BM_elem_index_get(e->v1)], coords[BM_elem_index_get(e->v2)]);
+ }
+ else {
+ mid_v3_v3v3(point, e->v1->co, e->v2->co);
+ }
+ mul_m4_v3(obedit->obmat, point);
+ const float dist_sq_test = dist_squared_to_ray_v3_normalized(
+ ray_origin, ray_direction, point);
+ if (dist_sq_test < dist_sq_best) {
+ dist_sq_best = dist_sq_test;
+ best.base_index = base_index;
+ best.ele = (BMElem *)e;
+ }
+ }
+ }
+ }
+ }
+
+ if (use_face) {
+ BMFace *f;
+ BMIter fiter;
+ BM_ITER_MESH (f, &fiter, bm, BM_FACES_OF_MESH) {
+ if (BM_elem_flag_test(f, BM_ELEM_HIDDEN) == false) {
+ float point[3];
+ if (coords) {
+ BM_face_calc_center_median_vcos(bm, f, point, coords);
+ }
+ else {
+ BM_face_calc_center_median(f, point);
+ }
+ mul_m4_v3(obedit->obmat, point);
+ const float dist_sq_test = dist_squared_to_ray_v3_normalized(
+ ray_origin, ray_direction, point);
+ if (dist_sq_test < dist_sq_best) {
+ dist_sq_best = dist_sq_test;
+ best.base_index = base_index;
+ best.ele = (BMElem *)f;
+ }
+ }
+ }
+ }
+ }
+ }
+
+ *r_base_index = best.base_index;
+ if (r_eve) {
+ *r_eve = NULL;
+ }
+ if (r_eed) {
+ *r_eed = NULL;
+ }
+ if (r_efa) {
+ *r_efa = NULL;
+ }
+
+ if (best.ele) {
+ switch (best.ele->head.htype) {
+ case BM_VERT:
+ *r_eve = (BMVert *)best.ele;
+ break;
+ case BM_EDGE:
+ *r_eed = (BMEdge *)best.ele;
+ break;
+ case BM_FACE:
+ *r_efa = (BMFace *)best.ele;
+ break;
+ default:
+ BLI_assert(0);
+ }
+ }
+ return (best.ele != NULL);
}
/** \} */
@@ -1290,90 +1305,87 @@ bool EDBM_unified_findnearest_from_raycast(
static int edbm_select_similar_region_exec(bContext *C, wmOperator *op)
{
- Object *obedit = CTX_data_edit_object(C);
- BMEditMesh *em = BKE_editmesh_from_object(obedit);
- BMesh *bm = em->bm;
- bool changed = false;
-
- /* group vars */
- int *groups_array;
- int (*group_index)[2];
- int group_tot;
- int i;
-
- if (bm->totfacesel < 2) {
- BKE_report(op->reports, RPT_ERROR, "No face regions selected");
- return OPERATOR_CANCELLED;
- }
-
- groups_array = MEM_mallocN(sizeof(*groups_array) * bm->totfacesel, __func__);
- group_tot = BM_mesh_calc_face_groups(
- bm, groups_array, &group_index,
- NULL, NULL,
- BM_ELEM_SELECT, BM_VERT);
-
- BM_mesh_elem_table_ensure(bm, BM_FACE);
-
- for (i = 0; i < group_tot; i++) {
- ListBase faces_regions;
- int tot;
-
- const int fg_sta = group_index[i][0];
- const int fg_len = group_index[i][1];
- int j;
- BMFace **fg = MEM_mallocN(sizeof(*fg) * fg_len, __func__);
-
-
- for (j = 0; j < fg_len; j++) {
- fg[j] = BM_face_at_index(bm, groups_array[fg_sta + j]);
- }
-
- tot = BM_mesh_region_match(bm, fg, fg_len, &faces_regions);
-
- MEM_freeN(fg);
-
- if (tot) {
- LinkData *link;
- while ((link = BLI_pophead(&faces_regions))) {
- BMFace *f, **faces = link->data;
- while ((f = *(faces++))) {
- BM_face_select_set(bm, f, true);
- }
- MEM_freeN(link->data);
- MEM_freeN(link);
-
- changed = true;
- }
- }
- }
-
- MEM_freeN(groups_array);
- MEM_freeN(group_index);
-
- if (changed) {
- DEG_id_tag_update(obedit->data, ID_RECALC_SELECT);
- WM_event_add_notifier(C, NC_GEOM | ND_SELECT, obedit->data);
- }
- else {
- BKE_report(op->reports, RPT_WARNING, "No matching face regions found");
- }
-
- return OPERATOR_FINISHED;
+ Object *obedit = CTX_data_edit_object(C);
+ BMEditMesh *em = BKE_editmesh_from_object(obedit);
+ BMesh *bm = em->bm;
+ bool changed = false;
+
+ /* group vars */
+ int *groups_array;
+ int(*group_index)[2];
+ int group_tot;
+ int i;
+
+ if (bm->totfacesel < 2) {
+ BKE_report(op->reports, RPT_ERROR, "No face regions selected");
+ return OPERATOR_CANCELLED;
+ }
+
+ groups_array = MEM_mallocN(sizeof(*groups_array) * bm->totfacesel, __func__);
+ group_tot = BM_mesh_calc_face_groups(
+ bm, groups_array, &group_index, NULL, NULL, BM_ELEM_SELECT, BM_VERT);
+
+ BM_mesh_elem_table_ensure(bm, BM_FACE);
+
+ for (i = 0; i < group_tot; i++) {
+ ListBase faces_regions;
+ int tot;
+
+ const int fg_sta = group_index[i][0];
+ const int fg_len = group_index[i][1];
+ int j;
+ BMFace **fg = MEM_mallocN(sizeof(*fg) * fg_len, __func__);
+
+ for (j = 0; j < fg_len; j++) {
+ fg[j] = BM_face_at_index(bm, groups_array[fg_sta + j]);
+ }
+
+ tot = BM_mesh_region_match(bm, fg, fg_len, &faces_regions);
+
+ MEM_freeN(fg);
+
+ if (tot) {
+ LinkData *link;
+ while ((link = BLI_pophead(&faces_regions))) {
+ BMFace *f, **faces = link->data;
+ while ((f = *(faces++))) {
+ BM_face_select_set(bm, f, true);
+ }
+ MEM_freeN(link->data);
+ MEM_freeN(link);
+
+ changed = true;
+ }
+ }
+ }
+
+ MEM_freeN(groups_array);
+ MEM_freeN(group_index);
+
+ if (changed) {
+ DEG_id_tag_update(obedit->data, ID_RECALC_SELECT);
+ WM_event_add_notifier(C, NC_GEOM | ND_SELECT, obedit->data);
+ }
+ else {
+ BKE_report(op->reports, RPT_WARNING, "No matching face regions found");
+ }
+
+ return OPERATOR_FINISHED;
}
void MESH_OT_select_similar_region(wmOperatorType *ot)
{
- /* identifiers */
- ot->name = "Select Similar Regions";
- ot->idname = "MESH_OT_select_similar_region";
- ot->description = "Select similar face regions to the current selection";
+ /* identifiers */
+ ot->name = "Select Similar Regions";
+ ot->idname = "MESH_OT_select_similar_region";
+ ot->description = "Select similar face regions to the current selection";
- /* api callbacks */
- ot->exec = edbm_select_similar_region_exec;
- ot->poll = ED_operator_editmesh;
+ /* api callbacks */
+ ot->exec = edbm_select_similar_region_exec;
+ ot->poll = ED_operator_editmesh;
- /* flags */
- ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
+ /* flags */
+ ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
}
/** \} */
@@ -1384,85 +1396,86 @@ void MESH_OT_select_similar_region(wmOperatorType *ot)
static int edbm_select_mode_exec(bContext *C, wmOperator *op)
{
- const int type = RNA_enum_get(op->ptr, "type");
- const int action = RNA_enum_get(op->ptr, "action");
- const bool use_extend = RNA_boolean_get(op->ptr, "use_extend");
- const bool use_expand = RNA_boolean_get(op->ptr, "use_expand");
-
- if (EDBM_selectmode_toggle(C, type, action, use_extend, use_expand)) {
- return OPERATOR_FINISHED;
- }
- else {
- return OPERATOR_CANCELLED;
- }
+ const int type = RNA_enum_get(op->ptr, "type");
+ const int action = RNA_enum_get(op->ptr, "action");
+ const bool use_extend = RNA_boolean_get(op->ptr, "use_extend");
+ const bool use_expand = RNA_boolean_get(op->ptr, "use_expand");
+
+ if (EDBM_selectmode_toggle(C, type, action, use_extend, use_expand)) {
+ return OPERATOR_FINISHED;
+ }
+ else {
+ return OPERATOR_CANCELLED;
+ }
}
static int edbm_select_mode_invoke(bContext *C, wmOperator *op, const wmEvent *event)
{
- /* Bypass when in UV non sync-select mode, fall through to keymap that edits. */
- if (CTX_wm_space_image(C)) {
- ToolSettings *ts = CTX_data_tool_settings(C);
- if ((ts->uv_flag & UV_SYNC_SELECTION) == 0) {
- return OPERATOR_PASS_THROUGH;
- }
- /* Bypass when no action is needed. */
- if (!RNA_struct_property_is_set(op->ptr, "type")) {
- return OPERATOR_CANCELLED;
- }
- }
-
- /* detecting these options based on shift/ctrl here is weak, but it's done
- * to make this work when clicking buttons or menus */
- if (!RNA_struct_property_is_set(op->ptr, "use_extend"))
- RNA_boolean_set(op->ptr, "use_extend", event->shift);
- if (!RNA_struct_property_is_set(op->ptr, "use_expand"))
- RNA_boolean_set(op->ptr, "use_expand", event->ctrl);
-
- return edbm_select_mode_exec(C, op);
+ /* Bypass when in UV non sync-select mode, fall through to keymap that edits. */
+ if (CTX_wm_space_image(C)) {
+ ToolSettings *ts = CTX_data_tool_settings(C);
+ if ((ts->uv_flag & UV_SYNC_SELECTION) == 0) {
+ return OPERATOR_PASS_THROUGH;
+ }
+ /* Bypass when no action is needed. */
+ if (!RNA_struct_property_is_set(op->ptr, "type")) {
+ return OPERATOR_CANCELLED;
+ }
+ }
+
+ /* detecting these options based on shift/ctrl here is weak, but it's done
+ * to make this work when clicking buttons or menus */
+ if (!RNA_struct_property_is_set(op->ptr, "use_extend"))
+ RNA_boolean_set(op->ptr, "use_extend", event->shift);
+ if (!RNA_struct_property_is_set(op->ptr, "use_expand"))
+ RNA_boolean_set(op->ptr, "use_expand", event->ctrl);
+
+ return edbm_select_mode_exec(C, op);
}
void MESH_OT_select_mode(wmOperatorType *ot)
{
- PropertyRNA *prop;
-
- static const EnumPropertyItem elem_items[] = {
- {SCE_SELECT_VERTEX, "VERT", ICON_VERTEXSEL, "Vertices", ""},
- {SCE_SELECT_EDGE, "EDGE", ICON_EDGESEL, "Edges", ""},
- {SCE_SELECT_FACE, "FACE", ICON_FACESEL, "Faces", ""},
- {0, NULL, 0, NULL, NULL},
- };
-
- static const EnumPropertyItem actions_items[] = {
- {0, "DISABLE", 0, "Disable", "Disable selected markers"},
- {1, "ENABLE", 0, "Enable", "Enable selected markers"},
- {2, "TOGGLE", 0, "Toggle", "Toggle disabled flag for selected markers"},
- {0, NULL, 0, NULL, NULL},
- };
-
- /* identifiers */
- ot->name = "Select Mode";
- ot->idname = "MESH_OT_select_mode";
- ot->description = "Change selection mode";
-
- /* api callbacks */
- ot->invoke = edbm_select_mode_invoke;
- ot->exec = edbm_select_mode_exec;
- ot->poll = ED_operator_editmesh;
-
- /* flags */
- ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
-
- /* properties */
- /* Hide all, not to show redo panel. */
- prop = RNA_def_boolean(ot->srna, "use_extend", false, "Extend", "");
- RNA_def_property_flag(prop, PROP_HIDDEN | PROP_SKIP_SAVE);
- prop = RNA_def_boolean(ot->srna, "use_expand", false, "Expand", "");
- RNA_def_property_flag(prop, PROP_HIDDEN | PROP_SKIP_SAVE);
- ot->prop = prop = RNA_def_enum(ot->srna, "type", elem_items, 0, "Type", "");
- RNA_def_property_flag(prop, PROP_HIDDEN | PROP_SKIP_SAVE);
-
- prop = RNA_def_enum(ot->srna, "action", actions_items, 2, "Action", "Selection action to execute");
- RNA_def_property_flag(prop, PROP_HIDDEN);
+ PropertyRNA *prop;
+
+ static const EnumPropertyItem elem_items[] = {
+ {SCE_SELECT_VERTEX, "VERT", ICON_VERTEXSEL, "Vertices", ""},
+ {SCE_SELECT_EDGE, "EDGE", ICON_EDGESEL, "Edges", ""},
+ {SCE_SELECT_FACE, "FACE", ICON_FACESEL, "Faces", ""},
+ {0, NULL, 0, NULL, NULL},
+ };
+
+ static const EnumPropertyItem actions_items[] = {
+ {0, "DISABLE", 0, "Disable", "Disable selected markers"},
+ {1, "ENABLE", 0, "Enable", "Enable selected markers"},
+ {2, "TOGGLE", 0, "Toggle", "Toggle disabled flag for selected markers"},
+ {0, NULL, 0, NULL, NULL},
+ };
+
+ /* identifiers */
+ ot->name = "Select Mode";
+ ot->idname = "MESH_OT_select_mode";
+ ot->description = "Change selection mode";
+
+ /* api callbacks */
+ ot->invoke = edbm_select_mode_invoke;
+ ot->exec = edbm_select_mode_exec;
+ ot->poll = ED_operator_editmesh;
+
+ /* flags */
+ ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
+
+ /* properties */
+ /* Hide all, not to show redo panel. */
+ prop = RNA_def_boolean(ot->srna, "use_extend", false, "Extend", "");
+ RNA_def_property_flag(prop, PROP_HIDDEN | PROP_SKIP_SAVE);
+ prop = RNA_def_boolean(ot->srna, "use_expand", false, "Expand", "");
+ RNA_def_property_flag(prop, PROP_HIDDEN | PROP_SKIP_SAVE);
+ ot->prop = prop = RNA_def_enum(ot->srna, "type", elem_items, 0, "Type", "");
+ RNA_def_property_flag(prop, PROP_HIDDEN | PROP_SKIP_SAVE);
+
+ prop = RNA_def_enum(
+ ot->srna, "action", actions_items, 2, "Action", "Selection action to execute");
+ RNA_def_property_flag(prop, PROP_HIDDEN);
}
/** \} */
@@ -1471,132 +1484,145 @@ void MESH_OT_select_mode(wmOperatorType *ot)
/** \name Select Loop (Non Modal) Operator
* \{ */
-static void walker_select_count(
- BMEditMesh *em, int walkercode, void *start, const bool select, const bool select_mix,
- int *r_totsel, int *r_totunsel)
+static void walker_select_count(BMEditMesh *em,
+ int walkercode,
+ void *start,
+ const bool select,
+ const bool select_mix,
+ int *r_totsel,
+ int *r_totunsel)
{
- BMesh *bm = em->bm;
- BMElem *ele;
- BMWalker walker;
- int tot[2] = {0, 0};
-
- BMW_init(&walker, bm, walkercode,
- BMW_MASK_NOP, BMW_MASK_NOP, BMW_MASK_NOP,
- BMW_FLAG_TEST_HIDDEN,
- BMW_NIL_LAY);
-
- for (ele = BMW_begin(&walker, start); ele; ele = BMW_step(&walker)) {
- tot[(BM_elem_flag_test_bool(ele, BM_ELEM_SELECT) != select)] += 1;
-
- if (!select_mix && tot[0] && tot[1]) {
- tot[0] = tot[1] = -1;
- break;
- }
- }
-
- *r_totsel = tot[0];
- *r_totunsel = tot[1];
-
- BMW_end(&walker);
+ BMesh *bm = em->bm;
+ BMElem *ele;
+ BMWalker walker;
+ int tot[2] = {0, 0};
+
+ BMW_init(&walker,
+ bm,
+ walkercode,
+ BMW_MASK_NOP,
+ BMW_MASK_NOP,
+ BMW_MASK_NOP,
+ BMW_FLAG_TEST_HIDDEN,
+ BMW_NIL_LAY);
+
+ for (ele = BMW_begin(&walker, start); ele; ele = BMW_step(&walker)) {
+ tot[(BM_elem_flag_test_bool(ele, BM_ELEM_SELECT) != select)] += 1;
+
+ if (!select_mix && tot[0] && tot[1]) {
+ tot[0] = tot[1] = -1;
+ break;
+ }
+ }
+
+ *r_totsel = tot[0];
+ *r_totunsel = tot[1];
+
+ BMW_end(&walker);
}
static void walker_select(BMEditMesh *em, int walkercode, void *start, const bool select)
{
- BMesh *bm = em->bm;
- BMElem *ele;
- BMWalker walker;
-
- BMW_init(&walker, bm, walkercode,
- BMW_MASK_NOP, BMW_MASK_NOP, BMW_MASK_NOP,
- BMW_FLAG_TEST_HIDDEN,
- BMW_NIL_LAY);
-
- for (ele = BMW_begin(&walker, start); ele; ele = BMW_step(&walker)) {
- if (!select) {
- BM_select_history_remove(bm, ele);
- }
- BM_elem_select_set(bm, ele, select);
- }
- BMW_end(&walker);
+ BMesh *bm = em->bm;
+ BMElem *ele;
+ BMWalker walker;
+
+ BMW_init(&walker,
+ bm,
+ walkercode,
+ BMW_MASK_NOP,
+ BMW_MASK_NOP,
+ BMW_MASK_NOP,
+ BMW_FLAG_TEST_HIDDEN,
+ BMW_NIL_LAY);
+
+ for (ele = BMW_begin(&walker, start); ele; ele = BMW_step(&walker)) {
+ if (!select) {
+ BM_select_history_remove(bm, ele);
+ }
+ BM_elem_select_set(bm, ele, select);
+ }
+ BMW_end(&walker);
}
static int edbm_loop_multiselect_exec(bContext *C, wmOperator *op)
{
- const bool is_ring = RNA_boolean_get(op->ptr, "ring");
- ViewLayer *view_layer = CTX_data_view_layer(C);
- uint objects_len = 0;
- Object **objects = BKE_view_layer_array_from_objects_in_edit_mode_unique_data(view_layer, CTX_wm_view3d(C), &objects_len);
- for (uint ob_index = 0; ob_index < objects_len; ob_index++) {
- Object *obedit = objects[ob_index];
- BMEditMesh *em = BKE_editmesh_from_object(obedit);
-
- if (em->bm->totedgesel == 0) {
- continue;
- }
-
- BMEdge *eed;
- BMEdge **edarray;
- int edindex;
- BMIter iter;
- int totedgesel = 0;
-
- BM_ITER_MESH(eed, &iter, em->bm, BM_EDGES_OF_MESH) {
- if (BM_elem_flag_test(eed, BM_ELEM_SELECT)) {
- totedgesel++;
- }
- }
-
- edarray = MEM_mallocN(sizeof(BMEdge *) * totedgesel, "edge array");
- edindex = 0;
-
- BM_ITER_MESH(eed, &iter, em->bm, BM_EDGES_OF_MESH) {
- if (BM_elem_flag_test(eed, BM_ELEM_SELECT)) {
- edarray[edindex] = eed;
- edindex++;
- }
- }
-
- if (is_ring) {
- for (edindex = 0; edindex < totedgesel; edindex += 1) {
- eed = edarray[edindex];
- walker_select(em, BMW_EDGERING, eed, true);
- }
- EDBM_selectmode_flush(em);
- }
- else {
- for (edindex = 0; edindex < totedgesel; edindex += 1) {
- eed = edarray[edindex];
- walker_select(em, BMW_EDGELOOP, eed, true);
- }
- EDBM_selectmode_flush(em);
- }
- MEM_freeN(edarray);
- // if (EM_texFaceCheck())
-
- DEG_id_tag_update(obedit->data, ID_RECALC_SELECT);
- WM_event_add_notifier(C, NC_GEOM | ND_SELECT, obedit->data);
- }
- MEM_freeN(objects);
-
- return OPERATOR_FINISHED;
+ const bool is_ring = RNA_boolean_get(op->ptr, "ring");
+ ViewLayer *view_layer = CTX_data_view_layer(C);
+ uint objects_len = 0;
+ Object **objects = BKE_view_layer_array_from_objects_in_edit_mode_unique_data(
+ view_layer, CTX_wm_view3d(C), &objects_len);
+ for (uint ob_index = 0; ob_index < objects_len; ob_index++) {
+ Object *obedit = objects[ob_index];
+ BMEditMesh *em = BKE_editmesh_from_object(obedit);
+
+ if (em->bm->totedgesel == 0) {
+ continue;
+ }
+
+ BMEdge *eed;
+ BMEdge **edarray;
+ int edindex;
+ BMIter iter;
+ int totedgesel = 0;
+
+ BM_ITER_MESH (eed, &iter, em->bm, BM_EDGES_OF_MESH) {
+ if (BM_elem_flag_test(eed, BM_ELEM_SELECT)) {
+ totedgesel++;
+ }
+ }
+
+ edarray = MEM_mallocN(sizeof(BMEdge *) * totedgesel, "edge array");
+ edindex = 0;
+
+ BM_ITER_MESH (eed, &iter, em->bm, BM_EDGES_OF_MESH) {
+ if (BM_elem_flag_test(eed, BM_ELEM_SELECT)) {
+ edarray[edindex] = eed;
+ edindex++;
+ }
+ }
+
+ if (is_ring) {
+ for (edindex = 0; edindex < totedgesel; edindex += 1) {
+ eed = edarray[edindex];
+ walker_select(em, BMW_EDGERING, eed, true);
+ }
+ EDBM_selectmode_flush(em);
+ }
+ else {
+ for (edindex = 0; edindex < totedgesel; edindex += 1) {
+ eed = edarray[edindex];
+ walker_select(em, BMW_EDGELOOP, eed, true);
+ }
+ EDBM_selectmode_flush(em);
+ }
+ MEM_freeN(edarray);
+ // if (EM_texFaceCheck())
+
+ DEG_id_tag_update(obedit->data, ID_RECALC_SELECT);
+ WM_event_add_notifier(C, NC_GEOM | ND_SELECT, obedit->data);
+ }
+ MEM_freeN(objects);
+
+ return OPERATOR_FINISHED;
}
void MESH_OT_loop_multi_select(wmOperatorType *ot)
{
- /* identifiers */
- ot->name = "Multi Select Loops";
- ot->idname = "MESH_OT_loop_multi_select";
- ot->description = "Select a loop of connected edges by connection type";
+ /* identifiers */
+ ot->name = "Multi Select Loops";
+ ot->idname = "MESH_OT_loop_multi_select";
+ ot->description = "Select a loop of connected edges by connection type";
- /* api callbacks */
- ot->exec = edbm_loop_multiselect_exec;
- ot->poll = ED_operator_editmesh;
+ /* api callbacks */
+ ot->exec = edbm_loop_multiselect_exec;
+ ot->poll = ED_operator_editmesh;
- /* flags */
- ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
+ /* flags */
+ ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
- /* properties */
- RNA_def_boolean(ot->srna, "ring", 0, "Ring", "");
+ /* properties */
+ RNA_def_boolean(ot->srna, "ring", 0, "Ring", "");
}
/** \} */
@@ -1607,285 +1633,281 @@ void MESH_OT_loop_multi_select(wmOperatorType *ot)
static void mouse_mesh_loop_face(BMEditMesh *em, BMEdge *eed, bool select, bool select_clear)
{
- if (select_clear) {
- EDBM_flag_disable_all(em, BM_ELEM_SELECT);
- }
+ if (select_clear) {
+ EDBM_flag_disable_all(em, BM_ELEM_SELECT);
+ }
- walker_select(em, BMW_FACELOOP, eed, select);
+ walker_select(em, BMW_FACELOOP, eed, select);
}
static void mouse_mesh_loop_edge_ring(BMEditMesh *em, BMEdge *eed, bool select, bool select_clear)
{
- if (select_clear) {
- EDBM_flag_disable_all(em, BM_ELEM_SELECT);
- }
+ if (select_clear) {
+ EDBM_flag_disable_all(em, BM_ELEM_SELECT);
+ }
- walker_select(em, BMW_EDGERING, eed, select);
+ walker_select(em, BMW_EDGERING, eed, select);
}
-static void mouse_mesh_loop_edge(BMEditMesh *em, BMEdge *eed, bool select, bool select_clear, bool select_cycle)
+static void mouse_mesh_loop_edge(
+ BMEditMesh *em, BMEdge *eed, bool select, bool select_clear, bool select_cycle)
{
- bool edge_boundary = false;
-
- /* cycle between BMW_EDGELOOP / BMW_EDGEBOUNDARY */
- if (select_cycle && BM_edge_is_boundary(eed)) {
- int tot[2];
-
- /* if the loops selected toggle the boundaries */
- walker_select_count(em, BMW_EDGELOOP, eed, select, false,
- &tot[0], &tot[1]);
- if (tot[select] == 0) {
- edge_boundary = true;
-
- /* if the boundaries selected, toggle back to the loop */
- walker_select_count(em, BMW_EDGEBOUNDARY, eed, select, false,
- &tot[0], &tot[1]);
- if (tot[select] == 0) {
- edge_boundary = false;
- }
- }
- }
-
- if (select_clear) {
- EDBM_flag_disable_all(em, BM_ELEM_SELECT);
- }
-
- if (edge_boundary) {
- walker_select(em, BMW_EDGEBOUNDARY, eed, select);
- }
- else {
- walker_select(em, BMW_EDGELOOP, eed, select);
- }
+ bool edge_boundary = false;
+
+ /* cycle between BMW_EDGELOOP / BMW_EDGEBOUNDARY */
+ if (select_cycle && BM_edge_is_boundary(eed)) {
+ int tot[2];
+
+ /* if the loops selected toggle the boundaries */
+ walker_select_count(em, BMW_EDGELOOP, eed, select, false, &tot[0], &tot[1]);
+ if (tot[select] == 0) {
+ edge_boundary = true;
+
+ /* if the boundaries selected, toggle back to the loop */
+ walker_select_count(em, BMW_EDGEBOUNDARY, eed, select, false, &tot[0], &tot[1]);
+ if (tot[select] == 0) {
+ edge_boundary = false;
+ }
+ }
+ }
+
+ if (select_clear) {
+ EDBM_flag_disable_all(em, BM_ELEM_SELECT);
+ }
+
+ if (edge_boundary) {
+ walker_select(em, BMW_EDGEBOUNDARY, eed, select);
+ }
+ else {
+ walker_select(em, BMW_EDGELOOP, eed, select);
+ }
}
-static bool mouse_mesh_loop(bContext *C, const int mval[2], bool extend, bool deselect, bool toggle, bool ring)
+static bool mouse_mesh_loop(
+ bContext *C, const int mval[2], bool extend, bool deselect, bool toggle, bool ring)
{
- Base *basact = NULL;
- BMVert *eve = NULL;
- BMEdge *eed = NULL;
- BMFace *efa = NULL;
-
- ViewContext vc;
- BMEditMesh *em;
- bool select = true;
- bool select_clear = false;
- bool select_cycle = true;
- float mvalf[2];
-
- em_setup_viewcontext(C, &vc);
- mvalf[0] = (float)(vc.mval[0] = mval[0]);
- mvalf[1] = (float)(vc.mval[1] = mval[1]);
-
- BMEditMesh *em_original = vc.em;
- const short selectmode = em_original->selectmode;
- em_original->selectmode = SCE_SELECT_EDGE;
-
- uint bases_len;
- Base **bases = BKE_view_layer_array_from_bases_in_edit_mode(vc.view_layer, vc.v3d, &bases_len);
-
- {
- int base_index = -1;
- if (EDBM_unified_findnearest(&vc, bases, bases_len, &base_index, &eve, &eed, &efa)) {
- basact = bases[base_index];
- ED_view3d_viewcontext_init_object(&vc, basact->object);
- em = vc.em;
- }
- else {
- em = NULL;
- }
- }
-
- em_original->selectmode = selectmode;
-
- if (em == NULL || eed == NULL) {
- MEM_freeN(bases);
- return false;
- }
-
- if (extend == false && deselect == false && toggle == false) {
- select_clear = true;
- }
-
- if (extend) {
- select = true;
- }
- else if (deselect) {
- select = false;
- }
- else if (select_clear || (BM_elem_flag_test(eed, BM_ELEM_SELECT) == 0)) {
- select = true;
- }
- else if (toggle) {
- select = false;
- select_cycle = false;
- }
-
- if (select_clear) {
- for (uint base_index = 0; base_index < bases_len; base_index++) {
- Base *base_iter = bases[base_index];
- Object *ob_iter = base_iter->object;
- BMEditMesh *em_iter = BKE_editmesh_from_object(ob_iter);
-
- if (em_iter->bm->totvertsel == 0) {
- continue;
- }
-
- if (em_iter == em) {
- continue;
- }
-
- EDBM_flag_disable_all(em_iter, BM_ELEM_SELECT);
- DEG_id_tag_update(ob_iter->data, ID_RECALC_SELECT);
- }
- }
-
- if (em->selectmode & SCE_SELECT_FACE) {
- mouse_mesh_loop_face(em, eed, select, select_clear);
- }
- else {
- if (ring) {
- mouse_mesh_loop_edge_ring(em, eed, select, select_clear);
- }
- else {
- mouse_mesh_loop_edge(em, eed, select, select_clear, select_cycle);
- }
- }
-
- EDBM_selectmode_flush(em);
-
- /* sets as active, useful for other tools */
- if (select) {
- if (em->selectmode & SCE_SELECT_VERTEX) {
- /* Find nearest vert from mouse
- * (initialize to large values in case only one vertex can be projected) */
- float v1_co[2], v2_co[2];
- float length_1 = FLT_MAX;
- float length_2 = FLT_MAX;
-
- /* We can't be sure this has already been set... */
- ED_view3d_init_mats_rv3d(vc.obedit, vc.rv3d);
-
- if (ED_view3d_project_float_object(
- vc.ar, eed->v1->co, v1_co, V3D_PROJ_TEST_CLIP_NEAR) == V3D_PROJ_RET_OK)
- {
- length_1 = len_squared_v2v2(mvalf, v1_co);
- }
-
- if (ED_view3d_project_float_object(
- vc.ar, eed->v2->co, v2_co, V3D_PROJ_TEST_CLIP_NEAR) == V3D_PROJ_RET_OK)
- {
- length_2 = len_squared_v2v2(mvalf, v2_co);
- }
+ Base *basact = NULL;
+ BMVert *eve = NULL;
+ BMEdge *eed = NULL;
+ BMFace *efa = NULL;
+
+ ViewContext vc;
+ BMEditMesh *em;
+ bool select = true;
+ bool select_clear = false;
+ bool select_cycle = true;
+ float mvalf[2];
+
+ em_setup_viewcontext(C, &vc);
+ mvalf[0] = (float)(vc.mval[0] = mval[0]);
+ mvalf[1] = (float)(vc.mval[1] = mval[1]);
+
+ BMEditMesh *em_original = vc.em;
+ const short selectmode = em_original->selectmode;
+ em_original->selectmode = SCE_SELECT_EDGE;
+
+ uint bases_len;
+ Base **bases = BKE_view_layer_array_from_bases_in_edit_mode(vc.view_layer, vc.v3d, &bases_len);
+
+ {
+ int base_index = -1;
+ if (EDBM_unified_findnearest(&vc, bases, bases_len, &base_index, &eve, &eed, &efa)) {
+ basact = bases[base_index];
+ ED_view3d_viewcontext_init_object(&vc, basact->object);
+ em = vc.em;
+ }
+ else {
+ em = NULL;
+ }
+ }
+
+ em_original->selectmode = selectmode;
+
+ if (em == NULL || eed == NULL) {
+ MEM_freeN(bases);
+ return false;
+ }
+
+ if (extend == false && deselect == false && toggle == false) {
+ select_clear = true;
+ }
+
+ if (extend) {
+ select = true;
+ }
+ else if (deselect) {
+ select = false;
+ }
+ else if (select_clear || (BM_elem_flag_test(eed, BM_ELEM_SELECT) == 0)) {
+ select = true;
+ }
+ else if (toggle) {
+ select = false;
+ select_cycle = false;
+ }
+
+ if (select_clear) {
+ for (uint base_index = 0; base_index < bases_len; base_index++) {
+ Base *base_iter = bases[base_index];
+ Object *ob_iter = base_iter->object;
+ BMEditMesh *em_iter = BKE_editmesh_from_object(ob_iter);
+
+ if (em_iter->bm->totvertsel == 0) {
+ continue;
+ }
+
+ if (em_iter == em) {
+ continue;
+ }
+
+ EDBM_flag_disable_all(em_iter, BM_ELEM_SELECT);
+ DEG_id_tag_update(ob_iter->data, ID_RECALC_SELECT);
+ }
+ }
+
+ if (em->selectmode & SCE_SELECT_FACE) {
+ mouse_mesh_loop_face(em, eed, select, select_clear);
+ }
+ else {
+ if (ring) {
+ mouse_mesh_loop_edge_ring(em, eed, select, select_clear);
+ }
+ else {
+ mouse_mesh_loop_edge(em, eed, select, select_clear, select_cycle);
+ }
+ }
+
+ EDBM_selectmode_flush(em);
+
+ /* sets as active, useful for other tools */
+ if (select) {
+ if (em->selectmode & SCE_SELECT_VERTEX) {
+ /* Find nearest vert from mouse
+ * (initialize to large values in case only one vertex can be projected) */
+ float v1_co[2], v2_co[2];
+ float length_1 = FLT_MAX;
+ float length_2 = FLT_MAX;
+
+ /* We can't be sure this has already been set... */
+ ED_view3d_init_mats_rv3d(vc.obedit, vc.rv3d);
+
+ if (ED_view3d_project_float_object(vc.ar, eed->v1->co, v1_co, V3D_PROJ_TEST_CLIP_NEAR) ==
+ V3D_PROJ_RET_OK) {
+ length_1 = len_squared_v2v2(mvalf, v1_co);
+ }
+
+ if (ED_view3d_project_float_object(vc.ar, eed->v2->co, v2_co, V3D_PROJ_TEST_CLIP_NEAR) ==
+ V3D_PROJ_RET_OK) {
+ length_2 = len_squared_v2v2(mvalf, v2_co);
+ }
#if 0
- printf("mouse to v1: %f\nmouse to v2: %f\n", len_squared_v2v2(mvalf, v1_co),
- len_squared_v2v2(mvalf, v2_co));
+ printf("mouse to v1: %f\nmouse to v2: %f\n", len_squared_v2v2(mvalf, v1_co),
+ len_squared_v2v2(mvalf, v2_co));
#endif
- BM_select_history_store(em->bm, (length_1 < length_2) ? eed->v1 : eed->v2);
- }
- else if (em->selectmode & SCE_SELECT_EDGE) {
- BM_select_history_store(em->bm, eed);
- }
- else if (em->selectmode & SCE_SELECT_FACE) {
- /* Select the face of eed which is the nearest of mouse. */
- BMFace *f;
- BMIter iterf;
- float best_dist = FLT_MAX;
- efa = NULL;
-
- /* We can't be sure this has already been set... */
- ED_view3d_init_mats_rv3d(vc.obedit, vc.rv3d);
-
- BM_ITER_ELEM (f, &iterf, eed, BM_FACES_OF_EDGE) {
- if (BM_elem_flag_test(f, BM_ELEM_SELECT)) {
- float cent[3];
- float co[2], tdist;
-
- BM_face_calc_center_median(f, cent);
- if (ED_view3d_project_float_object(
- vc.ar, cent, co, V3D_PROJ_TEST_CLIP_NEAR) == V3D_PROJ_RET_OK)
- {
- tdist = len_squared_v2v2(mvalf, co);
- if (tdist < best_dist) {
-/* printf("Best face: %p (%f)\n", f, tdist);*/
- best_dist = tdist;
- efa = f;
- }
- }
- }
- }
- if (efa) {
- BM_mesh_active_face_set(em->bm, efa);
- BM_select_history_store(em->bm, efa);
- }
- }
- }
-
- MEM_freeN(bases);
-
- DEG_id_tag_update(vc.obedit->data, ID_RECALC_SELECT);
- WM_event_add_notifier(C, NC_GEOM | ND_SELECT, vc.obedit->data);
-
- return true;
+ BM_select_history_store(em->bm, (length_1 < length_2) ? eed->v1 : eed->v2);
+ }
+ else if (em->selectmode & SCE_SELECT_EDGE) {
+ BM_select_history_store(em->bm, eed);
+ }
+ else if (em->selectmode & SCE_SELECT_FACE) {
+ /* Select the face of eed which is the nearest of mouse. */
+ BMFace *f;
+ BMIter iterf;
+ float best_dist = FLT_MAX;
+ efa = NULL;
+
+ /* We can't be sure this has already been set... */
+ ED_view3d_init_mats_rv3d(vc.obedit, vc.rv3d);
+
+ BM_ITER_ELEM (f, &iterf, eed, BM_FACES_OF_EDGE) {
+ if (BM_elem_flag_test(f, BM_ELEM_SELECT)) {
+ float cent[3];
+ float co[2], tdist;
+
+ BM_face_calc_center_median(f, cent);
+ if (ED_view3d_project_float_object(vc.ar, cent, co, V3D_PROJ_TEST_CLIP_NEAR) ==
+ V3D_PROJ_RET_OK) {
+ tdist = len_squared_v2v2(mvalf, co);
+ if (tdist < best_dist) {
+ /* printf("Best face: %p (%f)\n", f, tdist);*/
+ best_dist = tdist;
+ efa = f;
+ }
+ }
+ }
+ }
+ if (efa) {
+ BM_mesh_active_face_set(em->bm, efa);
+ BM_select_history_store(em->bm, efa);
+ }
+ }
+ }
+
+ MEM_freeN(bases);
+
+ DEG_id_tag_update(vc.obedit->data, ID_RECALC_SELECT);
+ WM_event_add_notifier(C, NC_GEOM | ND_SELECT, vc.obedit->data);
+
+ return true;
}
static int edbm_select_loop_invoke(bContext *C, wmOperator *op, const wmEvent *event)
{
- view3d_operator_needs_opengl(C);
-
- if (mouse_mesh_loop(
- C, event->mval,
- RNA_boolean_get(op->ptr, "extend"),
- RNA_boolean_get(op->ptr, "deselect"),
- RNA_boolean_get(op->ptr, "toggle"),
- RNA_boolean_get(op->ptr, "ring")))
- {
- return OPERATOR_FINISHED;
- }
- else {
- return OPERATOR_CANCELLED;
- }
+ view3d_operator_needs_opengl(C);
+
+ if (mouse_mesh_loop(C,
+ event->mval,
+ RNA_boolean_get(op->ptr, "extend"),
+ RNA_boolean_get(op->ptr, "deselect"),
+ RNA_boolean_get(op->ptr, "toggle"),
+ RNA_boolean_get(op->ptr, "ring"))) {
+ return OPERATOR_FINISHED;
+ }
+ else {
+ return OPERATOR_CANCELLED;
+ }
}
void MESH_OT_loop_select(wmOperatorType *ot)
{
- /* identifiers */
- ot->name = "Loop Select";
- ot->idname = "MESH_OT_loop_select";
- ot->description = "Select a loop of connected edges";
-
- /* api callbacks */
- ot->invoke = edbm_select_loop_invoke;
- ot->poll = ED_operator_editmesh_region_view3d;
-
- /* flags */
- ot->flag = OPTYPE_UNDO;
-
- /* properties */
- RNA_def_boolean(ot->srna, "extend", 0, "Extend Select", "Extend the selection");
- RNA_def_boolean(ot->srna, "deselect", 0, "Deselect", "Remove from the selection");
- RNA_def_boolean(ot->srna, "toggle", 0, "Toggle Select", "Toggle the selection");
- RNA_def_boolean(ot->srna, "ring", 0, "Select Ring", "Select ring");
+ /* identifiers */
+ ot->name = "Loop Select";
+ ot->idname = "MESH_OT_loop_select";
+ ot->description = "Select a loop of connected edges";
+
+ /* api callbacks */
+ ot->invoke = edbm_select_loop_invoke;
+ ot->poll = ED_operator_editmesh_region_view3d;
+
+ /* flags */
+ ot->flag = OPTYPE_UNDO;
+
+ /* properties */
+ RNA_def_boolean(ot->srna, "extend", 0, "Extend Select", "Extend the selection");
+ RNA_def_boolean(ot->srna, "deselect", 0, "Deselect", "Remove from the selection");
+ RNA_def_boolean(ot->srna, "toggle", 0, "Toggle Select", "Toggle the selection");
+ RNA_def_boolean(ot->srna, "ring", 0, "Select Ring", "Select ring");
}
void MESH_OT_edgering_select(wmOperatorType *ot)
{
- /* description */
- ot->name = "Edge Ring Select";
- ot->idname = "MESH_OT_edgering_select";
- ot->description = "Select an edge ring";
-
- /* callbacks */
- ot->invoke = edbm_select_loop_invoke;
- ot->poll = ED_operator_editmesh_region_view3d;
-
- /* flags */
- ot->flag = OPTYPE_UNDO;
-
- RNA_def_boolean(ot->srna, "extend", 0, "Extend", "Extend the selection");
- RNA_def_boolean(ot->srna, "deselect", 0, "Deselect", "Remove from the selection");
- RNA_def_boolean(ot->srna, "toggle", 0, "Toggle Select", "Toggle the selection");
- RNA_def_boolean(ot->srna, "ring", 1, "Select Ring", "Select ring");
+ /* description */
+ ot->name = "Edge Ring Select";
+ ot->idname = "MESH_OT_edgering_select";
+ ot->description = "Select an edge ring";
+
+ /* callbacks */
+ ot->invoke = edbm_select_loop_invoke;
+ ot->poll = ED_operator_editmesh_region_view3d;
+
+ /* flags */
+ ot->flag = OPTYPE_UNDO;
+
+ RNA_def_boolean(ot->srna, "extend", 0, "Extend", "Extend the selection");
+ RNA_def_boolean(ot->srna, "deselect", 0, "Deselect", "Remove from the selection");
+ RNA_def_boolean(ot->srna, "toggle", 0, "Toggle Select", "Toggle the selection");
+ RNA_def_boolean(ot->srna, "ring", 1, "Select Ring", "Select ring");
}
/** \} */
@@ -1896,63 +1918,64 @@ void MESH_OT_edgering_select(wmOperatorType *ot)
static int edbm_select_all_exec(bContext *C, wmOperator *op)
{
- ViewLayer *view_layer = CTX_data_view_layer(C);
- int action = RNA_enum_get(op->ptr, "action");
-
- uint objects_len = 0;
- Object **objects = BKE_view_layer_array_from_objects_in_edit_mode_unique_data(view_layer, CTX_wm_view3d(C), &objects_len);
-
- if (action == SEL_TOGGLE) {
- action = SEL_SELECT;
- for (uint ob_index = 0; ob_index < objects_len; ob_index++) {
- Object *obedit = objects[ob_index];
- BMEditMesh *em = BKE_editmesh_from_object(obedit);
- if (em->bm->totvertsel || em->bm->totedgesel || em->bm->totfacesel) {
- action = SEL_DESELECT;
- break;
- }
- }
- }
-
- for (uint ob_index = 0; ob_index < objects_len; ob_index++) {
- Object *obedit = objects[ob_index];
- BMEditMesh *em = BKE_editmesh_from_object(obedit);
- switch (action) {
- case SEL_SELECT:
- EDBM_flag_enable_all(em, BM_ELEM_SELECT);
- break;
- case SEL_DESELECT:
- EDBM_flag_disable_all(em, BM_ELEM_SELECT);
- break;
- case SEL_INVERT:
- EDBM_select_swap(em);
- EDBM_selectmode_flush(em);
- break;
- }
- DEG_id_tag_update(obedit->data, ID_RECALC_SELECT);
- WM_event_add_notifier(C, NC_GEOM | ND_SELECT, obedit->data);
- }
-
- MEM_freeN(objects);
-
- return OPERATOR_FINISHED;
+ ViewLayer *view_layer = CTX_data_view_layer(C);
+ int action = RNA_enum_get(op->ptr, "action");
+
+ uint objects_len = 0;
+ Object **objects = BKE_view_layer_array_from_objects_in_edit_mode_unique_data(
+ view_layer, CTX_wm_view3d(C), &objects_len);
+
+ if (action == SEL_TOGGLE) {
+ action = SEL_SELECT;
+ for (uint ob_index = 0; ob_index < objects_len; ob_index++) {
+ Object *obedit = objects[ob_index];
+ BMEditMesh *em = BKE_editmesh_from_object(obedit);
+ if (em->bm->totvertsel || em->bm->totedgesel || em->bm->totfacesel) {
+ action = SEL_DESELECT;
+ break;
+ }
+ }
+ }
+
+ for (uint ob_index = 0; ob_index < objects_len; ob_index++) {
+ Object *obedit = objects[ob_index];
+ BMEditMesh *em = BKE_editmesh_from_object(obedit);
+ switch (action) {
+ case SEL_SELECT:
+ EDBM_flag_enable_all(em, BM_ELEM_SELECT);
+ break;
+ case SEL_DESELECT:
+ EDBM_flag_disable_all(em, BM_ELEM_SELECT);
+ break;
+ case SEL_INVERT:
+ EDBM_select_swap(em);
+ EDBM_selectmode_flush(em);
+ break;
+ }
+ DEG_id_tag_update(obedit->data, ID_RECALC_SELECT);
+ WM_event_add_notifier(C, NC_GEOM | ND_SELECT, obedit->data);
+ }
+
+ MEM_freeN(objects);
+
+ return OPERATOR_FINISHED;
}
void MESH_OT_select_all(wmOperatorType *ot)
{
- /* identifiers */
- ot->name = "(De)select All";
- ot->idname = "MESH_OT_select_all";
- ot->description = "(De)select all vertices, edges or faces";
+ /* identifiers */
+ ot->name = "(De)select All";
+ ot->idname = "MESH_OT_select_all";
+ ot->description = "(De)select all vertices, edges or faces";
- /* api callbacks */
- ot->exec = edbm_select_all_exec;
- ot->poll = ED_operator_editmesh;
+ /* api callbacks */
+ ot->exec = edbm_select_all_exec;
+ ot->poll = ED_operator_editmesh;
- /* flags */
- ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
+ /* flags */
+ ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
- WM_operator_properties_select_all(ot);
+ WM_operator_properties_select_all(ot);
}
/** \} */
@@ -1963,39 +1986,40 @@ void MESH_OT_select_all(wmOperatorType *ot)
static int edbm_faces_select_interior_exec(bContext *C, wmOperator *UNUSED(op))
{
- ViewLayer *view_layer = CTX_data_view_layer(C);
- uint objects_len = 0;
- Object **objects = BKE_view_layer_array_from_objects_in_edit_mode_unique_data(view_layer, CTX_wm_view3d(C), &objects_len);
+ ViewLayer *view_layer = CTX_data_view_layer(C);
+ uint objects_len = 0;
+ Object **objects = BKE_view_layer_array_from_objects_in_edit_mode_unique_data(
+ view_layer, CTX_wm_view3d(C), &objects_len);
- for (uint ob_index = 0; ob_index < objects_len; ob_index++) {
- Object *obedit = objects[ob_index];
- BMEditMesh *em = BKE_editmesh_from_object(obedit);
+ for (uint ob_index = 0; ob_index < objects_len; ob_index++) {
+ Object *obedit = objects[ob_index];
+ BMEditMesh *em = BKE_editmesh_from_object(obedit);
- if (!EDBM_select_interior_faces(em)) {
- continue;
- }
+ if (!EDBM_select_interior_faces(em)) {
+ continue;
+ }
- DEG_id_tag_update(obedit->data, ID_RECALC_SELECT);
- WM_event_add_notifier(C, NC_GEOM | ND_SELECT, obedit->data);
- }
- MEM_freeN(objects);
+ DEG_id_tag_update(obedit->data, ID_RECALC_SELECT);
+ WM_event_add_notifier(C, NC_GEOM | ND_SELECT, obedit->data);
+ }
+ MEM_freeN(objects);
- return OPERATOR_FINISHED;
+ return OPERATOR_FINISHED;
}
void MESH_OT_select_interior_faces(wmOperatorType *ot)
{
- /* identifiers */
- ot->name = "Select Interior Faces";
- ot->idname = "MESH_OT_select_interior_faces";
- ot->description = "Select faces where all edges have more than 2 face users";
+ /* identifiers */
+ ot->name = "Select Interior Faces";
+ ot->idname = "MESH_OT_select_interior_faces";
+ ot->description = "Select faces where all edges have more than 2 face users";
- /* api callbacks */
- ot->exec = edbm_faces_select_interior_exec;
- ot->poll = ED_operator_editmesh;
+ /* api callbacks */
+ ot->exec = edbm_faces_select_interior_exec;
+ ot->poll = ED_operator_editmesh;
- /* flags */
- ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
+ /* flags */
+ ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
}
/** \} */
@@ -2009,163 +2033,162 @@ void MESH_OT_select_interior_faces(wmOperatorType *ot)
bool EDBM_select_pick(bContext *C, const int mval[2], bool extend, bool deselect, bool toggle)
{
- ViewContext vc;
-
- int base_index_active = -1;
- BMVert *eve = NULL;
- BMEdge *eed = NULL;
- BMFace *efa = NULL;
-
- /* setup view context for argument to callbacks */
- em_setup_viewcontext(C, &vc);
- vc.mval[0] = mval[0];
- vc.mval[1] = mval[1];
-
- uint bases_len = 0;
- Base **bases = BKE_view_layer_array_from_bases_in_edit_mode(vc.view_layer, vc.v3d, &bases_len);
-
- bool ok = false;
-
- if (unified_findnearest(&vc, bases, bases_len, &base_index_active, &eve, &eed, &efa)) {
- Base *basact = bases[base_index_active];
- ED_view3d_viewcontext_init_object(&vc, basact->object);
-
- /* Deselect everything */
- if (extend == false && deselect == false && toggle == false) {
- for (uint base_index = 0; base_index < bases_len; base_index++) {
- Base *base_iter = bases[base_index];
- Object *ob_iter = base_iter->object;
- EDBM_flag_disable_all(BKE_editmesh_from_object(ob_iter), BM_ELEM_SELECT);
- if (basact->object != ob_iter) {
- DEG_id_tag_update(ob_iter->data, ID_RECALC_SELECT);
- WM_event_add_notifier(C, NC_GEOM | ND_SELECT, ob_iter->data);
- }
- }
- }
-
- if (efa) {
- if (extend) {
- /* set the last selected face */
- BM_mesh_active_face_set(vc.em->bm, efa);
-
- /* Work-around: deselect first, so we can guarantee it will */
- /* be active even if it was already selected */
- BM_select_history_remove(vc.em->bm, efa);
- BM_face_select_set(vc.em->bm, efa, false);
- BM_select_history_store(vc.em->bm, efa);
- BM_face_select_set(vc.em->bm, efa, true);
- }
- else if (deselect) {
- BM_select_history_remove(vc.em->bm, efa);
- BM_face_select_set(vc.em->bm, efa, false);
- }
- else {
- /* set the last selected face */
- BM_mesh_active_face_set(vc.em->bm, efa);
-
- if (!BM_elem_flag_test(efa, BM_ELEM_SELECT)) {
- BM_select_history_store(vc.em->bm, efa);
- BM_face_select_set(vc.em->bm, efa, true);
- }
- else if (toggle) {
- BM_select_history_remove(vc.em->bm, efa);
- BM_face_select_set(vc.em->bm, efa, false);
- }
- }
- }
- else if (eed) {
- if (extend) {
- /* Work-around: deselect first, so we can guarantee it will */
- /* be active even if it was already selected */
- BM_select_history_remove(vc.em->bm, eed);
- BM_edge_select_set(vc.em->bm, eed, false);
- BM_select_history_store(vc.em->bm, eed);
- BM_edge_select_set(vc.em->bm, eed, true);
- }
- else if (deselect) {
- BM_select_history_remove(vc.em->bm, eed);
- BM_edge_select_set(vc.em->bm, eed, false);
- }
- else {
- if (!BM_elem_flag_test(eed, BM_ELEM_SELECT)) {
- BM_select_history_store(vc.em->bm, eed);
- BM_edge_select_set(vc.em->bm, eed, true);
- }
- else if (toggle) {
- BM_select_history_remove(vc.em->bm, eed);
- BM_edge_select_set(vc.em->bm, eed, false);
- }
- }
- }
- else if (eve) {
- if (extend) {
- /* Work-around: deselect first, so we can guarantee it will */
- /* be active even if it was already selected */
- BM_select_history_remove(vc.em->bm, eve);
- BM_vert_select_set(vc.em->bm, eve, false);
- BM_select_history_store(vc.em->bm, eve);
- BM_vert_select_set(vc.em->bm, eve, true);
- }
- else if (deselect) {
- BM_select_history_remove(vc.em->bm, eve);
- BM_vert_select_set(vc.em->bm, eve, false);
- }
- else {
- if (!BM_elem_flag_test(eve, BM_ELEM_SELECT)) {
- BM_select_history_store(vc.em->bm, eve);
- BM_vert_select_set(vc.em->bm, eve, true);
- }
- else if (toggle) {
- BM_select_history_remove(vc.em->bm, eve);
- BM_vert_select_set(vc.em->bm, eve, false);
- }
- }
- }
-
- EDBM_selectmode_flush(vc.em);
-
- if (efa) {
- /* Change active material on object. */
- if (efa->mat_nr != vc.obedit->actcol - 1) {
- vc.obedit->actcol = efa->mat_nr + 1;
- vc.em->mat_nr = efa->mat_nr;
- WM_event_add_notifier(C, NC_MATERIAL | ND_SHADING_LINKS, NULL);
- }
-
- /* Change active face-map on object. */
- if (!BLI_listbase_is_empty(&vc.obedit->fmaps)) {
- const int cd_fmap_offset = CustomData_get_offset(&vc.em->bm->pdata, CD_FACEMAP);
- if (cd_fmap_offset != -1) {
- int map = *((int *)BM_ELEM_CD_GET_VOID_P(efa, cd_fmap_offset));
- if ((map < -1) || (map > BLI_listbase_count_at_most(&vc.obedit->fmaps, map))) {
- map = -1;
- }
- map += 1;
- if (map != vc.obedit->actfmap) {
- /* We may want to add notifiers later,
- * currently select update handles redraw. */
- vc.obedit->actfmap = map;
- }
- }
- }
-
- }
-
- /* Changing active object is handy since it allows us to
- * switch UV layers, vgroups for eg. */
- if (vc.view_layer->basact != basact) {
- ED_object_base_activate(C, basact);
- }
-
- DEG_id_tag_update(vc.obedit->data, ID_RECALC_SELECT);
- WM_event_add_notifier(C, NC_GEOM | ND_SELECT, vc.obedit->data);
-
- ok = true;
- }
-
- MEM_freeN(bases);
-
- return ok;
+ ViewContext vc;
+
+ int base_index_active = -1;
+ BMVert *eve = NULL;
+ BMEdge *eed = NULL;
+ BMFace *efa = NULL;
+
+ /* setup view context for argument to callbacks */
+ em_setup_viewcontext(C, &vc);
+ vc.mval[0] = mval[0];
+ vc.mval[1] = mval[1];
+
+ uint bases_len = 0;
+ Base **bases = BKE_view_layer_array_from_bases_in_edit_mode(vc.view_layer, vc.v3d, &bases_len);
+
+ bool ok = false;
+
+ if (unified_findnearest(&vc, bases, bases_len, &base_index_active, &eve, &eed, &efa)) {
+ Base *basact = bases[base_index_active];
+ ED_view3d_viewcontext_init_object(&vc, basact->object);
+
+ /* Deselect everything */
+ if (extend == false && deselect == false && toggle == false) {
+ for (uint base_index = 0; base_index < bases_len; base_index++) {
+ Base *base_iter = bases[base_index];
+ Object *ob_iter = base_iter->object;
+ EDBM_flag_disable_all(BKE_editmesh_from_object(ob_iter), BM_ELEM_SELECT);
+ if (basact->object != ob_iter) {
+ DEG_id_tag_update(ob_iter->data, ID_RECALC_SELECT);
+ WM_event_add_notifier(C, NC_GEOM | ND_SELECT, ob_iter->data);
+ }
+ }
+ }
+
+ if (efa) {
+ if (extend) {
+ /* set the last selected face */
+ BM_mesh_active_face_set(vc.em->bm, efa);
+
+ /* Work-around: deselect first, so we can guarantee it will */
+ /* be active even if it was already selected */
+ BM_select_history_remove(vc.em->bm, efa);
+ BM_face_select_set(vc.em->bm, efa, false);
+ BM_select_history_store(vc.em->bm, efa);
+ BM_face_select_set(vc.em->bm, efa, true);
+ }
+ else if (deselect) {
+ BM_select_history_remove(vc.em->bm, efa);
+ BM_face_select_set(vc.em->bm, efa, false);
+ }
+ else {
+ /* set the last selected face */
+ BM_mesh_active_face_set(vc.em->bm, efa);
+
+ if (!BM_elem_flag_test(efa, BM_ELEM_SELECT)) {
+ BM_select_history_store(vc.em->bm, efa);
+ BM_face_select_set(vc.em->bm, efa, true);
+ }
+ else if (toggle) {
+ BM_select_history_remove(vc.em->bm, efa);
+ BM_face_select_set(vc.em->bm, efa, false);
+ }
+ }
+ }
+ else if (eed) {
+ if (extend) {
+ /* Work-around: deselect first, so we can guarantee it will */
+ /* be active even if it was already selected */
+ BM_select_history_remove(vc.em->bm, eed);
+ BM_edge_select_set(vc.em->bm, eed, false);
+ BM_select_history_store(vc.em->bm, eed);
+ BM_edge_select_set(vc.em->bm, eed, true);
+ }
+ else if (deselect) {
+ BM_select_history_remove(vc.em->bm, eed);
+ BM_edge_select_set(vc.em->bm, eed, false);
+ }
+ else {
+ if (!BM_elem_flag_test(eed, BM_ELEM_SELECT)) {
+ BM_select_history_store(vc.em->bm, eed);
+ BM_edge_select_set(vc.em->bm, eed, true);
+ }
+ else if (toggle) {
+ BM_select_history_remove(vc.em->bm, eed);
+ BM_edge_select_set(vc.em->bm, eed, false);
+ }
+ }
+ }
+ else if (eve) {
+ if (extend) {
+ /* Work-around: deselect first, so we can guarantee it will */
+ /* be active even if it was already selected */
+ BM_select_history_remove(vc.em->bm, eve);
+ BM_vert_select_set(vc.em->bm, eve, false);
+ BM_select_history_store(vc.em->bm, eve);
+ BM_vert_select_set(vc.em->bm, eve, true);
+ }
+ else if (deselect) {
+ BM_select_history_remove(vc.em->bm, eve);
+ BM_vert_select_set(vc.em->bm, eve, false);
+ }
+ else {
+ if (!BM_elem_flag_test(eve, BM_ELEM_SELECT)) {
+ BM_select_history_store(vc.em->bm, eve);
+ BM_vert_select_set(vc.em->bm, eve, true);
+ }
+ else if (toggle) {
+ BM_select_history_remove(vc.em->bm, eve);
+ BM_vert_select_set(vc.em->bm, eve, false);
+ }
+ }
+ }
+
+ EDBM_selectmode_flush(vc.em);
+
+ if (efa) {
+ /* Change active material on object. */
+ if (efa->mat_nr != vc.obedit->actcol - 1) {
+ vc.obedit->actcol = efa->mat_nr + 1;
+ vc.em->mat_nr = efa->mat_nr;
+ WM_event_add_notifier(C, NC_MATERIAL | ND_SHADING_LINKS, NULL);
+ }
+
+ /* Change active face-map on object. */
+ if (!BLI_listbase_is_empty(&vc.obedit->fmaps)) {
+ const int cd_fmap_offset = CustomData_get_offset(&vc.em->bm->pdata, CD_FACEMAP);
+ if (cd_fmap_offset != -1) {
+ int map = *((int *)BM_ELEM_CD_GET_VOID_P(efa, cd_fmap_offset));
+ if ((map < -1) || (map > BLI_listbase_count_at_most(&vc.obedit->fmaps, map))) {
+ map = -1;
+ }
+ map += 1;
+ if (map != vc.obedit->actfmap) {
+ /* We may want to add notifiers later,
+ * currently select update handles redraw. */
+ vc.obedit->actfmap = map;
+ }
+ }
+ }
+ }
+
+ /* Changing active object is handy since it allows us to
+ * switch UV layers, vgroups for eg. */
+ if (vc.view_layer->basact != basact) {
+ ED_object_base_activate(C, basact);
+ }
+
+ DEG_id_tag_update(vc.obedit->data, ID_RECALC_SELECT);
+ WM_event_add_notifier(C, NC_GEOM | ND_SELECT, vc.obedit->data);
+
+ ok = true;
+ }
+
+ MEM_freeN(bases);
+
+ return ok;
}
/** \} */
@@ -2176,91 +2199,91 @@ bool EDBM_select_pick(bContext *C, const int mval[2], bool extend, bool deselect
static void edbm_strip_selections(BMEditMesh *em)
{
- BMEditSelection *ese, *nextese;
-
- if (!(em->selectmode & SCE_SELECT_VERTEX)) {
- ese = em->bm->selected.first;
- while (ese) {
- nextese = ese->next;
- if (ese->htype == BM_VERT) BLI_freelinkN(&(em->bm->selected), ese);
- ese = nextese;
- }
- }
- if (!(em->selectmode & SCE_SELECT_EDGE)) {
- ese = em->bm->selected.first;
- while (ese) {
- nextese = ese->next;
- if (ese->htype == BM_EDGE) BLI_freelinkN(&(em->bm->selected), ese);
- ese = nextese;
- }
- }
- if (!(em->selectmode & SCE_SELECT_FACE)) {
- ese = em->bm->selected.first;
- while (ese) {
- nextese = ese->next;
- if (ese->htype == BM_FACE) BLI_freelinkN(&(em->bm->selected), ese);
- ese = nextese;
- }
- }
+ BMEditSelection *ese, *nextese;
+
+ if (!(em->selectmode & SCE_SELECT_VERTEX)) {
+ ese = em->bm->selected.first;
+ while (ese) {
+ nextese = ese->next;
+ if (ese->htype == BM_VERT)
+ BLI_freelinkN(&(em->bm->selected), ese);
+ ese = nextese;
+ }
+ }
+ if (!(em->selectmode & SCE_SELECT_EDGE)) {
+ ese = em->bm->selected.first;
+ while (ese) {
+ nextese = ese->next;
+ if (ese->htype == BM_EDGE)
+ BLI_freelinkN(&(em->bm->selected), ese);
+ ese = nextese;
+ }
+ }
+ if (!(em->selectmode & SCE_SELECT_FACE)) {
+ ese = em->bm->selected.first;
+ while (ese) {
+ nextese = ese->next;
+ if (ese->htype == BM_FACE)
+ BLI_freelinkN(&(em->bm->selected), ese);
+ ese = nextese;
+ }
+ }
}
/* when switching select mode, makes sure selection is consistent for editing */
/* also for paranoia checks to make sure edge or face mode works */
void EDBM_selectmode_set(BMEditMesh *em)
{
- BMVert *eve;
- BMEdge *eed;
- BMFace *efa;
- BMIter iter;
-
- em->bm->selectmode = em->selectmode;
-
- /* strip BMEditSelections from em->selected that are not relevant to new mode */
- edbm_strip_selections(em);
-
- if (em->bm->totvertsel == 0 &&
- em->bm->totedgesel == 0 &&
- em->bm->totfacesel == 0)
- {
- return;
- }
-
- if (em->selectmode & SCE_SELECT_VERTEX) {
- if (em->bm->totvertsel) {
- EDBM_select_flush(em);
- }
- }
- else if (em->selectmode & SCE_SELECT_EDGE) {
- /* deselect vertices, and select again based on edge select */
- BM_ITER_MESH (eve, &iter, em->bm, BM_VERTS_OF_MESH) {
- BM_vert_select_set(em->bm, eve, false);
- }
-
- if (em->bm->totedgesel) {
- BM_ITER_MESH (eed, &iter, em->bm, BM_EDGES_OF_MESH) {
- if (BM_elem_flag_test(eed, BM_ELEM_SELECT)) {
- BM_edge_select_set(em->bm, eed, true);
- }
- }
-
- /* selects faces based on edge status */
- EDBM_selectmode_flush(em);
- }
- }
- else if (em->selectmode & SCE_SELECT_FACE) {
- /* deselect eges, and select again based on face select */
- BM_ITER_MESH (eed, &iter, em->bm, BM_EDGES_OF_MESH) {
- BM_edge_select_set(em->bm, eed, false);
- }
-
- if (em->bm->totfacesel) {
- BM_ITER_MESH (efa, &iter, em->bm, BM_FACES_OF_MESH) {
- if (BM_elem_flag_test(efa, BM_ELEM_SELECT)) {
- BM_face_select_set(em->bm, efa, true);
- }
- }
- }
- }
+ BMVert *eve;
+ BMEdge *eed;
+ BMFace *efa;
+ BMIter iter;
+
+ em->bm->selectmode = em->selectmode;
+
+ /* strip BMEditSelections from em->selected that are not relevant to new mode */
+ edbm_strip_selections(em);
+
+ if (em->bm->totvertsel == 0 && em->bm->totedgesel == 0 && em->bm->totfacesel == 0) {
+ return;
+ }
+
+ if (em->selectmode & SCE_SELECT_VERTEX) {
+ if (em->bm->totvertsel) {
+ EDBM_select_flush(em);
+ }
+ }
+ else if (em->selectmode & SCE_SELECT_EDGE) {
+ /* deselect vertices, and select again based on edge select */
+ BM_ITER_MESH (eve, &iter, em->bm, BM_VERTS_OF_MESH) {
+ BM_vert_select_set(em->bm, eve, false);
+ }
+
+ if (em->bm->totedgesel) {
+ BM_ITER_MESH (eed, &iter, em->bm, BM_EDGES_OF_MESH) {
+ if (BM_elem_flag_test(eed, BM_ELEM_SELECT)) {
+ BM_edge_select_set(em->bm, eed, true);
+ }
+ }
+
+ /* selects faces based on edge status */
+ EDBM_selectmode_flush(em);
+ }
+ }
+ else if (em->selectmode & SCE_SELECT_FACE) {
+ /* deselect eges, and select again based on face select */
+ BM_ITER_MESH (eed, &iter, em->bm, BM_EDGES_OF_MESH) {
+ BM_edge_select_set(em->bm, eed, false);
+ }
+
+ if (em->bm->totfacesel) {
+ BM_ITER_MESH (efa, &iter, em->bm, BM_FACES_OF_MESH) {
+ if (BM_elem_flag_test(efa, BM_ELEM_SELECT)) {
+ BM_face_select_set(em->bm, efa, true);
+ }
+ }
+ }
+ }
}
/**
@@ -2277,230 +2300,235 @@ void EDBM_selectmode_set(BMEditMesh *em)
* - face -> vert
* - edge -> vert
*/
-void EDBM_selectmode_convert(BMEditMesh *em, const short selectmode_old, const short selectmode_new)
+void EDBM_selectmode_convert(BMEditMesh *em,
+ const short selectmode_old,
+ const short selectmode_new)
{
- BMesh *bm = em->bm;
-
- BMVert *eve;
- BMEdge *eed;
- BMFace *efa;
- BMIter iter;
-
- /* first tag-to-select, then select --- this avoids a feedback loop */
-
- /* have to find out what the selectionmode was previously */
- if (selectmode_old == SCE_SELECT_VERTEX) {
- if (bm->totvertsel == 0) {
- /* pass */
- }
- else if (selectmode_new == SCE_SELECT_EDGE) {
- /* flush up (vert -> edge) */
-
- /* select all edges associated with every selected vert */
- BM_ITER_MESH (eed, &iter, bm, BM_EDGES_OF_MESH) {
- BM_elem_flag_set(eed, BM_ELEM_TAG, BM_edge_is_any_vert_flag_test(eed, BM_ELEM_SELECT));
- }
-
- BM_ITER_MESH (eed, &iter, bm, BM_EDGES_OF_MESH) {
- if (BM_elem_flag_test(eed, BM_ELEM_TAG)) {
- BM_edge_select_set(bm, eed, true);
- }
- }
- }
- else if (selectmode_new == SCE_SELECT_FACE) {
- /* flush up (vert -> face) */
-
- /* select all faces associated with every selected vert */
- BM_ITER_MESH (efa, &iter, bm, BM_FACES_OF_MESH) {
- BM_elem_flag_set(efa, BM_ELEM_TAG, BM_face_is_any_vert_flag_test(efa, BM_ELEM_SELECT));
- }
-
- BM_ITER_MESH (efa, &iter, bm, BM_FACES_OF_MESH) {
- if (BM_elem_flag_test(efa, BM_ELEM_TAG)) {
- BM_face_select_set(bm, efa, true);
- }
- }
- }
- }
- else if (selectmode_old == SCE_SELECT_EDGE) {
- if (bm->totedgesel == 0) {
- /* pass */
- }
- else if (selectmode_new == SCE_SELECT_FACE) {
- /* flush up (edge -> face) */
-
- /* select all faces associated with every selected edge */
- BM_ITER_MESH (efa, &iter, bm, BM_FACES_OF_MESH) {
- BM_elem_flag_set(efa, BM_ELEM_TAG, BM_face_is_any_edge_flag_test(efa, BM_ELEM_SELECT));
- }
-
- BM_ITER_MESH (efa, &iter, bm, BM_FACES_OF_MESH) {
- if (BM_elem_flag_test(efa, BM_ELEM_TAG)) {
- BM_face_select_set(bm, efa, true);
- }
- }
- }
- else if (selectmode_new == SCE_SELECT_VERTEX) {
- /* flush down (edge -> vert) */
-
- BM_ITER_MESH (eve, &iter, bm, BM_VERTS_OF_MESH) {
- if (!BM_vert_is_all_edge_flag_test(eve, BM_ELEM_SELECT, true)) {
- BM_vert_select_set(bm, eve, false);
- }
- }
- /* deselect edges without both verts selected */
- BM_mesh_deselect_flush(bm);
- }
- }
- else if (selectmode_old == SCE_SELECT_FACE) {
- if (bm->totfacesel == 0) {
- /* pass */
- }
- else if (selectmode_new == SCE_SELECT_EDGE) {
- /* flush down (face -> edge) */
-
- BM_ITER_MESH (eed, &iter, bm, BM_EDGES_OF_MESH) {
- if (!BM_edge_is_all_face_flag_test(eed, BM_ELEM_SELECT, true)) {
- BM_edge_select_set(bm, eed, false);
- }
- }
- }
- else if (selectmode_new == SCE_SELECT_VERTEX) {
- /* flush down (face -> vert) */
-
- BM_ITER_MESH (eve, &iter, bm, BM_VERTS_OF_MESH) {
- if (!BM_vert_is_all_face_flag_test(eve, BM_ELEM_SELECT, true)) {
- BM_vert_select_set(bm, eve, false);
- }
- }
- /* deselect faces without verts selected */
- BM_mesh_deselect_flush(bm);
- }
- }
+ BMesh *bm = em->bm;
+
+ BMVert *eve;
+ BMEdge *eed;
+ BMFace *efa;
+ BMIter iter;
+
+ /* first tag-to-select, then select --- this avoids a feedback loop */
+
+ /* have to find out what the selectionmode was previously */
+ if (selectmode_old == SCE_SELECT_VERTEX) {
+ if (bm->totvertsel == 0) {
+ /* pass */
+ }
+ else if (selectmode_new == SCE_SELECT_EDGE) {
+ /* flush up (vert -> edge) */
+
+ /* select all edges associated with every selected vert */
+ BM_ITER_MESH (eed, &iter, bm, BM_EDGES_OF_MESH) {
+ BM_elem_flag_set(eed, BM_ELEM_TAG, BM_edge_is_any_vert_flag_test(eed, BM_ELEM_SELECT));
+ }
+
+ BM_ITER_MESH (eed, &iter, bm, BM_EDGES_OF_MESH) {
+ if (BM_elem_flag_test(eed, BM_ELEM_TAG)) {
+ BM_edge_select_set(bm, eed, true);
+ }
+ }
+ }
+ else if (selectmode_new == SCE_SELECT_FACE) {
+ /* flush up (vert -> face) */
+
+ /* select all faces associated with every selected vert */
+ BM_ITER_MESH (efa, &iter, bm, BM_FACES_OF_MESH) {
+ BM_elem_flag_set(efa, BM_ELEM_TAG, BM_face_is_any_vert_flag_test(efa, BM_ELEM_SELECT));
+ }
+
+ BM_ITER_MESH (efa, &iter, bm, BM_FACES_OF_MESH) {
+ if (BM_elem_flag_test(efa, BM_ELEM_TAG)) {
+ BM_face_select_set(bm, efa, true);
+ }
+ }
+ }
+ }
+ else if (selectmode_old == SCE_SELECT_EDGE) {
+ if (bm->totedgesel == 0) {
+ /* pass */
+ }
+ else if (selectmode_new == SCE_SELECT_FACE) {
+ /* flush up (edge -> face) */
+
+ /* select all faces associated with every selected edge */
+ BM_ITER_MESH (efa, &iter, bm, BM_FACES_OF_MESH) {
+ BM_elem_flag_set(efa, BM_ELEM_TAG, BM_face_is_any_edge_flag_test(efa, BM_ELEM_SELECT));
+ }
+
+ BM_ITER_MESH (efa, &iter, bm, BM_FACES_OF_MESH) {
+ if (BM_elem_flag_test(efa, BM_ELEM_TAG)) {
+ BM_face_select_set(bm, efa, true);
+ }
+ }
+ }
+ else if (selectmode_new == SCE_SELECT_VERTEX) {
+ /* flush down (edge -> vert) */
+
+ BM_ITER_MESH (eve, &iter, bm, BM_VERTS_OF_MESH) {
+ if (!BM_vert_is_all_edge_flag_test(eve, BM_ELEM_SELECT, true)) {
+ BM_vert_select_set(bm, eve, false);
+ }
+ }
+ /* deselect edges without both verts selected */
+ BM_mesh_deselect_flush(bm);
+ }
+ }
+ else if (selectmode_old == SCE_SELECT_FACE) {
+ if (bm->totfacesel == 0) {
+ /* pass */
+ }
+ else if (selectmode_new == SCE_SELECT_EDGE) {
+ /* flush down (face -> edge) */
+
+ BM_ITER_MESH (eed, &iter, bm, BM_EDGES_OF_MESH) {
+ if (!BM_edge_is_all_face_flag_test(eed, BM_ELEM_SELECT, true)) {
+ BM_edge_select_set(bm, eed, false);
+ }
+ }
+ }
+ else if (selectmode_new == SCE_SELECT_VERTEX) {
+ /* flush down (face -> vert) */
+
+ BM_ITER_MESH (eve, &iter, bm, BM_VERTS_OF_MESH) {
+ if (!BM_vert_is_all_face_flag_test(eve, BM_ELEM_SELECT, true)) {
+ BM_vert_select_set(bm, eve, false);
+ }
+ }
+ /* deselect faces without verts selected */
+ BM_mesh_deselect_flush(bm);
+ }
+ }
}
/* user facing function, does notification */
-bool EDBM_selectmode_toggle(
- bContext *C, const short selectmode_new,
- const int action, const bool use_extend, const bool use_expand)
+bool EDBM_selectmode_toggle(bContext *C,
+ const short selectmode_new,
+ const int action,
+ const bool use_extend,
+ const bool use_expand)
{
- Scene *scene = CTX_data_scene(C);
- ViewLayer *view_layer = CTX_data_view_layer(C);
- ToolSettings *ts = CTX_data_tool_settings(C);
- Object *obedit = CTX_data_edit_object(C);
- BMEditMesh *em = NULL;
- bool ret = false;
-
- if (obedit && obedit->type == OB_MESH) {
- em = BKE_editmesh_from_object(obedit);
- }
-
- if (em == NULL) {
- return ret;
- }
-
- bool only_update = false;
- switch (action) {
- case -1:
- /* already set */
- break;
- case 0: /* disable */
- /* check we have something to do */
- if ((em->selectmode & selectmode_new) == 0) {
- only_update = true;
- break;
- }
- em->selectmode &= ~selectmode_new;
- break;
- case 1: /* enable */
- /* check we have something to do */
- if ((em->selectmode & selectmode_new) != 0) {
- only_update = true;
- break;
- }
- em->selectmode |= selectmode_new;
- break;
- case 2: /* toggle */
- /* can't disable this flag if its the only one set */
- if (em->selectmode == selectmode_new) {
- only_update = true;
- break;
- }
- em->selectmode ^= selectmode_new;
- break;
- default:
- BLI_assert(0);
- break;
- }
-
- uint objects_len = 0;
- Object **objects = BKE_view_layer_array_from_objects_in_edit_mode_unique_data(view_layer, CTX_wm_view3d(C), &objects_len);
-
- for (uint ob_index = 0; ob_index < objects_len; ob_index++) {
- Object *ob_iter = objects[ob_index];
- BMEditMesh *em_iter = BKE_editmesh_from_object(ob_iter);
- if (em_iter != em) {
- em_iter->selectmode = em->selectmode;
- }
- }
-
- if (only_update) {
- MEM_freeN(objects);
- return false;
- }
-
- if (use_extend == 0 || em->selectmode == 0) {
- if (use_expand) {
- const short selmode_max = highest_order_bit_s(ts->selectmode);
- for (uint ob_index = 0; ob_index < objects_len; ob_index++) {
- Object *ob_iter = objects[ob_index];
- BMEditMesh *em_iter = BKE_editmesh_from_object(ob_iter);
- EDBM_selectmode_convert(em_iter, selmode_max, selectmode_new);
- }
- }
- }
-
- switch (selectmode_new) {
- case SCE_SELECT_VERTEX:
- if (use_extend == 0 || em->selectmode == 0) {
- em->selectmode = SCE_SELECT_VERTEX;
- }
- ret = true;
- break;
- case SCE_SELECT_EDGE:
- if (use_extend == 0 || em->selectmode == 0) {
- em->selectmode = SCE_SELECT_EDGE;
- }
- ret = true;
- break;
- case SCE_SELECT_FACE:
- if (use_extend == 0 || em->selectmode == 0) {
- em->selectmode = SCE_SELECT_FACE;
- }
- ret = true;
- break;
- default:
- BLI_assert(0);
- break;
- }
-
- if (ret == true) {
- ts->selectmode = em->selectmode;
- em = NULL;
- for (uint ob_index = 0; ob_index < objects_len; ob_index++) {
- Object *ob_iter = objects[ob_index];
- BMEditMesh *em_iter = BKE_editmesh_from_object(ob_iter);
- em_iter->selectmode = ts->selectmode;
- EDBM_selectmode_set(em_iter);
- DEG_id_tag_update(ob_iter->data, ID_RECALC_COPY_ON_WRITE | ID_RECALC_SELECT);
- WM_event_add_notifier(C, NC_GEOM | ND_SELECT, ob_iter->data);
- }
- WM_main_add_notifier(NC_SCENE | ND_TOOLSETTINGS, NULL);
- DEG_id_tag_update(&scene->id, ID_RECALC_COPY_ON_WRITE);
- }
-
- MEM_freeN(objects);
- return ret;
+ Scene *scene = CTX_data_scene(C);
+ ViewLayer *view_layer = CTX_data_view_layer(C);
+ ToolSettings *ts = CTX_data_tool_settings(C);
+ Object *obedit = CTX_data_edit_object(C);
+ BMEditMesh *em = NULL;
+ bool ret = false;
+
+ if (obedit && obedit->type == OB_MESH) {
+ em = BKE_editmesh_from_object(obedit);
+ }
+
+ if (em == NULL) {
+ return ret;
+ }
+
+ bool only_update = false;
+ switch (action) {
+ case -1:
+ /* already set */
+ break;
+ case 0: /* disable */
+ /* check we have something to do */
+ if ((em->selectmode & selectmode_new) == 0) {
+ only_update = true;
+ break;
+ }
+ em->selectmode &= ~selectmode_new;
+ break;
+ case 1: /* enable */
+ /* check we have something to do */
+ if ((em->selectmode & selectmode_new) != 0) {
+ only_update = true;
+ break;
+ }
+ em->selectmode |= selectmode_new;
+ break;
+ case 2: /* toggle */
+ /* can't disable this flag if its the only one set */
+ if (em->selectmode == selectmode_new) {
+ only_update = true;
+ break;
+ }
+ em->selectmode ^= selectmode_new;
+ break;
+ default:
+ BLI_assert(0);
+ break;
+ }
+
+ uint objects_len = 0;
+ Object **objects = BKE_view_layer_array_from_objects_in_edit_mode_unique_data(
+ view_layer, CTX_wm_view3d(C), &objects_len);
+
+ for (uint ob_index = 0; ob_index < objects_len; ob_index++) {
+ Object *ob_iter = objects[ob_index];
+ BMEditMesh *em_iter = BKE_editmesh_from_object(ob_iter);
+ if (em_iter != em) {
+ em_iter->selectmode = em->selectmode;
+ }
+ }
+
+ if (only_update) {
+ MEM_freeN(objects);
+ return false;
+ }
+
+ if (use_extend == 0 || em->selectmode == 0) {
+ if (use_expand) {
+ const short selmode_max = highest_order_bit_s(ts->selectmode);
+ for (uint ob_index = 0; ob_index < objects_len; ob_index++) {
+ Object *ob_iter = objects[ob_index];
+ BMEditMesh *em_iter = BKE_editmesh_from_object(ob_iter);
+ EDBM_selectmode_convert(em_iter, selmode_max, selectmode_new);
+ }
+ }
+ }
+
+ switch (selectmode_new) {
+ case SCE_SELECT_VERTEX:
+ if (use_extend == 0 || em->selectmode == 0) {
+ em->selectmode = SCE_SELECT_VERTEX;
+ }
+ ret = true;
+ break;
+ case SCE_SELECT_EDGE:
+ if (use_extend == 0 || em->selectmode == 0) {
+ em->selectmode = SCE_SELECT_EDGE;
+ }
+ ret = true;
+ break;
+ case SCE_SELECT_FACE:
+ if (use_extend == 0 || em->selectmode == 0) {
+ em->selectmode = SCE_SELECT_FACE;
+ }
+ ret = true;
+ break;
+ default:
+ BLI_assert(0);
+ break;
+ }
+
+ if (ret == true) {
+ ts->selectmode = em->selectmode;
+ em = NULL;
+ for (uint ob_index = 0; ob_index < objects_len; ob_index++) {
+ Object *ob_iter = objects[ob_index];
+ BMEditMesh *em_iter = BKE_editmesh_from_object(ob_iter);
+ em_iter->selectmode = ts->selectmode;
+ EDBM_selectmode_set(em_iter);
+ DEG_id_tag_update(ob_iter->data, ID_RECALC_COPY_ON_WRITE | ID_RECALC_SELECT);
+ WM_event_add_notifier(C, NC_GEOM | ND_SELECT, ob_iter->data);
+ }
+ WM_main_add_notifier(NC_SCENE | ND_TOOLSETTINGS, NULL);
+ DEG_id_tag_update(&scene->id, ID_RECALC_COPY_ON_WRITE);
+ }
+
+ MEM_freeN(objects);
+ return ret;
}
/**
@@ -2509,30 +2537,30 @@ bool EDBM_selectmode_toggle(
*
* \return true if the mode is changed.
*/
-bool EDBM_selectmode_disable(
- Scene *scene, BMEditMesh *em,
- const short selectmode_disable,
- const short selectmode_fallback)
+bool EDBM_selectmode_disable(Scene *scene,
+ BMEditMesh *em,
+ const short selectmode_disable,
+ const short selectmode_fallback)
{
- /* note essential, but switch out of vertex mode since the
- * selected regions wont be nicely isolated after flushing */
- if (em->selectmode & selectmode_disable) {
- if (em->selectmode == selectmode_disable) {
- em->selectmode = selectmode_fallback;
- }
- else {
- em->selectmode &= ~selectmode_disable;
- }
- scene->toolsettings->selectmode = em->selectmode;
- EDBM_selectmode_set(em);
-
- WM_main_add_notifier(NC_SCENE | ND_TOOLSETTINGS, scene);
-
- return true;
- }
- else {
- return false;
- }
+ /* note essential, but switch out of vertex mode since the
+ * selected regions wont be nicely isolated after flushing */
+ if (em->selectmode & selectmode_disable) {
+ if (em->selectmode == selectmode_disable) {
+ em->selectmode = selectmode_fallback;
+ }
+ else {
+ em->selectmode &= ~selectmode_disable;
+ }
+ scene->toolsettings->selectmode = em->selectmode;
+ EDBM_selectmode_set(em);
+
+ WM_main_add_notifier(NC_SCENE | ND_TOOLSETTINGS, scene);
+
+ return true;
+ }
+ else {
+ return false;
+ }
}
/** \} */
@@ -2543,88 +2571,88 @@ bool EDBM_selectmode_disable(
bool EDBM_deselect_by_material(BMEditMesh *em, const short index, const bool select)
{
- BMIter iter;
- BMFace *efa;
- bool changed = false;
-
- BM_ITER_MESH (efa, &iter, em->bm, BM_FACES_OF_MESH) {
- if (BM_elem_flag_test(efa, BM_ELEM_HIDDEN))
- continue;
- if (efa->mat_nr == index) {
- changed = true;
- BM_face_select_set(em->bm, efa, select);
- }
- }
- return changed;
+ BMIter iter;
+ BMFace *efa;
+ bool changed = false;
+
+ BM_ITER_MESH (efa, &iter, em->bm, BM_FACES_OF_MESH) {
+ if (BM_elem_flag_test(efa, BM_ELEM_HIDDEN))
+ continue;
+ if (efa->mat_nr == index) {
+ changed = true;
+ BM_face_select_set(em->bm, efa, select);
+ }
+ }
+ return changed;
}
void EDBM_select_toggle_all(BMEditMesh *em) /* exported for UV */
{
- if (em->bm->totvertsel || em->bm->totedgesel || em->bm->totfacesel)
- EDBM_flag_disable_all(em, BM_ELEM_SELECT);
- else
- EDBM_flag_enable_all(em, BM_ELEM_SELECT);
+ if (em->bm->totvertsel || em->bm->totedgesel || em->bm->totfacesel)
+ EDBM_flag_disable_all(em, BM_ELEM_SELECT);
+ else
+ EDBM_flag_enable_all(em, BM_ELEM_SELECT);
}
void EDBM_select_swap(BMEditMesh *em) /* exported for UV */
{
- BMIter iter;
- BMVert *eve;
- BMEdge *eed;
- BMFace *efa;
-
- if (em->bm->selectmode & SCE_SELECT_VERTEX) {
- BM_ITER_MESH (eve, &iter, em->bm, BM_VERTS_OF_MESH) {
- if (BM_elem_flag_test(eve, BM_ELEM_HIDDEN))
- continue;
- BM_vert_select_set(em->bm, eve, !BM_elem_flag_test(eve, BM_ELEM_SELECT));
- }
- }
- else if (em->selectmode & SCE_SELECT_EDGE) {
- BM_ITER_MESH (eed, &iter, em->bm, BM_EDGES_OF_MESH) {
- if (BM_elem_flag_test(eed, BM_ELEM_HIDDEN))
- continue;
- BM_edge_select_set(em->bm, eed, !BM_elem_flag_test(eed, BM_ELEM_SELECT));
- }
- }
- else {
- BM_ITER_MESH (efa, &iter, em->bm, BM_FACES_OF_MESH) {
- if (BM_elem_flag_test(efa, BM_ELEM_HIDDEN))
- continue;
- BM_face_select_set(em->bm, efa, !BM_elem_flag_test(efa, BM_ELEM_SELECT));
- }
-
- }
+ BMIter iter;
+ BMVert *eve;
+ BMEdge *eed;
+ BMFace *efa;
+
+ if (em->bm->selectmode & SCE_SELECT_VERTEX) {
+ BM_ITER_MESH (eve, &iter, em->bm, BM_VERTS_OF_MESH) {
+ if (BM_elem_flag_test(eve, BM_ELEM_HIDDEN))
+ continue;
+ BM_vert_select_set(em->bm, eve, !BM_elem_flag_test(eve, BM_ELEM_SELECT));
+ }
+ }
+ else if (em->selectmode & SCE_SELECT_EDGE) {
+ BM_ITER_MESH (eed, &iter, em->bm, BM_EDGES_OF_MESH) {
+ if (BM_elem_flag_test(eed, BM_ELEM_HIDDEN))
+ continue;
+ BM_edge_select_set(em->bm, eed, !BM_elem_flag_test(eed, BM_ELEM_SELECT));
+ }
+ }
+ else {
+ BM_ITER_MESH (efa, &iter, em->bm, BM_FACES_OF_MESH) {
+ if (BM_elem_flag_test(efa, BM_ELEM_HIDDEN))
+ continue;
+ BM_face_select_set(em->bm, efa, !BM_elem_flag_test(efa, BM_ELEM_SELECT));
+ }
+ }
}
bool EDBM_mesh_deselect_all_multi_ex(struct Base **bases, const uint bases_len)
{
- bool changed_multi = false;
- for (uint base_index = 0; base_index < bases_len; base_index++) {
- Base *base_iter = bases[base_index];
- Object *ob_iter = base_iter->object;
- BMEditMesh *em_iter = BKE_editmesh_from_object(ob_iter);
-
- if (em_iter->bm->totvertsel == 0) {
- continue;
- }
-
- EDBM_flag_disable_all(em_iter, BM_ELEM_SELECT);
- DEG_id_tag_update(ob_iter->data, ID_RECALC_SELECT);
- changed_multi = true;
- }
- return changed_multi;
+ bool changed_multi = false;
+ for (uint base_index = 0; base_index < bases_len; base_index++) {
+ Base *base_iter = bases[base_index];
+ Object *ob_iter = base_iter->object;
+ BMEditMesh *em_iter = BKE_editmesh_from_object(ob_iter);
+
+ if (em_iter->bm->totvertsel == 0) {
+ continue;
+ }
+
+ EDBM_flag_disable_all(em_iter, BM_ELEM_SELECT);
+ DEG_id_tag_update(ob_iter->data, ID_RECALC_SELECT);
+ changed_multi = true;
+ }
+ return changed_multi;
}
bool EDBM_mesh_deselect_all_multi(struct bContext *C)
{
- ViewContext vc;
- ED_view3d_viewcontext_init(C, &vc);
- uint bases_len = 0;
- Base **bases = BKE_view_layer_array_from_bases_in_edit_mode_unique_data(vc.view_layer, vc.v3d, &bases_len);
- bool changed_multi = EDBM_mesh_deselect_all_multi_ex(bases, bases_len);
- MEM_freeN(bases);
- return changed_multi;
+ ViewContext vc;
+ ED_view3d_viewcontext_init(C, &vc);
+ uint bases_len = 0;
+ Base **bases = BKE_view_layer_array_from_bases_in_edit_mode_unique_data(
+ vc.view_layer, vc.v3d, &bases_len);
+ bool changed_multi = EDBM_mesh_deselect_all_multi_ex(bases, bases_len);
+ MEM_freeN(bases);
+ return changed_multi;
}
/** \} */
@@ -2638,34 +2666,33 @@ bool EDBM_mesh_deselect_all_multi(struct bContext *C)
bool EDBM_select_interior_faces(BMEditMesh *em)
{
- BMesh *bm = em->bm;
- BMIter iter;
- BMIter eiter;
- BMFace *efa;
- BMEdge *eed;
- bool ok;
- bool changed = false;
-
- BM_ITER_MESH (efa, &iter, em->bm, BM_FACES_OF_MESH) {
- if (BM_elem_flag_test(efa, BM_ELEM_HIDDEN))
- continue;
-
-
- ok = true;
- BM_ITER_ELEM (eed, &eiter, efa, BM_EDGES_OF_FACE) {
- if (!BM_edge_face_count_is_over(eed, 2)) {
- ok = false;
- break;
- }
- }
-
- if (ok) {
- BM_face_select_set(bm, efa, true);
- changed = true;
- }
- }
-
- return changed;
+ BMesh *bm = em->bm;
+ BMIter iter;
+ BMIter eiter;
+ BMFace *efa;
+ BMEdge *eed;
+ bool ok;
+ bool changed = false;
+
+ BM_ITER_MESH (efa, &iter, em->bm, BM_FACES_OF_MESH) {
+ if (BM_elem_flag_test(efa, BM_ELEM_HIDDEN))
+ continue;
+
+ ok = true;
+ BM_ITER_ELEM (eed, &eiter, efa, BM_EDGES_OF_FACE) {
+ if (!BM_edge_face_count_is_over(eed, 2)) {
+ ok = false;
+ break;
+ }
+ }
+
+ if (ok) {
+ BM_face_select_set(bm, efa, true);
+ changed = true;
+ }
+ }
+
+ return changed;
}
/** \} */
@@ -2680,53 +2707,54 @@ bool EDBM_select_interior_faces(BMEditMesh *em)
#define USE_LINKED_SELECT_DEFAULT_HACK
struct DelimitData {
- int cd_loop_type;
- int cd_loop_offset;
+ int cd_loop_type;
+ int cd_loop_offset;
};
-static bool select_linked_delimit_test(
- BMEdge *e, int delimit,
- const struct DelimitData *delimit_data)
+static bool select_linked_delimit_test(BMEdge *e,
+ int delimit,
+ const struct DelimitData *delimit_data)
{
- BLI_assert(delimit);
-
- if (delimit & BMO_DELIM_SEAM) {
- if (BM_elem_flag_test(e, BM_ELEM_SEAM)) {
- return true;
- }
- }
-
- if (delimit & BMO_DELIM_SHARP) {
- if (BM_elem_flag_test(e, BM_ELEM_SMOOTH) == 0) {
- return true;
- }
- }
-
- if (delimit & BMO_DELIM_NORMAL) {
- if (!BM_edge_is_contiguous(e)) {
- return true;
- }
- }
-
- if (delimit & BMO_DELIM_MATERIAL) {
- if (e->l && e->l->radial_next != e->l) {
- const short mat_nr = e->l->f->mat_nr;
- BMLoop *l_iter = e->l->radial_next;
- do {
- if (l_iter->f->mat_nr != mat_nr) {
- return true;
- }
- } while ((l_iter = l_iter->radial_next) != e->l);
- }
- }
-
- if (delimit & BMO_DELIM_UV) {
- if (BM_edge_is_contiguous_loop_cd(e, delimit_data->cd_loop_type, delimit_data->cd_loop_offset) == 0) {
- return true;
- }
- }
-
- return false;
+ BLI_assert(delimit);
+
+ if (delimit & BMO_DELIM_SEAM) {
+ if (BM_elem_flag_test(e, BM_ELEM_SEAM)) {
+ return true;
+ }
+ }
+
+ if (delimit & BMO_DELIM_SHARP) {
+ if (BM_elem_flag_test(e, BM_ELEM_SMOOTH) == 0) {
+ return true;
+ }
+ }
+
+ if (delimit & BMO_DELIM_NORMAL) {
+ if (!BM_edge_is_contiguous(e)) {
+ return true;
+ }
+ }
+
+ if (delimit & BMO_DELIM_MATERIAL) {
+ if (e->l && e->l->radial_next != e->l) {
+ const short mat_nr = e->l->f->mat_nr;
+ BMLoop *l_iter = e->l->radial_next;
+ do {
+ if (l_iter->f->mat_nr != mat_nr) {
+ return true;
+ }
+ } while ((l_iter = l_iter->radial_next) != e->l);
+ }
+ }
+
+ if (delimit & BMO_DELIM_UV) {
+ if (BM_edge_is_contiguous_loop_cd(
+ e, delimit_data->cd_loop_type, delimit_data->cd_loop_offset) == 0) {
+ return true;
+ }
+ }
+
+ return false;
}
#ifdef USE_LINKED_SELECT_DEFAULT_HACK
@@ -2736,277 +2764,294 @@ static bool select_linked_delimit_test(
*/
static int select_linked_delimit_default_from_op(wmOperator *op, const int select_mode)
{
- static char delimit_last_store[2] = {0, BMO_DELIM_SEAM};
- int delimit_last_index = (select_mode & (SCE_SELECT_VERTEX | SCE_SELECT_EDGE)) == 0;
- char *delimit_last = &delimit_last_store[delimit_last_index];
- PropertyRNA *prop_delimit = RNA_struct_find_property(op->ptr, "delimit");
- int delimit;
-
- if (RNA_property_is_set(op->ptr, prop_delimit)) {
- delimit = RNA_property_enum_get(op->ptr, prop_delimit);
- *delimit_last = delimit;
- }
- else {
- delimit = *delimit_last;
- RNA_property_enum_set(op->ptr, prop_delimit, delimit);
- }
- return delimit;
+ static char delimit_last_store[2] = {0, BMO_DELIM_SEAM};
+ int delimit_last_index = (select_mode & (SCE_SELECT_VERTEX | SCE_SELECT_EDGE)) == 0;
+ char *delimit_last = &delimit_last_store[delimit_last_index];
+ PropertyRNA *prop_delimit = RNA_struct_find_property(op->ptr, "delimit");
+ int delimit;
+
+ if (RNA_property_is_set(op->ptr, prop_delimit)) {
+ delimit = RNA_property_enum_get(op->ptr, prop_delimit);
+ *delimit_last = delimit;
+ }
+ else {
+ delimit = *delimit_last;
+ RNA_property_enum_set(op->ptr, prop_delimit, delimit);
+ }
+ return delimit;
}
#endif
static void select_linked_delimit_validate(BMesh *bm, int *delimit)
{
- if ((*delimit) & BMO_DELIM_UV) {
- if (!CustomData_has_layer(&bm->ldata, CD_MLOOPUV)) {
- (*delimit) &= ~BMO_DELIM_UV;
- }
- }
+ if ((*delimit) & BMO_DELIM_UV) {
+ if (!CustomData_has_layer(&bm->ldata, CD_MLOOPUV)) {
+ (*delimit) &= ~BMO_DELIM_UV;
+ }
+ }
}
static void select_linked_delimit_begin(BMesh *bm, int delimit)
{
- struct DelimitData delimit_data = {0};
-
- if (delimit & BMO_DELIM_UV) {
- delimit_data.cd_loop_type = CD_MLOOPUV;
- delimit_data.cd_loop_offset = CustomData_get_offset(&bm->ldata, delimit_data.cd_loop_type);
- if (delimit_data.cd_loop_offset == -1) {
- delimit &= ~BMO_DELIM_UV;
- }
- }
-
- /* grr, shouldn't need to alloc BMO flags here */
- BM_mesh_elem_toolflags_ensure(bm);
-
- {
- BMIter iter;
- BMEdge *e;
-
- BM_ITER_MESH (e, &iter, bm, BM_EDGES_OF_MESH) {
- const bool is_walk_ok = (
- (select_linked_delimit_test(e, delimit, &delimit_data) == false));
-
- BMO_edge_flag_set(bm, e, BMO_ELE_TAG, is_walk_ok);
- }
- }
+ struct DelimitData delimit_data = {0};
+
+ if (delimit & BMO_DELIM_UV) {
+ delimit_data.cd_loop_type = CD_MLOOPUV;
+ delimit_data.cd_loop_offset = CustomData_get_offset(&bm->ldata, delimit_data.cd_loop_type);
+ if (delimit_data.cd_loop_offset == -1) {
+ delimit &= ~BMO_DELIM_UV;
+ }
+ }
+
+ /* grr, shouldn't need to alloc BMO flags here */
+ BM_mesh_elem_toolflags_ensure(bm);
+
+ {
+ BMIter iter;
+ BMEdge *e;
+
+ BM_ITER_MESH (e, &iter, bm, BM_EDGES_OF_MESH) {
+ const bool is_walk_ok = ((select_linked_delimit_test(e, delimit, &delimit_data) == false));
+
+ BMO_edge_flag_set(bm, e, BMO_ELE_TAG, is_walk_ok);
+ }
+ }
}
static void select_linked_delimit_end(BMEditMesh *em)
{
- BMesh *bm = em->bm;
+ BMesh *bm = em->bm;
- BM_mesh_elem_toolflags_clear(bm);
+ BM_mesh_elem_toolflags_clear(bm);
}
static int edbm_select_linked_exec(bContext *C, wmOperator *op)
{
- Scene *scene = CTX_data_scene(C);
- ViewLayer *view_layer = CTX_data_view_layer(C);
+ Scene *scene = CTX_data_scene(C);
+ ViewLayer *view_layer = CTX_data_view_layer(C);
#ifdef USE_LINKED_SELECT_DEFAULT_HACK
- const int delimit_init = select_linked_delimit_default_from_op(op, scene->toolsettings->selectmode);
+ const int delimit_init = select_linked_delimit_default_from_op(op,
+ scene->toolsettings->selectmode);
#else
- const int delimit_init = RNA_enum_get(op->ptr, "delimit");
+ const int delimit_init = RNA_enum_get(op->ptr, "delimit");
#endif
- uint objects_len = 0;
- Object **objects = BKE_view_layer_array_from_objects_in_edit_mode_unique_data(view_layer, CTX_wm_view3d(C), &objects_len);
-
- for (uint ob_index = 0; ob_index < objects_len; ob_index++) {
- Object *obedit = objects[ob_index];
-
- BMEditMesh *em = BKE_editmesh_from_object(obedit);
- BMesh *bm = em->bm;
- BMIter iter;
- BMWalker walker;
-
- int delimit = delimit_init;
-
- select_linked_delimit_validate(bm, &delimit);
-
- if (delimit) {
- select_linked_delimit_begin(em->bm, delimit);
- }
-
- if (em->selectmode & SCE_SELECT_VERTEX) {
- BMVert *v;
-
- BM_ITER_MESH (v, &iter, em->bm, BM_VERTS_OF_MESH) {
- BM_elem_flag_set(v, BM_ELEM_TAG, BM_elem_flag_test(v, BM_ELEM_SELECT));
- }
-
- /* exclude all delimited verts */
- if (delimit) {
- BMEdge *e;
- BM_ITER_MESH (e, &iter, em->bm, BM_EDGES_OF_MESH) {
- if (!BMO_edge_flag_test(bm, e, BMO_ELE_TAG)) {
- BM_elem_flag_disable(e->v1, BM_ELEM_TAG);
- BM_elem_flag_disable(e->v2, BM_ELEM_TAG);
- }
- }
- }
-
- BMW_init(&walker, em->bm, delimit ? BMW_LOOP_SHELL_WIRE : BMW_VERT_SHELL,
- BMW_MASK_NOP, delimit ? BMO_ELE_TAG : BMW_MASK_NOP, BMW_MASK_NOP,
- BMW_FLAG_TEST_HIDDEN,
- BMW_NIL_LAY);
-
- if (delimit) {
- BM_ITER_MESH (v, &iter, em->bm, BM_VERTS_OF_MESH) {
- if (BM_elem_flag_test(v, BM_ELEM_TAG)) {
- BMElem *ele_walk;
- BMW_ITER (ele_walk, &walker, v) {
- if (ele_walk->head.htype == BM_LOOP) {
- BMVert *v_step = ((BMLoop *)ele_walk)->v;
- BM_vert_select_set(em->bm, v_step, true);
- BM_elem_flag_disable(v_step, BM_ELEM_TAG);
- }
- else {
- BMEdge *e_step = (BMEdge *)ele_walk;
- BLI_assert(ele_walk->head.htype == BM_EDGE);
- BM_edge_select_set(em->bm, e_step, true);
- BM_elem_flag_disable(e_step->v1, BM_ELEM_TAG);
- BM_elem_flag_disable(e_step->v2, BM_ELEM_TAG);
- }
- }
- }
- }
- }
- else {
- BM_ITER_MESH (v, &iter, em->bm, BM_VERTS_OF_MESH) {
- if (BM_elem_flag_test(v, BM_ELEM_TAG)) {
- BMEdge *e_walk;
- BMW_ITER (e_walk, &walker, v) {
- BM_edge_select_set(em->bm, e_walk, true);
- BM_elem_flag_disable(e_walk, BM_ELEM_TAG);
- }
- }
- }
- }
-
- BMW_end(&walker);
-
- EDBM_selectmode_flush(em);
- }
- else if (em->selectmode & SCE_SELECT_EDGE) {
- BMEdge *e;
-
- if (delimit) {
- BM_ITER_MESH (e, &iter, em->bm, BM_EDGES_OF_MESH) {
- BM_elem_flag_set(
- e, BM_ELEM_TAG,
- (BM_elem_flag_test(e, BM_ELEM_SELECT) && BMO_edge_flag_test(bm, e, BMO_ELE_TAG)));
- }
- }
- else {
- BM_ITER_MESH (e, &iter, em->bm, BM_EDGES_OF_MESH) {
- BM_elem_flag_set(e, BM_ELEM_TAG, BM_elem_flag_test(e, BM_ELEM_SELECT));
- }
- }
-
- BMW_init(&walker, em->bm, delimit ? BMW_LOOP_SHELL_WIRE : BMW_VERT_SHELL,
- BMW_MASK_NOP, delimit ? BMO_ELE_TAG : BMW_MASK_NOP, BMW_MASK_NOP,
- BMW_FLAG_TEST_HIDDEN,
- BMW_NIL_LAY);
-
- if (delimit) {
- BM_ITER_MESH (e, &iter, em->bm, BM_EDGES_OF_MESH) {
- if (BM_elem_flag_test(e, BM_ELEM_TAG)) {
- BMElem *ele_walk;
- BMW_ITER (ele_walk, &walker, e) {
- if (ele_walk->head.htype == BM_LOOP) {
- BMLoop *l_step = (BMLoop *)ele_walk;
- BM_edge_select_set(em->bm, l_step->e, true);
- BM_edge_select_set(em->bm, l_step->prev->e, true);
- BM_elem_flag_disable(l_step->e, BM_ELEM_TAG);
- }
- else {
- BMEdge *e_step = (BMEdge *)ele_walk;
- BLI_assert(ele_walk->head.htype == BM_EDGE);
- BM_edge_select_set(em->bm, e_step, true);
- BM_elem_flag_disable(e_step, BM_ELEM_TAG);
- }
- }
- }
- }
- }
- else {
- BM_ITER_MESH (e, &iter, em->bm, BM_EDGES_OF_MESH) {
- if (BM_elem_flag_test(e, BM_ELEM_TAG)) {
- BMEdge *e_walk;
- BMW_ITER (e_walk, &walker, e) {
- BM_edge_select_set(em->bm, e_walk, true);
- BM_elem_flag_disable(e_walk, BM_ELEM_TAG);
- }
- }
- }
- }
-
- BMW_end(&walker);
-
- EDBM_selectmode_flush(em);
- }
- else {
- BMFace *f;
-
- BM_ITER_MESH (f, &iter, em->bm, BM_FACES_OF_MESH) {
- BM_elem_flag_set(f, BM_ELEM_TAG, BM_elem_flag_test(f, BM_ELEM_SELECT));
- }
-
- BMW_init(&walker, bm, BMW_ISLAND,
- BMW_MASK_NOP, delimit ? BMO_ELE_TAG : BMW_MASK_NOP, BMW_MASK_NOP,
- BMW_FLAG_TEST_HIDDEN,
- BMW_NIL_LAY);
-
- BM_ITER_MESH (f, &iter, em->bm, BM_FACES_OF_MESH) {
- if (BM_elem_flag_test(f, BM_ELEM_TAG)) {
- BMFace *f_walk;
- BMW_ITER (f_walk, &walker, f) {
- BM_face_select_set(bm, f_walk, true);
- BM_elem_flag_disable(f_walk, BM_ELEM_TAG);
- }
- }
- }
-
- BMW_end(&walker);
- }
-
- if (delimit) {
- select_linked_delimit_end(em);
- }
-
- DEG_id_tag_update(obedit->data, ID_RECALC_SELECT);
- WM_event_add_notifier(C, NC_GEOM | ND_SELECT, obedit->data);
-
- }
-
- MEM_freeN(objects);
-
- return OPERATOR_FINISHED;
+ uint objects_len = 0;
+ Object **objects = BKE_view_layer_array_from_objects_in_edit_mode_unique_data(
+ view_layer, CTX_wm_view3d(C), &objects_len);
+
+ for (uint ob_index = 0; ob_index < objects_len; ob_index++) {
+ Object *obedit = objects[ob_index];
+
+ BMEditMesh *em = BKE_editmesh_from_object(obedit);
+ BMesh *bm = em->bm;
+ BMIter iter;
+ BMWalker walker;
+
+ int delimit = delimit_init;
+
+ select_linked_delimit_validate(bm, &delimit);
+
+ if (delimit) {
+ select_linked_delimit_begin(em->bm, delimit);
+ }
+
+ if (em->selectmode & SCE_SELECT_VERTEX) {
+ BMVert *v;
+
+ BM_ITER_MESH (v, &iter, em->bm, BM_VERTS_OF_MESH) {
+ BM_elem_flag_set(v, BM_ELEM_TAG, BM_elem_flag_test(v, BM_ELEM_SELECT));
+ }
+
+ /* exclude all delimited verts */
+ if (delimit) {
+ BMEdge *e;
+ BM_ITER_MESH (e, &iter, em->bm, BM_EDGES_OF_MESH) {
+ if (!BMO_edge_flag_test(bm, e, BMO_ELE_TAG)) {
+ BM_elem_flag_disable(e->v1, BM_ELEM_TAG);
+ BM_elem_flag_disable(e->v2, BM_ELEM_TAG);
+ }
+ }
+ }
+
+ BMW_init(&walker,
+ em->bm,
+ delimit ? BMW_LOOP_SHELL_WIRE : BMW_VERT_SHELL,
+ BMW_MASK_NOP,
+ delimit ? BMO_ELE_TAG : BMW_MASK_NOP,
+ BMW_MASK_NOP,
+ BMW_FLAG_TEST_HIDDEN,
+ BMW_NIL_LAY);
+
+ if (delimit) {
+ BM_ITER_MESH (v, &iter, em->bm, BM_VERTS_OF_MESH) {
+ if (BM_elem_flag_test(v, BM_ELEM_TAG)) {
+ BMElem *ele_walk;
+ BMW_ITER (ele_walk, &walker, v) {
+ if (ele_walk->head.htype == BM_LOOP) {
+ BMVert *v_step = ((BMLoop *)ele_walk)->v;
+ BM_vert_select_set(em->bm, v_step, true);
+ BM_elem_flag_disable(v_step, BM_ELEM_TAG);
+ }
+ else {
+ BMEdge *e_step = (BMEdge *)ele_walk;
+ BLI_assert(ele_walk->head.htype == BM_EDGE);
+ BM_edge_select_set(em->bm, e_step, true);
+ BM_elem_flag_disable(e_step->v1, BM_ELEM_TAG);
+ BM_elem_flag_disable(e_step->v2, BM_ELEM_TAG);
+ }
+ }
+ }
+ }
+ }
+ else {
+ BM_ITER_MESH (v, &iter, em->bm, BM_VERTS_OF_MESH) {
+ if (BM_elem_flag_test(v, BM_ELEM_TAG)) {
+ BMEdge *e_walk;
+ BMW_ITER (e_walk, &walker, v) {
+ BM_edge_select_set(em->bm, e_walk, true);
+ BM_elem_flag_disable(e_walk, BM_ELEM_TAG);
+ }
+ }
+ }
+ }
+
+ BMW_end(&walker);
+
+ EDBM_selectmode_flush(em);
+ }
+ else if (em->selectmode & SCE_SELECT_EDGE) {
+ BMEdge *e;
+
+ if (delimit) {
+ BM_ITER_MESH (e, &iter, em->bm, BM_EDGES_OF_MESH) {
+ BM_elem_flag_set(
+ e,
+ BM_ELEM_TAG,
+ (BM_elem_flag_test(e, BM_ELEM_SELECT) && BMO_edge_flag_test(bm, e, BMO_ELE_TAG)));
+ }
+ }
+ else {
+ BM_ITER_MESH (e, &iter, em->bm, BM_EDGES_OF_MESH) {
+ BM_elem_flag_set(e, BM_ELEM_TAG, BM_elem_flag_test(e, BM_ELEM_SELECT));
+ }
+ }
+
+ BMW_init(&walker,
+ em->bm,
+ delimit ? BMW_LOOP_SHELL_WIRE : BMW_VERT_SHELL,
+ BMW_MASK_NOP,
+ delimit ? BMO_ELE_TAG : BMW_MASK_NOP,
+ BMW_MASK_NOP,
+ BMW_FLAG_TEST_HIDDEN,
+ BMW_NIL_LAY);
+
+ if (delimit) {
+ BM_ITER_MESH (e, &iter, em->bm, BM_EDGES_OF_MESH) {
+ if (BM_elem_flag_test(e, BM_ELEM_TAG)) {
+ BMElem *ele_walk;
+ BMW_ITER (ele_walk, &walker, e) {
+ if (ele_walk->head.htype == BM_LOOP) {
+ BMLoop *l_step = (BMLoop *)ele_walk;
+ BM_edge_select_set(em->bm, l_step->e, true);
+ BM_edge_select_set(em->bm, l_step->prev->e, true);
+ BM_elem_flag_disable(l_step->e, BM_ELEM_TAG);
+ }
+ else {
+ BMEdge *e_step = (BMEdge *)ele_walk;
+ BLI_assert(ele_walk->head.htype == BM_EDGE);
+ BM_edge_select_set(em->bm, e_step, true);
+ BM_elem_flag_disable(e_step, BM_ELEM_TAG);
+ }
+ }
+ }
+ }
+ }
+ else {
+ BM_ITER_MESH (e, &iter, em->bm, BM_EDGES_OF_MESH) {
+ if (BM_elem_flag_test(e, BM_ELEM_TAG)) {
+ BMEdge *e_walk;
+ BMW_ITER (e_walk, &walker, e) {
+ BM_edge_select_set(em->bm, e_walk, true);
+ BM_elem_flag_disable(e_walk, BM_ELEM_TAG);
+ }
+ }
+ }
+ }
+
+ BMW_end(&walker);
+
+ EDBM_selectmode_flush(em);
+ }
+ else {
+ BMFace *f;
+
+ BM_ITER_MESH (f, &iter, em->bm, BM_FACES_OF_MESH) {
+ BM_elem_flag_set(f, BM_ELEM_TAG, BM_elem_flag_test(f, BM_ELEM_SELECT));
+ }
+
+ BMW_init(&walker,
+ bm,
+ BMW_ISLAND,
+ BMW_MASK_NOP,
+ delimit ? BMO_ELE_TAG : BMW_MASK_NOP,
+ BMW_MASK_NOP,
+ BMW_FLAG_TEST_HIDDEN,
+ BMW_NIL_LAY);
+
+ BM_ITER_MESH (f, &iter, em->bm, BM_FACES_OF_MESH) {
+ if (BM_elem_flag_test(f, BM_ELEM_TAG)) {
+ BMFace *f_walk;
+ BMW_ITER (f_walk, &walker, f) {
+ BM_face_select_set(bm, f_walk, true);
+ BM_elem_flag_disable(f_walk, BM_ELEM_TAG);
+ }
+ }
+ }
+
+ BMW_end(&walker);
+ }
+
+ if (delimit) {
+ select_linked_delimit_end(em);
+ }
+
+ DEG_id_tag_update(obedit->data, ID_RECALC_SELECT);
+ WM_event_add_notifier(C, NC_GEOM | ND_SELECT, obedit->data);
+ }
+
+ MEM_freeN(objects);
+
+ return OPERATOR_FINISHED;
}
void MESH_OT_select_linked(wmOperatorType *ot)
{
- PropertyRNA *prop;
-
- /* identifiers */
- ot->name = "Select Linked All";
- ot->idname = "MESH_OT_select_linked";
- ot->description = "Select all vertices connected to the current selection";
-
- /* api callbacks */
- ot->exec = edbm_select_linked_exec;
- ot->poll = ED_operator_editmesh;
-
- /* flags */
- ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
-
- prop = RNA_def_enum_flag(ot->srna, "delimit", rna_enum_mesh_delimit_mode_items, BMO_DELIM_SEAM, "Delimit",
- "Delimit selected region");
+ PropertyRNA *prop;
+
+ /* identifiers */
+ ot->name = "Select Linked All";
+ ot->idname = "MESH_OT_select_linked";
+ ot->description = "Select all vertices connected to the current selection";
+
+ /* api callbacks */
+ ot->exec = edbm_select_linked_exec;
+ ot->poll = ED_operator_editmesh;
+
+ /* flags */
+ ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
+
+ prop = RNA_def_enum_flag(ot->srna,
+ "delimit",
+ rna_enum_mesh_delimit_mode_items,
+ BMO_DELIM_SEAM,
+ "Delimit",
+ "Delimit selected region");
#ifdef USE_LINKED_SELECT_DEFAULT_HACK
- RNA_def_property_flag(prop, PROP_SKIP_SAVE);
+ RNA_def_property_flag(prop, PROP_SKIP_SAVE);
#else
- UNUSED_VARS(prop);
+ UNUSED_VARS(prop);
#endif
}
@@ -3020,245 +3065,260 @@ static int edbm_select_linked_pick_exec(bContext *C, wmOperator *op);
static void edbm_select_linked_pick_ex(BMEditMesh *em, BMElem *ele, bool sel, int delimit)
{
- BMesh *bm = em->bm;
- BMWalker walker;
-
- select_linked_delimit_validate(bm, &delimit);
-
- if (delimit) {
- select_linked_delimit_begin(bm, delimit);
- }
-
- /* Note: logic closely matches 'edbm_select_linked_exec', keep in sync */
-
- if (ele->head.htype == BM_VERT) {
- BMVert *eve = (BMVert *)ele;
-
- BMW_init(&walker, bm, delimit ? BMW_LOOP_SHELL_WIRE : BMW_VERT_SHELL,
- BMW_MASK_NOP, delimit ? BMO_ELE_TAG : BMW_MASK_NOP, BMW_MASK_NOP,
- BMW_FLAG_TEST_HIDDEN,
- BMW_NIL_LAY);
-
- if (delimit) {
- BMElem *ele_walk;
- BMW_ITER (ele_walk, &walker, eve) {
- if (ele_walk->head.htype == BM_LOOP) {
- BMVert *v_step = ((BMLoop *)ele_walk)->v;
- BM_vert_select_set(bm, v_step, sel);
- }
- else {
- BMEdge *e_step = (BMEdge *)ele_walk;
- BLI_assert(ele_walk->head.htype == BM_EDGE);
- BM_edge_select_set(bm, e_step, sel);
- }
- }
- }
- else {
- BMEdge *e_walk;
- BMW_ITER (e_walk, &walker, eve) {
- BM_edge_select_set(bm, e_walk, sel);
- }
- }
-
- BMW_end(&walker);
-
- EDBM_selectmode_flush(em);
- }
- else if (ele->head.htype == BM_EDGE) {
- BMEdge *eed = (BMEdge *)ele;
-
- BMW_init(&walker, bm, delimit ? BMW_LOOP_SHELL_WIRE : BMW_VERT_SHELL,
- BMW_MASK_NOP, delimit ? BMO_ELE_TAG : BMW_MASK_NOP, BMW_MASK_NOP,
- BMW_FLAG_TEST_HIDDEN,
- BMW_NIL_LAY);
-
- if (delimit) {
- BMElem *ele_walk;
- BMW_ITER (ele_walk, &walker, eed) {
- if (ele_walk->head.htype == BM_LOOP) {
- BMEdge *e_step = ((BMLoop *)ele_walk)->e;
- BM_edge_select_set(bm, e_step, sel);
- }
- else {
- BMEdge *e_step = (BMEdge *)ele_walk;
- BLI_assert(ele_walk->head.htype == BM_EDGE);
- BM_edge_select_set(bm, e_step, sel);
- }
- }
- }
- else {
- BMEdge *e_walk;
- BMW_ITER (e_walk, &walker, eed) {
- BM_edge_select_set(bm, e_walk, sel);
- }
- }
-
- BMW_end(&walker);
-
- EDBM_selectmode_flush(em);
- }
- else if (ele->head.htype == BM_FACE) {
- BMFace *efa = (BMFace *)ele;
-
- BMW_init(&walker, bm, BMW_ISLAND,
- BMW_MASK_NOP, delimit ? BMO_ELE_TAG : BMW_MASK_NOP, BMW_MASK_NOP,
- BMW_FLAG_TEST_HIDDEN,
- BMW_NIL_LAY);
-
- {
- BMFace *f_walk;
- BMW_ITER (f_walk, &walker, efa) {
- BM_face_select_set(bm, f_walk, sel);
- BM_elem_flag_disable(f_walk, BM_ELEM_TAG);
- }
- }
-
- BMW_end(&walker);
- }
-
- if (delimit) {
- select_linked_delimit_end(em);
- }
+ BMesh *bm = em->bm;
+ BMWalker walker;
+
+ select_linked_delimit_validate(bm, &delimit);
+
+ if (delimit) {
+ select_linked_delimit_begin(bm, delimit);
+ }
+
+ /* Note: logic closely matches 'edbm_select_linked_exec', keep in sync */
+
+ if (ele->head.htype == BM_VERT) {
+ BMVert *eve = (BMVert *)ele;
+
+ BMW_init(&walker,
+ bm,
+ delimit ? BMW_LOOP_SHELL_WIRE : BMW_VERT_SHELL,
+ BMW_MASK_NOP,
+ delimit ? BMO_ELE_TAG : BMW_MASK_NOP,
+ BMW_MASK_NOP,
+ BMW_FLAG_TEST_HIDDEN,
+ BMW_NIL_LAY);
+
+ if (delimit) {
+ BMElem *ele_walk;
+ BMW_ITER (ele_walk, &walker, eve) {
+ if (ele_walk->head.htype == BM_LOOP) {
+ BMVert *v_step = ((BMLoop *)ele_walk)->v;
+ BM_vert_select_set(bm, v_step, sel);
+ }
+ else {
+ BMEdge *e_step = (BMEdge *)ele_walk;
+ BLI_assert(ele_walk->head.htype == BM_EDGE);
+ BM_edge_select_set(bm, e_step, sel);
+ }
+ }
+ }
+ else {
+ BMEdge *e_walk;
+ BMW_ITER (e_walk, &walker, eve) {
+ BM_edge_select_set(bm, e_walk, sel);
+ }
+ }
+
+ BMW_end(&walker);
+
+ EDBM_selectmode_flush(em);
+ }
+ else if (ele->head.htype == BM_EDGE) {
+ BMEdge *eed = (BMEdge *)ele;
+
+ BMW_init(&walker,
+ bm,
+ delimit ? BMW_LOOP_SHELL_WIRE : BMW_VERT_SHELL,
+ BMW_MASK_NOP,
+ delimit ? BMO_ELE_TAG : BMW_MASK_NOP,
+ BMW_MASK_NOP,
+ BMW_FLAG_TEST_HIDDEN,
+ BMW_NIL_LAY);
+
+ if (delimit) {
+ BMElem *ele_walk;
+ BMW_ITER (ele_walk, &walker, eed) {
+ if (ele_walk->head.htype == BM_LOOP) {
+ BMEdge *e_step = ((BMLoop *)ele_walk)->e;
+ BM_edge_select_set(bm, e_step, sel);
+ }
+ else {
+ BMEdge *e_step = (BMEdge *)ele_walk;
+ BLI_assert(ele_walk->head.htype == BM_EDGE);
+ BM_edge_select_set(bm, e_step, sel);
+ }
+ }
+ }
+ else {
+ BMEdge *e_walk;
+ BMW_ITER (e_walk, &walker, eed) {
+ BM_edge_select_set(bm, e_walk, sel);
+ }
+ }
+
+ BMW_end(&walker);
+
+ EDBM_selectmode_flush(em);
+ }
+ else if (ele->head.htype == BM_FACE) {
+ BMFace *efa = (BMFace *)ele;
+
+ BMW_init(&walker,
+ bm,
+ BMW_ISLAND,
+ BMW_MASK_NOP,
+ delimit ? BMO_ELE_TAG : BMW_MASK_NOP,
+ BMW_MASK_NOP,
+ BMW_FLAG_TEST_HIDDEN,
+ BMW_NIL_LAY);
+
+ {
+ BMFace *f_walk;
+ BMW_ITER (f_walk, &walker, efa) {
+ BM_face_select_set(bm, f_walk, sel);
+ BM_elem_flag_disable(f_walk, BM_ELEM_TAG);
+ }
+ }
+
+ BMW_end(&walker);
+ }
+
+ if (delimit) {
+ select_linked_delimit_end(em);
+ }
}
static int edbm_select_linked_pick_invoke(bContext *C, wmOperator *op, const wmEvent *event)
{
- ViewContext vc;
- Base *basact = NULL;
- BMVert *eve;
- BMEdge *eed;
- BMFace *efa;
- const bool sel = !RNA_boolean_get(op->ptr, "deselect");
- int index;
-
- if (RNA_struct_property_is_set(op->ptr, "index")) {
- return edbm_select_linked_pick_exec(C, op);
- }
-
- /* unified_finednearest needs ogl */
- view3d_operator_needs_opengl(C);
-
- /* setup view context for argument to callbacks */
- em_setup_viewcontext(C, &vc);
-
- uint bases_len;
- Base **bases = BKE_view_layer_array_from_bases_in_edit_mode(vc.view_layer, vc.v3d, &bases_len);
-
- {
- bool has_edges = false;
- for (uint base_index = 0; base_index < bases_len; base_index++) {
- Object *ob_iter = bases[base_index]->object;
- ED_view3d_viewcontext_init_object(&vc, ob_iter);
- if (vc.em->bm->totedge) {
- has_edges = true;
- }
- }
- if (has_edges == false) {
- MEM_freeN(bases);
- return OPERATOR_CANCELLED;
- }
- }
-
- vc.mval[0] = event->mval[0];
- vc.mval[1] = event->mval[1];
-
- /* return warning! */
- {
- int base_index = -1;
- const bool ok = unified_findnearest(&vc, bases, bases_len, &base_index, &eve, &eed, &efa);
- if (!ok) {
- MEM_freeN(bases);
- return OPERATOR_CANCELLED;
- }
- basact = bases[base_index];
- }
-
- ED_view3d_viewcontext_init_object(&vc, basact->object);
- BMEditMesh *em = vc.em;
- BMesh *bm = em->bm;
+ ViewContext vc;
+ Base *basact = NULL;
+ BMVert *eve;
+ BMEdge *eed;
+ BMFace *efa;
+ const bool sel = !RNA_boolean_get(op->ptr, "deselect");
+ int index;
+
+ if (RNA_struct_property_is_set(op->ptr, "index")) {
+ return edbm_select_linked_pick_exec(C, op);
+ }
+
+ /* unified_finednearest needs ogl */
+ view3d_operator_needs_opengl(C);
+
+ /* setup view context for argument to callbacks */
+ em_setup_viewcontext(C, &vc);
+
+ uint bases_len;
+ Base **bases = BKE_view_layer_array_from_bases_in_edit_mode(vc.view_layer, vc.v3d, &bases_len);
+
+ {
+ bool has_edges = false;
+ for (uint base_index = 0; base_index < bases_len; base_index++) {
+ Object *ob_iter = bases[base_index]->object;
+ ED_view3d_viewcontext_init_object(&vc, ob_iter);
+ if (vc.em->bm->totedge) {
+ has_edges = true;
+ }
+ }
+ if (has_edges == false) {
+ MEM_freeN(bases);
+ return OPERATOR_CANCELLED;
+ }
+ }
+
+ vc.mval[0] = event->mval[0];
+ vc.mval[1] = event->mval[1];
+
+ /* return warning! */
+ {
+ int base_index = -1;
+ const bool ok = unified_findnearest(&vc, bases, bases_len, &base_index, &eve, &eed, &efa);
+ if (!ok) {
+ MEM_freeN(bases);
+ return OPERATOR_CANCELLED;
+ }
+ basact = bases[base_index];
+ }
+
+ ED_view3d_viewcontext_init_object(&vc, basact->object);
+ BMEditMesh *em = vc.em;
+ BMesh *bm = em->bm;
#ifdef USE_LINKED_SELECT_DEFAULT_HACK
- int delimit = select_linked_delimit_default_from_op(op, vc.scene->toolsettings->selectmode);
+ int delimit = select_linked_delimit_default_from_op(op, vc.scene->toolsettings->selectmode);
#else
- int delimit = RNA_enum_get(op->ptr, "delimit");
+ int delimit = RNA_enum_get(op->ptr, "delimit");
#endif
- BMElem *ele = EDBM_elem_from_selectmode(em, eve, eed, efa);
+ BMElem *ele = EDBM_elem_from_selectmode(em, eve, eed, efa);
- edbm_select_linked_pick_ex(em, ele, sel, delimit);
+ edbm_select_linked_pick_ex(em, ele, sel, delimit);
- /* to support redo */
- BM_mesh_elem_index_ensure(bm, ele->head.htype);
- index = EDBM_elem_to_index_any(em, ele);
+ /* to support redo */
+ BM_mesh_elem_index_ensure(bm, ele->head.htype);
+ index = EDBM_elem_to_index_any(em, ele);
- /* TODO(MULTI_EDIT), index doesn't know which object,
- * index selections isn't very common. */
- RNA_int_set(op->ptr, "index", index);
+ /* TODO(MULTI_EDIT), index doesn't know which object,
+ * index selections isn't very common. */
+ RNA_int_set(op->ptr, "index", index);
- DEG_id_tag_update(basact->object->data, ID_RECALC_SELECT);
- WM_event_add_notifier(C, NC_GEOM | ND_SELECT, basact->object->data);
+ DEG_id_tag_update(basact->object->data, ID_RECALC_SELECT);
+ WM_event_add_notifier(C, NC_GEOM | ND_SELECT, basact->object->data);
- MEM_freeN(bases);
- return OPERATOR_FINISHED;
+ MEM_freeN(bases);
+ return OPERATOR_FINISHED;
}
-
static int edbm_select_linked_pick_exec(bContext *C, wmOperator *op)
{
- Object *obedit = CTX_data_edit_object(C);
- BMEditMesh *em = BKE_editmesh_from_object(obedit);
- BMesh *bm = em->bm;
- int index;
- const bool sel = !RNA_boolean_get(op->ptr, "deselect");
+ Object *obedit = CTX_data_edit_object(C);
+ BMEditMesh *em = BKE_editmesh_from_object(obedit);
+ BMesh *bm = em->bm;
+ int index;
+ const bool sel = !RNA_boolean_get(op->ptr, "deselect");
- index = RNA_int_get(op->ptr, "index");
- if (index < 0 || index >= (bm->totvert + bm->totedge + bm->totface)) {
- return OPERATOR_CANCELLED;
- }
+ index = RNA_int_get(op->ptr, "index");
+ if (index < 0 || index >= (bm->totvert + bm->totedge + bm->totface)) {
+ return OPERATOR_CANCELLED;
+ }
- BMElem *ele = EDBM_elem_from_index_any(em, index);
+ BMElem *ele = EDBM_elem_from_index_any(em, index);
#ifdef USE_LINKED_SELECT_DEFAULT_HACK
- int delimit = select_linked_delimit_default_from_op(op, em->selectmode);
+ int delimit = select_linked_delimit_default_from_op(op, em->selectmode);
#else
- int delimit = RNA_enum_get(op->ptr, "delimit");
+ int delimit = RNA_enum_get(op->ptr, "delimit");
#endif
- edbm_select_linked_pick_ex(em, ele, sel, delimit);
+ edbm_select_linked_pick_ex(em, ele, sel, delimit);
- DEG_id_tag_update(obedit->data, ID_RECALC_SELECT);
- WM_event_add_notifier(C, NC_GEOM | ND_SELECT, obedit->data);
+ DEG_id_tag_update(obedit->data, ID_RECALC_SELECT);
+ WM_event_add_notifier(C, NC_GEOM | ND_SELECT, obedit->data);
- return OPERATOR_FINISHED;
+ return OPERATOR_FINISHED;
}
void MESH_OT_select_linked_pick(wmOperatorType *ot)
{
- PropertyRNA *prop;
-
- /* identifiers */
- ot->name = "Select Linked";
- ot->idname = "MESH_OT_select_linked_pick";
- ot->description = "(De)select all vertices linked to the edge under the mouse cursor";
-
- /* api callbacks */
- ot->invoke = edbm_select_linked_pick_invoke;
- ot->exec = edbm_select_linked_pick_exec;
- ot->poll = ED_operator_editmesh;
-
- /* flags */
- ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
-
- RNA_def_boolean(ot->srna, "deselect", 0, "Deselect", "");
- prop = RNA_def_enum_flag(ot->srna, "delimit", rna_enum_mesh_delimit_mode_items, BMO_DELIM_SEAM, "Delimit",
- "Delimit selected region");
+ PropertyRNA *prop;
+
+ /* identifiers */
+ ot->name = "Select Linked";
+ ot->idname = "MESH_OT_select_linked_pick";
+ ot->description = "(De)select all vertices linked to the edge under the mouse cursor";
+
+ /* api callbacks */
+ ot->invoke = edbm_select_linked_pick_invoke;
+ ot->exec = edbm_select_linked_pick_exec;
+ ot->poll = ED_operator_editmesh;
+
+ /* flags */
+ ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
+
+ RNA_def_boolean(ot->srna, "deselect", 0, "Deselect", "");
+ prop = RNA_def_enum_flag(ot->srna,
+ "delimit",
+ rna_enum_mesh_delimit_mode_items,
+ BMO_DELIM_SEAM,
+ "Delimit",
+ "Delimit selected region");
#ifdef USE_LINKED_SELECT_DEFAULT_HACK
- RNA_def_property_flag(prop, PROP_SKIP_SAVE);
+ RNA_def_property_flag(prop, PROP_SKIP_SAVE);
#endif
- /* use for redo */
- prop = RNA_def_int(ot->srna, "index", -1, -1, INT_MAX, "", "", 0, INT_MAX);
- RNA_def_property_flag(prop, PROP_HIDDEN | PROP_SKIP_SAVE);
+ /* use for redo */
+ prop = RNA_def_int(ot->srna, "index", -1, -1, INT_MAX, "", "", 0, INT_MAX);
+ RNA_def_property_flag(prop, PROP_HIDDEN | PROP_SKIP_SAVE);
}
/** \} */
@@ -3269,86 +3329,87 @@ void MESH_OT_select_linked_pick(wmOperatorType *ot)
static int edbm_select_face_by_sides_exec(bContext *C, wmOperator *op)
{
- ViewLayer *view_layer = CTX_data_view_layer(C);
- uint objects_len = 0;
- const bool extend = RNA_boolean_get(op->ptr, "extend");
- const int numverts = RNA_int_get(op->ptr, "number");
- const int type = RNA_enum_get(op->ptr, "type");
- Object **objects = BKE_view_layer_array_from_objects_in_edit_mode_unique_data(view_layer, CTX_wm_view3d(C), &objects_len);
-
- for (uint ob_index = 0; ob_index < objects_len; ob_index++) {
- Object *obedit = objects[ob_index];
- BMEditMesh *em = BKE_editmesh_from_object(obedit);
- BMFace *efa;
- BMIter iter;
-
- if (!extend) {
- EDBM_flag_disable_all(em, BM_ELEM_SELECT);
- }
-
- BM_ITER_MESH(efa, &iter, em->bm, BM_FACES_OF_MESH) {
- bool select;
-
- switch (type) {
- case 0:
- select = (efa->len < numverts);
- break;
- case 1:
- select = (efa->len == numverts);
- break;
- case 2:
- select = (efa->len > numverts);
- break;
- case 3:
- select = (efa->len != numverts);
- break;
- default:
- BLI_assert(0);
- select = false;
- break;
- }
-
- if (select) {
- BM_face_select_set(em->bm, efa, true);
- }
- }
-
- EDBM_selectmode_flush(em);
-
- DEG_id_tag_update(obedit->data, ID_RECALC_SELECT);
- WM_event_add_notifier(C, NC_GEOM | ND_SELECT, obedit->data);
- }
-
- MEM_freeN(objects);
- return OPERATOR_FINISHED;
+ ViewLayer *view_layer = CTX_data_view_layer(C);
+ uint objects_len = 0;
+ const bool extend = RNA_boolean_get(op->ptr, "extend");
+ const int numverts = RNA_int_get(op->ptr, "number");
+ const int type = RNA_enum_get(op->ptr, "type");
+ Object **objects = BKE_view_layer_array_from_objects_in_edit_mode_unique_data(
+ view_layer, CTX_wm_view3d(C), &objects_len);
+
+ for (uint ob_index = 0; ob_index < objects_len; ob_index++) {
+ Object *obedit = objects[ob_index];
+ BMEditMesh *em = BKE_editmesh_from_object(obedit);
+ BMFace *efa;
+ BMIter iter;
+
+ if (!extend) {
+ EDBM_flag_disable_all(em, BM_ELEM_SELECT);
+ }
+
+ BM_ITER_MESH (efa, &iter, em->bm, BM_FACES_OF_MESH) {
+ bool select;
+
+ switch (type) {
+ case 0:
+ select = (efa->len < numverts);
+ break;
+ case 1:
+ select = (efa->len == numverts);
+ break;
+ case 2:
+ select = (efa->len > numverts);
+ break;
+ case 3:
+ select = (efa->len != numverts);
+ break;
+ default:
+ BLI_assert(0);
+ select = false;
+ break;
+ }
+
+ if (select) {
+ BM_face_select_set(em->bm, efa, true);
+ }
+ }
+
+ EDBM_selectmode_flush(em);
+
+ DEG_id_tag_update(obedit->data, ID_RECALC_SELECT);
+ WM_event_add_notifier(C, NC_GEOM | ND_SELECT, obedit->data);
+ }
+
+ MEM_freeN(objects);
+ return OPERATOR_FINISHED;
}
void MESH_OT_select_face_by_sides(wmOperatorType *ot)
{
- static const EnumPropertyItem type_items[] = {
- {0, "LESS", 0, "Less Than", ""},
- {1, "EQUAL", 0, "Equal To", ""},
- {2, "GREATER", 0, "Greater Than", ""},
- {3, "NOTEQUAL", 0, "Not Equal To", ""},
- {0, NULL, 0, NULL, NULL},
- };
-
- /* identifiers */
- ot->name = "Select Faces by Sides";
- ot->description = "Select vertices or faces by the number of polygon sides";
- ot->idname = "MESH_OT_select_face_by_sides";
-
- /* api callbacks */
- ot->exec = edbm_select_face_by_sides_exec;
- ot->poll = ED_operator_editmesh;
-
- /* flags */
- ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
-
- /* properties */
- RNA_def_int(ot->srna, "number", 4, 3, INT_MAX, "Number of Vertices", "", 3, INT_MAX);
- RNA_def_enum(ot->srna, "type", type_items, 1, "Type", "Type of comparison to make");
- RNA_def_boolean(ot->srna, "extend", true, "Extend", "Extend the selection");
+ static const EnumPropertyItem type_items[] = {
+ {0, "LESS", 0, "Less Than", ""},
+ {1, "EQUAL", 0, "Equal To", ""},
+ {2, "GREATER", 0, "Greater Than", ""},
+ {3, "NOTEQUAL", 0, "Not Equal To", ""},
+ {0, NULL, 0, NULL, NULL},
+ };
+
+ /* identifiers */
+ ot->name = "Select Faces by Sides";
+ ot->description = "Select vertices or faces by the number of polygon sides";
+ ot->idname = "MESH_OT_select_face_by_sides";
+
+ /* api callbacks */
+ ot->exec = edbm_select_face_by_sides_exec;
+ ot->poll = ED_operator_editmesh;
+
+ /* flags */
+ ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
+
+ /* properties */
+ RNA_def_int(ot->srna, "number", 4, 3, INT_MAX, "Number of Vertices", "", 3, INT_MAX);
+ RNA_def_enum(ot->srna, "type", type_items, 1, "Type", "Type of comparison to make");
+ RNA_def_boolean(ot->srna, "extend", true, "Extend", "Extend the selection");
}
/** \} */
@@ -3359,85 +3420,86 @@ void MESH_OT_select_face_by_sides(wmOperatorType *ot)
static int edbm_select_loose_exec(bContext *C, wmOperator *op)
{
- ViewLayer *view_layer = CTX_data_view_layer(C);
- const bool extend = RNA_boolean_get(op->ptr, "extend");
-
- uint objects_len = 0;
- Object **objects = BKE_view_layer_array_from_objects_in_edit_mode_unique_data(view_layer, CTX_wm_view3d(C), &objects_len);
-
- for (uint ob_index = 0; ob_index < objects_len; ob_index++) {
- Object *obedit = objects[ob_index];
- BMEditMesh *em = BKE_editmesh_from_object(obedit);
- BMesh *bm = em->bm;
- BMIter iter;
-
- if (!extend) {
- EDBM_flag_disable_all(em, BM_ELEM_SELECT);
- }
-
- if (em->selectmode & SCE_SELECT_VERTEX) {
- BMVert *eve;
- BM_ITER_MESH (eve, &iter, bm, BM_VERTS_OF_MESH) {
- if (!eve->e) {
- BM_vert_select_set(bm, eve, true);
- }
- }
- }
-
- if (em->selectmode & SCE_SELECT_EDGE) {
- BMEdge *eed;
- BM_ITER_MESH (eed, &iter, bm, BM_EDGES_OF_MESH) {
- if (BM_edge_is_wire(eed)) {
- BM_edge_select_set(bm, eed, true);
- }
- }
- }
-
- if (em->selectmode & SCE_SELECT_FACE) {
- BMFace *efa;
- BM_ITER_MESH (efa, &iter, bm, BM_FACES_OF_MESH) {
- BMIter liter;
- BMLoop *l;
- bool is_loose = true;
- BM_ITER_ELEM (l, &liter, efa, BM_LOOPS_OF_FACE) {
- if (!BM_edge_is_boundary(l->e)) {
- is_loose = false;
- break;
- }
- }
- if (is_loose) {
- BM_face_select_set(bm, efa, true);
- }
- }
- }
-
- EDBM_selectmode_flush(em);
-
- DEG_id_tag_update(obedit->data, ID_RECALC_SELECT);
- WM_event_add_notifier(C, NC_GEOM | ND_SELECT, obedit->data);
- }
-
- MEM_freeN(objects);
-
- return OPERATOR_FINISHED;
+ ViewLayer *view_layer = CTX_data_view_layer(C);
+ const bool extend = RNA_boolean_get(op->ptr, "extend");
+
+ uint objects_len = 0;
+ Object **objects = BKE_view_layer_array_from_objects_in_edit_mode_unique_data(
+ view_layer, CTX_wm_view3d(C), &objects_len);
+
+ for (uint ob_index = 0; ob_index < objects_len; ob_index++) {
+ Object *obedit = objects[ob_index];
+ BMEditMesh *em = BKE_editmesh_from_object(obedit);
+ BMesh *bm = em->bm;
+ BMIter iter;
+
+ if (!extend) {
+ EDBM_flag_disable_all(em, BM_ELEM_SELECT);
+ }
+
+ if (em->selectmode & SCE_SELECT_VERTEX) {
+ BMVert *eve;
+ BM_ITER_MESH (eve, &iter, bm, BM_VERTS_OF_MESH) {
+ if (!eve->e) {
+ BM_vert_select_set(bm, eve, true);
+ }
+ }
+ }
+
+ if (em->selectmode & SCE_SELECT_EDGE) {
+ BMEdge *eed;
+ BM_ITER_MESH (eed, &iter, bm, BM_EDGES_OF_MESH) {
+ if (BM_edge_is_wire(eed)) {
+ BM_edge_select_set(bm, eed, true);
+ }
+ }
+ }
+
+ if (em->selectmode & SCE_SELECT_FACE) {
+ BMFace *efa;
+ BM_ITER_MESH (efa, &iter, bm, BM_FACES_OF_MESH) {
+ BMIter liter;
+ BMLoop *l;
+ bool is_loose = true;
+ BM_ITER_ELEM (l, &liter, efa, BM_LOOPS_OF_FACE) {
+ if (!BM_edge_is_boundary(l->e)) {
+ is_loose = false;
+ break;
+ }
+ }
+ if (is_loose) {
+ BM_face_select_set(bm, efa, true);
+ }
+ }
+ }
+
+ EDBM_selectmode_flush(em);
+
+ DEG_id_tag_update(obedit->data, ID_RECALC_SELECT);
+ WM_event_add_notifier(C, NC_GEOM | ND_SELECT, obedit->data);
+ }
+
+ MEM_freeN(objects);
+
+ return OPERATOR_FINISHED;
}
void MESH_OT_select_loose(wmOperatorType *ot)
{
- /* identifiers */
- ot->name = "Select Loose Geometry";
- ot->description = "Select loose geometry based on the selection mode";
- ot->idname = "MESH_OT_select_loose";
+ /* identifiers */
+ ot->name = "Select Loose Geometry";
+ ot->description = "Select loose geometry based on the selection mode";
+ ot->idname = "MESH_OT_select_loose";
- /* api callbacks */
- ot->exec = edbm_select_loose_exec;
- ot->poll = ED_operator_editmesh;
+ /* api callbacks */
+ ot->exec = edbm_select_loose_exec;
+ ot->poll = ED_operator_editmesh;
- /* flags */
- ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
+ /* flags */
+ ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
- /* props */
- RNA_def_boolean(ot->srna, "extend", false, "Extend", "Extend the selection");
+ /* props */
+ RNA_def_boolean(ot->srna, "extend", false, "Extend", "Extend the selection");
}
/** \} */
@@ -3448,69 +3510,70 @@ void MESH_OT_select_loose(wmOperatorType *ot)
static int edbm_select_mirror_exec(bContext *C, wmOperator *op)
{
- ViewLayer *view_layer = CTX_data_view_layer(C);
- const int axis_flag = RNA_enum_get(op->ptr, "axis");
- const bool extend = RNA_boolean_get(op->ptr, "extend");
- Object *obedit_active = CTX_data_edit_object(C);
- BMEditMesh *em_active = BKE_editmesh_from_object(obedit_active);
- const int select_mode = em_active->bm->selectmode;
- int tot_mirr = 0, tot_fail = 0;
-
- uint objects_len = 0;
- Object **objects = BKE_view_layer_array_from_objects_in_edit_mode_unique_data(view_layer, CTX_wm_view3d(C), &objects_len);
-
- for (uint ob_index = 0; ob_index < objects_len; ob_index++) {
- Object *obedit = objects[ob_index];
- BMEditMesh *em = BKE_editmesh_from_object(obedit);
-
- if (em->bm->totvertsel == 0) {
- continue;
- }
-
- int tot_mirr_iter = 0, tot_fail_iter = 0;
-
- for (int axis = 0; axis < 3; axis++) {
- if ((1 << axis) & axis_flag) {
- EDBM_select_mirrored(em, axis, extend, &tot_mirr_iter, &tot_fail_iter);
- }
- }
-
- if (tot_mirr_iter) {
- EDBM_selectmode_flush(em);
-
- DEG_id_tag_update(obedit->data, ID_RECALC_SELECT);
- WM_event_add_notifier(C, NC_GEOM | ND_SELECT, obedit->data);
- }
-
- tot_fail += tot_fail_iter;
- tot_mirr += tot_mirr_iter;
- }
- MEM_freeN(objects);
-
- if (tot_mirr || tot_fail) {
- ED_mesh_report_mirror_ex(op, tot_mirr, tot_fail, select_mode);
- }
- return OPERATOR_FINISHED;
+ ViewLayer *view_layer = CTX_data_view_layer(C);
+ const int axis_flag = RNA_enum_get(op->ptr, "axis");
+ const bool extend = RNA_boolean_get(op->ptr, "extend");
+ Object *obedit_active = CTX_data_edit_object(C);
+ BMEditMesh *em_active = BKE_editmesh_from_object(obedit_active);
+ const int select_mode = em_active->bm->selectmode;
+ int tot_mirr = 0, tot_fail = 0;
+
+ uint objects_len = 0;
+ Object **objects = BKE_view_layer_array_from_objects_in_edit_mode_unique_data(
+ view_layer, CTX_wm_view3d(C), &objects_len);
+
+ for (uint ob_index = 0; ob_index < objects_len; ob_index++) {
+ Object *obedit = objects[ob_index];
+ BMEditMesh *em = BKE_editmesh_from_object(obedit);
+
+ if (em->bm->totvertsel == 0) {
+ continue;
+ }
+
+ int tot_mirr_iter = 0, tot_fail_iter = 0;
+
+ for (int axis = 0; axis < 3; axis++) {
+ if ((1 << axis) & axis_flag) {
+ EDBM_select_mirrored(em, axis, extend, &tot_mirr_iter, &tot_fail_iter);
+ }
+ }
+
+ if (tot_mirr_iter) {
+ EDBM_selectmode_flush(em);
+
+ DEG_id_tag_update(obedit->data, ID_RECALC_SELECT);
+ WM_event_add_notifier(C, NC_GEOM | ND_SELECT, obedit->data);
+ }
+
+ tot_fail += tot_fail_iter;
+ tot_mirr += tot_mirr_iter;
+ }
+ MEM_freeN(objects);
+
+ if (tot_mirr || tot_fail) {
+ ED_mesh_report_mirror_ex(op, tot_mirr, tot_fail, select_mode);
+ }
+ return OPERATOR_FINISHED;
}
void MESH_OT_select_mirror(wmOperatorType *ot)
{
- /* identifiers */
- ot->name = "Select Mirror";
- ot->description = "Select mesh items at mirrored locations";
- ot->idname = "MESH_OT_select_mirror";
+ /* identifiers */
+ ot->name = "Select Mirror";
+ ot->description = "Select mesh items at mirrored locations";
+ ot->idname = "MESH_OT_select_mirror";
- /* api callbacks */
- ot->exec = edbm_select_mirror_exec;
- ot->poll = ED_operator_editmesh;
+ /* api callbacks */
+ ot->exec = edbm_select_mirror_exec;
+ ot->poll = ED_operator_editmesh;
- /* flags */
- ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
+ /* flags */
+ ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
- /* props */
- RNA_def_enum_flag(ot->srna, "axis", rna_enum_axis_flag_xyz_items, (1 << 0), "Axis", "");
+ /* props */
+ RNA_def_enum_flag(ot->srna, "axis", rna_enum_axis_flag_xyz_items, (1 << 0), "Axis", "");
- RNA_def_boolean(ot->srna, "extend", 0, "Extend", "Extend the existing selection");
+ RNA_def_boolean(ot->srna, "extend", 0, "Extend", "Extend the existing selection");
}
/** \} */
@@ -3521,47 +3584,46 @@ void MESH_OT_select_mirror(wmOperatorType *ot)
static int edbm_select_more_exec(bContext *C, wmOperator *op)
{
- ViewLayer *view_layer = CTX_data_view_layer(C);
- const bool use_face_step = RNA_boolean_get(op->ptr, "use_face_step");
-
- uint objects_len = 0;
- Object **objects = BKE_view_layer_array_from_objects_in_edit_mode_unique_data(view_layer, CTX_wm_view3d(C), &objects_len);
- for (uint ob_index = 0; ob_index < objects_len; ob_index++) {
- Object *obedit = objects[ob_index];
- BMEditMesh *em = BKE_editmesh_from_object(obedit);
- BMesh *bm = em->bm;
-
- if ((bm->totvertsel == 0) &&
- (bm->totedgesel == 0) &&
- (bm->totfacesel == 0))
- {
- continue;
- }
-
- EDBM_select_more(em, use_face_step);
- DEG_id_tag_update(obedit->data, ID_RECALC_SELECT);
- WM_event_add_notifier(C, NC_GEOM | ND_SELECT, obedit->data);
- }
-
- MEM_freeN(objects);
- return OPERATOR_FINISHED;
+ ViewLayer *view_layer = CTX_data_view_layer(C);
+ const bool use_face_step = RNA_boolean_get(op->ptr, "use_face_step");
+
+ uint objects_len = 0;
+ Object **objects = BKE_view_layer_array_from_objects_in_edit_mode_unique_data(
+ view_layer, CTX_wm_view3d(C), &objects_len);
+ for (uint ob_index = 0; ob_index < objects_len; ob_index++) {
+ Object *obedit = objects[ob_index];
+ BMEditMesh *em = BKE_editmesh_from_object(obedit);
+ BMesh *bm = em->bm;
+
+ if ((bm->totvertsel == 0) && (bm->totedgesel == 0) && (bm->totfacesel == 0)) {
+ continue;
+ }
+
+ EDBM_select_more(em, use_face_step);
+ DEG_id_tag_update(obedit->data, ID_RECALC_SELECT);
+ WM_event_add_notifier(C, NC_GEOM | ND_SELECT, obedit->data);
+ }
+
+ MEM_freeN(objects);
+ return OPERATOR_FINISHED;
}
void MESH_OT_select_more(wmOperatorType *ot)
{
- /* identifiers */
- ot->name = "Select More";
- ot->idname = "MESH_OT_select_more";
- ot->description = "Select more vertices, edges or faces connected to initial selection";
+ /* identifiers */
+ ot->name = "Select More";
+ ot->idname = "MESH_OT_select_more";
+ ot->description = "Select more vertices, edges or faces connected to initial selection";
- /* api callbacks */
- ot->exec = edbm_select_more_exec;
- ot->poll = ED_operator_editmesh;
+ /* api callbacks */
+ ot->exec = edbm_select_more_exec;
+ ot->poll = ED_operator_editmesh;
- /* flags */
- ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
+ /* flags */
+ ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
- RNA_def_boolean(ot->srna, "use_face_step", true, "Face Step", "Connected faces (instead of edges)");
+ RNA_def_boolean(
+ ot->srna, "use_face_step", true, "Face Step", "Connected faces (instead of edges)");
}
/** \} */
@@ -3572,47 +3634,46 @@ void MESH_OT_select_more(wmOperatorType *ot)
static int edbm_select_less_exec(bContext *C, wmOperator *op)
{
- ViewLayer *view_layer = CTX_data_view_layer(C);
- const bool use_face_step = RNA_boolean_get(op->ptr, "use_face_step");
-
- uint objects_len = 0;
- Object **objects = BKE_view_layer_array_from_objects_in_edit_mode_unique_data(view_layer, CTX_wm_view3d(C), &objects_len);
- for (uint ob_index = 0; ob_index < objects_len; ob_index++) {
- Object *obedit = objects[ob_index];
- BMEditMesh *em = BKE_editmesh_from_object(obedit);
- BMesh *bm = em->bm;
-
- if ((bm->totvertsel == 0) &&
- (bm->totedgesel == 0) &&
- (bm->totfacesel == 0))
- {
- continue;
- }
-
- EDBM_select_less(em, use_face_step);
- DEG_id_tag_update(obedit->data, ID_RECALC_SELECT);
- WM_event_add_notifier(C, NC_GEOM | ND_SELECT, obedit->data);
- }
-
- MEM_freeN(objects);
- return OPERATOR_FINISHED;
+ ViewLayer *view_layer = CTX_data_view_layer(C);
+ const bool use_face_step = RNA_boolean_get(op->ptr, "use_face_step");
+
+ uint objects_len = 0;
+ Object **objects = BKE_view_layer_array_from_objects_in_edit_mode_unique_data(
+ view_layer, CTX_wm_view3d(C), &objects_len);
+ for (uint ob_index = 0; ob_index < objects_len; ob_index++) {
+ Object *obedit = objects[ob_index];
+ BMEditMesh *em = BKE_editmesh_from_object(obedit);
+ BMesh *bm = em->bm;
+
+ if ((bm->totvertsel == 0) && (bm->totedgesel == 0) && (bm->totfacesel == 0)) {
+ continue;
+ }
+
+ EDBM_select_less(em, use_face_step);
+ DEG_id_tag_update(obedit->data, ID_RECALC_SELECT);
+ WM_event_add_notifier(C, NC_GEOM | ND_SELECT, obedit->data);
+ }
+
+ MEM_freeN(objects);
+ return OPERATOR_FINISHED;
}
void MESH_OT_select_less(wmOperatorType *ot)
{
- /* identifiers */
- ot->name = "Select Less";
- ot->idname = "MESH_OT_select_less";
- ot->description = "Deselect vertices, edges or faces at the boundary of each selection region";
+ /* identifiers */
+ ot->name = "Select Less";
+ ot->idname = "MESH_OT_select_less";
+ ot->description = "Deselect vertices, edges or faces at the boundary of each selection region";
- /* api callbacks */
- ot->exec = edbm_select_less_exec;
- ot->poll = ED_operator_editmesh;
+ /* api callbacks */
+ ot->exec = edbm_select_less_exec;
+ ot->poll = ED_operator_editmesh;
- /* flags */
- ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
+ /* flags */
+ ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
- RNA_def_boolean(ot->srna, "use_face_step", true, "Face Step", "Connected faces (instead of edges)");
+ RNA_def_boolean(
+ ot->srna, "use_face_step", true, "Face Step", "Connected faces (instead of edges)");
}
/** \} */
@@ -3626,249 +3687,250 @@ void MESH_OT_select_less(wmOperatorType *ot)
*/
static bool bm_edge_is_select_isolated(BMEdge *e)
{
- BMIter viter;
- BMVert *v;
-
- BM_ITER_ELEM (v, &viter, e, BM_VERTS_OF_EDGE) {
- BMIter eiter;
- BMEdge *e_other;
-
- BM_ITER_ELEM (e_other, &eiter, v, BM_EDGES_OF_VERT) {
- if ((e_other != e) && BM_elem_flag_test(e_other, BM_ELEM_SELECT)) {
- return false;
- }
- }
- }
- return true;
+ BMIter viter;
+ BMVert *v;
+
+ BM_ITER_ELEM (v, &viter, e, BM_VERTS_OF_EDGE) {
+ BMIter eiter;
+ BMEdge *e_other;
+
+ BM_ITER_ELEM (e_other, &eiter, v, BM_EDGES_OF_VERT) {
+ if ((e_other != e) && BM_elem_flag_test(e_other, BM_ELEM_SELECT)) {
+ return false;
+ }
+ }
+ }
+ return true;
}
/* Walk all reachable elements of the same type as h_act in breadth-first
* order, starting from h_act. Deselects elements if the depth when they
* are reached is not a multiple of "nth". */
-static void walker_deselect_nth(
- BMEditMesh *em, const struct CheckerIntervalParams *op_params,
- BMHeader *h_act)
+static void walker_deselect_nth(BMEditMesh *em,
+ const struct CheckerIntervalParams *op_params,
+ BMHeader *h_act)
{
- BMElem *ele;
- BMesh *bm = em->bm;
- BMWalker walker;
- BMIter iter;
- int walktype = 0, itertype = 0, flushtype = 0;
- short mask_vert = 0, mask_edge = 0, mask_face = 0;
-
- /* No active element from which to start - nothing to do */
- if (h_act == NULL) {
- return;
- }
-
- /* Determine which type of iter, walker, and select flush to use
- * based on type of the elements being deselected */
- switch (h_act->htype) {
- case BM_VERT:
- itertype = BM_VERTS_OF_MESH;
- walktype = BMW_CONNECTED_VERTEX;
- flushtype = SCE_SELECT_VERTEX;
- mask_vert = BMO_ELE_TAG;
- break;
- case BM_EDGE:
- /* When an edge has no connected-selected edges,
- * use face-stepping (supports edge-rings) */
- itertype = BM_EDGES_OF_MESH;
- walktype = bm_edge_is_select_isolated((BMEdge *)h_act) ? BMW_FACE_SHELL : BMW_VERT_SHELL;
- flushtype = SCE_SELECT_EDGE;
- mask_edge = BMO_ELE_TAG;
- break;
- case BM_FACE:
- itertype = BM_FACES_OF_MESH;
- walktype = BMW_ISLAND;
- flushtype = SCE_SELECT_FACE;
- mask_face = BMO_ELE_TAG;
- break;
- }
-
- /* grr, shouldn't need to alloc BMO flags here */
- BM_mesh_elem_toolflags_ensure(bm);
-
- /* Walker restrictions uses BMO flags, not header flags,
- * so transfer BM_ELEM_SELECT from HFlags onto a BMO flag layer. */
- BMO_push(bm, NULL);
- BM_ITER_MESH (ele, &iter, bm, itertype) {
- if (BM_elem_flag_test(ele, BM_ELEM_SELECT)) {
- BMO_elem_flag_enable(bm, (BMElemF *)ele, BMO_ELE_TAG);
- }
- }
-
- /* Walk over selected elements starting at active */
- BMW_init(&walker, bm, walktype,
- mask_vert, mask_edge, mask_face,
- BMW_FLAG_NOP, /* don't use BMW_FLAG_TEST_HIDDEN here since we want to desel all */
- BMW_NIL_LAY);
-
- /* use tag to avoid touching the same verts twice */
- BM_ITER_MESH (ele, &iter, bm, itertype) {
- BM_elem_flag_disable(ele, BM_ELEM_TAG);
- }
-
- BLI_assert(walker.order == BMW_BREADTH_FIRST);
- for (ele = BMW_begin(&walker, h_act); ele != NULL; ele = BMW_step(&walker)) {
- if (!BM_elem_flag_test(ele, BM_ELEM_TAG)) {
- /* Deselect elements that aren't at "nth" depth from active */
- const int depth = BMW_current_depth(&walker) - 1;
- if (WM_operator_properties_checker_interval_test(op_params, depth)) {
- BM_elem_select_set(bm, ele, false);
- }
- BM_elem_flag_enable(ele, BM_ELEM_TAG);
- }
- }
- BMW_end(&walker);
-
- BMO_pop(bm);
-
- /* Flush selection up */
- EDBM_selectmode_flush_ex(em, flushtype);
+ BMElem *ele;
+ BMesh *bm = em->bm;
+ BMWalker walker;
+ BMIter iter;
+ int walktype = 0, itertype = 0, flushtype = 0;
+ short mask_vert = 0, mask_edge = 0, mask_face = 0;
+
+ /* No active element from which to start - nothing to do */
+ if (h_act == NULL) {
+ return;
+ }
+
+ /* Determine which type of iter, walker, and select flush to use
+ * based on type of the elements being deselected */
+ switch (h_act->htype) {
+ case BM_VERT:
+ itertype = BM_VERTS_OF_MESH;
+ walktype = BMW_CONNECTED_VERTEX;
+ flushtype = SCE_SELECT_VERTEX;
+ mask_vert = BMO_ELE_TAG;
+ break;
+ case BM_EDGE:
+ /* When an edge has no connected-selected edges,
+ * use face-stepping (supports edge-rings) */
+ itertype = BM_EDGES_OF_MESH;
+ walktype = bm_edge_is_select_isolated((BMEdge *)h_act) ? BMW_FACE_SHELL : BMW_VERT_SHELL;
+ flushtype = SCE_SELECT_EDGE;
+ mask_edge = BMO_ELE_TAG;
+ break;
+ case BM_FACE:
+ itertype = BM_FACES_OF_MESH;
+ walktype = BMW_ISLAND;
+ flushtype = SCE_SELECT_FACE;
+ mask_face = BMO_ELE_TAG;
+ break;
+ }
+
+ /* grr, shouldn't need to alloc BMO flags here */
+ BM_mesh_elem_toolflags_ensure(bm);
+
+ /* Walker restrictions uses BMO flags, not header flags,
+ * so transfer BM_ELEM_SELECT from HFlags onto a BMO flag layer. */
+ BMO_push(bm, NULL);
+ BM_ITER_MESH (ele, &iter, bm, itertype) {
+ if (BM_elem_flag_test(ele, BM_ELEM_SELECT)) {
+ BMO_elem_flag_enable(bm, (BMElemF *)ele, BMO_ELE_TAG);
+ }
+ }
+
+ /* Walk over selected elements starting at active */
+ BMW_init(&walker,
+ bm,
+ walktype,
+ mask_vert,
+ mask_edge,
+ mask_face,
+ BMW_FLAG_NOP, /* don't use BMW_FLAG_TEST_HIDDEN here since we want to desel all */
+ BMW_NIL_LAY);
+
+ /* use tag to avoid touching the same verts twice */
+ BM_ITER_MESH (ele, &iter, bm, itertype) {
+ BM_elem_flag_disable(ele, BM_ELEM_TAG);
+ }
+
+ BLI_assert(walker.order == BMW_BREADTH_FIRST);
+ for (ele = BMW_begin(&walker, h_act); ele != NULL; ele = BMW_step(&walker)) {
+ if (!BM_elem_flag_test(ele, BM_ELEM_TAG)) {
+ /* Deselect elements that aren't at "nth" depth from active */
+ const int depth = BMW_current_depth(&walker) - 1;
+ if (WM_operator_properties_checker_interval_test(op_params, depth)) {
+ BM_elem_select_set(bm, ele, false);
+ }
+ BM_elem_flag_enable(ele, BM_ELEM_TAG);
+ }
+ }
+ BMW_end(&walker);
+
+ BMO_pop(bm);
+
+ /* Flush selection up */
+ EDBM_selectmode_flush_ex(em, flushtype);
}
static void deselect_nth_active(BMEditMesh *em, BMVert **r_eve, BMEdge **r_eed, BMFace **r_efa)
{
- BMIter iter;
- BMElem *ele;
-
- *r_eve = NULL;
- *r_eed = NULL;
- *r_efa = NULL;
-
- EDBM_selectmode_flush(em);
- ele = BM_mesh_active_elem_get(em->bm);
-
- if (ele && BM_elem_flag_test(ele, BM_ELEM_SELECT)) {
- switch (ele->head.htype) {
- case BM_VERT:
- *r_eve = (BMVert *)ele;
- return;
- case BM_EDGE:
- *r_eed = (BMEdge *)ele;
- return;
- case BM_FACE:
- *r_efa = (BMFace *)ele;
- return;
- }
- }
-
- if (em->selectmode & SCE_SELECT_VERTEX) {
- BMVert *v;
- BM_ITER_MESH (v, &iter, em->bm, BM_VERTS_OF_MESH) {
- if (BM_elem_flag_test(v, BM_ELEM_SELECT)) {
- *r_eve = v;
- return;
- }
- }
- }
- else if (em->selectmode & SCE_SELECT_EDGE) {
- BMEdge *e;
- BM_ITER_MESH (e, &iter, em->bm, BM_EDGES_OF_MESH) {
- if (BM_elem_flag_test(e, BM_ELEM_SELECT)) {
- *r_eed = e;
- return;
- }
- }
- }
- else if (em->selectmode & SCE_SELECT_FACE) {
- BMFace *f = BM_mesh_active_face_get(em->bm, true, false);
- if (f && BM_elem_flag_test(f, BM_ELEM_SELECT)) {
- *r_efa = f;
- return;
- }
- }
+ BMIter iter;
+ BMElem *ele;
+
+ *r_eve = NULL;
+ *r_eed = NULL;
+ *r_efa = NULL;
+
+ EDBM_selectmode_flush(em);
+ ele = BM_mesh_active_elem_get(em->bm);
+
+ if (ele && BM_elem_flag_test(ele, BM_ELEM_SELECT)) {
+ switch (ele->head.htype) {
+ case BM_VERT:
+ *r_eve = (BMVert *)ele;
+ return;
+ case BM_EDGE:
+ *r_eed = (BMEdge *)ele;
+ return;
+ case BM_FACE:
+ *r_efa = (BMFace *)ele;
+ return;
+ }
+ }
+
+ if (em->selectmode & SCE_SELECT_VERTEX) {
+ BMVert *v;
+ BM_ITER_MESH (v, &iter, em->bm, BM_VERTS_OF_MESH) {
+ if (BM_elem_flag_test(v, BM_ELEM_SELECT)) {
+ *r_eve = v;
+ return;
+ }
+ }
+ }
+ else if (em->selectmode & SCE_SELECT_EDGE) {
+ BMEdge *e;
+ BM_ITER_MESH (e, &iter, em->bm, BM_EDGES_OF_MESH) {
+ if (BM_elem_flag_test(e, BM_ELEM_SELECT)) {
+ *r_eed = e;
+ return;
+ }
+ }
+ }
+ else if (em->selectmode & SCE_SELECT_FACE) {
+ BMFace *f = BM_mesh_active_face_get(em->bm, true, false);
+ if (f && BM_elem_flag_test(f, BM_ELEM_SELECT)) {
+ *r_efa = f;
+ return;
+ }
+ }
}
static bool edbm_deselect_nth(BMEditMesh *em, const struct CheckerIntervalParams *op_params)
{
- BMVert *v;
- BMEdge *e;
- BMFace *f;
-
- deselect_nth_active(em, &v, &e, &f);
-
- if (v) {
- walker_deselect_nth(em, op_params, &v->head);
- return true;
- }
- else if (e) {
- walker_deselect_nth(em, op_params, &e->head);
- return true;
- }
- else if (f) {
- walker_deselect_nth(em, op_params, &f->head);
- return true;
- }
-
- return false;
+ BMVert *v;
+ BMEdge *e;
+ BMFace *f;
+
+ deselect_nth_active(em, &v, &e, &f);
+
+ if (v) {
+ walker_deselect_nth(em, op_params, &v->head);
+ return true;
+ }
+ else if (e) {
+ walker_deselect_nth(em, op_params, &e->head);
+ return true;
+ }
+ else if (f) {
+ walker_deselect_nth(em, op_params, &f->head);
+ return true;
+ }
+
+ return false;
}
static int edbm_select_nth_exec(bContext *C, wmOperator *op)
{
- ViewLayer *view_layer = CTX_data_view_layer(C);
- struct CheckerIntervalParams op_params;
- WM_operator_properties_checker_interval_from_op(op, &op_params);
- bool found_active_elt = false;
-
- uint objects_len = 0;
- Object **objects = BKE_view_layer_array_from_objects_in_edit_mode_unique_data(view_layer, CTX_wm_view3d(C), &objects_len);
-
- for (uint ob_index = 0; ob_index < objects_len; ob_index++) {
- Object *obedit = objects[ob_index];
- BMEditMesh *em = BKE_editmesh_from_object(obedit);
-
- if ((em->bm->totvertsel == 0) &&
- (em->bm->totedgesel == 0) &&
- (em->bm->totfacesel == 0))
- {
- continue;
- }
-
- if (edbm_deselect_nth(em, &op_params) == true) {
- found_active_elt = true;
- EDBM_update_generic(em, false, false);
- }
- }
- MEM_freeN(objects);
-
- if (!found_active_elt) {
- BKE_report(op->reports, RPT_ERROR,
- (objects_len == 1 ?
- "Mesh has no active vert/edge/face" :
- "Meshes have no active vert/edge/face"));
- return OPERATOR_CANCELLED;
- }
-
- return OPERATOR_FINISHED;
+ ViewLayer *view_layer = CTX_data_view_layer(C);
+ struct CheckerIntervalParams op_params;
+ WM_operator_properties_checker_interval_from_op(op, &op_params);
+ bool found_active_elt = false;
+
+ uint objects_len = 0;
+ Object **objects = BKE_view_layer_array_from_objects_in_edit_mode_unique_data(
+ view_layer, CTX_wm_view3d(C), &objects_len);
+
+ for (uint ob_index = 0; ob_index < objects_len; ob_index++) {
+ Object *obedit = objects[ob_index];
+ BMEditMesh *em = BKE_editmesh_from_object(obedit);
+
+ if ((em->bm->totvertsel == 0) && (em->bm->totedgesel == 0) && (em->bm->totfacesel == 0)) {
+ continue;
+ }
+
+ if (edbm_deselect_nth(em, &op_params) == true) {
+ found_active_elt = true;
+ EDBM_update_generic(em, false, false);
+ }
+ }
+ MEM_freeN(objects);
+
+ if (!found_active_elt) {
+ BKE_report(op->reports,
+ RPT_ERROR,
+ (objects_len == 1 ? "Mesh has no active vert/edge/face" :
+ "Meshes have no active vert/edge/face"));
+ return OPERATOR_CANCELLED;
+ }
+
+ return OPERATOR_FINISHED;
}
-
void MESH_OT_select_nth(wmOperatorType *ot)
{
- /* identifiers */
- ot->name = "Checker Deselect";
- ot->idname = "MESH_OT_select_nth";
- ot->description = "Deselect every Nth element starting from the active vertex, edge or face";
+ /* identifiers */
+ ot->name = "Checker Deselect";
+ ot->idname = "MESH_OT_select_nth";
+ ot->description = "Deselect every Nth element starting from the active vertex, edge or face";
- /* api callbacks */
- ot->exec = edbm_select_nth_exec;
- ot->poll = ED_operator_editmesh;
+ /* api callbacks */
+ ot->exec = edbm_select_nth_exec;
+ ot->poll = ED_operator_editmesh;
- /* flags */
- ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
+ /* flags */
+ ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
- WM_operator_properties_checker_interval(ot, false);
+ WM_operator_properties_checker_interval(ot, false);
}
void em_setup_viewcontext(bContext *C, ViewContext *vc)
{
- ED_view3d_viewcontext_init(C, vc);
+ ED_view3d_viewcontext_init(C, vc);
- if (vc->obedit) {
- vc->em = BKE_editmesh_from_object(vc->obedit);
- }
+ if (vc->obedit) {
+ vc->em = BKE_editmesh_from_object(vc->obedit);
+ }
}
/** \} */
@@ -3879,71 +3941,78 @@ void em_setup_viewcontext(bContext *C, ViewContext *vc)
static int edbm_select_sharp_edges_exec(bContext *C, wmOperator *op)
{
- /* Find edges that have exactly two neighboring faces,
- * check the angle between those faces, and if angle is
- * small enough, select the edge
- */
- const float angle_limit_cos = cosf(RNA_float_get(op->ptr, "sharpness"));
-
- ViewLayer *view_layer = CTX_data_view_layer(C);
- uint objects_len = 0;
- Object **objects = BKE_view_layer_array_from_objects_in_edit_mode_unique_data(view_layer, CTX_wm_view3d(C), &objects_len);
-
- for (uint ob_index = 0; ob_index < objects_len; ob_index++) {
- Object *obedit = objects[ob_index];
- BMEditMesh *em = BKE_editmesh_from_object(obedit);
- BMIter iter;
- BMEdge *e;
- BMLoop *l1, *l2;
-
- BM_ITER_MESH (e, &iter, em->bm, BM_EDGES_OF_MESH) {
- if (BM_elem_flag_test(e, BM_ELEM_HIDDEN) == false &&
- BM_edge_loop_pair(e, &l1, &l2))
- {
- /* edge has exactly two neighboring faces, check angle */
- const float angle_cos = dot_v3v3(l1->f->no, l2->f->no);
-
- if (angle_cos < angle_limit_cos) {
- BM_edge_select_set(em->bm, e, true);
- }
- }
- }
-
- if ((em->bm->selectmode & (SCE_SELECT_VERTEX | SCE_SELECT_EDGE)) == 0) {
- /* Since we can't select individual edges, select faces connected to them. */
- EDBM_selectmode_convert(em, SCE_SELECT_EDGE, SCE_SELECT_FACE);
- }
- else {
- EDBM_selectmode_flush(em);
- }
- DEG_id_tag_update(obedit->data, ID_RECALC_SELECT);
- WM_event_add_notifier(C, NC_GEOM | ND_SELECT, obedit->data);
- }
- MEM_freeN(objects);
-
- return OPERATOR_FINISHED;
+ /* Find edges that have exactly two neighboring faces,
+ * check the angle between those faces, and if angle is
+ * small enough, select the edge
+ */
+ const float angle_limit_cos = cosf(RNA_float_get(op->ptr, "sharpness"));
+
+ ViewLayer *view_layer = CTX_data_view_layer(C);
+ uint objects_len = 0;
+ Object **objects = BKE_view_layer_array_from_objects_in_edit_mode_unique_data(
+ view_layer, CTX_wm_view3d(C), &objects_len);
+
+ for (uint ob_index = 0; ob_index < objects_len; ob_index++) {
+ Object *obedit = objects[ob_index];
+ BMEditMesh *em = BKE_editmesh_from_object(obedit);
+ BMIter iter;
+ BMEdge *e;
+ BMLoop *l1, *l2;
+
+ BM_ITER_MESH (e, &iter, em->bm, BM_EDGES_OF_MESH) {
+ if (BM_elem_flag_test(e, BM_ELEM_HIDDEN) == false && BM_edge_loop_pair(e, &l1, &l2)) {
+ /* edge has exactly two neighboring faces, check angle */
+ const float angle_cos = dot_v3v3(l1->f->no, l2->f->no);
+
+ if (angle_cos < angle_limit_cos) {
+ BM_edge_select_set(em->bm, e, true);
+ }
+ }
+ }
+
+ if ((em->bm->selectmode & (SCE_SELECT_VERTEX | SCE_SELECT_EDGE)) == 0) {
+ /* Since we can't select individual edges, select faces connected to them. */
+ EDBM_selectmode_convert(em, SCE_SELECT_EDGE, SCE_SELECT_FACE);
+ }
+ else {
+ EDBM_selectmode_flush(em);
+ }
+ DEG_id_tag_update(obedit->data, ID_RECALC_SELECT);
+ WM_event_add_notifier(C, NC_GEOM | ND_SELECT, obedit->data);
+ }
+ MEM_freeN(objects);
+
+ return OPERATOR_FINISHED;
}
void MESH_OT_edges_select_sharp(wmOperatorType *ot)
{
- PropertyRNA *prop;
-
- /* identifiers */
- ot->name = "Select Sharp Edges";
- ot->description = "Select all sharp-enough edges";
- ot->idname = "MESH_OT_edges_select_sharp";
-
- /* api callbacks */
- ot->exec = edbm_select_sharp_edges_exec;
- ot->poll = ED_operator_editmesh;
-
- /* flags */
- ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
-
- /* props */
- prop = RNA_def_float_rotation(ot->srna, "sharpness", 0, NULL, DEG2RADF(0.01f), DEG2RADF(180.0f),
- "Sharpness", "", DEG2RADF(1.0f), DEG2RADF(180.0f));
- RNA_def_property_float_default(prop, DEG2RADF(30.0f));
+ PropertyRNA *prop;
+
+ /* identifiers */
+ ot->name = "Select Sharp Edges";
+ ot->description = "Select all sharp-enough edges";
+ ot->idname = "MESH_OT_edges_select_sharp";
+
+ /* api callbacks */
+ ot->exec = edbm_select_sharp_edges_exec;
+ ot->poll = ED_operator_editmesh;
+
+ /* flags */
+ ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
+
+ /* props */
+ prop = RNA_def_float_rotation(ot->srna,
+ "sharpness",
+ 0,
+ NULL,
+ DEG2RADF(0.01f),
+ DEG2RADF(180.0f),
+ "Sharpness",
+ "",
+ DEG2RADF(1.0f),
+ DEG2RADF(180.0f));
+ RNA_def_property_float_default(prop, DEG2RADF(30.0f));
}
/** \} */
@@ -3954,95 +4023,102 @@ void MESH_OT_edges_select_sharp(wmOperatorType *ot)
static int edbm_select_linked_flat_faces_exec(bContext *C, wmOperator *op)
{
- ViewLayer *view_layer = CTX_data_view_layer(C);
- uint objects_len = 0;
- Object **objects = BKE_view_layer_array_from_objects_in_edit_mode_unique_data(view_layer, CTX_wm_view3d(C), &objects_len);
- const float angle_limit_cos = cosf(RNA_float_get(op->ptr, "sharpness"));
+ ViewLayer *view_layer = CTX_data_view_layer(C);
+ uint objects_len = 0;
+ Object **objects = BKE_view_layer_array_from_objects_in_edit_mode_unique_data(
+ view_layer, CTX_wm_view3d(C), &objects_len);
+ const float angle_limit_cos = cosf(RNA_float_get(op->ptr, "sharpness"));
- for (uint ob_index = 0; ob_index < objects_len; ob_index++) {
- Object *obedit = objects[ob_index];
- BMEditMesh *em = BKE_editmesh_from_object(obedit);
- BMesh *bm = em->bm;
+ for (uint ob_index = 0; ob_index < objects_len; ob_index++) {
+ Object *obedit = objects[ob_index];
+ BMEditMesh *em = BKE_editmesh_from_object(obedit);
+ BMesh *bm = em->bm;
- if (bm->totfacesel == 0) {
- continue;
- }
+ if (bm->totfacesel == 0) {
+ continue;
+ }
- BLI_LINKSTACK_DECLARE(stack, BMFace *);
+ BLI_LINKSTACK_DECLARE(stack, BMFace *);
- BMIter iter, liter, liter2;
- BMFace *f;
- BMLoop *l, *l2;
+ BMIter iter, liter, liter2;
+ BMFace *f;
+ BMLoop *l, *l2;
- BM_mesh_elem_hflag_disable_all(bm, BM_FACE, BM_ELEM_TAG, false);
+ BM_mesh_elem_hflag_disable_all(bm, BM_FACE, BM_ELEM_TAG, false);
- BLI_LINKSTACK_INIT(stack);
+ BLI_LINKSTACK_INIT(stack);
- BM_ITER_MESH (f, &iter, bm, BM_FACES_OF_MESH) {
- if ((BM_elem_flag_test(f, BM_ELEM_HIDDEN) != 0) ||
- (BM_elem_flag_test(f, BM_ELEM_TAG) != 0) ||
- (BM_elem_flag_test(f, BM_ELEM_SELECT) == 0))
- {
- continue;
- }
+ BM_ITER_MESH (f, &iter, bm, BM_FACES_OF_MESH) {
+ if ((BM_elem_flag_test(f, BM_ELEM_HIDDEN) != 0) ||
+ (BM_elem_flag_test(f, BM_ELEM_TAG) != 0) ||
+ (BM_elem_flag_test(f, BM_ELEM_SELECT) == 0)) {
+ continue;
+ }
- BLI_assert(BLI_LINKSTACK_SIZE(stack) == 0);
+ BLI_assert(BLI_LINKSTACK_SIZE(stack) == 0);
- do {
- BM_face_select_set(bm, f, true);
+ do {
+ BM_face_select_set(bm, f, true);
- BM_elem_flag_enable(f, BM_ELEM_TAG);
+ BM_elem_flag_enable(f, BM_ELEM_TAG);
- BM_ITER_ELEM (l, &liter, f, BM_LOOPS_OF_FACE) {
- BM_ITER_ELEM (l2, &liter2, l, BM_LOOPS_OF_LOOP) {
- float angle_cos;
+ BM_ITER_ELEM (l, &liter, f, BM_LOOPS_OF_FACE) {
+ BM_ITER_ELEM (l2, &liter2, l, BM_LOOPS_OF_LOOP) {
+ float angle_cos;
- if (BM_elem_flag_test(l2->f, BM_ELEM_TAG) ||
- BM_elem_flag_test(l2->f, BM_ELEM_HIDDEN))
- {
- continue;
- }
+ if (BM_elem_flag_test(l2->f, BM_ELEM_TAG) ||
+ BM_elem_flag_test(l2->f, BM_ELEM_HIDDEN)) {
+ continue;
+ }
- angle_cos = dot_v3v3(f->no, l2->f->no);
+ angle_cos = dot_v3v3(f->no, l2->f->no);
- if (angle_cos > angle_limit_cos) {
- BLI_LINKSTACK_PUSH(stack, l2->f);
- }
- }
- }
- } while ((f = BLI_LINKSTACK_POP(stack)));
- }
+ if (angle_cos > angle_limit_cos) {
+ BLI_LINKSTACK_PUSH(stack, l2->f);
+ }
+ }
+ }
+ } while ((f = BLI_LINKSTACK_POP(stack)));
+ }
- BLI_LINKSTACK_FREE(stack);
+ BLI_LINKSTACK_FREE(stack);
- DEG_id_tag_update(obedit->data, ID_RECALC_SELECT);
- WM_event_add_notifier(C, NC_GEOM | ND_SELECT, obedit->data);
- }
- MEM_freeN(objects);
+ DEG_id_tag_update(obedit->data, ID_RECALC_SELECT);
+ WM_event_add_notifier(C, NC_GEOM | ND_SELECT, obedit->data);
+ }
+ MEM_freeN(objects);
- return OPERATOR_FINISHED;
+ return OPERATOR_FINISHED;
}
void MESH_OT_faces_select_linked_flat(wmOperatorType *ot)
{
- PropertyRNA *prop;
-
- /* identifiers */
- ot->name = "Select Linked Flat Faces";
- ot->description = "Select linked faces by angle";
- ot->idname = "MESH_OT_faces_select_linked_flat";
-
- /* api callbacks */
- ot->exec = edbm_select_linked_flat_faces_exec;
- ot->poll = ED_operator_editmesh;
-
- /* flags */
- ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
-
- /* props */
- prop = RNA_def_float_rotation(ot->srna, "sharpness", 0, NULL, DEG2RADF(0.01f), DEG2RADF(180.0f),
- "Sharpness", "", DEG2RADF(1.0f), DEG2RADF(180.0f));
- RNA_def_property_float_default(prop, DEG2RADF(1.0f));
+ PropertyRNA *prop;
+
+ /* identifiers */
+ ot->name = "Select Linked Flat Faces";
+ ot->description = "Select linked faces by angle";
+ ot->idname = "MESH_OT_faces_select_linked_flat";
+
+ /* api callbacks */
+ ot->exec = edbm_select_linked_flat_faces_exec;
+ ot->poll = ED_operator_editmesh;
+
+ /* flags */
+ ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
+
+ /* props */
+ prop = RNA_def_float_rotation(ot->srna,
+ "sharpness",
+ 0,
+ NULL,
+ DEG2RADF(0.01f),
+ DEG2RADF(180.0f),
+ "Sharpness",
+ "",
+ DEG2RADF(1.0f),
+ DEG2RADF(180.0f));
+ RNA_def_property_float_default(prop, DEG2RADF(1.0f));
}
/** \} */
@@ -4053,103 +4129,102 @@ void MESH_OT_faces_select_linked_flat(wmOperatorType *ot)
static int edbm_select_non_manifold_exec(bContext *C, wmOperator *op)
{
- const bool use_extend = RNA_boolean_get(op->ptr, "extend");
- const bool use_wire = RNA_boolean_get(op->ptr, "use_wire");
- const bool use_boundary = RNA_boolean_get(op->ptr, "use_boundary");
- const bool use_multi_face = RNA_boolean_get(op->ptr, "use_multi_face");
- const bool use_non_contiguous = RNA_boolean_get(op->ptr, "use_non_contiguous");
- const bool use_verts = RNA_boolean_get(op->ptr, "use_verts");
-
- ViewLayer *view_layer = CTX_data_view_layer(C);
- uint objects_len = 0;
- Object **objects = BKE_view_layer_array_from_objects_in_edit_mode_unique_data(view_layer, CTX_wm_view3d(C), &objects_len);
-
- for (uint ob_index = 0; ob_index < objects_len; ob_index++) {
- Object *obedit = objects[ob_index];
- BMEditMesh *em = BKE_editmesh_from_object(obedit);
- BMVert *v;
- BMEdge *e;
- BMIter iter;
-
- if (!use_extend) {
- EDBM_flag_disable_all(em, BM_ELEM_SELECT);
- }
-
- /* Selects isolated verts, and edges that do not have 2 neighboring
- * faces
- */
-
- if (em->selectmode == SCE_SELECT_FACE) {
- BKE_report(op->reports, RPT_ERROR, "Does not work in face selection mode");
- MEM_freeN(objects);
- return OPERATOR_CANCELLED;
- }
-
- if (use_verts) {
- BM_ITER_MESH (v, &iter, em->bm, BM_VERTS_OF_MESH) {
- if (!BM_elem_flag_test(v, BM_ELEM_HIDDEN)) {
- if (!BM_vert_is_manifold(v)) {
- BM_vert_select_set(em->bm, v, true);
- }
- }
- }
- }
-
- if (use_wire || use_boundary || use_multi_face || use_non_contiguous) {
- BM_ITER_MESH (e, &iter, em->bm, BM_EDGES_OF_MESH) {
- if (!BM_elem_flag_test(e, BM_ELEM_HIDDEN)) {
- if ((use_wire && BM_edge_is_wire(e)) ||
- (use_boundary && BM_edge_is_boundary(e)) ||
- (use_non_contiguous && (BM_edge_is_manifold(e) && !BM_edge_is_contiguous(e))) ||
- (use_multi_face && (BM_edge_face_count_is_over(e, 2))))
- {
- /* check we never select perfect edge (in test above) */
- BLI_assert(!(BM_edge_is_manifold(e) && BM_edge_is_contiguous(e)));
-
- BM_edge_select_set(em->bm, e, true);
- }
- }
- }
- }
-
- DEG_id_tag_update(obedit->data, ID_RECALC_SELECT);
- WM_event_add_notifier(C, NC_GEOM | ND_SELECT, obedit->data);
-
- EDBM_selectmode_flush(em);
- }
- MEM_freeN(objects);
-
- return OPERATOR_FINISHED;
+ const bool use_extend = RNA_boolean_get(op->ptr, "extend");
+ const bool use_wire = RNA_boolean_get(op->ptr, "use_wire");
+ const bool use_boundary = RNA_boolean_get(op->ptr, "use_boundary");
+ const bool use_multi_face = RNA_boolean_get(op->ptr, "use_multi_face");
+ const bool use_non_contiguous = RNA_boolean_get(op->ptr, "use_non_contiguous");
+ const bool use_verts = RNA_boolean_get(op->ptr, "use_verts");
+
+ ViewLayer *view_layer = CTX_data_view_layer(C);
+ uint objects_len = 0;
+ Object **objects = BKE_view_layer_array_from_objects_in_edit_mode_unique_data(
+ view_layer, CTX_wm_view3d(C), &objects_len);
+
+ for (uint ob_index = 0; ob_index < objects_len; ob_index++) {
+ Object *obedit = objects[ob_index];
+ BMEditMesh *em = BKE_editmesh_from_object(obedit);
+ BMVert *v;
+ BMEdge *e;
+ BMIter iter;
+
+ if (!use_extend) {
+ EDBM_flag_disable_all(em, BM_ELEM_SELECT);
+ }
+
+ /* Selects isolated verts, and edges that do not have 2 neighboring
+ * faces
+ */
+
+ if (em->selectmode == SCE_SELECT_FACE) {
+ BKE_report(op->reports, RPT_ERROR, "Does not work in face selection mode");
+ MEM_freeN(objects);
+ return OPERATOR_CANCELLED;
+ }
+
+ if (use_verts) {
+ BM_ITER_MESH (v, &iter, em->bm, BM_VERTS_OF_MESH) {
+ if (!BM_elem_flag_test(v, BM_ELEM_HIDDEN)) {
+ if (!BM_vert_is_manifold(v)) {
+ BM_vert_select_set(em->bm, v, true);
+ }
+ }
+ }
+ }
+
+ if (use_wire || use_boundary || use_multi_face || use_non_contiguous) {
+ BM_ITER_MESH (e, &iter, em->bm, BM_EDGES_OF_MESH) {
+ if (!BM_elem_flag_test(e, BM_ELEM_HIDDEN)) {
+ if ((use_wire && BM_edge_is_wire(e)) || (use_boundary && BM_edge_is_boundary(e)) ||
+ (use_non_contiguous && (BM_edge_is_manifold(e) && !BM_edge_is_contiguous(e))) ||
+ (use_multi_face && (BM_edge_face_count_is_over(e, 2)))) {
+ /* check we never select perfect edge (in test above) */
+ BLI_assert(!(BM_edge_is_manifold(e) && BM_edge_is_contiguous(e)));
+
+ BM_edge_select_set(em->bm, e, true);
+ }
+ }
+ }
+ }
+
+ DEG_id_tag_update(obedit->data, ID_RECALC_SELECT);
+ WM_event_add_notifier(C, NC_GEOM | ND_SELECT, obedit->data);
+
+ EDBM_selectmode_flush(em);
+ }
+ MEM_freeN(objects);
+
+ return OPERATOR_FINISHED;
}
void MESH_OT_select_non_manifold(wmOperatorType *ot)
{
- /* identifiers */
- ot->name = "Select Non Manifold";
- ot->description = "Select all non-manifold vertices or edges";
- ot->idname = "MESH_OT_select_non_manifold";
-
- /* api callbacks */
- ot->exec = edbm_select_non_manifold_exec;
- ot->poll = ED_operator_editmesh;
-
- /* flags */
- ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
-
- /* props */
- RNA_def_boolean(ot->srna, "extend", true, "Extend", "Extend the selection");
- /* edges */
- RNA_def_boolean(ot->srna, "use_wire", true, "Wire",
- "Wire edges");
- RNA_def_boolean(ot->srna, "use_boundary", true, "Boundaries",
- "Boundary edges");
- RNA_def_boolean(ot->srna, "use_multi_face", true,
- "Multiple Faces", "Edges shared by 3+ faces");
- RNA_def_boolean(ot->srna, "use_non_contiguous", true, "Non Contiguous",
- "Edges between faces pointing in alternate directions");
- /* verts */
- RNA_def_boolean(ot->srna, "use_verts", true, "Vertices",
- "Vertices connecting multiple face regions");
+ /* identifiers */
+ ot->name = "Select Non Manifold";
+ ot->description = "Select all non-manifold vertices or edges";
+ ot->idname = "MESH_OT_select_non_manifold";
+
+ /* api callbacks */
+ ot->exec = edbm_select_non_manifold_exec;
+ ot->poll = ED_operator_editmesh;
+
+ /* flags */
+ ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
+
+ /* props */
+ RNA_def_boolean(ot->srna, "extend", true, "Extend", "Extend the selection");
+ /* edges */
+ RNA_def_boolean(ot->srna, "use_wire", true, "Wire", "Wire edges");
+ RNA_def_boolean(ot->srna, "use_boundary", true, "Boundaries", "Boundary edges");
+ RNA_def_boolean(ot->srna, "use_multi_face", true, "Multiple Faces", "Edges shared by 3+ faces");
+ RNA_def_boolean(ot->srna,
+ "use_non_contiguous",
+ true,
+ "Non Contiguous",
+ "Edges between faces pointing in alternate directions");
+ /* verts */
+ RNA_def_boolean(
+ ot->srna, "use_verts", true, "Vertices", "Vertices connecting multiple face regions");
}
/** \} */
@@ -4160,86 +4235,87 @@ void MESH_OT_select_non_manifold(wmOperatorType *ot)
static int edbm_select_random_exec(bContext *C, wmOperator *op)
{
- const bool select = (RNA_enum_get(op->ptr, "action") == SEL_SELECT);
- const float randfac = RNA_float_get(op->ptr, "percent") / 100.0f;
- const int seed = WM_operator_properties_select_random_seed_increment_get(op);
-
- ViewLayer *view_layer = CTX_data_view_layer(C);
-
- uint objects_len = 0;
- Object **objects = BKE_view_layer_array_from_objects_in_edit_mode_unique_data(view_layer, CTX_wm_view3d(C), &objects_len);
- for (uint ob_index = 0; ob_index < objects_len; ob_index++) {
- Object *obedit = objects[ob_index];
- BMEditMesh *em = BKE_editmesh_from_object(obedit);
- BMIter iter;
- int seed_iter = seed;
-
- /* This gives a consistent result regardless of object order. */
- if (ob_index) {
- seed_iter += BLI_ghashutil_strhash_p(obedit->id.name);
- }
-
- RNG *rng = BLI_rng_new_srandom(seed_iter);
-
- if (em->selectmode & SCE_SELECT_VERTEX) {
- BMVert *eve;
- BM_ITER_MESH (eve, &iter, em->bm, BM_VERTS_OF_MESH) {
- if (!BM_elem_flag_test(eve, BM_ELEM_HIDDEN) && BLI_rng_get_float(rng) < randfac) {
- BM_vert_select_set(em->bm, eve, select);
- }
- }
- }
- else if (em->selectmode & SCE_SELECT_EDGE) {
- BMEdge *eed;
- BM_ITER_MESH (eed, &iter, em->bm, BM_EDGES_OF_MESH) {
- if (!BM_elem_flag_test(eed, BM_ELEM_HIDDEN) && BLI_rng_get_float(rng) < randfac) {
- BM_edge_select_set(em->bm, eed, select);
- }
- }
- }
- else {
- BMFace *efa;
- BM_ITER_MESH (efa, &iter, em->bm, BM_FACES_OF_MESH) {
- if (!BM_elem_flag_test(efa, BM_ELEM_HIDDEN) && BLI_rng_get_float(rng) < randfac) {
- BM_face_select_set(em->bm, efa, select);
- }
- }
- }
-
- BLI_rng_free(rng);
-
- if (select) {
- /* was EDBM_select_flush, but it over select in edge/face mode */
- EDBM_selectmode_flush(em);
- }
- else {
- EDBM_deselect_flush(em);
- }
-
- DEG_id_tag_update(obedit->data, ID_RECALC_SELECT);
- WM_event_add_notifier(C, NC_GEOM | ND_SELECT, obedit->data);
- }
-
- MEM_freeN(objects);
- return OPERATOR_FINISHED;
+ const bool select = (RNA_enum_get(op->ptr, "action") == SEL_SELECT);
+ const float randfac = RNA_float_get(op->ptr, "percent") / 100.0f;
+ const int seed = WM_operator_properties_select_random_seed_increment_get(op);
+
+ ViewLayer *view_layer = CTX_data_view_layer(C);
+
+ uint objects_len = 0;
+ Object **objects = BKE_view_layer_array_from_objects_in_edit_mode_unique_data(
+ view_layer, CTX_wm_view3d(C), &objects_len);
+ for (uint ob_index = 0; ob_index < objects_len; ob_index++) {
+ Object *obedit = objects[ob_index];
+ BMEditMesh *em = BKE_editmesh_from_object(obedit);
+ BMIter iter;
+ int seed_iter = seed;
+
+ /* This gives a consistent result regardless of object order. */
+ if (ob_index) {
+ seed_iter += BLI_ghashutil_strhash_p(obedit->id.name);
+ }
+
+ RNG *rng = BLI_rng_new_srandom(seed_iter);
+
+ if (em->selectmode & SCE_SELECT_VERTEX) {
+ BMVert *eve;
+ BM_ITER_MESH (eve, &iter, em->bm, BM_VERTS_OF_MESH) {
+ if (!BM_elem_flag_test(eve, BM_ELEM_HIDDEN) && BLI_rng_get_float(rng) < randfac) {
+ BM_vert_select_set(em->bm, eve, select);
+ }
+ }
+ }
+ else if (em->selectmode & SCE_SELECT_EDGE) {
+ BMEdge *eed;
+ BM_ITER_MESH (eed, &iter, em->bm, BM_EDGES_OF_MESH) {
+ if (!BM_elem_flag_test(eed, BM_ELEM_HIDDEN) && BLI_rng_get_float(rng) < randfac) {
+ BM_edge_select_set(em->bm, eed, select);
+ }
+ }
+ }
+ else {
+ BMFace *efa;
+ BM_ITER_MESH (efa, &iter, em->bm, BM_FACES_OF_MESH) {
+ if (!BM_elem_flag_test(efa, BM_ELEM_HIDDEN) && BLI_rng_get_float(rng) < randfac) {
+ BM_face_select_set(em->bm, efa, select);
+ }
+ }
+ }
+
+ BLI_rng_free(rng);
+
+ if (select) {
+ /* was EDBM_select_flush, but it over select in edge/face mode */
+ EDBM_selectmode_flush(em);
+ }
+ else {
+ EDBM_deselect_flush(em);
+ }
+
+ DEG_id_tag_update(obedit->data, ID_RECALC_SELECT);
+ WM_event_add_notifier(C, NC_GEOM | ND_SELECT, obedit->data);
+ }
+
+ MEM_freeN(objects);
+ return OPERATOR_FINISHED;
}
void MESH_OT_select_random(wmOperatorType *ot)
{
- /* identifiers */
- ot->name = "Select Random";
- ot->description = "Randomly select vertices";
- ot->idname = "MESH_OT_select_random";
+ /* identifiers */
+ ot->name = "Select Random";
+ ot->description = "Randomly select vertices";
+ ot->idname = "MESH_OT_select_random";
- /* api callbacks */
- ot->exec = edbm_select_random_exec;
- ot->poll = ED_operator_editmesh;
+ /* api callbacks */
+ ot->exec = edbm_select_random_exec;
+ ot->poll = ED_operator_editmesh;
- /* flags */
- ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
+ /* flags */
+ ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
- /* props */
- WM_operator_properties_select_random(ot);
+ /* props */
+ WM_operator_properties_select_random(ot);
}
/** \} */
@@ -4250,90 +4326,91 @@ void MESH_OT_select_random(wmOperatorType *ot)
static bool edbm_select_ungrouped_poll(bContext *C)
{
- if (ED_operator_editmesh(C)) {
- Object *obedit = CTX_data_edit_object(C);
- BMEditMesh *em = BKE_editmesh_from_object(obedit);
- const int cd_dvert_offset = CustomData_get_offset(&em->bm->vdata, CD_MDEFORMVERT);
-
- if ((em->selectmode & SCE_SELECT_VERTEX) == 0) {
- CTX_wm_operator_poll_msg_set(C, "Must be in vertex selection mode");
- }
- else if (BLI_listbase_is_empty(&obedit->defbase) || cd_dvert_offset == -1) {
- CTX_wm_operator_poll_msg_set(C, "No weights/vertex groups on object");
- }
- else {
- return true;
- }
- }
- return false;
+ if (ED_operator_editmesh(C)) {
+ Object *obedit = CTX_data_edit_object(C);
+ BMEditMesh *em = BKE_editmesh_from_object(obedit);
+ const int cd_dvert_offset = CustomData_get_offset(&em->bm->vdata, CD_MDEFORMVERT);
+
+ if ((em->selectmode & SCE_SELECT_VERTEX) == 0) {
+ CTX_wm_operator_poll_msg_set(C, "Must be in vertex selection mode");
+ }
+ else if (BLI_listbase_is_empty(&obedit->defbase) || cd_dvert_offset == -1) {
+ CTX_wm_operator_poll_msg_set(C, "No weights/vertex groups on object");
+ }
+ else {
+ return true;
+ }
+ }
+ return false;
}
static int edbm_select_ungrouped_exec(bContext *C, wmOperator *op)
{
- const bool extend = RNA_boolean_get(op->ptr, "extend");
- ViewLayer *view_layer = CTX_data_view_layer(C);
-
- uint objects_len = 0;
- Object **objects = BKE_view_layer_array_from_objects_in_edit_mode_unique_data(view_layer, CTX_wm_view3d(C), &objects_len);
-
- for (uint ob_index = 0; ob_index < objects_len; ob_index++) {
- Object *obedit = objects[ob_index];
- BMEditMesh *em = BKE_editmesh_from_object(obedit);
-
- const int cd_dvert_offset = CustomData_get_offset(&em->bm->vdata, CD_MDEFORMVERT);
-
- if (cd_dvert_offset == -1) {
- continue;
- }
-
- BMVert *eve;
- BMIter iter;
-
- bool changed = false;
-
- if (!extend) {
- if (em->bm->totvertsel) {
- EDBM_flag_disable_all(em, BM_ELEM_SELECT);
- changed = true;
- }
- }
-
- BM_ITER_MESH (eve, &iter, em->bm, BM_VERTS_OF_MESH) {
- if (!BM_elem_flag_test(eve, BM_ELEM_HIDDEN)) {
- MDeformVert *dv = BM_ELEM_CD_GET_VOID_P(eve, cd_dvert_offset);
- /* no dv or dv set with no weight */
- if (ELEM(NULL, dv, dv->dw)) {
- BM_vert_select_set(em->bm, eve, true);
- changed = true;
- }
- }
- }
-
- if (changed) {
- EDBM_selectmode_flush(em);
- DEG_id_tag_update(obedit->data, ID_RECALC_SELECT);
- WM_event_add_notifier(C, NC_GEOM | ND_SELECT, obedit->data);
- }
- }
- MEM_freeN(objects);
- return OPERATOR_FINISHED;
+ const bool extend = RNA_boolean_get(op->ptr, "extend");
+ ViewLayer *view_layer = CTX_data_view_layer(C);
+
+ uint objects_len = 0;
+ Object **objects = BKE_view_layer_array_from_objects_in_edit_mode_unique_data(
+ view_layer, CTX_wm_view3d(C), &objects_len);
+
+ for (uint ob_index = 0; ob_index < objects_len; ob_index++) {
+ Object *obedit = objects[ob_index];
+ BMEditMesh *em = BKE_editmesh_from_object(obedit);
+
+ const int cd_dvert_offset = CustomData_get_offset(&em->bm->vdata, CD_MDEFORMVERT);
+
+ if (cd_dvert_offset == -1) {
+ continue;
+ }
+
+ BMVert *eve;
+ BMIter iter;
+
+ bool changed = false;
+
+ if (!extend) {
+ if (em->bm->totvertsel) {
+ EDBM_flag_disable_all(em, BM_ELEM_SELECT);
+ changed = true;
+ }
+ }
+
+ BM_ITER_MESH (eve, &iter, em->bm, BM_VERTS_OF_MESH) {
+ if (!BM_elem_flag_test(eve, BM_ELEM_HIDDEN)) {
+ MDeformVert *dv = BM_ELEM_CD_GET_VOID_P(eve, cd_dvert_offset);
+ /* no dv or dv set with no weight */
+ if (ELEM(NULL, dv, dv->dw)) {
+ BM_vert_select_set(em->bm, eve, true);
+ changed = true;
+ }
+ }
+ }
+
+ if (changed) {
+ EDBM_selectmode_flush(em);
+ DEG_id_tag_update(obedit->data, ID_RECALC_SELECT);
+ WM_event_add_notifier(C, NC_GEOM | ND_SELECT, obedit->data);
+ }
+ }
+ MEM_freeN(objects);
+ return OPERATOR_FINISHED;
}
void MESH_OT_select_ungrouped(wmOperatorType *ot)
{
- /* identifiers */
- ot->name = "Select Ungrouped";
- ot->idname = "MESH_OT_select_ungrouped";
- ot->description = "Select vertices without a group";
+ /* identifiers */
+ ot->name = "Select Ungrouped";
+ ot->idname = "MESH_OT_select_ungrouped";
+ ot->description = "Select vertices without a group";
- /* api callbacks */
- ot->exec = edbm_select_ungrouped_exec;
- ot->poll = edbm_select_ungrouped_poll;
+ /* api callbacks */
+ ot->exec = edbm_select_ungrouped_exec;
+ ot->poll = edbm_select_ungrouped_poll;
- /* flags */
- ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
+ /* flags */
+ ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
- RNA_def_boolean(ot->srna, "extend", false, "Extend", "Extend the selection");
+ RNA_def_boolean(ot->srna, "extend", false, "Extend", "Extend the selection");
}
/** \} */
@@ -4343,131 +4420,149 @@ void MESH_OT_select_ungrouped(wmOperatorType *ot)
* \{ */
enum {
- SELECT_AXIS_POS = 0,
- SELECT_AXIS_NEG = 1,
- SELECT_AXIS_ALIGN = 2,
+ SELECT_AXIS_POS = 0,
+ SELECT_AXIS_NEG = 1,
+ SELECT_AXIS_ALIGN = 2,
};
static int edbm_select_axis_exec(bContext *C, wmOperator *op)
{
- Scene *scene = CTX_data_scene(C);
- ViewLayer *view_layer = CTX_data_view_layer(C);
- Object *obedit = CTX_data_edit_object(C);
- BMEditMesh *em = BKE_editmesh_from_object(obedit);
- BMVert *v_act = BM_mesh_active_vert_get(em->bm);
- const int orientation = RNA_enum_get(op->ptr, "orientation");
- const int axis = RNA_enum_get(op->ptr, "axis");
- const int sign = RNA_enum_get(op->ptr, "sign");
-
- if (v_act == NULL) {
- BKE_report(op->reports, RPT_WARNING, "This operator requires an active vertex (last selected)");
- return OPERATOR_CANCELLED;
- }
-
- const float limit = RNA_float_get(op->ptr, "threshold");
-
- float value;
- float axis_mat[3][3];
-
- /* 3D view variables may be NULL, (no need to check in poll function). */
- ED_transform_calc_orientation_from_type_ex(
- C, axis_mat,
- scene, CTX_wm_region_view3d(C), obedit, obedit,
- orientation, 0, V3D_AROUND_ACTIVE);
-
- const float *axis_vector = axis_mat[axis];
-
- {
- float vertex_world[3];
- mul_v3_m4v3(vertex_world, obedit->obmat, v_act->co);
- value = dot_v3v3(axis_vector, vertex_world);
- }
-
- if (sign == SELECT_AXIS_NEG) {
- value += limit;
- }
- else if (sign == SELECT_AXIS_POS) {
- value -= limit;
- }
-
- uint objects_len = 0;
- Object **objects = BKE_view_layer_array_from_objects_in_edit_mode(view_layer, CTX_wm_view3d(C), &objects_len);
- for (uint ob_index = 0; ob_index < objects_len; ob_index++) {
- Object *obedit_iter = objects[ob_index];
- BMEditMesh *em_iter = BKE_editmesh_from_object(obedit_iter);
- BMesh *bm = em_iter->bm;
-
- if (bm->totvert == bm->totvertsel) {
- continue;
- }
-
- BMIter iter;
- BMVert *v;
- bool changed = false;
-
- BM_ITER_MESH (v, &iter, bm, BM_VERTS_OF_MESH) {
- if (!BM_elem_flag_test(v, BM_ELEM_HIDDEN | BM_ELEM_SELECT)) {
- float v_iter_world[3];
- mul_v3_m4v3(v_iter_world, obedit_iter->obmat, v->co);
- const float value_iter = dot_v3v3(axis_vector, v_iter_world);
- switch (sign) {
- case SELECT_AXIS_ALIGN:
- if (fabsf(value_iter - value) < limit) {
- BM_vert_select_set(bm, v, true);
- changed = true;
- }
- break;
- case SELECT_AXIS_NEG:
- if (value_iter < value) {
- BM_vert_select_set(bm, v, true);
- changed = true;
- }
- break;
- case SELECT_AXIS_POS:
- if (value_iter > value) {
- BM_vert_select_set(bm, v, true);
- changed = true;
- }
- break;
- }
- }
- }
- if (changed) {
- EDBM_selectmode_flush(em_iter);
- WM_event_add_notifier(C, NC_GEOM | ND_DATA, obedit_iter->data);
- DEG_id_tag_update(obedit_iter->data, ID_RECALC_SELECT);
- }
- }
- MEM_freeN(objects);
- return OPERATOR_FINISHED;
+ Scene *scene = CTX_data_scene(C);
+ ViewLayer *view_layer = CTX_data_view_layer(C);
+ Object *obedit = CTX_data_edit_object(C);
+ BMEditMesh *em = BKE_editmesh_from_object(obedit);
+ BMVert *v_act = BM_mesh_active_vert_get(em->bm);
+ const int orientation = RNA_enum_get(op->ptr, "orientation");
+ const int axis = RNA_enum_get(op->ptr, "axis");
+ const int sign = RNA_enum_get(op->ptr, "sign");
+
+ if (v_act == NULL) {
+ BKE_report(
+ op->reports, RPT_WARNING, "This operator requires an active vertex (last selected)");
+ return OPERATOR_CANCELLED;
+ }
+
+ const float limit = RNA_float_get(op->ptr, "threshold");
+
+ float value;
+ float axis_mat[3][3];
+
+ /* 3D view variables may be NULL, (no need to check in poll function). */
+ ED_transform_calc_orientation_from_type_ex(C,
+ axis_mat,
+ scene,
+ CTX_wm_region_view3d(C),
+ obedit,
+ obedit,
+ orientation,
+ 0,
+ V3D_AROUND_ACTIVE);
+
+ const float *axis_vector = axis_mat[axis];
+
+ {
+ float vertex_world[3];
+ mul_v3_m4v3(vertex_world, obedit->obmat, v_act->co);
+ value = dot_v3v3(axis_vector, vertex_world);
+ }
+
+ if (sign == SELECT_AXIS_NEG) {
+ value += limit;
+ }
+ else if (sign == SELECT_AXIS_POS) {
+ value -= limit;
+ }
+
+ uint objects_len = 0;
+ Object **objects = BKE_view_layer_array_from_objects_in_edit_mode(
+ view_layer, CTX_wm_view3d(C), &objects_len);
+ for (uint ob_index = 0; ob_index < objects_len; ob_index++) {
+ Object *obedit_iter = objects[ob_index];
+ BMEditMesh *em_iter = BKE_editmesh_from_object(obedit_iter);
+ BMesh *bm = em_iter->bm;
+
+ if (bm->totvert == bm->totvertsel) {
+ continue;
+ }
+
+ BMIter iter;
+ BMVert *v;
+ bool changed = false;
+
+ BM_ITER_MESH (v, &iter, bm, BM_VERTS_OF_MESH) {
+ if (!BM_elem_flag_test(v, BM_ELEM_HIDDEN | BM_ELEM_SELECT)) {
+ float v_iter_world[3];
+ mul_v3_m4v3(v_iter_world, obedit_iter->obmat, v->co);
+ const float value_iter = dot_v3v3(axis_vector, v_iter_world);
+ switch (sign) {
+ case SELECT_AXIS_ALIGN:
+ if (fabsf(value_iter - value) < limit) {
+ BM_vert_select_set(bm, v, true);
+ changed = true;
+ }
+ break;
+ case SELECT_AXIS_NEG:
+ if (value_iter < value) {
+ BM_vert_select_set(bm, v, true);
+ changed = true;
+ }
+ break;
+ case SELECT_AXIS_POS:
+ if (value_iter > value) {
+ BM_vert_select_set(bm, v, true);
+ changed = true;
+ }
+ break;
+ }
+ }
+ }
+ if (changed) {
+ EDBM_selectmode_flush(em_iter);
+ WM_event_add_notifier(C, NC_GEOM | ND_DATA, obedit_iter->data);
+ DEG_id_tag_update(obedit_iter->data, ID_RECALC_SELECT);
+ }
+ }
+ MEM_freeN(objects);
+ return OPERATOR_FINISHED;
}
void MESH_OT_select_axis(wmOperatorType *ot)
{
- static const EnumPropertyItem axis_sign_items[] = {
- {SELECT_AXIS_POS, "POS", 0, "Positive Axis", ""},
- {SELECT_AXIS_NEG, "NEG", 0, "Negative Axis", ""},
- {SELECT_AXIS_ALIGN, "ALIGN", 0, "Aligned Axis", ""},
- {0, NULL, 0, NULL, NULL},
- };
-
- /* identifiers */
- ot->name = "Select Axis";
- ot->description = "Select all data in the mesh on a single axis";
- ot->idname = "MESH_OT_select_axis";
-
- /* api callbacks */
- ot->exec = edbm_select_axis_exec;
- ot->poll = ED_operator_editmesh;
-
- /* flags */
- ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
-
- /* properties */
- RNA_def_enum(ot->srna, "orientation", rna_enum_transform_orientation_items, V3D_ORIENT_LOCAL, "Axis Mode", "Axis orientation");
- RNA_def_enum(ot->srna, "sign", axis_sign_items, SELECT_AXIS_POS, "Axis Sign", "Side to select");
- RNA_def_enum(ot->srna, "axis", rna_enum_axis_xyz_items, 0, "Axis", "Select the axis to compare each vertex on");
- RNA_def_float(ot->srna, "threshold", 0.0001f, 0.000001f, 50.0f, "Threshold", "", 0.00001f, 10.0f);
+ static const EnumPropertyItem axis_sign_items[] = {
+ {SELECT_AXIS_POS, "POS", 0, "Positive Axis", ""},
+ {SELECT_AXIS_NEG, "NEG", 0, "Negative Axis", ""},
+ {SELECT_AXIS_ALIGN, "ALIGN", 0, "Aligned Axis", ""},
+ {0, NULL, 0, NULL, NULL},
+ };
+
+ /* identifiers */
+ ot->name = "Select Axis";
+ ot->description = "Select all data in the mesh on a single axis";
+ ot->idname = "MESH_OT_select_axis";
+
+ /* api callbacks */
+ ot->exec = edbm_select_axis_exec;
+ ot->poll = ED_operator_editmesh;
+
+ /* flags */
+ ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
+
+ /* properties */
+ RNA_def_enum(ot->srna,
+ "orientation",
+ rna_enum_transform_orientation_items,
+ V3D_ORIENT_LOCAL,
+ "Axis Mode",
+ "Axis orientation");
+ RNA_def_enum(ot->srna, "sign", axis_sign_items, SELECT_AXIS_POS, "Axis Sign", "Side to select");
+ RNA_def_enum(ot->srna,
+ "axis",
+ rna_enum_axis_xyz_items,
+ 0,
+ "Axis",
+ "Select the axis to compare each vertex on");
+ RNA_def_float(
+ ot->srna, "threshold", 0.0001f, 0.000001f, 50.0f, "Threshold", "", 0.00001f, 10.0f);
}
/** \} */
@@ -4478,76 +4573,77 @@ void MESH_OT_select_axis(wmOperatorType *ot)
static int edbm_region_to_loop_exec(bContext *C, wmOperator *UNUSED(op))
{
- ViewLayer *view_layer = CTX_data_view_layer(C);
- uint objects_len = 0;
- Object **objects = BKE_view_layer_array_from_objects_in_edit_mode_unique_data(view_layer, CTX_wm_view3d(C), &objects_len);
- for (uint ob_index = 0; ob_index < objects_len; ob_index++) {
- Object *obedit = objects[ob_index];
- BMEditMesh *em = BKE_editmesh_from_object(obedit);
-
- if (em->bm->totfacesel == 0) {
- continue;
- }
- BMFace *f;
- BMEdge *e;
- BMIter iter;
-
- BM_mesh_elem_hflag_disable_all(em->bm, BM_EDGE, BM_ELEM_TAG, false);
-
- BM_ITER_MESH(f, &iter, em->bm, BM_FACES_OF_MESH) {
- BMLoop *l1, *l2;
- BMIter liter1, liter2;
-
- BM_ITER_ELEM(l1, &liter1, f, BM_LOOPS_OF_FACE) {
- int tot = 0, totsel = 0;
-
- BM_ITER_ELEM(l2, &liter2, l1->e, BM_LOOPS_OF_EDGE) {
- tot++;
- totsel += BM_elem_flag_test(l2->f, BM_ELEM_SELECT) != 0;
- }
-
- if ((tot != totsel && totsel > 0) || (totsel == 1 && tot == 1))
- BM_elem_flag_enable(l1->e, BM_ELEM_TAG);
- }
- }
-
- EDBM_flag_disable_all(em, BM_ELEM_SELECT);
-
- BM_ITER_MESH(e, &iter, em->bm, BM_EDGES_OF_MESH) {
- if (BM_elem_flag_test(e, BM_ELEM_TAG)) {
- BM_edge_select_set(em->bm, e, true);
- }
- }
-
- /* If in face-only select mode, switch to edge select mode so that
- * an edge-only selection is not inconsistent state */
- if (em->selectmode == SCE_SELECT_FACE) {
- em->selectmode = SCE_SELECT_EDGE;
- EDBM_selectmode_set(em);
- EDBM_selectmode_to_scene(C);
- }
-
- DEG_id_tag_update(obedit->data, ID_RECALC_SELECT);
- WM_event_add_notifier(C, NC_GEOM | ND_SELECT, obedit->data);
- }
- MEM_freeN(objects);
-
- return OPERATOR_FINISHED;
+ ViewLayer *view_layer = CTX_data_view_layer(C);
+ uint objects_len = 0;
+ Object **objects = BKE_view_layer_array_from_objects_in_edit_mode_unique_data(
+ view_layer, CTX_wm_view3d(C), &objects_len);
+ for (uint ob_index = 0; ob_index < objects_len; ob_index++) {
+ Object *obedit = objects[ob_index];
+ BMEditMesh *em = BKE_editmesh_from_object(obedit);
+
+ if (em->bm->totfacesel == 0) {
+ continue;
+ }
+ BMFace *f;
+ BMEdge *e;
+ BMIter iter;
+
+ BM_mesh_elem_hflag_disable_all(em->bm, BM_EDGE, BM_ELEM_TAG, false);
+
+ BM_ITER_MESH (f, &iter, em->bm, BM_FACES_OF_MESH) {
+ BMLoop *l1, *l2;
+ BMIter liter1, liter2;
+
+ BM_ITER_ELEM (l1, &liter1, f, BM_LOOPS_OF_FACE) {
+ int tot = 0, totsel = 0;
+
+ BM_ITER_ELEM (l2, &liter2, l1->e, BM_LOOPS_OF_EDGE) {
+ tot++;
+ totsel += BM_elem_flag_test(l2->f, BM_ELEM_SELECT) != 0;
+ }
+
+ if ((tot != totsel && totsel > 0) || (totsel == 1 && tot == 1))
+ BM_elem_flag_enable(l1->e, BM_ELEM_TAG);
+ }
+ }
+
+ EDBM_flag_disable_all(em, BM_ELEM_SELECT);
+
+ BM_ITER_MESH (e, &iter, em->bm, BM_EDGES_OF_MESH) {
+ if (BM_elem_flag_test(e, BM_ELEM_TAG)) {
+ BM_edge_select_set(em->bm, e, true);
+ }
+ }
+
+ /* If in face-only select mode, switch to edge select mode so that
+ * an edge-only selection is not inconsistent state */
+ if (em->selectmode == SCE_SELECT_FACE) {
+ em->selectmode = SCE_SELECT_EDGE;
+ EDBM_selectmode_set(em);
+ EDBM_selectmode_to_scene(C);
+ }
+
+ DEG_id_tag_update(obedit->data, ID_RECALC_SELECT);
+ WM_event_add_notifier(C, NC_GEOM | ND_SELECT, obedit->data);
+ }
+ MEM_freeN(objects);
+
+ return OPERATOR_FINISHED;
}
void MESH_OT_region_to_loop(wmOperatorType *ot)
{
- /* identifiers */
- ot->name = "Select Boundary Loop";
- ot->idname = "MESH_OT_region_to_loop";
- ot->description = "Select boundary edges around the selected faces";
+ /* identifiers */
+ ot->name = "Select Boundary Loop";
+ ot->idname = "MESH_OT_region_to_loop";
+ ot->description = "Select boundary edges around the selected faces";
- /* api callbacks */
- ot->exec = edbm_region_to_loop_exec;
- ot->poll = ED_operator_editmesh;
+ /* api callbacks */
+ ot->exec = edbm_region_to_loop_exec;
+ ot->poll = ED_operator_editmesh;
- /* flags */
- ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
+ /* flags */
+ ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
}
/** \} */
@@ -4556,61 +4652,61 @@ void MESH_OT_region_to_loop(wmOperatorType *ot)
/** \name Select Loop to Region Operator
* \{ */
-static int loop_find_region(
- BMLoop *l, int flag,
- GSet *visit_face_set, BMFace ***region_out)
+static int loop_find_region(BMLoop *l, int flag, GSet *visit_face_set, BMFace ***region_out)
{
- BMFace **region = NULL;
- BMFace **stack = NULL;
- BLI_array_declare(region);
- BLI_array_declare(stack);
- BMFace *f;
-
- BLI_array_append(stack, l->f);
- BLI_gset_insert(visit_face_set, l->f);
-
- while (BLI_array_len(stack) > 0) {
- BMIter liter1, liter2;
- BMLoop *l1, *l2;
-
- f = BLI_array_pop(stack);
- BLI_array_append(region, f);
-
- BM_ITER_ELEM (l1, &liter1, f, BM_LOOPS_OF_FACE) {
- if (BM_elem_flag_test(l1->e, flag))
- continue;
-
- BM_ITER_ELEM (l2, &liter2, l1->e, BM_LOOPS_OF_EDGE) {
- /* avoids finding same region twice
- * (otherwise) the logic works fine without */
- if (BM_elem_flag_test(l2->f, BM_ELEM_TAG)) {
- continue;
- }
-
- if (BLI_gset_add(visit_face_set, l2->f)) {
- BLI_array_append(stack, l2->f);
- }
- }
- }
- }
-
- BLI_array_free(stack);
-
- *region_out = region;
- return BLI_array_len(region);
+ BMFace **region = NULL;
+ BMFace **stack = NULL;
+ BLI_array_declare(region);
+ BLI_array_declare(stack);
+ BMFace *f;
+
+ BLI_array_append(stack, l->f);
+ BLI_gset_insert(visit_face_set, l->f);
+
+ while (BLI_array_len(stack) > 0) {
+ BMIter liter1, liter2;
+ BMLoop *l1, *l2;
+
+ f = BLI_array_pop(stack);
+ BLI_array_append(region, f);
+
+ BM_ITER_ELEM (l1, &liter1, f, BM_LOOPS_OF_FACE) {
+ if (BM_elem_flag_test(l1->e, flag))
+ continue;
+
+ BM_ITER_ELEM (l2, &liter2, l1->e, BM_LOOPS_OF_EDGE) {
+ /* avoids finding same region twice
+ * (otherwise) the logic works fine without */
+ if (BM_elem_flag_test(l2->f, BM_ELEM_TAG)) {
+ continue;
+ }
+
+ if (BLI_gset_add(visit_face_set, l2->f)) {
+ BLI_array_append(stack, l2->f);
+ }
+ }
+ }
+ }
+
+ BLI_array_free(stack);
+
+ *region_out = region;
+ return BLI_array_len(region);
}
static int verg_radial(const void *va, const void *vb)
{
- const BMEdge *e_a = *((const BMEdge **)va);
- const BMEdge *e_b = *((const BMEdge **)vb);
+ const BMEdge *e_a = *((const BMEdge **)va);
+ const BMEdge *e_b = *((const BMEdge **)vb);
- const int a = BM_edge_face_count(e_a);
- const int b = BM_edge_face_count(e_b);
+ const int a = BM_edge_face_count(e_a);
+ const int b = BM_edge_face_count(e_b);
- if (a > b) return -1;
- if (a < b) return 1;
- return 0;
+ if (a > b)
+ return -1;
+ if (a < b)
+ return 1;
+ return 0;
}
/**
@@ -4621,143 +4717,148 @@ static int verg_radial(const void *va, const void *vb)
*/
static int loop_find_regions(BMEditMesh *em, const bool selbigger)
{
- GSet *visit_face_set;
- BMIter iter;
- const int edges_len = em->bm->totedgesel;
- BMEdge *e, **edges;
- int count = 0, i;
-
- visit_face_set = BLI_gset_ptr_new_ex(__func__, edges_len);
- edges = MEM_mallocN(sizeof(*edges) * edges_len, __func__);
-
- i = 0;
- BM_ITER_MESH (e, &iter, em->bm, BM_EDGES_OF_MESH) {
- if (BM_elem_flag_test(e, BM_ELEM_SELECT)) {
- edges[i++] = e;
- BM_elem_flag_enable(e, BM_ELEM_TAG);
- }
- else {
- BM_elem_flag_disable(e, BM_ELEM_TAG);
- }
- }
-
- /* sort edges by radial cycle length */
- qsort(edges, edges_len, sizeof(*edges), verg_radial);
-
- for (i = 0; i < edges_len; i++) {
- BMIter liter;
- BMLoop *l;
- BMFace **region = NULL, **region_out;
- int c, tot = 0;
-
- e = edges[i];
-
- if (!BM_elem_flag_test(e, BM_ELEM_TAG))
- continue;
-
- BM_ITER_ELEM (l, &liter, e, BM_LOOPS_OF_EDGE) {
- if (BLI_gset_haskey(visit_face_set, l->f))
- continue;
-
- c = loop_find_region(l, BM_ELEM_SELECT, visit_face_set, &region_out);
-
- if (!region || (selbigger ? c >= tot : c < tot)) {
- /* this region is the best seen so far */
- tot = c;
- if (region) {
- /* free the previous best */
- MEM_freeN(region);
- }
- /* track the current region as the new best */
- region = region_out;
- }
- else {
- /* this region is not as good as best so far, just free it */
- MEM_freeN(region_out);
- }
- }
-
- if (region) {
- int j;
-
- for (j = 0; j < tot; j++) {
- BM_elem_flag_enable(region[j], BM_ELEM_TAG);
- BM_ITER_ELEM (l, &liter, region[j], BM_LOOPS_OF_FACE) {
- BM_elem_flag_disable(l->e, BM_ELEM_TAG);
- }
- }
-
- count += tot;
-
- MEM_freeN(region);
- }
- }
-
- MEM_freeN(edges);
- BLI_gset_free(visit_face_set, NULL);
-
- return count;
+ GSet *visit_face_set;
+ BMIter iter;
+ const int edges_len = em->bm->totedgesel;
+ BMEdge *e, **edges;
+ int count = 0, i;
+
+ visit_face_set = BLI_gset_ptr_new_ex(__func__, edges_len);
+ edges = MEM_mallocN(sizeof(*edges) * edges_len, __func__);
+
+ i = 0;
+ BM_ITER_MESH (e, &iter, em->bm, BM_EDGES_OF_MESH) {
+ if (BM_elem_flag_test(e, BM_ELEM_SELECT)) {
+ edges[i++] = e;
+ BM_elem_flag_enable(e, BM_ELEM_TAG);
+ }
+ else {
+ BM_elem_flag_disable(e, BM_ELEM_TAG);
+ }
+ }
+
+ /* sort edges by radial cycle length */
+ qsort(edges, edges_len, sizeof(*edges), verg_radial);
+
+ for (i = 0; i < edges_len; i++) {
+ BMIter liter;
+ BMLoop *l;
+ BMFace **region = NULL, **region_out;
+ int c, tot = 0;
+
+ e = edges[i];
+
+ if (!BM_elem_flag_test(e, BM_ELEM_TAG))
+ continue;
+
+ BM_ITER_ELEM (l, &liter, e, BM_LOOPS_OF_EDGE) {
+ if (BLI_gset_haskey(visit_face_set, l->f))
+ continue;
+
+ c = loop_find_region(l, BM_ELEM_SELECT, visit_face_set, &region_out);
+
+ if (!region || (selbigger ? c >= tot : c < tot)) {
+ /* this region is the best seen so far */
+ tot = c;
+ if (region) {
+ /* free the previous best */
+ MEM_freeN(region);
+ }
+ /* track the current region as the new best */
+ region = region_out;
+ }
+ else {
+ /* this region is not as good as best so far, just free it */
+ MEM_freeN(region_out);
+ }
+ }
+
+ if (region) {
+ int j;
+
+ for (j = 0; j < tot; j++) {
+ BM_elem_flag_enable(region[j], BM_ELEM_TAG);
+ BM_ITER_ELEM (l, &liter, region[j], BM_LOOPS_OF_FACE) {
+ BM_elem_flag_disable(l->e, BM_ELEM_TAG);
+ }
+ }
+
+ count += tot;
+
+ MEM_freeN(region);
+ }
+ }
+
+ MEM_freeN(edges);
+ BLI_gset_free(visit_face_set, NULL);
+
+ return count;
}
static int edbm_loop_to_region_exec(bContext *C, wmOperator *op)
{
- const bool select_bigger = RNA_boolean_get(op->ptr, "select_bigger");
+ const bool select_bigger = RNA_boolean_get(op->ptr, "select_bigger");
- ViewLayer *view_layer = CTX_data_view_layer(C);
- uint objects_len = 0;
- Object **objects = BKE_view_layer_array_from_objects_in_edit_mode_unique_data(view_layer, CTX_wm_view3d(C), &objects_len);
- for (uint ob_index = 0; ob_index < objects_len; ob_index++) {
- Object *obedit = objects[ob_index];
- BMEditMesh *em = BKE_editmesh_from_object(obedit);
+ ViewLayer *view_layer = CTX_data_view_layer(C);
+ uint objects_len = 0;
+ Object **objects = BKE_view_layer_array_from_objects_in_edit_mode_unique_data(
+ view_layer, CTX_wm_view3d(C), &objects_len);
+ for (uint ob_index = 0; ob_index < objects_len; ob_index++) {
+ Object *obedit = objects[ob_index];
+ BMEditMesh *em = BKE_editmesh_from_object(obedit);
- if (em->bm->totedgesel == 0) {
- continue;
- }
+ if (em->bm->totedgesel == 0) {
+ continue;
+ }
- BMIter iter;
- BMFace *f;
+ BMIter iter;
+ BMFace *f;
- /* find the set of regions with smallest number of total faces */
- BM_mesh_elem_hflag_disable_all(em->bm, BM_FACE, BM_ELEM_TAG, false);
- const int a = loop_find_regions(em, select_bigger);
- const int b = loop_find_regions(em, !select_bigger);
+ /* find the set of regions with smallest number of total faces */
+ BM_mesh_elem_hflag_disable_all(em->bm, BM_FACE, BM_ELEM_TAG, false);
+ const int a = loop_find_regions(em, select_bigger);
+ const int b = loop_find_regions(em, !select_bigger);
- BM_mesh_elem_hflag_disable_all(em->bm, BM_FACE, BM_ELEM_TAG, false);
- loop_find_regions(em, ((a <= b) != select_bigger) ? select_bigger : !select_bigger);
+ BM_mesh_elem_hflag_disable_all(em->bm, BM_FACE, BM_ELEM_TAG, false);
+ loop_find_regions(em, ((a <= b) != select_bigger) ? select_bigger : !select_bigger);
- EDBM_flag_disable_all(em, BM_ELEM_SELECT);
+ EDBM_flag_disable_all(em, BM_ELEM_SELECT);
- BM_ITER_MESH(f, &iter, em->bm, BM_FACES_OF_MESH) {
- if (BM_elem_flag_test(f, BM_ELEM_TAG) && !BM_elem_flag_test(f, BM_ELEM_HIDDEN)) {
- BM_face_select_set(em->bm, f, true);
- }
- }
+ BM_ITER_MESH (f, &iter, em->bm, BM_FACES_OF_MESH) {
+ if (BM_elem_flag_test(f, BM_ELEM_TAG) && !BM_elem_flag_test(f, BM_ELEM_HIDDEN)) {
+ BM_face_select_set(em->bm, f, true);
+ }
+ }
- EDBM_selectmode_flush(em);
+ EDBM_selectmode_flush(em);
- DEG_id_tag_update(obedit->data, ID_RECALC_SELECT);
- WM_event_add_notifier(C, NC_GEOM | ND_SELECT, obedit->data);
- }
- MEM_freeN(objects);
+ DEG_id_tag_update(obedit->data, ID_RECALC_SELECT);
+ WM_event_add_notifier(C, NC_GEOM | ND_SELECT, obedit->data);
+ }
+ MEM_freeN(objects);
- return OPERATOR_FINISHED;
+ return OPERATOR_FINISHED;
}
void MESH_OT_loop_to_region(wmOperatorType *ot)
{
- /* identifiers */
- ot->name = "Select Loop Inner-Region";
- ot->idname = "MESH_OT_loop_to_region";
- ot->description = "Select region of faces inside of a selected loop of edges";
-
- /* api callbacks */
- ot->exec = edbm_loop_to_region_exec;
- ot->poll = ED_operator_editmesh;
-
- /* flags */
- ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
-
- RNA_def_boolean(ot->srna, "select_bigger", 0, "Select Bigger", "Select bigger regions instead of smaller ones");
+ /* identifiers */
+ ot->name = "Select Loop Inner-Region";
+ ot->idname = "MESH_OT_loop_to_region";
+ ot->description = "Select region of faces inside of a selected loop of edges";
+
+ /* api callbacks */
+ ot->exec = edbm_loop_to_region_exec;
+ ot->poll = ED_operator_editmesh;
+
+ /* flags */
+ ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
+
+ RNA_def_boolean(ot->srna,
+ "select_bigger",
+ 0,
+ "Select Bigger",
+ "Select bigger regions instead of smaller ones");
}
/** \} */