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