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