UI: hide mesh mode element redo panel
[blender.git] / source / blender / editors / mesh / editmesh_select.c
1 /*
2  * ***** BEGIN GPL LICENSE BLOCK *****
3  *
4  * This program is free software; you can redistribute it and/or
5  * modify it under the terms of the GNU General Public License
6  * as published by the Free Software Foundation; either version 2
7  * of the License, or (at your option) any later version.
8  *
9  * This program is distributed in the hope that it will be useful,
10  * but WITHOUT ANY WARRANTY; without even the implied warranty of
11  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
12  * GNU General Public License for more details.
13  *
14  * You should have received a copy of the GNU General Public License
15  * along with this program; if not, write to the Free Software Foundation,
16  * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
17  *
18  * The Original Code is Copyright (C) 2004 Blender Foundation.
19  * All rights reserved.
20  *
21  * The Original Code is: all of this file.
22  *
23  * Contributor(s): none yet.
24  *
25  * ***** END GPL LICENSE BLOCK *****
26  */
27
28 /** \file blender/editors/mesh/editmesh_select.c
29  *  \ingroup edmesh
30  */
31
32 #include "MEM_guardedalloc.h"
33
34 #include "BLI_bitmap.h"
35 #include "BLI_bitmap_draw_2d.h"
36 #include "BLI_listbase.h"
37 #include "BLI_linklist.h"
38 #include "BLI_linklist_stack.h"
39 #include "BLI_math.h"
40 #include "BLI_math_bits.h"
41 #include "BLI_rand.h"
42 #include "BLI_array.h"
43
44 #include "BKE_context.h"
45 #include "BKE_report.h"
46 #include "BKE_paint.h"
47 #include "BKE_editmesh.h"
48 #include "BKE_layer.h"
49
50 #include "IMB_imbuf_types.h"
51 #include "IMB_imbuf.h"
52
53 #include "WM_api.h"
54 #include "WM_types.h"
55
56 #include "RNA_access.h"
57 #include "RNA_define.h"
58 #include "RNA_enum_types.h"
59
60 #include "ED_mesh.h"
61 #include "ED_screen.h"
62 #include "ED_transform.h"
63 #include "ED_select_utils.h"
64 #include "ED_view3d.h"
65
66 #include "DNA_mesh_types.h"
67 #include "DNA_meshdata_types.h"
68 #include "DNA_object_types.h"
69
70 #include "UI_resources.h"
71
72 #include "bmesh_tools.h"
73
74 #include "DEG_depsgraph.h"
75 #include "DEG_depsgraph_query.h"
76
77 #include "mesh_intern.h"  /* own include */
78
79 /* use bmesh operator flags for a few operators */
80 #define BMO_ELE_TAG 1
81
82 /* -------------------------------------------------------------------- */
83 /** \name Select Mirror
84  * \{ */
85
86 void EDBM_select_mirrored(
87         BMEditMesh *em, const int axis, const bool extend,
88         int *r_totmirr, int *r_totfail)
89 {
90         Mesh *me = (Mesh *)em->ob->data;
91         BMesh *bm = em->bm;
92         BMIter iter;
93         int totmirr = 0;
94         int totfail = 0;
95         bool use_topology = (me && (me->editflag & ME_EDIT_MIRROR_TOPO));
96
97         *r_totmirr = *r_totfail = 0;
98
99         /* select -> tag */
100         if (bm->selectmode & SCE_SELECT_VERTEX) {
101                 BMVert *v;
102                 BM_ITER_MESH (v, &iter, bm, BM_VERTS_OF_MESH) {
103                         BM_elem_flag_set(v, BM_ELEM_TAG, BM_elem_flag_test(v, BM_ELEM_SELECT));
104                 }
105         }
106         else if (em->selectmode & SCE_SELECT_EDGE) {
107                 BMEdge *e;
108                 BM_ITER_MESH (e, &iter, bm, BM_EDGES_OF_MESH) {
109                         BM_elem_flag_set(e, BM_ELEM_TAG, BM_elem_flag_test(e, BM_ELEM_SELECT));
110                 }
111         }
112         else {
113                 BMFace *f;
114                 BM_ITER_MESH (f, &iter, bm, BM_FACES_OF_MESH) {
115                         BM_elem_flag_set(f, BM_ELEM_TAG, BM_elem_flag_test(f, BM_ELEM_SELECT));
116                 }
117         }
118
119         EDBM_verts_mirror_cache_begin(em, axis, true, true, use_topology);
120
121         if (!extend)
122                 EDBM_flag_disable_all(em, BM_ELEM_SELECT);
123
124
125         if (bm->selectmode & SCE_SELECT_VERTEX) {
126                 BMVert *v;
127                 BM_ITER_MESH (v, &iter, bm, BM_VERTS_OF_MESH) {
128                         if (!BM_elem_flag_test(v, BM_ELEM_HIDDEN) && BM_elem_flag_test(v, BM_ELEM_TAG)) {
129                                 BMVert *v_mirr = EDBM_verts_mirror_get(em, v);
130                                 if (v_mirr && !BM_elem_flag_test(v_mirr, BM_ELEM_HIDDEN)) {
131                                         BM_vert_select_set(bm, v_mirr, true);
132                                         totmirr++;
133                                 }
134                                 else {
135                                         totfail++;
136                                 }
137                         }
138                 }
139         }
140         else if (em->selectmode & SCE_SELECT_EDGE) {
141                 BMEdge *e;
142                 BM_ITER_MESH (e, &iter, bm, BM_EDGES_OF_MESH) {
143                         if (!BM_elem_flag_test(e, BM_ELEM_HIDDEN) && BM_elem_flag_test(e, BM_ELEM_TAG)) {
144                                 BMEdge *e_mirr = EDBM_verts_mirror_get_edge(em, e);
145                                 if (e_mirr && !BM_elem_flag_test(e_mirr, BM_ELEM_HIDDEN)) {
146                                         BM_edge_select_set(bm, e_mirr, true);
147                                         totmirr++;
148                                 }
149                                 else {
150                                         totfail++;
151                                 }
152                         }
153                 }
154         }
155         else {
156                 BMFace *f;
157                 BM_ITER_MESH (f, &iter, bm, BM_FACES_OF_MESH) {
158                         if (!BM_elem_flag_test(f, BM_ELEM_HIDDEN) && BM_elem_flag_test(f, BM_ELEM_TAG)) {
159                                 BMFace *f_mirr = EDBM_verts_mirror_get_face(em, f);
160                                 if (f_mirr && !BM_elem_flag_test(f_mirr, BM_ELEM_HIDDEN)) {
161                                         BM_face_select_set(bm, f_mirr, true);
162                                         totmirr++;
163                                 }
164                                 else {
165                                         totfail++;
166                                 }
167                         }
168                 }
169         }
170
171         EDBM_verts_mirror_cache_end(em);
172
173         *r_totmirr = totmirr;
174         *r_totfail = totfail;
175 }
176
177 /** \} */
178
179 /* -------------------------------------------------------------------- */
180 /** \name Select Auto-Merge
181  *
182  * Used after transform operations.
183  * \{ */
184
185 void EDBM_automerge(Scene *scene, Object *obedit, bool update, const char hflag)
186 {
187         bool ok;
188         BMEditMesh *em = BKE_editmesh_from_object(obedit);
189
190         ok = BMO_op_callf(
191                 em->bm, BMO_FLAG_DEFAULTS,
192                 "automerge verts=%hv dist=%f",
193                 hflag, scene->toolsettings->doublimit);
194
195         if (LIKELY(ok) && update) {
196                 EDBM_update_generic(em, true, true);
197         }
198 }
199
200 /** \} */
201
202 /* -------------------------------------------------------------------- */
203 /** \name Back-Buffer OpenGL Selection
204  * \{ */
205
206 unsigned int bm_solidoffs = 0, bm_wireoffs = 0, bm_vertoffs = 0;    /* set in drawobject.c ... for colorindices */
207
208 /* facilities for border select and circle select */
209 static BLI_bitmap *selbuf = NULL;
210
211 static BLI_bitmap *edbm_backbuf_alloc(const int size)
212 {
213         return BLI_BITMAP_NEW(size, "selbuf");
214 }
215
216 /* reads rect, and builds selection array for quick lookup */
217 /* returns if all is OK */
218 bool EDBM_backbuf_border_init(
219         ViewContext *vc, short xmin,
220         short ymin, short xmax, short ymax)
221 {
222         struct ImBuf *buf;
223         unsigned int *dr;
224         int a;
225
226         if (vc->obedit == NULL || !V3D_IS_ZBUF(vc->v3d)) {
227                 return false;
228         }
229
230         buf = ED_view3d_backbuf_read(vc, xmin, ymin, xmax, ymax);
231         if ((buf == NULL) || (bm_vertoffs == 0)) {
232                 return false;
233         }
234
235         dr = buf->rect;
236
237         /* build selection lookup */
238         selbuf = edbm_backbuf_alloc(bm_vertoffs + 1);
239
240         a = (xmax - xmin + 1) * (ymax - ymin + 1);
241         while (a--) {
242                 if (*dr > 0 && *dr <= bm_vertoffs) {
243                         BLI_BITMAP_ENABLE(selbuf, *dr);
244                 }
245                 dr++;
246         }
247         IMB_freeImBuf(buf);
248         return true;
249 }
250
251 bool EDBM_backbuf_check(unsigned int index)
252 {
253         /* odd logic, if selbuf is NULL we assume no zbuf-selection is enabled
254          * and just ignore the depth buffer, this is error prone since its possible
255          * code doesn't set the depth buffer by accident, but leave for now. - Campbell */
256         if (selbuf == NULL)
257                 return true;
258
259         if (index > 0 && index <= bm_vertoffs)
260                 return BLI_BITMAP_TEST_BOOL(selbuf, index);
261
262         return false;
263 }
264
265 void EDBM_backbuf_free(void)
266 {
267         if (selbuf) MEM_freeN(selbuf);
268         selbuf = NULL;
269 }
270
271 struct LassoMaskData {
272         unsigned int *px;
273         int width;
274 };
275
276 static void edbm_mask_lasso_px_cb(int x, int x_end, int y, void *user_data)
277 {
278         struct LassoMaskData *data = user_data;
279         unsigned int *px = &data->px[(y * data->width) + x];
280         do {
281                 *px = true;
282                 px++;
283         } while (++x != x_end);
284 }
285
286
287 /* mcords is a polygon mask
288  * - grab backbuffer,
289  * - draw with black in backbuffer,
290  * - grab again and compare
291  * returns 'OK'
292  */
293 bool EDBM_backbuf_border_mask_init(ViewContext *vc, const int mcords[][2], short tot, short xmin, short ymin, short xmax, short ymax)
294 {
295         unsigned int *dr, *dr_mask, *dr_mask_arr;
296         struct ImBuf *buf;
297         int a;
298         struct LassoMaskData lasso_mask_data;
299
300         /* method in use for face selecting too */
301         if (vc->obedit == NULL) {
302                 if (!BKE_paint_select_elem_test(vc->obact)) {
303                         return false;
304                 }
305         }
306         else if (!V3D_IS_ZBUF(vc->v3d)) {
307                 return false;
308         }
309
310         buf = ED_view3d_backbuf_read(vc, xmin, ymin, xmax, ymax);
311         if ((buf == NULL) || (bm_vertoffs == 0)) {
312                 return false;
313         }
314
315         dr = buf->rect;
316
317         dr_mask = dr_mask_arr = MEM_callocN(sizeof(*dr_mask) * buf->x * buf->y, __func__);
318         lasso_mask_data.px = dr_mask;
319         lasso_mask_data.width = (xmax - xmin) + 1;
320
321         BLI_bitmap_draw_2d_poly_v2i_n(
322                xmin, ymin, xmax + 1, ymax + 1,
323                mcords, tot,
324                edbm_mask_lasso_px_cb, &lasso_mask_data);
325
326         /* build selection lookup */
327         selbuf = edbm_backbuf_alloc(bm_vertoffs + 1);
328
329         a = (xmax - xmin + 1) * (ymax - ymin + 1);
330         while (a--) {
331                 if (*dr > 0 && *dr <= bm_vertoffs && *dr_mask == true) {
332                         BLI_BITMAP_ENABLE(selbuf, *dr);
333                 }
334                 dr++; dr_mask++;
335         }
336         IMB_freeImBuf(buf);
337         MEM_freeN(dr_mask_arr);
338
339         return true;
340 }
341
342 /* circle shaped sample area */
343 bool EDBM_backbuf_circle_init(
344         ViewContext *vc,
345         short xs, short ys, short rads)
346 {
347         struct ImBuf *buf;
348         unsigned int *dr;
349         short xmin, ymin, xmax, ymax, xc, yc;
350         int radsq;
351
352         /* method in use for face selecting too */
353         if (vc->obedit == NULL) {
354                 if (!BKE_paint_select_elem_test(vc->obact)) {
355                         return false;
356                 }
357         }
358         else if (!V3D_IS_ZBUF(vc->v3d)) {
359                 return false;
360         }
361
362         xmin = xs - rads; xmax = xs + rads;
363         ymin = ys - rads; ymax = ys + rads;
364         buf = ED_view3d_backbuf_read(vc, xmin, ymin, xmax, ymax);
365         if ((buf == NULL) || (bm_vertoffs == 0)) {
366                 return false;
367         }
368
369         dr = buf->rect;
370
371         /* build selection lookup */
372         selbuf = edbm_backbuf_alloc(bm_vertoffs + 1);
373         radsq = rads * rads;
374         for (yc = -rads; yc <= rads; yc++) {
375                 for (xc = -rads; xc <= rads; xc++, dr++) {
376                         if (xc * xc + yc * yc < radsq) {
377                                 if (*dr > 0 && *dr <= bm_vertoffs) {
378                                         BLI_BITMAP_ENABLE(selbuf, *dr);
379                                 }
380                         }
381                 }
382         }
383
384         IMB_freeImBuf(buf);
385         return true;
386
387 }
388
389 /** \} */
390
391 /* -------------------------------------------------------------------- */
392 /** \name Find Nearest Vert/Edge/Face
393  *
394  * \note Screen-space manhatten distances are used here,
395  * since its faster and good enough for the purpose of selection.
396  *
397  * \note \a dist_bias is used so we can bias against selected items.
398  * when choosing between elements of a single type, but return the real distance
399  * to avoid the bias interfering with distance comparisons when mixing types.
400  * \{ */
401
402 #define FAKE_SELECT_MODE_BEGIN(vc, fake_select_mode, select_mode, select_mode_required) \
403         short select_mode = select_mode_required; \
404         bool fake_select_mode = (select_mode & (vc)->scene->toolsettings->selectmode) == 0; \
405         if (fake_select_mode) { \
406                 (vc)->v3d->flag |= V3D_INVALID_BACKBUF; \
407         } ((void)0)
408
409 #define FAKE_SELECT_MODE_END(vc, fake_select_mode) \
410         if (fake_select_mode) { \
411                 (vc)->v3d->flag |= V3D_INVALID_BACKBUF; \
412         } ((void)0)
413
414 #define FIND_NEAR_SELECT_BIAS 5
415 #define FIND_NEAR_CYCLE_THRESHOLD_MIN 3
416
417 struct NearestVertUserData_Hit {
418         float   dist;
419         float   dist_bias;
420         int     index;
421         BMVert *vert;
422 };
423
424 struct NearestVertUserData {
425         float mval_fl[2];
426         bool use_select_bias;
427         bool use_cycle;
428         int cycle_index_prev;
429
430         struct NearestVertUserData_Hit hit;
431         struct NearestVertUserData_Hit hit_cycle;
432 };
433
434 static void findnearestvert__doClosest(void *userData, BMVert *eve, const float screen_co[2], int index)
435 {
436         struct NearestVertUserData *data = userData;
437         float dist_test, dist_test_bias;
438
439         dist_test = dist_test_bias = len_manhattan_v2v2(data->mval_fl, screen_co);
440
441         if (data->use_select_bias && BM_elem_flag_test(eve, BM_ELEM_SELECT)) {
442                 dist_test_bias += FIND_NEAR_SELECT_BIAS;
443         }
444
445         if (dist_test_bias < data->hit.dist_bias) {
446                 data->hit.dist_bias = dist_test_bias;
447                 data->hit.dist = dist_test;
448                 data->hit.index = index;
449                 data->hit.vert = eve;
450         }
451
452         if (data->use_cycle) {
453                 if ((data->hit_cycle.vert == NULL) &&
454                     (index > data->cycle_index_prev) &&
455                     (dist_test_bias < FIND_NEAR_CYCLE_THRESHOLD_MIN))
456                 {
457                         data->hit_cycle.dist_bias = dist_test_bias;
458                         data->hit_cycle.dist = dist_test;
459                         data->hit_cycle.index = index;
460                         data->hit_cycle.vert = eve;
461                 }
462         }
463 }
464
465 /**
466  * Nearest vertex under the cursor.
467  *
468  * \param r_dist (in/out), minimal distance to the nearest and at the end, actual distance
469  * \param use_select_bias
470  * - When true, selected vertice are given a 5 pixel bias to make them further than unselect verts.
471  * - When false, unselected vertice are given the bias.
472  * \param use_cycle Cycle over elements within #FIND_NEAR_CYCLE_THRESHOLD_MIN in order of index.
473  */
474 BMVert *EDBM_vert_find_nearest_ex(
475         ViewContext *vc, float *r_dist,
476         const bool use_select_bias, bool use_cycle)
477 {
478         BMesh *bm = vc->em->bm;
479
480         if (V3D_IS_ZBUF(vc->v3d)) {
481                 const int dist_px = ED_view3d_backbuf_sample_size_clamp(vc->ar, *r_dist);
482                 float dist_test;
483                 unsigned int index;
484                 BMVert *eve;
485
486                 /* No afterqueue (yet), so we check it now, otherwise the bm_xxxofs indices are bad. */
487                 {
488                         FAKE_SELECT_MODE_BEGIN(vc, fake_select_mode, select_mode, SCE_SELECT_VERTEX);
489                         ED_view3d_backbuf_validate_with_select_mode(vc, select_mode);
490
491                         index = ED_view3d_backbuf_sample_rect(
492                                     vc, vc->mval, dist_px, bm_wireoffs, 0xFFFFFF, &dist_test);
493                         eve = index ? BM_vert_at_index_find_or_table(bm, index - 1) : NULL;
494
495                         FAKE_SELECT_MODE_END(vc, fake_select_mode);
496                 }
497
498                 if (eve) {
499                         if (dist_test < *r_dist) {
500                                 *r_dist = dist_test;
501                                 return eve;
502                         }
503                 }
504                 return NULL;
505         }
506         else {
507                 struct NearestVertUserData data = {{0}};
508                 const struct NearestVertUserData_Hit *hit;
509                 const eV3DProjTest clip_flag = V3D_PROJ_TEST_CLIP_DEFAULT;
510
511                 static int prev_select_index = 0;
512                 static const BMVert *prev_select_elem = NULL;
513
514                 if ((use_cycle == false) ||
515                     (prev_select_elem && (prev_select_elem != BM_vert_at_index_find_or_table(bm, prev_select_index))))
516                 {
517                         prev_select_index = 0;
518                         prev_select_elem = NULL;
519                 }
520
521                 data.mval_fl[0] = vc->mval[0];
522                 data.mval_fl[1] = vc->mval[1];
523                 data.use_select_bias = use_select_bias;
524                 data.use_cycle = use_cycle;
525                 data.hit.dist      = data.hit_cycle.dist = \
526                 data.hit.dist_bias = data.hit_cycle.dist_bias = *r_dist;
527                 data.cycle_index_prev = prev_select_index;
528
529                 ED_view3d_init_mats_rv3d(vc->obedit, vc->rv3d);
530                 mesh_foreachScreenVert(vc, findnearestvert__doClosest, &data, clip_flag);
531
532                 hit = (data.use_cycle && data.hit_cycle.vert) ? &data.hit_cycle : &data.hit;
533                 *r_dist = hit->dist;
534
535                 prev_select_elem = hit->vert;
536                 prev_select_index = hit->index;
537
538                 return hit->vert;
539         }
540 }
541
542 BMVert *EDBM_vert_find_nearest(ViewContext *vc, float *r_dist)
543 {
544         return EDBM_vert_find_nearest_ex(vc, r_dist, false, false);
545 }
546
547 /* find the distance to the edge we already have */
548 struct NearestEdgeUserData_ZBuf {
549         float mval_fl[2];
550         float dist;
551         const BMEdge *edge_test;
552 };
553
554 static void find_nearest_edge_center__doZBuf(
555         void *userData, BMEdge *eed,
556         const float screen_co_a[2], const float screen_co_b[2],
557         int UNUSED(index))
558 {
559         struct NearestEdgeUserData_ZBuf *data = userData;
560
561         if (eed == data->edge_test) {
562                 float dist_test;
563                 float screen_co_mid[2];
564
565                 mid_v2_v2v2(screen_co_mid, screen_co_a, screen_co_b);
566                 dist_test = len_manhattan_v2v2(data->mval_fl, screen_co_mid);
567
568                 if (dist_test < data->dist) {
569                         data->dist = dist_test;
570                 }
571         }
572 }
573
574 struct NearestEdgeUserData_Hit {
575         float   dist;
576         float   dist_bias;
577         int     index;
578         BMEdge *edge;
579
580         /* edges only, un-biased manhatten distance to which ever edge we pick
581          * (not used for choosing) */
582         float   dist_center;
583 };
584
585 struct NearestEdgeUserData {
586         ViewContext vc;
587         float mval_fl[2];
588         bool use_select_bias;
589         bool use_cycle;
590         int cycle_index_prev;
591
592         struct NearestEdgeUserData_Hit hit;
593         struct NearestEdgeUserData_Hit hit_cycle;
594 };
595
596 /* note; uses v3d, so needs active 3d window */
597 static void find_nearest_edge__doClosest(
598         void *userData, BMEdge *eed,
599         const float screen_co_a[2], const float screen_co_b[2],
600         int index)
601 {
602         struct NearestEdgeUserData *data = userData;
603         float dist_test, dist_test_bias;
604
605         float fac = line_point_factor_v2(data->mval_fl, screen_co_a, screen_co_b);
606         float screen_co[2];
607
608         if (fac <= 0.0f) {
609                 fac = 0.0f;
610                 copy_v2_v2(screen_co, screen_co_a);
611         }
612         else if (fac >= 1.0f) {
613                 fac = 1.0f;
614                 copy_v2_v2(screen_co, screen_co_b);
615         }
616         else {
617                 interp_v2_v2v2(screen_co, screen_co_a, screen_co_b, fac);
618         }
619
620         dist_test = dist_test_bias = len_manhattan_v2v2(data->mval_fl, screen_co);
621
622         if (data->use_select_bias && BM_elem_flag_test(eed, BM_ELEM_SELECT)) {
623                 dist_test_bias += FIND_NEAR_SELECT_BIAS;
624         }
625
626         if (data->vc.rv3d->rflag & RV3D_CLIPPING) {
627                 float vec[3];
628
629                 interp_v3_v3v3(vec, eed->v1->co, eed->v2->co, fac);
630                 if (ED_view3d_clipping_test(data->vc.rv3d, vec, true)) {
631                         return;
632                 }
633         }
634
635         if (dist_test_bias < data->hit.dist_bias) {
636                 float screen_co_mid[2];
637
638                 data->hit.dist_bias = dist_test_bias;
639                 data->hit.dist = dist_test;
640                 data->hit.index = index;
641                 data->hit.edge = eed;
642
643                 mid_v2_v2v2(screen_co_mid, screen_co_a, screen_co_b);
644                 data->hit.dist_center = len_manhattan_v2v2(data->mval_fl, screen_co_mid);
645         }
646
647         if (data->use_cycle) {
648                 if ((data->hit_cycle.edge == NULL) &&
649                     (index > data->cycle_index_prev) &&
650                     (dist_test_bias < FIND_NEAR_CYCLE_THRESHOLD_MIN))
651                 {
652                         float screen_co_mid[2];
653
654                         data->hit_cycle.dist_bias = dist_test_bias;
655                         data->hit_cycle.dist = dist_test;
656                         data->hit_cycle.index = index;
657                         data->hit_cycle.edge = eed;
658
659                         mid_v2_v2v2(screen_co_mid, screen_co_a, screen_co_b);
660                         data->hit_cycle.dist_center = len_manhattan_v2v2(data->mval_fl, screen_co_mid);
661                 }
662         }
663 }
664
665 BMEdge *EDBM_edge_find_nearest_ex(
666         ViewContext *vc, float *r_dist,
667         float *r_dist_center,
668         const bool use_select_bias, const bool use_cycle,
669         BMEdge **r_eed_zbuf)
670 {
671         BMesh *bm = vc->em->bm;
672
673         if (V3D_IS_ZBUF(vc->v3d)) {
674                 const int dist_px = ED_view3d_backbuf_sample_size_clamp(vc->ar, *r_dist);
675                 float dist_test = 0.0f;
676                 unsigned int index;
677                 BMEdge *eed;
678
679                 /* No afterqueue (yet), so we check it now, otherwise the bm_xxxofs indices are bad. */
680                 {
681                         FAKE_SELECT_MODE_BEGIN(vc, fake_select_mode, select_mode, SCE_SELECT_EDGE);
682                         ED_view3d_backbuf_validate_with_select_mode(vc, select_mode);
683
684                         index = ED_view3d_backbuf_sample_rect(vc, vc->mval, dist_px, bm_solidoffs, bm_wireoffs, &dist_test);
685                         eed = index ? BM_edge_at_index_find_or_table(bm, index - 1) : NULL;
686
687                         FAKE_SELECT_MODE_END(vc, fake_select_mode);
688                 }
689
690                 if (r_eed_zbuf) {
691                         *r_eed_zbuf = eed;
692                 }
693
694                 /* exception for faces (verts don't need this) */
695                 if (r_dist_center && eed) {
696                         struct NearestEdgeUserData_ZBuf data;
697
698                         data.mval_fl[0] = vc->mval[0];
699                         data.mval_fl[1] = vc->mval[1];
700                         data.dist = FLT_MAX;
701                         data.edge_test = eed;
702
703                         ED_view3d_init_mats_rv3d(vc->obedit, vc->rv3d);
704
705                         mesh_foreachScreenEdge(vc, find_nearest_edge_center__doZBuf, &data, V3D_PROJ_TEST_CLIP_DEFAULT);
706
707                         *r_dist_center = data.dist;
708                 }
709                 /* end exception */
710
711                 if (eed) {
712                         if (dist_test < *r_dist) {
713                                 *r_dist = dist_test;
714                                 return eed;
715                         }
716                 }
717                 return NULL;
718         }
719         else {
720                 struct NearestEdgeUserData data = {{0}};
721                 const struct NearestEdgeUserData_Hit *hit;
722                 /* interpolate along the edge before doing a clipping plane test */
723                 const eV3DProjTest clip_flag = V3D_PROJ_TEST_CLIP_DEFAULT & ~V3D_PROJ_TEST_CLIP_BB;
724
725                 static int prev_select_index = 0;
726                 static const BMEdge *prev_select_elem = NULL;
727
728                 if ((use_cycle == false) ||
729                     (prev_select_elem && (prev_select_elem != BM_edge_at_index_find_or_table(bm, prev_select_index))))
730                 {
731                         prev_select_index = 0;
732                         prev_select_elem = NULL;
733                 }
734
735                 data.vc = *vc;
736                 data.mval_fl[0] = vc->mval[0];
737                 data.mval_fl[1] = vc->mval[1];
738                 data.use_select_bias = use_select_bias;
739                 data.use_cycle = use_cycle;
740                 data.hit.dist      = data.hit_cycle.dist = \
741                 data.hit.dist_bias = data.hit_cycle.dist_bias = *r_dist;
742                 data.cycle_index_prev = prev_select_index;
743
744                 ED_view3d_init_mats_rv3d(vc->obedit, vc->rv3d);
745                 mesh_foreachScreenEdge(vc, find_nearest_edge__doClosest, &data, clip_flag);
746
747                 hit = (data.use_cycle && data.hit_cycle.edge) ? &data.hit_cycle : &data.hit;
748                 *r_dist = hit->dist;
749                 if (r_dist_center) {
750                         *r_dist_center = hit->dist_center;
751                 }
752
753                 prev_select_elem = hit->edge;
754                 prev_select_index = hit->index;
755
756                 return hit->edge;
757         }
758 }
759
760 BMEdge *EDBM_edge_find_nearest(
761         ViewContext *vc, float *r_dist)
762 {
763         return EDBM_edge_find_nearest_ex(vc, r_dist, NULL, false, false, NULL);
764 }
765
766 /* find the distance to the face we already have */
767 struct NearestFaceUserData_ZBuf {
768         float mval_fl[2];
769         float dist;
770         const BMFace *face_test;
771 };
772
773 static void find_nearest_face_center__doZBuf(void *userData, BMFace *efa, const float screen_co[2], int UNUSED(index))
774 {
775         struct NearestFaceUserData_ZBuf *data = userData;
776
777         if (efa == data->face_test) {
778                 const float dist_test = len_manhattan_v2v2(data->mval_fl, screen_co);
779
780                 if (dist_test < data->dist) {
781                         data->dist = dist_test;
782                 }
783         }
784 }
785
786
787 struct NearestFaceUserData_Hit {
788         float   dist;
789         float   dist_bias;
790         int     index;
791         BMFace *face;
792 };
793
794 struct NearestFaceUserData {
795         float mval_fl[2];
796         bool use_select_bias;
797         bool use_cycle;
798         int cycle_index_prev;
799
800         struct NearestFaceUserData_Hit hit;
801         struct NearestFaceUserData_Hit hit_cycle;
802 };
803
804 static void findnearestface__doClosest(void *userData, BMFace *efa, const float screen_co[2], int index)
805 {
806         struct NearestFaceUserData *data = userData;
807         float dist_test, dist_test_bias;
808
809         dist_test = dist_test_bias = len_manhattan_v2v2(data->mval_fl, screen_co);
810
811         if (data->use_select_bias && BM_elem_flag_test(efa, BM_ELEM_SELECT)) {
812                 dist_test_bias += FIND_NEAR_SELECT_BIAS;
813         }
814
815         if (dist_test_bias < data->hit.dist_bias) {
816                 data->hit.dist_bias = dist_test_bias;
817                 data->hit.dist = dist_test;
818                 data->hit.index = index;
819                 data->hit.face = efa;
820         }
821
822         if (data->use_cycle) {
823                 if ((data->hit_cycle.face == NULL) &&
824                     (index > data->cycle_index_prev) &&
825                     (dist_test_bias < FIND_NEAR_CYCLE_THRESHOLD_MIN))
826                 {
827                         data->hit_cycle.dist_bias = dist_test_bias;
828                         data->hit_cycle.dist = dist_test;
829                         data->hit_cycle.index = index;
830                         data->hit_cycle.face = efa;
831                 }
832         }
833 }
834
835
836 BMFace *EDBM_face_find_nearest_ex(
837         ViewContext *vc, float *r_dist,
838         float *r_dist_center,
839         const bool use_select_bias, const bool use_cycle,
840         BMFace **r_efa_zbuf)
841 {
842         BMesh *bm = vc->em->bm;
843
844         if (V3D_IS_ZBUF(vc->v3d)) {
845                 float dist_test = 0.0f;
846                 unsigned int index;
847                 BMFace *efa;
848
849                 {
850                         FAKE_SELECT_MODE_BEGIN(vc, fake_select_mode, select_mode, SCE_SELECT_FACE);
851                         ED_view3d_backbuf_validate_with_select_mode(vc, select_mode);
852
853                         index = ED_view3d_backbuf_sample(vc, vc->mval[0], vc->mval[1]);
854                         efa = index ? BM_face_at_index_find_or_table(bm, index - 1) : NULL;
855
856                         FAKE_SELECT_MODE_END(vc, fake_select_mode);
857                 }
858
859                 if (r_efa_zbuf) {
860                         *r_efa_zbuf = efa;
861                 }
862
863                 /* exception for faces (verts don't need this) */
864                 if (r_dist_center && efa) {
865                         struct NearestFaceUserData_ZBuf data;
866
867                         data.mval_fl[0] = vc->mval[0];
868                         data.mval_fl[1] = vc->mval[1];
869                         data.dist = FLT_MAX;
870                         data.face_test = efa;
871
872                         ED_view3d_init_mats_rv3d(vc->obedit, vc->rv3d);
873
874                         mesh_foreachScreenFace(vc, find_nearest_face_center__doZBuf, &data, V3D_PROJ_TEST_CLIP_DEFAULT);
875
876                         *r_dist_center = data.dist;
877                 }
878                 /* end exception */
879
880                 if (efa) {
881                         if (dist_test < *r_dist) {
882                                 *r_dist = dist_test;
883                                 return efa;
884                         }
885                 }
886                 return NULL;
887         }
888         else {
889                 struct NearestFaceUserData data = {{0}};
890                 const struct NearestFaceUserData_Hit *hit;
891                 const eV3DProjTest clip_flag = V3D_PROJ_TEST_CLIP_DEFAULT;
892
893                 static int prev_select_index = 0;
894                 static const BMFace *prev_select_elem = NULL;
895
896                 if ((use_cycle == false) ||
897                     (prev_select_elem && (prev_select_elem != BM_face_at_index_find_or_table(bm, prev_select_index))))
898                 {
899                         prev_select_index = 0;
900                         prev_select_elem = NULL;
901                 }
902
903                 data.mval_fl[0] = vc->mval[0];
904                 data.mval_fl[1] = vc->mval[1];
905                 data.use_select_bias = use_select_bias;
906                 data.use_cycle = use_cycle;
907                 data.hit.dist      = data.hit_cycle.dist = \
908                 data.hit.dist_bias = data.hit_cycle.dist_bias = *r_dist;
909                 data.cycle_index_prev = prev_select_index;
910
911                 ED_view3d_init_mats_rv3d(vc->obedit, vc->rv3d);
912                 mesh_foreachScreenFace(vc, findnearestface__doClosest, &data, clip_flag);
913
914                 hit = (data.use_cycle && data.hit_cycle.face) ? &data.hit_cycle : &data.hit;
915                 *r_dist = hit->dist;
916                 if (r_dist_center) {
917                         *r_dist_center = hit->dist;
918                 }
919
920                 prev_select_elem = hit->face;
921                 prev_select_index = hit->index;
922
923                 return hit->face;
924         }
925 }
926
927 BMFace *EDBM_face_find_nearest(ViewContext *vc, float *r_dist)
928 {
929         return EDBM_face_find_nearest_ex(vc, r_dist, NULL, false, false, NULL);
930 }
931
932 #undef FIND_NEAR_SELECT_BIAS
933 #undef FIND_NEAR_CYCLE_THRESHOLD_MIN
934
935
936 /* best distance based on screen coords.
937  * use em->selectmode to define how to use
938  * selected vertices and edges get disadvantage
939  * return 1 if found one
940  */
941 static bool unified_findnearest(
942         ViewContext *vc,
943         Base **r_base, BMVert **r_eve, BMEdge **r_eed, BMFace **r_efa)
944 {
945         BMEditMesh *em = vc->em;
946         static short mval_prev[2] = {-1, -1};
947         /* only cycle while the mouse remains still */
948         const bool use_cycle = ((mval_prev[0] == vc->mval[0]) && (mval_prev[1] == vc->mval[1]));
949         const float dist_init = ED_view3d_select_dist_px();
950         /* since edges select lines, we give dots advantage of ~20 pix */
951         const float dist_margin = (dist_init / 2);
952         float dist = dist_init;
953
954         struct {
955                 struct {
956                         BMVert *ele;
957                         Base *base;
958                 } v;
959                 struct {
960                         BMEdge *ele;
961                         Base *base;
962                 } e, e_zbuf;
963                 struct {
964                         BMFace *ele;
965                         Base *base;
966                 } f, f_zbuf;
967         } hit = {{NULL}};
968
969         /* TODO(campbell): perform selection as one pass
970          * instead of many smaller passes (which doesn't work for zbuf occlusion). */
971         uint bases_len = 0;
972         Base **bases = BKE_view_layer_array_from_bases_in_edit_mode(vc->view_layer, &bases_len);
973
974         /* no afterqueue (yet), so we check it now, otherwise the em_xxxofs indices are bad */
975
976         if ((dist > 0.0f) && em->selectmode & SCE_SELECT_FACE) {
977                 float dist_center = 0.0f;
978                 float *dist_center_p = (em->selectmode & (SCE_SELECT_EDGE | SCE_SELECT_VERTEX)) ? &dist_center : NULL;
979
980                 for (uint base_index = 0; base_index < bases_len; base_index++) {
981                         Base *base_iter = bases[base_index];
982                         Object *obedit = base_iter->object;
983                         ED_view3d_viewcontext_init_object(vc, obedit);
984                         ED_view3d_backbuf_validate(vc);
985                         BMFace *efa_zbuf = NULL;
986                         BMFace *efa_test = EDBM_face_find_nearest_ex(vc, &dist, dist_center_p, true, use_cycle, &efa_zbuf);
987                         if (hit.f.ele && dist_center_p) {
988                                 dist = min_ff(dist_margin, dist_center);
989                         }
990                         if (efa_test) {
991                                 hit.f.base = base_iter;
992                                 hit.f.ele  = efa_test;
993                         }
994                         if (efa_zbuf) {
995                                 hit.f_zbuf.base = base_iter;
996                                 hit.f_zbuf.ele  = efa_zbuf;
997                         }
998                 } /* bases */
999         }
1000
1001         if ((dist > 0.0f) && (em->selectmode & SCE_SELECT_EDGE)) {
1002                 float dist_center = 0.0f;
1003                 float *dist_center_p = (em->selectmode & SCE_SELECT_VERTEX) ? &dist_center : NULL;
1004
1005                 for (uint base_index = 0; base_index < bases_len; base_index++) {
1006                         Base *base_iter = bases[base_index];
1007                         Object *obedit = base_iter->object;
1008                         ED_view3d_viewcontext_init_object(vc, obedit);
1009                         ED_view3d_backbuf_validate(vc);
1010                         BMEdge *eed_zbuf = NULL;
1011                         BMEdge *eed_test = EDBM_edge_find_nearest_ex(vc, &dist, dist_center_p, true, use_cycle, &eed_zbuf);
1012                         if (hit.e.ele && dist_center_p) {
1013                                 dist = min_ff(dist_margin, dist_center);
1014                         }
1015                         if (eed_test) {
1016                                 hit.e.base = base_iter;
1017                                 hit.e.ele  = eed_test;
1018                         }
1019                         if (eed_zbuf) {
1020                                 hit.e_zbuf.base = base_iter;
1021                                 hit.e_zbuf.ele  = eed_zbuf;
1022                         }
1023                 } /* bases */
1024         }
1025
1026         if ((dist > 0.0f) && em->selectmode & SCE_SELECT_VERTEX) {
1027                 for (uint base_index = 0; base_index < bases_len; base_index++) {
1028                         Base *base_iter = bases[base_index];
1029                         Object *obedit = base_iter->object;
1030                         ED_view3d_viewcontext_init_object(vc, obedit);
1031                         ED_view3d_backbuf_validate(vc);
1032                         BMVert *eve_test = EDBM_vert_find_nearest_ex(vc, &dist, true, use_cycle);
1033                         if (eve_test) {
1034                                 hit.v.base = base_iter;
1035                                 hit.v.ele  = eve_test;
1036                         }
1037                 } /* bases */
1038         }
1039
1040         MEM_SAFE_FREE(bases);
1041
1042         /* return only one of 3 pointers, for frontbuffer redraws */
1043         if (hit.v.ele) {
1044                 hit.f.ele = NULL;
1045                 hit.e.ele = NULL;
1046         }
1047         else if (hit.e.ele) {
1048                 hit.f.ele = NULL;
1049         }
1050
1051         /* there may be a face under the cursor, who's center if too far away
1052          * use this if all else fails, it makes sense to select this */
1053         if ((hit.v.ele || hit.e.ele || hit.f.ele) == 0) {
1054                 if (hit.e_zbuf.ele) {
1055                         hit.e.base = hit.e_zbuf.base;
1056                         hit.e.ele  = hit.e_zbuf.ele;
1057                 }
1058                 else if (hit.f_zbuf.ele) {
1059                         hit.f.base = hit.f_zbuf.base;
1060                         hit.f.ele  = hit.f_zbuf.ele;
1061                 }
1062         }
1063
1064         mval_prev[0] = vc->mval[0];
1065         mval_prev[1] = vc->mval[1];
1066
1067         /* Only one element type will be non-null. */
1068         BLI_assert(((hit.v.ele != NULL) + (hit.e.ele != NULL) + (hit.f.ele != NULL)) <= 1);
1069
1070         if (hit.v.ele) {
1071                 *r_base = hit.v.base;
1072         }
1073         if (hit.e.ele) {
1074                 *r_base = hit.e.base;
1075         }
1076         if (hit.f.ele) {
1077                 *r_base = hit.f.base;
1078         }
1079
1080         *r_eve = hit.v.ele;
1081         *r_eed = hit.e.ele;
1082         *r_efa = hit.f.ele;
1083
1084         return (hit.v.ele || hit.e.ele || hit.f.ele);
1085 }
1086
1087 #undef FAKE_SELECT_MODE_BEGIN
1088 #undef FAKE_SELECT_MODE_END
1089
1090 bool EDBM_unified_findnearest(
1091         ViewContext *vc,
1092         Base **r_base, BMVert **r_eve, BMEdge **r_eed, BMFace **r_efa)
1093 {
1094         return unified_findnearest(vc, r_base, r_eve, r_eed, r_efa);
1095 }
1096
1097 /** \} */
1098
1099 /* -------------------------------------------------------------------- */
1100 /** \name Select Similar (Vert/Edge/Face) Operator
1101  * \{ */
1102
1103 static const EnumPropertyItem prop_similar_compare_types[] = {
1104         {SIM_CMP_EQ, "EQUAL", 0, "Equal", ""},
1105         {SIM_CMP_GT, "GREATER", 0, "Greater", ""},
1106         {SIM_CMP_LT, "LESS", 0, "Less", ""},
1107
1108         {0, NULL, 0, NULL, NULL}
1109 };
1110
1111 static const EnumPropertyItem prop_similar_types[] = {
1112         {SIMVERT_NORMAL, "NORMAL", 0, "Normal", ""},
1113         {SIMVERT_FACE, "FACE", 0, "Amount of Adjacent Faces", ""},
1114         {SIMVERT_VGROUP, "VGROUP", 0, "Vertex Groups", ""},
1115         {SIMVERT_EDGE, "EDGE", 0, "Amount of connecting edges", ""},
1116
1117         {SIMEDGE_LENGTH, "LENGTH", 0, "Length", ""},
1118         {SIMEDGE_DIR, "DIR", 0, "Direction", ""},
1119         {SIMEDGE_FACE, "FACE", 0, "Amount of Faces Around an Edge", ""},
1120         {SIMEDGE_FACE_ANGLE, "FACE_ANGLE", 0, "Face Angles", ""},
1121         {SIMEDGE_CREASE, "CREASE", 0, "Crease", ""},
1122         {SIMEDGE_BEVEL, "BEVEL", 0, "Bevel", ""},
1123         {SIMEDGE_SEAM, "SEAM", 0, "Seam", ""},
1124         {SIMEDGE_SHARP, "SHARP", 0, "Sharpness", ""},
1125 #ifdef WITH_FREESTYLE
1126         {SIMEDGE_FREESTYLE, "FREESTYLE_EDGE", 0, "Freestyle Edge Marks", ""},
1127 #endif
1128
1129         {SIMFACE_MATERIAL, "MATERIAL", 0, "Material", ""},
1130         {SIMFACE_AREA, "AREA", 0, "Area", ""},
1131         {SIMFACE_SIDES, "SIDES", 0, "Polygon Sides", ""},
1132         {SIMFACE_PERIMETER, "PERIMETER", 0, "Perimeter", ""},
1133         {SIMFACE_NORMAL, "NORMAL", 0, "Normal", ""},
1134         {SIMFACE_COPLANAR, "COPLANAR", 0, "Co-planar", ""},
1135         {SIMFACE_SMOOTH, "SMOOTH", 0, "Flat/Smooth", ""},
1136         {SIMFACE_FACEMAP, "FACE_MAP", 0, "Face-Map", ""},
1137 #ifdef WITH_FREESTYLE
1138         {SIMFACE_FREESTYLE, "FREESTYLE_FACE", 0, "Freestyle Face Marks", ""},
1139 #endif
1140
1141         {0, NULL, 0, NULL, NULL}
1142 };
1143
1144 /* selects new faces/edges/verts based on the existing selection */
1145
1146 static int similar_face_select_exec(bContext *C, wmOperator *op)
1147 {
1148         Object *ob = CTX_data_edit_object(C);
1149         BMEditMesh *em = BKE_editmesh_from_object(ob);
1150         BMOperator bmop;
1151
1152         /* get the type from RNA */
1153         const int type = RNA_enum_get(op->ptr, "type");
1154         const float thresh = RNA_float_get(op->ptr, "threshold");
1155         const int compare = RNA_enum_get(op->ptr, "compare");
1156
1157         /* initialize the bmop using EDBM api, which does various ui error reporting and other stuff */
1158         EDBM_op_init(em, &bmop, op,
1159                      "similar_faces faces=%hf type=%i thresh=%f compare=%i",
1160                      BM_ELEM_SELECT, type, thresh, compare);
1161
1162         /* execute the operator */
1163         BMO_op_exec(em->bm, &bmop);
1164
1165         /* clear the existing selection */
1166         EDBM_flag_disable_all(em, BM_ELEM_SELECT);
1167
1168         /* select the output */
1169         BMO_slot_buffer_hflag_enable(em->bm, bmop.slots_out, "faces.out", BM_FACE, BM_ELEM_SELECT, true);
1170
1171         /* finish the operator */
1172         if (!EDBM_op_finish(em, &bmop, op, true)) {
1173                 return OPERATOR_CANCELLED;
1174         }
1175
1176         EDBM_update_generic(em, false, false);
1177
1178         return OPERATOR_FINISHED;
1179 }
1180
1181 /* ***************************************************** */
1182
1183 /* EDGE GROUP */
1184
1185 /* wrap the above function but do selection flushing edge to face */
1186 static int similar_edge_select_exec(bContext *C, wmOperator *op)
1187 {
1188         Object *ob = CTX_data_edit_object(C);
1189         BMEditMesh *em = BKE_editmesh_from_object(ob);
1190         BMOperator bmop;
1191
1192         /* get the type from RNA */
1193         const int type = RNA_enum_get(op->ptr, "type");
1194         const float thresh = RNA_float_get(op->ptr, "threshold");
1195         const int compare = RNA_enum_get(op->ptr, "compare");
1196
1197         /* initialize the bmop using EDBM api, which does various ui error reporting and other stuff */
1198         EDBM_op_init(em, &bmop, op,
1199                      "similar_edges edges=%he type=%i thresh=%f compare=%i",
1200                      BM_ELEM_SELECT, type, thresh, compare);
1201
1202         /* execute the operator */
1203         BMO_op_exec(em->bm, &bmop);
1204
1205         /* clear the existing selection */
1206         EDBM_flag_disable_all(em, BM_ELEM_SELECT);
1207
1208         /* select the output */
1209         BMO_slot_buffer_hflag_enable(em->bm, bmop.slots_out, "edges.out", BM_EDGE, BM_ELEM_SELECT, true);
1210         EDBM_selectmode_flush(em);
1211
1212         /* finish the operator */
1213         if (!EDBM_op_finish(em, &bmop, op, true)) {
1214                 return OPERATOR_CANCELLED;
1215         }
1216
1217         EDBM_update_generic(em, false, false);
1218
1219         return OPERATOR_FINISHED;
1220 }
1221
1222 /* ********************************* */
1223
1224 /*
1225  * VERT GROUP
1226  * mode 1: same normal
1227  * mode 2: same number of face users
1228  * mode 3: same vertex groups
1229  */
1230 static int similar_vert_select_exec(bContext *C, wmOperator *op)
1231 {
1232         Object *ob = CTX_data_edit_object(C);
1233         BMEditMesh *em = BKE_editmesh_from_object(ob);
1234         BMOperator bmop;
1235         /* get the type from RNA */
1236         const int type = RNA_enum_get(op->ptr, "type");
1237         const float thresh = RNA_float_get(op->ptr, "threshold");
1238         const int compare = RNA_enum_get(op->ptr, "compare");
1239
1240         /* initialize the bmop using EDBM api, which does various ui error reporting and other stuff */
1241         EDBM_op_init(em, &bmop, op,
1242                      "similar_verts verts=%hv type=%i thresh=%f compare=%i",
1243                      BM_ELEM_SELECT, type, thresh, compare);
1244
1245         /* execute the operator */
1246         BMO_op_exec(em->bm, &bmop);
1247
1248         /* clear the existing selection */
1249         EDBM_flag_disable_all(em, BM_ELEM_SELECT);
1250
1251         /* select the output */
1252         BMO_slot_buffer_hflag_enable(em->bm, bmop.slots_out, "verts.out", BM_VERT, BM_ELEM_SELECT, true);
1253
1254         /* finish the operator */
1255         if (!EDBM_op_finish(em, &bmop, op, true)) {
1256                 return OPERATOR_CANCELLED;
1257         }
1258
1259         EDBM_selectmode_flush(em);
1260
1261         EDBM_update_generic(em, false, false);
1262
1263         return OPERATOR_FINISHED;
1264 }
1265
1266 static int edbm_select_similar_exec(bContext *C, wmOperator *op)
1267 {
1268         ToolSettings *ts = CTX_data_tool_settings(C);
1269         PropertyRNA *prop = RNA_struct_find_property(op->ptr, "threshold");
1270
1271         const int type = RNA_enum_get(op->ptr, "type");
1272
1273         if (!RNA_property_is_set(op->ptr, prop)) {
1274                 RNA_property_float_set(op->ptr, prop, ts->select_thresh);
1275         }
1276         else {
1277                 ts->select_thresh = RNA_property_float_get(op->ptr, prop);
1278         }
1279
1280         if      (type < 100) return similar_vert_select_exec(C, op);
1281         else if (type < 200) return similar_edge_select_exec(C, op);
1282         else                 return similar_face_select_exec(C, op);
1283 }
1284
1285 static const EnumPropertyItem *select_similar_type_itemf(
1286         bContext *C, PointerRNA *UNUSED(ptr), PropertyRNA *UNUSED(prop),
1287         bool *r_free)
1288 {
1289         Object *obedit;
1290
1291         if (!C) /* needed for docs and i18n tools */
1292                 return prop_similar_types;
1293
1294         obedit = CTX_data_edit_object(C);
1295
1296         if (obedit && obedit->type == OB_MESH) {
1297                 EnumPropertyItem *item = NULL;
1298                 int a, totitem = 0;
1299                 BMEditMesh *em = BKE_editmesh_from_object(obedit);
1300
1301                 if (em->selectmode & SCE_SELECT_VERTEX) {
1302                         for (a = SIMVERT_NORMAL; a < SIMEDGE_LENGTH; a++) {
1303                                 RNA_enum_items_add_value(&item, &totitem, prop_similar_types, a);
1304                         }
1305                 }
1306                 else if (em->selectmode & SCE_SELECT_EDGE) {
1307                         for (a = SIMEDGE_LENGTH; a < SIMFACE_MATERIAL; a++) {
1308                                 RNA_enum_items_add_value(&item, &totitem, prop_similar_types, a);
1309                         }
1310                 }
1311                 else if (em->selectmode & SCE_SELECT_FACE) {
1312 #ifdef WITH_FREESTYLE
1313                         const int a_end = SIMFACE_FREESTYLE;
1314 #else
1315                         const int a_end = SIMFACE_FACEMAP;
1316 #endif
1317                         for (a = SIMFACE_MATERIAL; a <= a_end; a++) {
1318                                 RNA_enum_items_add_value(&item, &totitem, prop_similar_types, a);
1319                         }
1320                 }
1321                 RNA_enum_item_end(&item, &totitem);
1322
1323                 *r_free = true;
1324
1325                 return item;
1326         }
1327
1328         return prop_similar_types;
1329 }
1330
1331 void MESH_OT_select_similar(wmOperatorType *ot)
1332 {
1333         PropertyRNA *prop;
1334
1335         /* identifiers */
1336         ot->name = "Select Similar";
1337         ot->idname = "MESH_OT_select_similar";
1338         ot->description = "Select similar vertices, edges or faces by property types";
1339
1340         /* api callbacks */
1341         ot->invoke = WM_menu_invoke;
1342         ot->exec = edbm_select_similar_exec;
1343         ot->poll = ED_operator_editmesh;
1344
1345         /* flags */
1346         ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
1347
1348         /* properties */
1349         prop = ot->prop = RNA_def_enum(ot->srna, "type", prop_similar_types, SIMVERT_NORMAL, "Type", "");
1350         RNA_def_enum_funcs(prop, select_similar_type_itemf);
1351
1352         RNA_def_enum(ot->srna, "compare", prop_similar_compare_types, SIM_CMP_EQ, "Compare", "");
1353
1354         RNA_def_float(ot->srna, "threshold", 0.0f, 0.0f, 1.0f, "Threshold", "", 0.0f, 1.0f);
1355 }
1356
1357 /** \} */
1358
1359 /* -------------------------------------------------------------------- */
1360 /** \name Select Similar Region Operator
1361  * \{ */
1362
1363 static int edbm_select_similar_region_exec(bContext *C, wmOperator *op)
1364 {
1365         Object *obedit = CTX_data_edit_object(C);
1366         BMEditMesh *em = BKE_editmesh_from_object(obedit);
1367         BMesh *bm = em->bm;
1368         bool changed = false;
1369
1370         /* group vars */
1371         int *groups_array;
1372         int (*group_index)[2];
1373         int group_tot;
1374         int i;
1375
1376         if (bm->totfacesel < 2) {
1377                 BKE_report(op->reports, RPT_ERROR, "No face regions selected");
1378                 return OPERATOR_CANCELLED;
1379         }
1380
1381         groups_array = MEM_mallocN(sizeof(*groups_array) * bm->totfacesel, __func__);
1382         group_tot = BM_mesh_calc_face_groups(
1383                 bm, groups_array, &group_index,
1384                 NULL, NULL,
1385                 BM_ELEM_SELECT, BM_VERT);
1386
1387         BM_mesh_elem_table_ensure(bm, BM_FACE);
1388
1389         for (i = 0; i < group_tot; i++) {
1390                 ListBase faces_regions;
1391                 int tot;
1392
1393                 const int fg_sta = group_index[i][0];
1394                 const int fg_len = group_index[i][1];
1395                 int j;
1396                 BMFace **fg = MEM_mallocN(sizeof(*fg) * fg_len, __func__);
1397
1398
1399                 for (j = 0; j < fg_len; j++) {
1400                         fg[j] = BM_face_at_index(bm, groups_array[fg_sta + j]);
1401                 }
1402
1403                 tot = BM_mesh_region_match(bm, fg, fg_len, &faces_regions);
1404
1405                 MEM_freeN(fg);
1406
1407                 if (tot) {
1408                         LinkData *link;
1409                         while ((link = BLI_pophead(&faces_regions))) {
1410                                 BMFace *f, **faces = link->data;
1411                                 while ((f = *(faces++))) {
1412                                         BM_face_select_set(bm, f, true);
1413                                 }
1414                                 MEM_freeN(link->data);
1415                                 MEM_freeN(link);
1416
1417                                 changed = true;
1418                         }
1419                 }
1420         }
1421
1422         MEM_freeN(groups_array);
1423         MEM_freeN(group_index);
1424
1425         if (changed) {
1426                 DEG_id_tag_update(obedit->data, DEG_TAG_SELECT_UPDATE);
1427                 WM_event_add_notifier(C, NC_GEOM | ND_SELECT, obedit->data);
1428         }
1429         else {
1430                 BKE_report(op->reports, RPT_WARNING, "No matching face regions found");
1431         }
1432
1433         return OPERATOR_FINISHED;
1434 }
1435
1436 void MESH_OT_select_similar_region(wmOperatorType *ot)
1437 {
1438         /* identifiers */
1439         ot->name = "Select Similar Regions";
1440         ot->idname = "MESH_OT_select_similar_region";
1441         ot->description = "Select similar face regions to the current selection";
1442
1443         /* api callbacks */
1444         ot->exec = edbm_select_similar_region_exec;
1445         ot->poll = ED_operator_editmesh;
1446
1447         /* flags */
1448         ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
1449 }
1450
1451 /** \} */
1452
1453 /* -------------------------------------------------------------------- */
1454 /** \name Select Mode Vert/Edge/Face Operator
1455  * \{ */
1456
1457 static int edbm_select_mode_exec(bContext *C, wmOperator *op)
1458 {
1459         const int type        = RNA_enum_get(op->ptr,    "type");
1460         const int action      = RNA_enum_get(op->ptr,    "action");
1461         const bool use_extend = RNA_boolean_get(op->ptr, "use_extend");
1462         const bool use_expand = RNA_boolean_get(op->ptr, "use_expand");
1463
1464         if (EDBM_selectmode_toggle(C, type, action, use_extend, use_expand)) {
1465                 return OPERATOR_FINISHED;
1466         }
1467         else {
1468                 return OPERATOR_CANCELLED;
1469         }
1470 }
1471
1472 static int edbm_select_mode_invoke(bContext *C, wmOperator *op, const wmEvent *event)
1473 {
1474         /* Bypass when in UV non sync-select mode, fall through to keymap that edits. */
1475         if (CTX_wm_space_image(C)) {
1476                 ToolSettings *ts = CTX_data_tool_settings(C);
1477                 if ((ts->uv_flag & UV_SYNC_SELECTION) == 0) {
1478                         return OPERATOR_PASS_THROUGH;
1479                 }
1480                 /* Bypass when no action is needed. */
1481                 if (!RNA_struct_property_is_set(op->ptr, "type")) {
1482                         return OPERATOR_CANCELLED;
1483                 }
1484         }
1485
1486         /* detecting these options based on shift/ctrl here is weak, but it's done
1487          * to make this work when clicking buttons or menus */
1488         if (!RNA_struct_property_is_set(op->ptr, "use_extend"))
1489                 RNA_boolean_set(op->ptr, "use_extend", event->shift);
1490         if (!RNA_struct_property_is_set(op->ptr, "use_expand"))
1491                 RNA_boolean_set(op->ptr, "use_expand", event->ctrl);
1492
1493         return edbm_select_mode_exec(C, op);
1494 }
1495
1496 void MESH_OT_select_mode(wmOperatorType *ot)
1497 {
1498         PropertyRNA *prop;
1499
1500         static const EnumPropertyItem elem_items[] = {
1501                 {SCE_SELECT_VERTEX, "VERT", ICON_VERTEXSEL, "Vertices", ""},
1502                 {SCE_SELECT_EDGE,   "EDGE", ICON_EDGESEL, "Edges", ""},
1503                 {SCE_SELECT_FACE,   "FACE", ICON_FACESEL, "Faces", ""},
1504                 {0, NULL, 0, NULL, NULL},
1505         };
1506
1507         static const EnumPropertyItem actions_items[] = {
1508                 {0, "DISABLE", 0, "Disable", "Disable selected markers"},
1509                 {1, "ENABLE", 0, "Enable", "Enable selected markers"},
1510                 {2, "TOGGLE", 0, "Toggle", "Toggle disabled flag for selected markers"},
1511                 {0, NULL, 0, NULL, NULL}
1512         };
1513
1514         /* identifiers */
1515         ot->name = "Select Mode";
1516         ot->idname = "MESH_OT_select_mode";
1517         ot->description = "Change selection mode";
1518
1519         /* api callbacks */
1520         ot->invoke = edbm_select_mode_invoke;
1521         ot->exec = edbm_select_mode_exec;
1522         ot->poll = ED_operator_editmesh;
1523
1524         /* flags */
1525         ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
1526
1527         /* properties */
1528         /* Hide all, not to show redo panel. */
1529         prop = RNA_def_boolean(ot->srna, "use_extend", false, "Extend", "");
1530         RNA_def_property_flag(prop, PROP_HIDDEN | PROP_SKIP_SAVE);
1531         prop = RNA_def_boolean(ot->srna, "use_expand", false, "Expand", "");
1532         RNA_def_property_flag(prop, PROP_HIDDEN | PROP_SKIP_SAVE);
1533         ot->prop = prop = RNA_def_enum(ot->srna, "type", elem_items, 0, "Type", "");
1534         RNA_def_property_flag(prop, PROP_HIDDEN | PROP_SKIP_SAVE);
1535
1536         prop = RNA_def_enum(ot->srna, "action", actions_items, 2, "Action", "Selection action to execute");
1537         RNA_def_property_flag(prop, PROP_HIDDEN);
1538 }
1539
1540 /** \} */
1541
1542 /* -------------------------------------------------------------------- */
1543 /** \name Select Loop (Non Modal) Operator
1544  * \{ */
1545
1546 static void walker_select_count(
1547         BMEditMesh *em, int walkercode, void *start, const bool select, const bool select_mix,
1548         int *r_totsel, int *r_totunsel)
1549 {
1550         BMesh *bm = em->bm;
1551         BMElem *ele;
1552         BMWalker walker;
1553         int tot[2] = {0, 0};
1554
1555         BMW_init(&walker, bm, walkercode,
1556                  BMW_MASK_NOP, BMW_MASK_NOP, BMW_MASK_NOP,
1557                  BMW_FLAG_TEST_HIDDEN,
1558                  BMW_NIL_LAY);
1559
1560         for (ele = BMW_begin(&walker, start); ele; ele = BMW_step(&walker)) {
1561                 tot[(BM_elem_flag_test_bool(ele, BM_ELEM_SELECT) != select)] += 1;
1562
1563                 if (!select_mix && tot[0] && tot[1]) {
1564                         tot[0] = tot[1] = -1;
1565                         break;
1566                 }
1567         }
1568
1569         *r_totsel = tot[0];
1570         *r_totunsel = tot[1];
1571
1572         BMW_end(&walker);
1573 }
1574
1575 static void walker_select(BMEditMesh *em, int walkercode, void *start, const bool select)
1576 {
1577         BMesh *bm = em->bm;
1578         BMElem *ele;
1579         BMWalker walker;
1580
1581         BMW_init(&walker, bm, walkercode,
1582                  BMW_MASK_NOP, BMW_MASK_NOP, BMW_MASK_NOP,
1583                  BMW_FLAG_TEST_HIDDEN,
1584                  BMW_NIL_LAY);
1585
1586         for (ele = BMW_begin(&walker, start); ele; ele = BMW_step(&walker)) {
1587                 if (!select) {
1588                         BM_select_history_remove(bm, ele);
1589                 }
1590                 BM_elem_select_set(bm, ele, select);
1591         }
1592         BMW_end(&walker);
1593 }
1594
1595 static int edbm_loop_multiselect_exec(bContext *C, wmOperator *op)
1596 {
1597         const bool is_ring = RNA_boolean_get(op->ptr, "ring");
1598         ViewLayer *view_layer = CTX_data_view_layer(C);
1599         uint objects_len = 0;
1600         Object **objects = BKE_view_layer_array_from_objects_in_edit_mode_unique_data(view_layer, &objects_len);
1601         for (uint ob_index = 0; ob_index < objects_len; ob_index++) {
1602                 Object *obedit = objects[ob_index];
1603                 BMEditMesh *em = BKE_editmesh_from_object(obedit);
1604
1605                 if (em->bm->totedgesel == 0) {
1606                         continue;
1607                 }
1608
1609                 BMEdge *eed;
1610                 BMEdge **edarray;
1611                 int edindex;
1612                 BMIter iter;
1613                 int totedgesel = 0;
1614
1615                 BM_ITER_MESH(eed, &iter, em->bm, BM_EDGES_OF_MESH) {
1616                         if (BM_elem_flag_test(eed, BM_ELEM_SELECT)) {
1617                                 totedgesel++;
1618                         }
1619                 }
1620
1621                 edarray = MEM_mallocN(sizeof(BMEdge *) * totedgesel, "edge array");
1622                 edindex = 0;
1623
1624                 BM_ITER_MESH(eed, &iter, em->bm, BM_EDGES_OF_MESH) {
1625                         if (BM_elem_flag_test(eed, BM_ELEM_SELECT)) {
1626                                 edarray[edindex] = eed;
1627                                 edindex++;
1628                         }
1629                 }
1630
1631                 if (is_ring) {
1632                         for (edindex = 0; edindex < totedgesel; edindex += 1) {
1633                                 eed = edarray[edindex];
1634                                 walker_select(em, BMW_EDGERING, eed, true);
1635                         }
1636                         EDBM_selectmode_flush(em);
1637                 }
1638                 else {
1639                         for (edindex = 0; edindex < totedgesel; edindex += 1) {
1640                                 eed = edarray[edindex];
1641                                 walker_select(em, BMW_EDGELOOP, eed, true);
1642                         }
1643                         EDBM_selectmode_flush(em);
1644                 }
1645                 MEM_freeN(edarray);
1646                 //      if (EM_texFaceCheck())
1647
1648                 DEG_id_tag_update(obedit->data, DEG_TAG_SELECT_UPDATE);
1649                 WM_event_add_notifier(C, NC_GEOM | ND_SELECT, obedit->data);
1650         }
1651         MEM_freeN(objects);
1652
1653         return OPERATOR_FINISHED;
1654 }
1655
1656 void MESH_OT_loop_multi_select(wmOperatorType *ot)
1657 {
1658         /* identifiers */
1659         ot->name = "Multi Select Loops";
1660         ot->idname = "MESH_OT_loop_multi_select";
1661         ot->description = "Select a loop of connected edges by connection type";
1662
1663         /* api callbacks */
1664         ot->exec = edbm_loop_multiselect_exec;
1665         ot->poll = ED_operator_editmesh;
1666
1667         /* flags */
1668         ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
1669
1670         /* properties */
1671         RNA_def_boolean(ot->srna, "ring", 0, "Ring", "");
1672 }
1673
1674 /** \} */
1675
1676 /* -------------------------------------------------------------------- */
1677 /** \name Select Loop (Cursor Pick) Operator
1678  * \{ */
1679
1680 static void mouse_mesh_loop_face(BMEditMesh *em, BMEdge *eed, bool select, bool select_clear)
1681 {
1682         if (select_clear) {
1683                 EDBM_flag_disable_all(em, BM_ELEM_SELECT);
1684         }
1685
1686         walker_select(em, BMW_FACELOOP, eed, select);
1687 }
1688
1689 static void mouse_mesh_loop_edge_ring(BMEditMesh *em, BMEdge *eed, bool select, bool select_clear)
1690 {
1691         if (select_clear) {
1692                 EDBM_flag_disable_all(em, BM_ELEM_SELECT);
1693         }
1694
1695         walker_select(em, BMW_EDGERING, eed, select);
1696 }
1697
1698 static void mouse_mesh_loop_edge(BMEditMesh *em, BMEdge *eed, bool select, bool select_clear, bool select_cycle)
1699 {
1700         bool edge_boundary = false;
1701
1702         /* cycle between BMW_EDGELOOP / BMW_EDGEBOUNDARY  */
1703         if (select_cycle && BM_edge_is_boundary(eed)) {
1704                 int tot[2];
1705
1706                 /* if the loops selected toggle the boundaries */
1707                 walker_select_count(em, BMW_EDGELOOP, eed, select, false,
1708                                     &tot[0], &tot[1]);
1709                 if (tot[select] == 0) {
1710                         edge_boundary = true;
1711
1712                         /* if the boundaries selected, toggle back to the loop */
1713                         walker_select_count(em, BMW_EDGEBOUNDARY, eed, select, false,
1714                                             &tot[0], &tot[1]);
1715                         if (tot[select] == 0) {
1716                                 edge_boundary = false;
1717                         }
1718                 }
1719         }
1720
1721         if (select_clear) {
1722                 EDBM_flag_disable_all(em, BM_ELEM_SELECT);
1723         }
1724
1725         if (edge_boundary) {
1726                 walker_select(em, BMW_EDGEBOUNDARY, eed, select);
1727         }
1728         else {
1729                 walker_select(em, BMW_EDGELOOP, eed, select);
1730         }
1731 }
1732
1733 static bool mouse_mesh_loop(bContext *C, const int mval[2], bool extend, bool deselect, bool toggle, bool ring)
1734 {
1735         Base *basact = NULL;
1736         BMVert *eve = NULL;
1737         BMEdge *eed = NULL;
1738         BMFace *efa = NULL;
1739
1740         ViewContext vc;
1741         BMEditMesh *em;
1742         bool select = true;
1743         bool select_clear = false;
1744         bool select_cycle = true;
1745         float mvalf[2];
1746
1747         em_setup_viewcontext(C, &vc);
1748         mvalf[0] = (float)(vc.mval[0] = mval[0]);
1749         mvalf[1] = (float)(vc.mval[1] = mval[1]);
1750
1751         BMEditMesh *em_original = vc.em;
1752         const short selectmode = em_original->selectmode;
1753         em_original->selectmode = SCE_SELECT_EDGE;
1754
1755         if (EDBM_unified_findnearest(&vc, &basact, &eve, &eed, &efa)) {
1756                 ED_view3d_viewcontext_init_object(&vc, basact->object);
1757                 em = vc.em;
1758         }
1759         else {
1760                 em = NULL;
1761         }
1762
1763         em_original->selectmode = selectmode;
1764
1765         if (em == NULL || eed == NULL) {
1766                 return false;
1767         }
1768
1769         if (extend == false && deselect == false && toggle == false) {
1770                 select_clear = true;
1771         }
1772
1773         if (extend) {
1774                 select = true;
1775         }
1776         else if (deselect) {
1777                 select = false;
1778         }
1779         else if (select_clear || (BM_elem_flag_test(eed, BM_ELEM_SELECT) == 0)) {
1780                 select = true;
1781         }
1782         else if (toggle) {
1783                 select = false;
1784                 select_cycle = false;
1785         }
1786
1787         if (select_clear) {
1788                 ViewLayer *view_layer = CTX_data_view_layer(C);
1789                 uint objects_len = 0;
1790                 Object **objects = BKE_view_layer_array_from_objects_in_edit_mode_unique_data(view_layer, &objects_len);
1791                 for (uint ob_index = 0; ob_index < objects_len; ob_index++) {
1792                         Object *ob_iter = objects[ob_index];
1793                         BMEditMesh *em_iter = BKE_editmesh_from_object(ob_iter);
1794
1795                         if (em_iter->bm->totvertsel == 0) {
1796                                 continue;
1797                         }
1798
1799                         if (em_iter == em) {
1800                                 continue;
1801                         }
1802
1803                         EDBM_flag_disable_all(em_iter, BM_ELEM_SELECT);
1804                         DEG_id_tag_update(ob_iter->data, DEG_TAG_SELECT_UPDATE);
1805                 }
1806                 MEM_freeN(objects);
1807         }
1808
1809         if (em->selectmode & SCE_SELECT_FACE) {
1810                 mouse_mesh_loop_face(em, eed, select, select_clear);
1811         }
1812         else {
1813                 if (ring) {
1814                         mouse_mesh_loop_edge_ring(em, eed, select, select_clear);
1815                 }
1816                 else {
1817                         mouse_mesh_loop_edge(em, eed, select, select_clear, select_cycle);
1818                 }
1819         }
1820
1821         EDBM_selectmode_flush(em);
1822
1823         /* sets as active, useful for other tools */
1824         if (select) {
1825                 if (em->selectmode & SCE_SELECT_VERTEX) {
1826                         /* Find nearest vert from mouse
1827                          * (initialize to large values incase only one vertex can be projected) */
1828                         float v1_co[2], v2_co[2];
1829                         float length_1 = FLT_MAX;
1830                         float length_2 = FLT_MAX;
1831
1832                         /* We can't be sure this has already been set... */
1833                         ED_view3d_init_mats_rv3d(vc.obedit, vc.rv3d);
1834
1835                         if (ED_view3d_project_float_object(
1836                                     vc.ar, eed->v1->co, v1_co, V3D_PROJ_TEST_CLIP_NEAR) == V3D_PROJ_RET_OK)
1837                         {
1838                                 length_1 = len_squared_v2v2(mvalf, v1_co);
1839                         }
1840
1841                         if (ED_view3d_project_float_object(
1842                                     vc.ar, eed->v2->co, v2_co, V3D_PROJ_TEST_CLIP_NEAR) == V3D_PROJ_RET_OK)
1843                         {
1844                                 length_2 = len_squared_v2v2(mvalf, v2_co);
1845                         }
1846 #if 0
1847                         printf("mouse to v1: %f\nmouse to v2: %f\n", len_squared_v2v2(mvalf, v1_co),
1848                                len_squared_v2v2(mvalf, v2_co));
1849 #endif
1850                         BM_select_history_store(em->bm, (length_1 < length_2) ? eed->v1 : eed->v2);
1851                 }
1852                 else if (em->selectmode & SCE_SELECT_EDGE) {
1853                         BM_select_history_store(em->bm, eed);
1854                 }
1855                 else if (em->selectmode & SCE_SELECT_FACE) {
1856                         /* Select the face of eed which is the nearest of mouse. */
1857                         BMFace *f;
1858                         BMIter iterf;
1859                         float best_dist = FLT_MAX;
1860                         efa = NULL;
1861
1862                         /* We can't be sure this has already been set... */
1863                         ED_view3d_init_mats_rv3d(vc.obedit, vc.rv3d);
1864
1865                         BM_ITER_ELEM (f, &iterf, eed, BM_FACES_OF_EDGE) {
1866                                 if (BM_elem_flag_test(f, BM_ELEM_SELECT)) {
1867                                         float cent[3];
1868                                         float co[2], tdist;
1869
1870                                         BM_face_calc_center_mean(f, cent);
1871                                         if (ED_view3d_project_float_object(
1872                                                     vc.ar, cent, co, V3D_PROJ_TEST_CLIP_NEAR) == V3D_PROJ_RET_OK)
1873                                         {
1874                                                 tdist = len_squared_v2v2(mvalf, co);
1875                                                 if (tdist < best_dist) {
1876 /*                                                      printf("Best face: %p (%f)\n", f, tdist);*/
1877                                                         best_dist = tdist;
1878                                                         efa = f;
1879                                                 }
1880                                         }
1881                                 }
1882                         }
1883                         if (efa) {
1884                                 BM_mesh_active_face_set(em->bm, efa);
1885                                 BM_select_history_store(em->bm, efa);
1886                         }
1887                 }
1888         }
1889
1890         DEG_id_tag_update(vc.obedit->data, DEG_TAG_SELECT_UPDATE);
1891         WM_event_add_notifier(C, NC_GEOM | ND_SELECT, vc.obedit->data);
1892
1893         return true;
1894 }
1895
1896 static int edbm_select_loop_invoke(bContext *C, wmOperator *op, const wmEvent *event)
1897 {
1898
1899         view3d_operator_needs_opengl(C);
1900
1901         if (mouse_mesh_loop(
1902                     C, event->mval,
1903                     RNA_boolean_get(op->ptr, "extend"),
1904                     RNA_boolean_get(op->ptr, "deselect"),
1905                     RNA_boolean_get(op->ptr, "toggle"),
1906                     RNA_boolean_get(op->ptr, "ring")))
1907         {
1908                 return OPERATOR_FINISHED;
1909         }
1910         else {
1911                 return OPERATOR_CANCELLED;
1912         }
1913 }
1914
1915 void MESH_OT_loop_select(wmOperatorType *ot)
1916 {
1917         /* identifiers */
1918         ot->name = "Loop Select";
1919         ot->idname = "MESH_OT_loop_select";
1920         ot->description = "Select a loop of connected edges";
1921
1922         /* api callbacks */
1923         ot->invoke = edbm_select_loop_invoke;
1924         ot->poll = ED_operator_editmesh_region_view3d;
1925
1926         /* flags */
1927         ot->flag = OPTYPE_UNDO;
1928
1929         /* properties */
1930         RNA_def_boolean(ot->srna, "extend", 0, "Extend Select", "Extend the selection");
1931         RNA_def_boolean(ot->srna, "deselect", 0, "Deselect", "Remove from the selection");
1932         RNA_def_boolean(ot->srna, "toggle", 0, "Toggle Select", "Toggle the selection");
1933         RNA_def_boolean(ot->srna, "ring", 0, "Select Ring", "Select ring");
1934 }
1935
1936 void MESH_OT_edgering_select(wmOperatorType *ot)
1937 {
1938         /* description */
1939         ot->name = "Edge Ring Select";
1940         ot->idname = "MESH_OT_edgering_select";
1941         ot->description = "Select an edge ring";
1942
1943         /* callbacks */
1944         ot->invoke = edbm_select_loop_invoke;
1945         ot->poll = ED_operator_editmesh_region_view3d;
1946
1947         /* flags */
1948         ot->flag = OPTYPE_UNDO;
1949
1950         RNA_def_boolean(ot->srna, "extend", 0, "Extend", "Extend the selection");
1951         RNA_def_boolean(ot->srna, "deselect", 0, "Deselect", "Remove from the selection");
1952         RNA_def_boolean(ot->srna, "toggle", 0, "Toggle Select", "Toggle the selection");
1953         RNA_def_boolean(ot->srna, "ring", 1, "Select Ring", "Select ring");
1954 }
1955
1956 /** \} */
1957
1958 /* -------------------------------------------------------------------- */
1959 /** \name (De)Select All Operator
1960  * \{ */
1961
1962 static int edbm_select_all_exec(bContext *C, wmOperator *op)
1963 {
1964         ViewLayer *view_layer = CTX_data_view_layer(C);
1965         int action = RNA_enum_get(op->ptr, "action");
1966
1967         uint objects_len = 0;
1968         Object **objects = BKE_view_layer_array_from_objects_in_edit_mode_unique_data(view_layer, &objects_len);
1969
1970         if (action == SEL_TOGGLE) {
1971                 action = SEL_SELECT;
1972                 for (uint ob_index = 0; ob_index < objects_len; ob_index++) {
1973                         Object *obedit = objects[ob_index];
1974                         BMEditMesh *em = BKE_editmesh_from_object(obedit);
1975                         if (em->bm->totvertsel || em->bm->totedgesel || em->bm->totfacesel) {
1976                                 action = SEL_DESELECT;
1977                                 break;
1978                         }
1979                 }
1980         }
1981
1982         for (uint ob_index = 0; ob_index < objects_len; ob_index++) {
1983                 Object *obedit = objects[ob_index];
1984                 BMEditMesh *em = BKE_editmesh_from_object(obedit);
1985                 switch (action) {
1986                         case SEL_SELECT:
1987                                 EDBM_flag_enable_all(em, BM_ELEM_SELECT);
1988                                 break;
1989                         case SEL_DESELECT:
1990                                 EDBM_flag_disable_all(em, BM_ELEM_SELECT);
1991                                 break;
1992                         case SEL_INVERT:
1993                                 EDBM_select_swap(em);
1994                                 EDBM_selectmode_flush(em);
1995                                 break;
1996                 }
1997                 DEG_id_tag_update(obedit->data, DEG_TAG_SELECT_UPDATE);
1998                 WM_event_add_notifier(C, NC_GEOM | ND_SELECT, obedit->data);
1999         }
2000
2001         MEM_freeN(objects);
2002
2003         return OPERATOR_FINISHED;
2004 }
2005
2006 void MESH_OT_select_all(wmOperatorType *ot)
2007 {
2008         /* identifiers */
2009         ot->name = "(De)select All";
2010         ot->idname = "MESH_OT_select_all";
2011         ot->description = "(De)select all vertices, edges or faces";
2012
2013         /* api callbacks */
2014         ot->exec = edbm_select_all_exec;
2015         ot->poll = ED_operator_editmesh;
2016
2017         /* flags */
2018         ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
2019
2020         WM_operator_properties_select_all(ot);
2021 }
2022
2023 /** \} */
2024
2025 /* -------------------------------------------------------------------- */
2026 /** \name Select Interior Faces Operator
2027  * \{ */
2028
2029 static int edbm_faces_select_interior_exec(bContext *C, wmOperator *UNUSED(op))
2030 {
2031         ViewLayer *view_layer = CTX_data_view_layer(C);
2032         uint objects_len = 0;
2033         Object **objects = BKE_view_layer_array_from_objects_in_edit_mode_unique_data(view_layer, &objects_len);
2034
2035         for (uint ob_index = 0; ob_index < objects_len; ob_index++) {
2036                 Object *obedit = objects[ob_index];
2037                 BMEditMesh *em = BKE_editmesh_from_object(obedit);
2038
2039                 if (!EDBM_select_interior_faces(em)) {
2040                         continue;
2041                 }
2042
2043                 DEG_id_tag_update(obedit->data, DEG_TAG_SELECT_UPDATE);
2044                 WM_event_add_notifier(C, NC_GEOM | ND_SELECT, obedit->data);
2045         }
2046         MEM_freeN(objects);
2047
2048         return OPERATOR_FINISHED;
2049 }
2050
2051 void MESH_OT_select_interior_faces(wmOperatorType *ot)
2052 {
2053         /* identifiers */
2054         ot->name = "Select Interior Faces";
2055         ot->idname = "MESH_OT_select_interior_faces";
2056         ot->description = "Select faces where all edges have more than 2 face users";
2057
2058         /* api callbacks */
2059         ot->exec = edbm_faces_select_interior_exec;
2060         ot->poll = ED_operator_editmesh;
2061
2062         /* flags */
2063         ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
2064 }
2065
2066 /** \} */
2067
2068 /* -------------------------------------------------------------------- */
2069 /** \name Select Picking API
2070  *
2071  * Here actual select happens,
2072  * Gets called via generic mouse select operator.
2073  * \{ */
2074
2075 bool EDBM_select_pick(bContext *C, const int mval[2], bool extend, bool deselect, bool toggle)
2076 {
2077         ViewContext vc;
2078
2079         Base *basact = NULL;
2080         BMVert *eve = NULL;
2081         BMEdge *eed = NULL;
2082         BMFace *efa = NULL;
2083
2084         /* setup view context for argument to callbacks */
2085         em_setup_viewcontext(C, &vc);
2086         vc.mval[0] = mval[0];
2087         vc.mval[1] = mval[1];
2088
2089         if (unified_findnearest(&vc, &basact, &eve, &eed, &efa)) {
2090                 ED_view3d_viewcontext_init_object(&vc, basact->object);
2091
2092                 /* Deselect everything */
2093                 if (extend == false && deselect == false && toggle == false) {
2094                         uint objects_len = 0;
2095                         Object **objects = BKE_view_layer_array_from_objects_in_edit_mode_unique_data(vc.view_layer, &objects_len);
2096
2097                         for (uint ob_index = 0; ob_index < objects_len; ob_index++) {
2098                                 Object *ob_iter = objects[ob_index];
2099                                 EDBM_flag_disable_all(BKE_editmesh_from_object(ob_iter), BM_ELEM_SELECT);
2100                                 if (basact->object != ob_iter) {
2101                                         DEG_id_tag_update(ob_iter->data, DEG_TAG_SELECT_UPDATE);
2102                                         WM_event_add_notifier(C, NC_GEOM | ND_SELECT, ob_iter->data);
2103                                 }
2104                         }
2105                         MEM_freeN(objects);
2106                 }
2107
2108                 if (efa) {
2109                         if (extend) {
2110                                 /* set the last selected face */
2111                                 BM_mesh_active_face_set(vc.em->bm, efa);
2112
2113                                 /* Work-around: deselect first, so we can guarantee it will */
2114                                 /* be active even if it was already selected */
2115                                 BM_select_history_remove(vc.em->bm, efa);
2116                                 BM_face_select_set(vc.em->bm, efa, false);
2117                                 BM_select_history_store(vc.em->bm, efa);
2118                                 BM_face_select_set(vc.em->bm, efa, true);
2119                         }
2120                         else if (deselect) {
2121                                 BM_select_history_remove(vc.em->bm, efa);
2122                                 BM_face_select_set(vc.em->bm, efa, false);
2123                         }
2124                         else {
2125                                 /* set the last selected face */
2126                                 BM_mesh_active_face_set(vc.em->bm, efa);
2127
2128                                 if (!BM_elem_flag_test(efa, BM_ELEM_SELECT)) {
2129                                         BM_select_history_store(vc.em->bm, efa);
2130                                         BM_face_select_set(vc.em->bm, efa, true);
2131                                 }
2132                                 else if (toggle) {
2133                                         BM_select_history_remove(vc.em->bm, efa);
2134                                         BM_face_select_set(vc.em->bm, efa, false);
2135                                 }
2136                         }
2137                 }
2138                 else if (eed) {
2139                         if (extend) {
2140                                 /* Work-around: deselect first, so we can guarantee it will */
2141                                 /* be active even if it was already selected */
2142                                 BM_select_history_remove(vc.em->bm, eed);
2143                                 BM_edge_select_set(vc.em->bm, eed, false);
2144                                 BM_select_history_store(vc.em->bm, eed);
2145                                 BM_edge_select_set(vc.em->bm, eed, true);
2146                         }
2147                         else if (deselect) {
2148                                 BM_select_history_remove(vc.em->bm, eed);
2149                                 BM_edge_select_set(vc.em->bm, eed, false);
2150                         }
2151                         else {
2152                                 if (!BM_elem_flag_test(eed, BM_ELEM_SELECT)) {
2153                                         BM_select_history_store(vc.em->bm, eed);
2154                                         BM_edge_select_set(vc.em->bm, eed, true);
2155                                 }
2156                                 else if (toggle) {
2157                                         BM_select_history_remove(vc.em->bm, eed);
2158                                         BM_edge_select_set(vc.em->bm, eed, false);
2159                                 }
2160                         }
2161                 }
2162                 else if (eve) {
2163                         if (extend) {
2164                                 /* Work-around: deselect first, so we can guarantee it will */
2165                                 /* be active even if it was already selected */
2166                                 BM_select_history_remove(vc.em->bm, eve);
2167                                 BM_vert_select_set(vc.em->bm, eve, false);
2168                                 BM_select_history_store(vc.em->bm, eve);
2169                                 BM_vert_select_set(vc.em->bm, eve, true);
2170                         }
2171                         else if (deselect) {
2172                                 BM_select_history_remove(vc.em->bm, eve);
2173                                 BM_vert_select_set(vc.em->bm, eve, false);
2174                         }
2175                         else {
2176                                 if (!BM_elem_flag_test(eve, BM_ELEM_SELECT)) {
2177                                         BM_select_history_store(vc.em->bm, eve);
2178                                         BM_vert_select_set(vc.em->bm, eve, true);
2179                                 }
2180                                 else if (toggle) {
2181                                         BM_select_history_remove(vc.em->bm, eve);
2182                                         BM_vert_select_set(vc.em->bm, eve, false);
2183                                 }
2184                         }
2185                 }
2186
2187                 EDBM_selectmode_flush(vc.em);
2188
2189                 if (efa) {
2190                         /* Change active material on object. */
2191                         if (efa->mat_nr != vc.obedit->actcol - 1) {
2192                                 vc.obedit->actcol = efa->mat_nr + 1;
2193                                 vc.em->mat_nr = efa->mat_nr;
2194                                 WM_event_add_notifier(C, NC_MATERIAL | ND_SHADING_LINKS, NULL);
2195                         }
2196
2197                         /* Change active face-map on object. */
2198                         if (!BLI_listbase_is_empty(&vc.obedit->fmaps)) {
2199                                 const int cd_fmap_offset = CustomData_get_offset(&vc.em->bm->pdata, CD_FACEMAP);
2200                                 if (cd_fmap_offset != -1) {
2201                                         int map = *((int *)BM_ELEM_CD_GET_VOID_P(efa, cd_fmap_offset));
2202                                         if ((map < -1) || (map > BLI_listbase_count_at_most(&vc.obedit->fmaps, map))) {
2203                                                 map = -1;
2204                                         }
2205                                         map += 1;
2206                                         if (map != vc.obedit->actfmap) {
2207                                                 /* We may want to add notifiers later,
2208                                                  * currently select update handles redraw. */
2209                                                 vc.obedit->actfmap = map;
2210                                         }
2211                                 }
2212                         }
2213
2214                 }
2215
2216                 /* Changing active object is handy since it allows us to
2217                  * switch UV layers, vgroups for eg. */
2218                 if (vc.view_layer->basact != basact) {
2219                         vc.view_layer->basact = basact;
2220                         DEG_id_tag_update(&vc.scene->id, DEG_TAG_SELECT_UPDATE);
2221                         WM_event_add_notifier(C, NC_SCENE | ND_OB_ACTIVE, vc.scene);
2222                 }
2223                 DEG_id_tag_update(vc.obedit->data, DEG_TAG_SELECT_UPDATE);
2224                 WM_event_add_notifier(C, NC_GEOM | ND_SELECT, vc.obedit->data);
2225
2226                 return true;
2227         }
2228
2229         return false;
2230 }
2231
2232 /** \} */
2233
2234 /* -------------------------------------------------------------------- */
2235 /** \name Select Mode Utilities
2236  * \{ */
2237
2238 static void edbm_strip_selections(BMEditMesh *em)
2239 {
2240         BMEditSelection *ese, *nextese;
2241
2242         if (!(em->selectmode & SCE_SELECT_VERTEX)) {
2243                 ese = em->bm->selected.first;
2244                 while (ese) {
2245                         nextese = ese->next;
2246                         if (ese->htype == BM_VERT) BLI_freelinkN(&(em->bm->selected), ese);
2247                         ese = nextese;
2248                 }
2249         }
2250         if (!(em->selectmode & SCE_SELECT_EDGE)) {
2251                 ese = em->bm->selected.first;
2252                 while (ese) {
2253                         nextese = ese->next;
2254                         if (ese->htype == BM_EDGE) BLI_freelinkN(&(em->bm->selected), ese);
2255                         ese = nextese;
2256                 }
2257         }
2258         if (!(em->selectmode & SCE_SELECT_FACE)) {
2259                 ese = em->bm->selected.first;
2260                 while (ese) {
2261                         nextese = ese->next;
2262                         if (ese->htype == BM_FACE) BLI_freelinkN(&(em->bm->selected), ese);
2263                         ese = nextese;
2264                 }
2265         }
2266 }
2267
2268 /* when switching select mode, makes sure selection is consistent for editing */
2269 /* also for paranoia checks to make sure edge or face mode works */
2270 void EDBM_selectmode_set(BMEditMesh *em)
2271 {
2272         BMVert *eve;
2273         BMEdge *eed;
2274         BMFace *efa;
2275         BMIter iter;
2276
2277         em->bm->selectmode = em->selectmode;
2278
2279         edbm_strip_selections(em); /* strip BMEditSelections from em->selected that are not relevant to new mode */
2280
2281         if (em->bm->totvertsel == 0 &&
2282             em->bm->totedgesel == 0 &&
2283             em->bm->totfacesel == 0)
2284         {
2285                 return;
2286         }
2287
2288         if (em->selectmode & SCE_SELECT_VERTEX) {
2289                 if (em->bm->totvertsel) {
2290                         EDBM_select_flush(em);
2291                 }
2292         }
2293         else if (em->selectmode & SCE_SELECT_EDGE) {
2294                 /* deselect vertices, and select again based on edge select */
2295                 BM_ITER_MESH (eve, &iter, em->bm, BM_VERTS_OF_MESH) {
2296                         BM_vert_select_set(em->bm, eve, false);
2297                 }
2298
2299                 if (em->bm->totedgesel) {
2300                         BM_ITER_MESH (eed, &iter, em->bm, BM_EDGES_OF_MESH) {
2301                                 if (BM_elem_flag_test(eed, BM_ELEM_SELECT)) {
2302                                         BM_edge_select_set(em->bm, eed, true);
2303                                 }
2304                         }
2305
2306                         /* selects faces based on edge status */
2307                         EDBM_selectmode_flush(em);
2308                 }
2309         }
2310         else if (em->selectmode & SCE_SELECT_FACE) {
2311                 /* deselect eges, and select again based on face select */
2312                 BM_ITER_MESH (eed, &iter, em->bm, BM_EDGES_OF_MESH) {
2313                         BM_edge_select_set(em->bm, eed, false);
2314                 }
2315
2316                 if (em->bm->totfacesel) {
2317                         BM_ITER_MESH (efa, &iter, em->bm, BM_FACES_OF_MESH) {
2318                                 if (BM_elem_flag_test(efa, BM_ELEM_SELECT)) {
2319                                         BM_face_select_set(em->bm, efa, true);
2320                                 }
2321                         }
2322                 }
2323         }
2324 }
2325
2326 /**
2327  * Expand & Contract the Selection
2328  * (used when changing modes and Ctrl key held)
2329  *
2330  * Flush the selection up:
2331  * - vert -> edge
2332  * - vert -> face
2333  * - edge -> face
2334  *
2335  * Flush the selection down:
2336  * - face -> edge
2337  * - face -> vert
2338  * - edge -> vert
2339  */
2340 void EDBM_selectmode_convert(BMEditMesh *em, const short selectmode_old, const short selectmode_new)
2341 {
2342         BMesh *bm = em->bm;
2343
2344         BMVert *eve;
2345         BMEdge *eed;
2346         BMFace *efa;
2347         BMIter iter;
2348
2349         /* first tag-to-select, then select --- this avoids a feedback loop */
2350
2351         /* have to find out what the selectionmode was previously */
2352         if (selectmode_old == SCE_SELECT_VERTEX) {
2353                 if (bm->totvertsel == 0) {
2354                         /* pass */
2355                 }
2356                 else if (selectmode_new == SCE_SELECT_EDGE) {
2357                         /* flush up (vert -> edge) */
2358
2359                         /* select all edges associated with every selected vert */
2360                         BM_ITER_MESH (eed, &iter, bm, BM_EDGES_OF_MESH) {
2361                                 BM_elem_flag_set(eed, BM_ELEM_TAG, BM_edge_is_any_vert_flag_test(eed, BM_ELEM_SELECT));
2362                         }
2363
2364                         BM_ITER_MESH (eed, &iter, bm, BM_EDGES_OF_MESH) {
2365                                 if (BM_elem_flag_test(eed, BM_ELEM_TAG)) {
2366                                         BM_edge_select_set(bm, eed, true);
2367                                 }
2368                         }
2369                 }
2370                 else if (selectmode_new == SCE_SELECT_FACE) {
2371                         /* flush up (vert -> face) */
2372
2373                         /* select all faces associated with every selected vert */
2374                         BM_ITER_MESH (efa, &iter, bm, BM_FACES_OF_MESH) {
2375                                 BM_elem_flag_set(efa, BM_ELEM_TAG, BM_face_is_any_vert_flag_test(efa, BM_ELEM_SELECT));
2376                         }
2377
2378                         BM_ITER_MESH (efa, &iter, bm, BM_FACES_OF_MESH) {
2379                                 if (BM_elem_flag_test(efa, BM_ELEM_TAG)) {
2380                                         BM_face_select_set(bm, efa, true);
2381                                 }
2382                         }
2383                 }
2384         }
2385         else if (selectmode_old == SCE_SELECT_EDGE) {
2386                 if (bm->totedgesel == 0) {
2387                         /* pass */
2388                 }
2389                 else if (selectmode_new == SCE_SELECT_FACE) {
2390                         /* flush up (edge -> face) */
2391
2392                         /* select all faces associated with every selected edge */
2393                         BM_ITER_MESH (efa, &iter, bm, BM_FACES_OF_MESH) {
2394                                 BM_elem_flag_set(efa, BM_ELEM_TAG, BM_face_is_any_edge_flag_test(efa, BM_ELEM_SELECT));
2395                         }
2396
2397                         BM_ITER_MESH (efa, &iter, bm, BM_FACES_OF_MESH) {
2398                                 if (BM_elem_flag_test(efa, BM_ELEM_TAG)) {
2399                                         BM_face_select_set(bm, efa, true);
2400                                 }
2401                         }
2402                 }
2403                 else if (selectmode_new == SCE_SELECT_VERTEX) {
2404                         /* flush down (edge -> vert) */
2405
2406                         BM_ITER_MESH (eve, &iter, bm, BM_VERTS_OF_MESH) {
2407                                 if (!BM_vert_is_all_edge_flag_test(eve, BM_ELEM_SELECT, true)) {
2408                                         BM_vert_select_set(bm, eve, false);
2409                                 }
2410                         }
2411                         /* deselect edges without both verts selected */
2412                         BM_mesh_deselect_flush(bm);
2413                 }
2414         }
2415         else if (selectmode_old == SCE_SELECT_FACE) {
2416                 if (bm->totfacesel == 0) {
2417                         /* pass */
2418                 }
2419                 else if (selectmode_new == SCE_SELECT_EDGE) {
2420                         /* flush down (face -> edge) */
2421
2422                         BM_ITER_MESH (eed, &iter, bm, BM_EDGES_OF_MESH) {
2423                                 if (!BM_edge_is_all_face_flag_test(eed, BM_ELEM_SELECT, true)) {
2424                                         BM_edge_select_set(bm, eed, false);
2425                                 }
2426                         }
2427                 }
2428                 else if (selectmode_new == SCE_SELECT_VERTEX) {
2429                         /* flush down (face -> vert) */
2430
2431                         BM_ITER_MESH (eve, &iter, bm, BM_VERTS_OF_MESH) {
2432                                 if (!BM_vert_is_all_face_flag_test(eve, BM_ELEM_SELECT, true)) {
2433                                         BM_vert_select_set(bm, eve, false);
2434                                 }
2435                         }
2436                         /* deselect faces without verts selected */
2437                         BM_mesh_deselect_flush(bm);
2438                 }
2439         }
2440 }
2441
2442 /* user facing function, does notification */
2443 bool EDBM_selectmode_toggle(
2444         bContext *C, const short selectmode_new,
2445         const int action, const bool use_extend, const bool use_expand)
2446 {
2447         Scene *scene = CTX_data_scene(C);
2448         ViewLayer *view_layer = CTX_data_view_layer(C);
2449         ToolSettings *ts = CTX_data_tool_settings(C);
2450         Object *obedit = CTX_data_edit_object(C);
2451         BMEditMesh *em = NULL;
2452         bool ret = false;
2453
2454         if (obedit && obedit->type == OB_MESH) {
2455                 em = BKE_editmesh_from_object(obedit);
2456         }
2457
2458         if (em == NULL) {
2459                 return ret;
2460         }
2461
2462         bool only_update = false;
2463         switch (action) {
2464                 case -1:
2465                         /* already set */
2466                         break;
2467                 case 0:  /* disable */
2468                         /* check we have something to do */
2469                         if ((em->selectmode & selectmode_new) == 0) {
2470                                 only_update = true;
2471                                 break;
2472                         }
2473                         em->selectmode &= ~selectmode_new;
2474                         break;
2475                 case 1:  /* enable */
2476                         /* check we have something to do */
2477                         if ((em->selectmode & selectmode_new) != 0) {
2478                                 only_update = true;
2479                                 break;
2480                         }
2481                         em->selectmode |= selectmode_new;
2482                         break;
2483                 case 2:  /* toggle */
2484                         /* can't disable this flag if its the only one set */
2485                         if (em->selectmode == selectmode_new) {
2486                                 only_update = true;
2487                                 break;
2488                         }
2489                         em->selectmode ^= selectmode_new;
2490                         break;
2491                 default:
2492                         BLI_assert(0);
2493                         break;
2494         }
2495
2496         uint objects_len = 0;
2497         Object **objects = BKE_view_layer_array_from_objects_in_edit_mode_unique_data(view_layer, &objects_len);
2498
2499         for (uint ob_index = 0; ob_index < objects_len; ob_index++) {
2500                 Object *ob_iter = objects[ob_index];
2501                 BMEditMesh *em_iter = BKE_editmesh_from_object(ob_iter);
2502                 if (em_iter != em) {
2503                         em_iter->selectmode = em->selectmode;
2504                 }
2505         }
2506
2507         if (only_update) {
2508                 MEM_freeN(objects);
2509                 return false;
2510         }
2511
2512         if (use_extend == 0 || em->selectmode == 0) {
2513                 if (use_expand) {
2514                         const short selmode_max = highest_order_bit_s(ts->selectmode);
2515                         for (uint ob_index = 0; ob_index < objects_len; ob_index++) {
2516                                 Object *ob_iter = objects[ob_index];
2517                                 BMEditMesh *em_iter = BKE_editmesh_from_object(ob_iter);
2518                                 EDBM_selectmode_convert(em_iter, selmode_max, selectmode_new);
2519                         }
2520                 }
2521         }
2522
2523         switch (selectmode_new) {
2524                 case SCE_SELECT_VERTEX:
2525                         if (use_extend == 0 || em->selectmode == 0) {
2526                                 em->selectmode = SCE_SELECT_VERTEX;
2527                         }
2528                         ret = true;
2529                         break;
2530                 case SCE_SELECT_EDGE:
2531                         if (use_extend == 0 || em->selectmode == 0) {
2532                                 em->selectmode = SCE_SELECT_EDGE;
2533                         }
2534                         ret = true;
2535                         break;
2536                 case SCE_SELECT_FACE:
2537                         if (use_extend == 0 || em->selectmode == 0) {
2538                                 em->selectmode = SCE_SELECT_FACE;
2539                         }
2540                         ret = true;
2541                         break;
2542                 default:
2543                         BLI_assert(0);
2544                         break;
2545         }
2546
2547         if (ret == true) {
2548                 ts->selectmode = em->selectmode;
2549                 em = NULL;
2550                 for (uint ob_index = 0; ob_index < objects_len; ob_index++) {
2551                         Object *ob_iter = objects[ob_index];
2552                         BMEditMesh *em_iter = BKE_editmesh_from_object(ob_iter);
2553                         EDBM_selectmode_set(em_iter);
2554                         DEG_id_tag_update(ob_iter->data, DEG_TAG_COPY_ON_WRITE | DEG_TAG_SELECT_UPDATE);
2555                         WM_event_add_notifier(C, NC_GEOM | ND_SELECT, ob_iter->data);
2556                 }
2557                 WM_main_add_notifier(NC_SCENE | ND_TOOLSETTINGS, NULL);
2558                 DEG_id_tag_update(&scene->id, DEG_TAG_COPY_ON_WRITE);
2559         }
2560
2561         MEM_freeN(objects);
2562         return ret;
2563 }
2564
2565 /**
2566  * Use to disable a selectmode if its enabled, Using another mode as a fallback
2567  * if the disabled mode is the only mode set.
2568  *
2569  * \return true if the mode is changed.
2570  */
2571 bool EDBM_selectmode_disable(
2572         Scene *scene, BMEditMesh *em,
2573         const short selectmode_disable,
2574         const short selectmode_fallback)
2575 {
2576         /* note essential, but switch out of vertex mode since the
2577          * selected regions wont be nicely isolated after flushing */
2578         if (em->selectmode & selectmode_disable) {
2579                 if (em->selectmode == selectmode_disable) {
2580                         em->selectmode = selectmode_fallback;
2581                 }
2582                 else {
2583                         em->selectmode &= ~selectmode_disable;
2584                 }
2585                 scene->toolsettings->selectmode = em->selectmode;
2586                 EDBM_selectmode_set(em);
2587
2588                 WM_main_add_notifier(NC_SCENE | ND_TOOLSETTINGS, scene);
2589
2590                 return true;
2591         }
2592         else {
2593                 return false;
2594         }
2595 }
2596
2597 /** \} */
2598
2599 /* -------------------------------------------------------------------- */
2600 /** \name Select Toggle
2601  * \{ */
2602
2603 void EDBM_deselect_by_material(BMEditMesh *em, const short index, const bool select)
2604 {
2605         BMIter iter;
2606         BMFace *efa;
2607
2608         BM_ITER_MESH (efa, &iter, em->bm, BM_FACES_OF_MESH) {
2609                 if (BM_elem_flag_test(efa, BM_ELEM_HIDDEN))
2610                         continue;
2611                 if (efa->mat_nr == index) {
2612                         BM_face_select_set(em->bm, efa, select);
2613                 }
2614         }
2615 }
2616
2617 void EDBM_select_toggle_all(BMEditMesh *em) /* exported for UV */
2618 {
2619         if (em->bm->totvertsel || em->bm->totedgesel || em->bm->totfacesel)
2620                 EDBM_flag_disable_all(em, BM_ELEM_SELECT);
2621         else
2622                 EDBM_flag_enable_all(em, BM_ELEM_SELECT);
2623 }
2624
2625 void EDBM_select_swap(BMEditMesh *em) /* exported for UV */
2626 {
2627         BMIter iter;
2628         BMVert *eve;
2629         BMEdge *eed;
2630         BMFace *efa;
2631
2632         if (em->bm->selectmode & SCE_SELECT_VERTEX) {
2633                 BM_ITER_MESH (eve, &iter, em->bm, BM_VERTS_OF_MESH) {
2634                         if (BM_elem_flag_test(eve, BM_ELEM_HIDDEN))
2635                                 continue;
2636                         BM_vert_select_set(em->bm, eve, !BM_elem_flag_test(eve, BM_ELEM_SELECT));
2637                 }
2638         }
2639         else if (em->selectmode & SCE_SELECT_EDGE) {
2640                 BM_ITER_MESH (eed, &iter, em->bm, BM_EDGES_OF_MESH) {
2641                         if (BM_elem_flag_test(eed, BM_ELEM_HIDDEN))
2642                                 continue;
2643                         BM_edge_select_set(em->bm, eed, !BM_elem_flag_test(eed, BM_ELEM_SELECT));
2644                 }
2645         }
2646         else {
2647                 BM_ITER_MESH (efa, &iter, em->bm, BM_FACES_OF_MESH) {
2648                         if (BM_elem_flag_test(efa, BM_ELEM_HIDDEN))
2649                                 continue;
2650                         BM_face_select_set(em->bm, efa, !BM_elem_flag_test(efa, BM_ELEM_SELECT));
2651                 }
2652
2653         }
2654 }
2655
2656 /** \} */
2657
2658 /* -------------------------------------------------------------------- */
2659 /** \name Select Interior Faces
2660  *
2661  * \note This algorithm is limited to single faces and could be improved, see:
2662  * https://blender.stackexchange.com/questions/18916
2663  * \{ */
2664
2665 bool EDBM_select_interior_faces(BMEditMesh *em)
2666 {
2667         BMesh *bm = em->bm;
2668         BMIter iter;
2669         BMIter eiter;
2670         BMFace *efa;
2671         BMEdge *eed;
2672         bool ok;
2673         bool changed = false;
2674
2675         BM_ITER_MESH (efa, &iter, em->bm, BM_FACES_OF_MESH) {
2676                 if (BM_elem_flag_test(efa, BM_ELEM_HIDDEN))
2677                         continue;
2678
2679
2680                 ok = true;
2681                 BM_ITER_ELEM (eed, &eiter, efa, BM_EDGES_OF_FACE) {
2682                         if (!BM_edge_face_count_is_over(eed, 2)) {
2683                                 ok = false;
2684                                 break;
2685                         }
2686                 }
2687
2688                 if (ok) {
2689                         BM_face_select_set(bm, efa, true);
2690                         changed = true;
2691                 }
2692         }
2693
2694         return changed;
2695 }
2696
2697 /** \} */
2698
2699 /* -------------------------------------------------------------------- */
2700 /** \name Select Linked Operator
2701  *
2702  * Support delimiting on different edge properties.
2703  * \{ */
2704
2705 /* so we can have last-used default depend on selection mode (rare exception!) */
2706 #define USE_LINKED_SELECT_DEFAULT_HACK
2707
2708 struct DelimitData {
2709         int cd_loop_type;
2710         int cd_loop_offset;
2711 };
2712
2713 static bool select_linked_delimit_test(
2714         BMEdge *e, int delimit,
2715         const struct DelimitData *delimit_data)
2716 {
2717         BLI_assert(delimit);
2718
2719         if (delimit & BMO_DELIM_SEAM) {
2720                 if (BM_elem_flag_test(e, BM_ELEM_SEAM)) {
2721                         return true;
2722                 }
2723         }
2724
2725         if (delimit & BMO_DELIM_SHARP) {
2726                 if (BM_elem_flag_test(e, BM_ELEM_SMOOTH) == 0) {
2727                         return true;
2728                 }
2729         }
2730
2731         if (delimit & BMO_DELIM_NORMAL) {
2732                 if (!BM_edge_is_contiguous(e)) {
2733                         return true;
2734                 }
2735         }
2736
2737         if (delimit & BMO_DELIM_MATERIAL) {
2738                 if (e->l && e->l->radial_next != e->l) {
2739                         const short mat_nr = e->l->f->mat_nr;
2740                         BMLoop *l_iter = e->l->radial_next;
2741                         do {
2742                                 if (l_iter->f->mat_nr != mat_nr) {
2743                                         return true;
2744                                 }
2745                         } while ((l_iter = l_iter->radial_next) != e->l);
2746                 }
2747         }
2748
2749         if (delimit & BMO_DELIM_UV) {
2750                 if (BM_edge_is_contiguous_loop_cd(e, delimit_data->cd_loop_type, delimit_data->cd_loop_offset) == 0) {
2751                         return true;
2752                 }
2753         }
2754
2755         return false;
2756 }
2757
2758 #ifdef USE_LINKED_SELECT_DEFAULT_HACK
2759 /**
2760  * Gets the default from the operator fallback to own last-used value
2761  * (selected based on mode)
2762  */
2763 static int select_linked_delimit_default_from_op(wmOperator *op, const int select_mode)
2764 {
2765         static char delimit_last_store[2] = {0, BMO_DELIM_SEAM};
2766         int delimit_last_index = (select_mode & (SCE_SELECT_VERTEX | SCE_SELECT_EDGE)) == 0;
2767         char *delimit_last = &delimit_last_store[delimit_last_index];
2768         PropertyRNA *prop_delimit = RNA_struct_find_property(op->ptr, "delimit");
2769         int delimit;
2770
2771         if (RNA_property_is_set(op->ptr, prop_delimit)) {
2772                 delimit = RNA_property_enum_get(op->ptr, prop_delimit);
2773                 *delimit_last = delimit;
2774         }
2775         else {
2776                 delimit = *delimit_last;
2777                 RNA_property_enum_set(op->ptr, prop_delimit, delimit);
2778         }
2779         return delimit;
2780 }
2781 #endif
2782
2783 static void select_linked_delimit_validate(BMesh *bm, int *delimit)
2784 {
2785         if ((*delimit) & BMO_DELIM_UV) {
2786                 if (!CustomData_has_layer(&bm->ldata, CD_MLOOPUV)) {
2787                         (*delimit) &= ~BMO_DELIM_UV;
2788                 }
2789         }
2790 }
2791
2792 static void select_linked_delimit_begin(BMesh *bm, int delimit)
2793 {
2794         struct DelimitData delimit_data = {0};
2795
2796         if (delimit & BMO_DELIM_UV) {
2797                 delimit_data.cd_loop_type = CD_MLOOPUV;
2798                 delimit_data.cd_loop_offset = CustomData_get_offset(&bm->ldata, delimit_data.cd_loop_type);
2799                 if (delimit_data.cd_loop_offset == -1) {
2800                         delimit &= ~BMO_DELIM_UV;
2801                 }
2802         }
2803
2804         /* grr, shouldn't need to alloc BMO flags here */
2805         BM_mesh_elem_toolflags_ensure(bm);
2806
2807         {
2808                 BMIter iter;
2809                 BMEdge *e;
2810
2811                 BM_ITER_MESH (e, &iter, bm, BM_EDGES_OF_MESH) {
2812                         const bool is_walk_ok = (
2813                                 (select_linked_delimit_test(e, delimit, &delimit_data) == false));
2814
2815                         BMO_edge_flag_set(bm, e, BMO_ELE_TAG, is_walk_ok);
2816                 }
2817         }
2818 }
2819
2820 static void select_linked_delimit_end(BMEditMesh *em)
2821 {
2822         BMesh *bm = em->bm;
2823
2824         BM_mesh_elem_toolflags_clear(bm);
2825 }
2826
2827 static int edbm_select_linked_exec(bContext *C, wmOperator *op)
2828 {
2829         Scene *scene = CTX_data_scene(C);
2830         ViewLayer *view_layer = CTX_data_view_layer(C);
2831
2832 #ifdef USE_LINKED_SELECT_DEFAULT_HACK
2833         const int delimit_init = select_linked_delimit_default_from_op(op, scene->toolsettings->selectmode);
2834 #else
2835         const int delimit_init = RNA_enum_get(op->ptr, "delimit");
2836 #endif
2837
2838         uint objects_len = 0;
2839         Object **objects = BKE_view_layer_array_from_objects_in_edit_mode_unique_data(view_layer, &objects_len);
2840
2841         for (uint ob_index = 0; ob_index < objects_len; ob_index++) {
2842                 Object *obedit = objects[ob_index];
2843
2844                 BMEditMesh *em = BKE_editmesh_from_object(obedit);
2845                 BMesh *bm = em->bm;
2846                 BMIter iter;
2847                 BMWalker walker;
2848
2849                 int delimit = delimit_init;
2850
2851                 select_linked_delimit_validate(bm, &delimit);
2852
2853                 if (delimit) {
2854                         select_linked_delimit_begin(em->bm, delimit);
2855                 }
2856
2857                 if (em->selectmode & SCE_SELECT_VERTEX) {
2858                         BMVert *v;
2859
2860                         BM_ITER_MESH (v, &iter, em->bm, BM_VERTS_OF_MESH) {
2861                                 BM_elem_flag_set(v, BM_ELEM_TAG, BM_elem_flag_test(v, BM_ELEM_SELECT));
2862                         }
2863
2864                         /* exclude all delimited verts */
2865                         if (delimit) {
2866                                 BMEdge *e;
2867                                 BM_ITER_MESH (e, &iter, em->bm, BM_EDGES_OF_MESH) {
2868                                         if (!BMO_edge_flag_test(bm, e, BMO_ELE_TAG)) {
2869                                                 BM_elem_flag_disable(e->v1, BM_ELEM_TAG);
2870                                                 BM_elem_flag_disable(e->v2, BM_ELEM_TAG);
2871                                         }
2872                                 }
2873                         }
2874
2875                         BMW_init(&walker, em->bm, delimit ? BMW_LOOP_SHELL_WIRE : BMW_VERT_SHELL,
2876                                  BMW_MASK_NOP, delimit ? BMO_ELE_TAG : BMW_MASK_NOP, BMW_MASK_NOP,
2877                                  BMW_FLAG_TEST_HIDDEN,
2878                                  BMW_NIL_LAY);
2879
2880                         if (delimit) {
2881                                 BM_ITER_MESH (v, &iter, em->bm, BM_VERTS_OF_MESH) {
2882                                         if (BM_elem_flag_test(v, BM_ELEM_TAG)) {
2883                                                 BMElem *ele_walk;
2884                                                 BMW_ITER (ele_walk, &walker, v) {
2885                                                         if (ele_walk->head.htype == BM_LOOP) {
2886                                                                 BMVert *v_step = ((BMLoop *)ele_walk)->v;
2887                                                                 BM_vert_select_set(em->bm, v_step, true);
2888                                                                 BM_elem_flag_disable(v_step, BM_ELEM_TAG);
2889                                                         }
2890                                                         else {
2891                                                                 BMEdge *e_step = (BMEdge *)ele_walk;
2892                                                                 BLI_assert(ele_walk->head.htype == BM_EDGE);
2893                                                                 BM_edge_select_set(em->bm, e_step, true);
2894                                                                 BM_elem_flag_disable(e_step->v1, BM_ELEM_TAG);
2895                                                                 BM_elem_flag_disable(e_step->v2, BM_ELEM_TAG);
2896                                                         }
2897                                                 }
2898                                         }
2899                                 }
2900                         }
2901                         else {
2902                                 BM_ITER_MESH (v, &iter, em->bm, BM_VERTS_OF_MESH) {
2903                                         if (BM_elem_flag_test(v, BM_ELEM_TAG)) {
2904                                                 BMEdge *e_walk;
2905                                                 BMW_ITER (e_walk, &walker, v) {
2906                                                         BM_edge_select_set(em->bm, e_walk, true);
2907                                                         BM_elem_flag_disable(e_walk, BM_ELEM_TAG);
2908                                                 }
2909                                         }
2910                                 }
2911                         }
2912
2913                         BMW_end(&walker);
2914
2915                         EDBM_selectmode_flush(em);
2916                 }
2917                 else if (em->selectmode & SCE_SELECT_EDGE) {
2918                         BMEdge *e;
2919
2920                         if (delimit) {
2921                                 BM_ITER_MESH (e, &iter, em->bm, BM_EDGES_OF_MESH) {
2922                                         BM_elem_flag_set(
2923                                                 e, BM_ELEM_TAG,
2924                                                 (BM_elem_flag_test(e, BM_ELEM_SELECT) && BMO_edge_flag_test(bm, e, BMO_ELE_TAG)));
2925                                 }
2926                         }
2927                         else {
2928                                 BM_ITER_MESH (e, &iter, em->bm, BM_EDGES_OF_MESH) {
2929                                         BM_elem_flag_set(e, BM_ELEM_TAG, BM_elem_flag_test(e, BM_ELEM_SELECT));
2930                                 }
2931                         }
2932
2933                         BMW_init(&walker, em->bm, delimit ? BMW_LOOP_SHELL_WIRE : BMW_VERT_SHELL,
2934                                  BMW_MASK_NOP, delimit ? BMO_ELE_TAG : BMW_MASK_NOP, BMW_MASK_NOP,
2935                                  BMW_FLAG_TEST_HIDDEN,
2936                                  BMW_NIL_LAY);
2937
2938                         if (delimit) {
2939                                 BM_ITER_MESH (e, &iter, em->bm, BM_EDGES_OF_MESH) {
2940                                         if (BM_elem_flag_test(e, BM_ELEM_TAG)) {
2941                                                 BMElem *ele_walk;
2942                                                 BMW_ITER (ele_walk, &walker, e) {
2943                                                         if (ele_walk->head.htype == BM_LOOP) {
2944                                                                 BMLoop *l_step = (BMLoop *)ele_walk;
2945                                                                 BM_edge_select_set(em->bm, l_step->e, true);
2946                                                                 BM_edge_select_set(em->bm, l_step->prev->e, true);
2947                                                                 BM_elem_flag_disable(l_step->e, BM_ELEM_TAG);
2948                                                         }
2949                                                         else {
2950                                                                 BMEdge *e_step = (BMEdge *)ele_walk;
2951                                                                 BLI_assert(ele_walk->head.htype == BM_EDGE);
2952                                                                 BM_edge_select_set(em->bm, e_step, true);
2953                                                                 BM_elem_flag_disable(e_step, BM_ELEM_TAG);
2954                                                         }
2955                                                 }
2956                                         }
2957                                 }
2958                         }
2959                         else {
2960                                 BM_ITER_MESH (e, &iter, em->bm, BM_EDGES_OF_MESH) {
2961                                         if (BM_elem_flag_test(e, BM_ELEM_TAG)) {
2962                                                 BMEdge *e_walk;
2963                                                 BMW_ITER (e_walk, &walker, e) {
2964                                                         BM_edge_select_set(em->bm, e_walk, true);
2965                                                         BM_elem_flag_disable(e_walk, BM_ELEM_TAG);
2966                                                 }
2967                                         }
2968                                 }
2969                         }
2970
2971                         BMW_end(&walker);
2972
2973                         EDBM_selectmode_flush(em);
2974                 }
2975                 else {
2976                         BMFace *f;
2977
2978                         BM_ITER_MESH (f, &iter, em->bm, BM_FACES_OF_MESH) {
2979                                 BM_elem_flag_set(f, BM_ELEM_TAG, BM_elem_flag_test(f, BM_ELEM_SELECT));
2980                         }
2981
2982                         BMW_init(&walker, bm, BMW_ISLAND,
2983                                  BMW_MASK_NOP, delimit ? BMO_ELE_TAG : BMW_MASK_NOP, BMW_MASK_NOP,
2984                                  BMW_FLAG_TEST_HIDDEN,
2985                                  BMW_NIL_LAY);
2986
2987                         BM_ITER_MESH (f, &iter, em->bm, BM_FACES_OF_MESH) {
2988                                 if (BM_elem_flag_test(f, BM_ELEM_TAG)) {
2989                                         BMFace *f_walk;
2990                                         BMW_ITER (f_walk, &walker, f) {
2991                                                 BM_face_select_set(bm, f_walk, true);
2992                                                 BM_elem_flag_disable(f_walk, BM_ELEM_TAG);
2993                                         }
2994                                 }
2995                         }
2996
2997                         BMW_end(&walker);
2998                 }
2999
3000                 if (delimit) {
3001                         select_linked_delimit_end(em);
3002                 }
3003
3004                 DEG_id_tag_update(obedit->data, DEG_TAG_SELECT_UPDATE);
3005                 WM_event_add_notifier(C, NC_GEOM | ND_SELECT, obedit->data);
3006
3007         }
3008
3009         MEM_freeN(objects);
3010
3011         return OPERATOR_FINISHED;
3012 }
3013
3014 void MESH_OT_select_linked(wmOperatorType *ot)
3015 {
3016         PropertyRNA *prop;
3017
3018         /* identifiers */
3019         ot->name = "Select Linked All";
3020         ot->idname = "MESH_OT_select_linked";
3021         ot->description = "Select all vertices connected to the current selection";
3022
3023         /* api callbacks */
3024         ot->exec = edbm_select_linked_exec;
3025         ot->poll = ED_operator_editmesh;
3026
3027         /* flags */
3028         ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
3029
3030         prop = RNA_def_enum_flag(ot->srna, "delimit", rna_enum_mesh_delimit_mode_items, BMO_DELIM_SEAM, "Delimit",
3031                                  "Delimit selected region");
3032 #ifdef USE_LINKED_SELECT_DEFAULT_HACK
3033         RNA_def_property_flag(prop, PROP_SKIP_SAVE);
3034 #else
3035         UNUSED_VARS(prop);
3036 #endif
3037 }
3038
3039 /** \} */
3040
3041 /* -------------------------------------------------------------------- */
3042 /** \name Select Linked (Cursor Pick) Operator
3043  * \{ */
3044
3045 static int edbm_select_linked_pick_exec(bContext *C, wmOperator *op);
3046
3047 static void edbm_select_linked_pick_ex(BMEditMesh *em, BMElem *ele, bool sel, int delimit)
3048 {
3049         BMesh *bm = em->bm;
3050         BMWalker walker;
3051
3052         select_linked_delimit_validate(bm, &delimit);
3053
3054         if (delimit) {
3055                 select_linked_delimit_begin(bm, delimit);
3056         }
3057
3058         /* Note: logic closely matches 'edbm_select_linked_exec', keep in sync */
3059
3060         if (ele->head.htype == BM_VERT) {
3061                 BMVert *eve = (BMVert *)ele;
3062
3063                 BMW_init(&walker, bm, delimit ? BMW_LOOP_SHELL_WIRE : BMW_VERT_SHELL,
3064                          BMW_MASK_NOP, delimit ? BMO_ELE_TAG : BMW_MASK_NOP, BMW_MASK_NOP,
3065                          BMW_FLAG_TEST_HIDDEN,
3066                          BMW_NIL_LAY);
3067
3068                 if (delimit) {
3069                         BMElem *ele_walk;
3070                         BMW_ITER (ele_walk, &walker, eve) {
3071                                 if (ele_walk->head.htype == BM_LOOP) {
3072                                         BMVert *v_step = ((BMLoop *)ele_walk)->v;
3073                                         BM_vert_select_set(bm, v_step, sel);
3074                                 }
3075                                 else {
3076                                         BMEdge *e_step = (BMEdge *)ele_walk;
3077                                         BLI_assert(ele_walk->head.htype == BM_EDGE);
3078                                         BM_edge_select_set(bm, e_step, sel);
3079                                 }
3080                         }
3081                 }
3082                 else {
3083                         BMEdge *e_walk;
3084                         BMW_ITER (e_walk, &walker, eve) {
3085                                 BM_edge_select_set(bm, e_walk, sel);
3086                         }
3087                 }
3088
3089                 BMW_end(&walker);
3090
3091                 EDBM_selectmode_flush(em);
3092         }
3093         else if (ele->head.htype == BM_EDGE) {
3094                 BMEdge *eed = (BMEdge *)ele;
3095
3096                 BMW_init(&walker, bm, delimit ? BMW_LOOP_SHELL_WIRE : BMW_VERT_SHELL,
3097                          BMW_MASK_NOP, delimit ? BMO_ELE_TAG : BMW_MASK_NOP, BMW_MASK_NOP,
3098                          BMW_FLAG_TEST_HIDDEN,
3099                          BMW_NIL_LAY);
3100
3101                 if (delimit) {
3102                         BMElem *ele_walk;
3103                         BMW_ITER (ele_walk, &walker, eed) {
3104                                 if (ele_walk->head.htype == BM_LOOP) {
3105                                         BMEdge *e_step = ((BMLoop *)ele_walk)->e;
3106                                         BM_edge_select_set(bm, e_step, sel);
3107                                 }
3108                                 else {
3109                                         BMEdge *e_step = (BMEdge *)ele_walk;
3110                                         BLI_assert(ele_walk->head.htype == BM_EDGE);
3111                                         BM_edge_select_set(bm, e_step, sel);
3112                                 }
3113                         }
3114                 }
3115                 else {
3116                         BMEdge *e_walk;
3117                         BMW_ITER (e_walk, &walker, eed) {
3118                                 BM_edge_select_set(bm, e_walk, sel);
3119                         }
3120                 }
3121
3122                 BMW_end(&walker);
3123
3124                 EDBM_selectmode_flush(em);
3125         }
3126         else if (ele->head.htype == BM_FACE) {
3127                 BMFace *efa = (BMFace *)ele;
3128
3129                 BMW_init(&walker, bm, BMW_ISLAND,
3130                          BMW_MASK_NOP, delimit ? BMO_ELE_TAG : BMW_MASK_NOP, BMW_MASK_NOP,
3131                          BMW_FLAG_TEST_HIDDEN,
3132                          BMW_NIL_LAY);
3133
3134                 {
3135                         BMFace *f_walk;
3136                         BMW_ITER (f_walk, &walker, efa) {
3137                                 BM_face_select_set(bm, f_walk, sel);
3138                                 BM_elem_flag_disable(f_walk, BM_ELEM_TAG);
3139                         }
3140                 }
3141
3142                 BMW_end(&walker);
3143         }
3144
3145         if (delimit) {
3146                 select_linked_delimit_end(em);
3147         }
3148 }
3149
3150 static int edbm_select_linked_pick_invoke(bContext *C, wmOperator *op, const wmEvent *event)
3151 {
3152         ViewContext vc;
3153