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