Revert "UI: use correct singular and plural nouns in report messages"
[blender.git] / source / blender / editors / mesh / editmesh_tools.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 by Blender Foundation.
17  * All rights reserved.
18  */
19
20 /** \file
21  * \ingroup edmesh
22  */
23
24 #include <stddef.h>
25
26 #include "MEM_guardedalloc.h"
27
28 #include "DNA_key_types.h"
29 #include "DNA_material_types.h"
30 #include "DNA_mesh_types.h"
31 #include "DNA_meshdata_types.h"
32 #include "DNA_modifier_types.h"
33 #include "DNA_object_types.h"
34 #include "DNA_scene_types.h"
35
36 #include "BLI_bitmap.h"
37 #include "BLI_heap_simple.h"
38 #include "BLI_listbase.h"
39 #include "BLI_linklist.h"
40 #include "BLI_linklist_stack.h"
41 #include "BLI_math.h"
42 #include "BLI_rand.h"
43 #include "BLI_sort_utils.h"
44 #include "BLI_string.h"
45
46 #include "BKE_editmesh.h"
47 #include "BKE_context.h"
48 #include "BKE_deform.h"
49 #include "BKE_key.h"
50 #include "BKE_layer.h"
51 #include "BKE_library.h"
52 #include "BKE_main.h"
53 #include "BKE_material.h"
54 #include "BKE_mesh.h"
55 #include "BKE_report.h"
56 #include "BKE_texture.h"
57
58 #include "DEG_depsgraph.h"
59 #include "DEG_depsgraph_build.h"
60
61 #include "BLT_translation.h"
62
63 #include "RNA_define.h"
64 #include "RNA_access.h"
65 #include "RNA_enum_types.h"
66
67 #include "WM_api.h"
68 #include "WM_types.h"
69
70 #include "ED_mesh.h"
71 #include "ED_object.h"
72 #include "ED_screen.h"
73 #include "ED_transform.h"
74 #include "ED_transform_snap_object_context.h"
75 #include "ED_uvedit.h"
76 #include "ED_view3d.h"
77
78 #include "RE_render_ext.h"
79
80 #include "UI_interface.h"
81 #include "UI_resources.h"
82
83 #include "mesh_intern.h" /* own include */
84
85 #include "bmesh_tools.h"
86
87 #define USE_FACE_CREATE_SEL_EXTEND
88
89 /* -------------------------------------------------------------------- */
90 /** \name Subdivide Operator
91  * \{ */
92
93 static int edbm_subdivide_exec(bContext *C, wmOperator *op)
94 {
95   const int cuts = RNA_int_get(op->ptr, "number_cuts");
96   const float smooth = RNA_float_get(op->ptr, "smoothness");
97   const float fractal = RNA_float_get(op->ptr, "fractal") / 2.5f;
98   const float along_normal = RNA_float_get(op->ptr, "fractal_along_normal");
99
100   if (RNA_boolean_get(op->ptr, "ngon") &&
101       RNA_enum_get(op->ptr, "quadcorner") == SUBD_CORNER_STRAIGHT_CUT) {
102     RNA_enum_set(op->ptr, "quadcorner", SUBD_CORNER_INNERVERT);
103   }
104   const int quad_corner_type = RNA_enum_get(op->ptr, "quadcorner");
105   const bool use_quad_tri = !RNA_boolean_get(op->ptr, "ngon");
106   const int seed = RNA_int_get(op->ptr, "seed");
107
108   ViewLayer *view_layer = CTX_data_view_layer(C);
109   uint objects_len = 0;
110   Object **objects = BKE_view_layer_array_from_objects_in_edit_mode_unique_data(
111       view_layer, CTX_wm_view3d(C), &objects_len);
112
113   for (uint ob_index = 0; ob_index < objects_len; ob_index++) {
114     Object *obedit = objects[ob_index];
115     BMEditMesh *em = BKE_editmesh_from_object(obedit);
116
117     if (!(em->bm->totedgesel || em->bm->totfacesel)) {
118       continue;
119     }
120
121     BM_mesh_esubdivide(em->bm,
122                        BM_ELEM_SELECT,
123                        smooth,
124                        SUBD_FALLOFF_LIN,
125                        false,
126                        fractal,
127                        along_normal,
128                        cuts,
129                        SUBDIV_SELECT_ORIG,
130                        quad_corner_type,
131                        use_quad_tri,
132                        true,
133                        false,
134                        seed);
135
136     EDBM_update_generic(em, true, true);
137   }
138
139   MEM_freeN(objects);
140
141   return OPERATOR_FINISHED;
142 }
143
144 /* Note, these values must match delete_mesh() event values */
145 static const EnumPropertyItem prop_mesh_cornervert_types[] = {
146     {SUBD_CORNER_INNERVERT, "INNERVERT", 0, "Inner Vert", ""},
147     {SUBD_CORNER_PATH, "PATH", 0, "Path", ""},
148     {SUBD_CORNER_STRAIGHT_CUT, "STRAIGHT_CUT", 0, "Straight Cut", ""},
149     {SUBD_CORNER_FAN, "FAN", 0, "Fan", ""},
150     {0, NULL, 0, NULL, NULL},
151 };
152
153 void MESH_OT_subdivide(wmOperatorType *ot)
154 {
155   PropertyRNA *prop;
156
157   /* identifiers */
158   ot->name = "Subdivide";
159   ot->description = "Subdivide selected edges";
160   ot->idname = "MESH_OT_subdivide";
161
162   /* api callbacks */
163   ot->exec = edbm_subdivide_exec;
164   ot->poll = ED_operator_editmesh;
165
166   /* flags */
167   ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
168
169   /* properties */
170   prop = RNA_def_int(ot->srna, "number_cuts", 1, 1, 100, "Number of Cuts", "", 1, 10);
171   /* avoid re-using last var because it can cause
172    * _very_ high poly meshes and annoy users (or worse crash) */
173   RNA_def_property_flag(prop, PROP_SKIP_SAVE);
174
175   RNA_def_float(
176       ot->srna, "smoothness", 0.0f, 0.0f, 1e3f, "Smoothness", "Smoothness factor", 0.0f, 1.0f);
177
178   WM_operatortype_props_advanced_begin(ot);
179
180   RNA_def_boolean(ot->srna,
181                   "ngon",
182                   true,
183                   "Create N-Gons",
184                   "When disabled, newly created faces are limited to 3-4 sided faces");
185   RNA_def_enum(
186       ot->srna,
187       "quadcorner",
188       prop_mesh_cornervert_types,
189       SUBD_CORNER_STRAIGHT_CUT,
190       "Quad Corner Type",
191       "How to subdivide quad corners (anything other than Straight Cut will prevent ngons)");
192
193   RNA_def_float(ot->srna,
194                 "fractal",
195                 0.0f,
196                 0.0f,
197                 1e6f,
198                 "Fractal",
199                 "Fractal randomness factor",
200                 0.0f,
201                 1000.0f);
202   RNA_def_float(ot->srna,
203                 "fractal_along_normal",
204                 0.0f,
205                 0.0f,
206                 1.0f,
207                 "Along Normal",
208                 "Apply fractal displacement along normal only",
209                 0.0f,
210                 1.0f);
211   RNA_def_int(ot->srna,
212               "seed",
213               0,
214               0,
215               INT_MAX,
216               "Random Seed",
217               "Seed for the random number generator",
218               0,
219               255);
220 }
221
222 /** \} */
223
224 /* -------------------------------------------------------------------- */
225 /** \name Edge Ring Subdivide Operator
226  *
227  * Bridge code shares props.
228  *
229  * \{ */
230
231 struct EdgeRingOpSubdProps {
232   int interp_mode;
233   int cuts;
234   float smooth;
235
236   int profile_shape;
237   float profile_shape_factor;
238 };
239
240 static void mesh_operator_edgering_props(wmOperatorType *ot,
241                                          const int cuts_min,
242                                          const int cuts_default)
243 {
244   /* Note, these values must match delete_mesh() event values */
245   static const EnumPropertyItem prop_subd_edgering_types[] = {
246       {SUBD_RING_INTERP_LINEAR, "LINEAR", 0, "Linear", ""},
247       {SUBD_RING_INTERP_PATH, "PATH", 0, "Blend Path", ""},
248       {SUBD_RING_INTERP_SURF, "SURFACE", 0, "Blend Surface", ""},
249       {0, NULL, 0, NULL, NULL},
250   };
251
252   PropertyRNA *prop;
253
254   prop = RNA_def_int(
255       ot->srna, "number_cuts", cuts_default, 0, 1000, "Number of Cuts", "", cuts_min, 64);
256   RNA_def_property_flag(prop, PROP_SKIP_SAVE);
257
258   RNA_def_enum(ot->srna,
259                "interpolation",
260                prop_subd_edgering_types,
261                SUBD_RING_INTERP_PATH,
262                "Interpolation",
263                "Interpolation method");
264
265   RNA_def_float(
266       ot->srna, "smoothness", 1.0f, 0.0f, 1e3f, "Smoothness", "Smoothness factor", 0.0f, 2.0f);
267
268   /* profile-shape */
269   RNA_def_float(ot->srna,
270                 "profile_shape_factor",
271                 0.0f,
272                 -1e3f,
273                 1e3f,
274                 "Profile Factor",
275                 "How much intermediary new edges are shrunk/expanded",
276                 -2.0f,
277                 2.0f);
278
279   prop = RNA_def_property(ot->srna, "profile_shape", PROP_ENUM, PROP_NONE);
280   RNA_def_property_enum_items(prop, rna_enum_proportional_falloff_curve_only_items);
281   RNA_def_property_enum_default(prop, PROP_SMOOTH);
282   RNA_def_property_ui_text(prop, "Profile Shape", "Shape of the profile");
283   RNA_def_property_translation_context(prop, BLT_I18NCONTEXT_ID_CURVE); /* Abusing id_curve :/ */
284 }
285
286 static void mesh_operator_edgering_props_get(wmOperator *op, struct EdgeRingOpSubdProps *op_props)
287 {
288   op_props->interp_mode = RNA_enum_get(op->ptr, "interpolation");
289   op_props->cuts = RNA_int_get(op->ptr, "number_cuts");
290   op_props->smooth = RNA_float_get(op->ptr, "smoothness");
291
292   op_props->profile_shape = RNA_enum_get(op->ptr, "profile_shape");
293   op_props->profile_shape_factor = RNA_float_get(op->ptr, "profile_shape_factor");
294 }
295
296 static int edbm_subdivide_edge_ring_exec(bContext *C, wmOperator *op)
297 {
298
299   ViewLayer *view_layer = CTX_data_view_layer(C);
300   uint objects_len = 0;
301   Object **objects = BKE_view_layer_array_from_objects_in_edit_mode_unique_data(
302       view_layer, CTX_wm_view3d(C), &objects_len);
303   struct EdgeRingOpSubdProps op_props;
304
305   mesh_operator_edgering_props_get(op, &op_props);
306
307   for (uint ob_index = 0; ob_index < objects_len; ob_index++) {
308     Object *obedit = objects[ob_index];
309     BMEditMesh *em = BKE_editmesh_from_object(obedit);
310
311     if (em->bm->totedgesel == 0) {
312       continue;
313     }
314
315     if (!EDBM_op_callf(em,
316                        op,
317                        "subdivide_edgering edges=%he interp_mode=%i cuts=%i smooth=%f "
318                        "profile_shape=%i profile_shape_factor=%f",
319                        BM_ELEM_SELECT,
320                        op_props.interp_mode,
321                        op_props.cuts,
322                        op_props.smooth,
323                        op_props.profile_shape,
324                        op_props.profile_shape_factor)) {
325       continue;
326     }
327
328     EDBM_update_generic(em, true, true);
329   }
330
331   MEM_freeN(objects);
332   return OPERATOR_FINISHED;
333 }
334
335 void MESH_OT_subdivide_edgering(wmOperatorType *ot)
336 {
337   /* identifiers */
338   ot->name = "Subdivide Edge-Ring";
339   ot->description = "Subdivide perpendicular edges to the selected edge ring";
340   ot->idname = "MESH_OT_subdivide_edgering";
341
342   /* api callbacks */
343   ot->exec = edbm_subdivide_edge_ring_exec;
344   ot->poll = ED_operator_editmesh;
345
346   /* flags */
347   ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
348
349   /* properties */
350   mesh_operator_edgering_props(ot, 1, 10);
351 }
352
353 /** \} */
354
355 /* -------------------------------------------------------------------- */
356 /** \name Un-Subdivide Operator
357  * \{ */
358
359 static int edbm_unsubdivide_exec(bContext *C, wmOperator *op)
360 {
361   const int iterations = RNA_int_get(op->ptr, "iterations");
362   ViewLayer *view_layer = CTX_data_view_layer(C);
363   uint objects_len = 0;
364   Object **objects = BKE_view_layer_array_from_objects_in_edit_mode(
365       view_layer, CTX_wm_view3d(C), &objects_len);
366   for (uint ob_index = 0; ob_index < objects_len; ob_index++) {
367     Object *obedit = objects[ob_index];
368     BMEditMesh *em = BKE_editmesh_from_object(obedit);
369
370     if ((em->bm->totvertsel == 0) && (em->bm->totedgesel == 0) && (em->bm->totfacesel == 0)) {
371       continue;
372     }
373
374     BMOperator bmop;
375     EDBM_op_init(em, &bmop, op, "unsubdivide verts=%hv iterations=%i", BM_ELEM_SELECT, iterations);
376
377     BMO_op_exec(em->bm, &bmop);
378
379     if (!EDBM_op_finish(em, &bmop, op, true)) {
380       continue;
381     }
382
383     if ((em->selectmode & SCE_SELECT_VERTEX) == 0) {
384       EDBM_selectmode_flush_ex(em, SCE_SELECT_VERTEX); /* need to flush vert->face first */
385     }
386     EDBM_selectmode_flush(em);
387
388     EDBM_update_generic(em, true, true);
389   }
390   MEM_freeN(objects);
391
392   return OPERATOR_FINISHED;
393 }
394
395 void MESH_OT_unsubdivide(wmOperatorType *ot)
396 {
397   /* identifiers */
398   ot->name = "Un-Subdivide";
399   ot->description = "UnSubdivide selected edges & faces";
400   ot->idname = "MESH_OT_unsubdivide";
401
402   /* api callbacks */
403   ot->exec = edbm_unsubdivide_exec;
404   ot->poll = ED_operator_editmesh;
405
406   /* flags */
407   ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
408
409   /* props */
410   RNA_def_int(
411       ot->srna, "iterations", 2, 1, 1000, "Iterations", "Number of times to unsubdivide", 1, 100);
412 }
413
414 void EDBM_project_snap_verts(bContext *C, Depsgraph *depsgraph, ARegion *ar, BMEditMesh *em)
415 {
416   Main *bmain = CTX_data_main(C);
417   Object *obedit = em->ob;
418   BMIter iter;
419   BMVert *eve;
420
421   ED_view3d_init_mats_rv3d(obedit, ar->regiondata);
422
423   struct SnapObjectContext *snap_context = ED_transform_snap_object_context_create_view3d(
424       bmain, CTX_data_scene(C), depsgraph, 0, ar, CTX_wm_view3d(C));
425
426   BM_ITER_MESH (eve, &iter, em->bm, BM_VERTS_OF_MESH) {
427     if (BM_elem_flag_test(eve, BM_ELEM_SELECT)) {
428       float mval[2], co_proj[3];
429       if (ED_view3d_project_float_object(ar, eve->co, mval, V3D_PROJ_TEST_NOP) ==
430           V3D_PROJ_RET_OK) {
431         if (ED_transform_snap_object_project_view3d(snap_context,
432                                                     SCE_SNAP_MODE_FACE,
433                                                     &(const struct SnapObjectParams){
434                                                         .snap_select = SNAP_NOT_ACTIVE,
435                                                         .use_object_edit_cage = false,
436                                                         .use_occlusion_test = true,
437                                                     },
438                                                     mval,
439                                                     NULL,
440                                                     NULL,
441                                                     co_proj,
442                                                     NULL)) {
443           mul_v3_m4v3(eve->co, obedit->imat, co_proj);
444         }
445       }
446     }
447   }
448
449   ED_transform_snap_object_context_destroy(snap_context);
450 }
451
452 /** \} */
453
454 /* -------------------------------------------------------------------- */
455 /** \name Delete Operator
456  * \{ */
457
458 /* Note, these values must match delete_mesh() event values */
459 enum {
460   MESH_DELETE_VERT = 0,
461   MESH_DELETE_EDGE = 1,
462   MESH_DELETE_FACE = 2,
463   MESH_DELETE_EDGE_FACE = 3,
464   MESH_DELETE_ONLY_FACE = 4,
465 };
466
467 static void edbm_report_delete_info(ReportList *reports,
468                                     const int totelem_old[3],
469                                     const int totelem_new[3])
470 {
471   BKE_reportf(reports,
472               RPT_INFO,
473               "Removed: %d vertices, %d edges, %d faces",
474               totelem_old[0] - totelem_new[0],
475               totelem_old[1] - totelem_new[1],
476               totelem_old[2] - totelem_new[2]);
477 }
478
479 static int edbm_delete_exec(bContext *C, wmOperator *op)
480 {
481   ViewLayer *view_layer = CTX_data_view_layer(C);
482
483   uint objects_len = 0;
484   Object **objects = BKE_view_layer_array_from_objects_in_edit_mode_unique_data(
485       view_layer, CTX_wm_view3d(C), &objects_len);
486   bool changed_multi = false;
487
488   for (uint ob_index = 0; ob_index < objects_len; ob_index++) {
489     Object *obedit = objects[ob_index];
490     BMEditMesh *em = BKE_editmesh_from_object(obedit);
491     const int type = RNA_enum_get(op->ptr, "type");
492
493     switch (type) {
494       case MESH_DELETE_VERT: /* Erase Vertices */
495         if (!(em->bm->totvertsel &&
496               EDBM_op_callf(em, op, "delete geom=%hv context=%i", BM_ELEM_SELECT, DEL_VERTS))) {
497           continue;
498         }
499         break;
500       case MESH_DELETE_EDGE: /* Erase Edges */
501         if (!(em->bm->totedgesel &&
502               EDBM_op_callf(em, op, "delete geom=%he context=%i", BM_ELEM_SELECT, DEL_EDGES))) {
503           continue;
504         }
505         break;
506       case MESH_DELETE_FACE: /* Erase Faces */
507         if (!(em->bm->totfacesel &&
508               EDBM_op_callf(em, op, "delete geom=%hf context=%i", BM_ELEM_SELECT, DEL_FACES))) {
509           continue;
510         }
511         break;
512       case MESH_DELETE_EDGE_FACE:
513         /* Edges and Faces */
514         if (!((em->bm->totedgesel || em->bm->totfacesel) &&
515               EDBM_op_callf(
516                   em, op, "delete geom=%hef context=%i", BM_ELEM_SELECT, DEL_EDGESFACES))) {
517           continue;
518         }
519         break;
520       case MESH_DELETE_ONLY_FACE:
521         /* Only faces. */
522         if (!(em->bm->totfacesel &&
523               EDBM_op_callf(
524                   em, op, "delete geom=%hf context=%i", BM_ELEM_SELECT, DEL_ONLYFACES))) {
525           continue;
526         }
527         break;
528       default:
529         BLI_assert(0);
530         break;
531     }
532
533     changed_multi = true;
534
535     EDBM_flag_disable_all(em, BM_ELEM_SELECT);
536
537     EDBM_update_generic(em, true, true);
538
539     DEG_id_tag_update(obedit->data, ID_RECALC_SELECT);
540     WM_event_add_notifier(C, NC_GEOM | ND_SELECT, obedit->data);
541   }
542
543   MEM_freeN(objects);
544
545   return changed_multi ? OPERATOR_FINISHED : OPERATOR_CANCELLED;
546 }
547
548 void MESH_OT_delete(wmOperatorType *ot)
549 {
550   static const EnumPropertyItem prop_mesh_delete_types[] = {
551       {MESH_DELETE_VERT, "VERT", 0, "Vertices", ""},
552       {MESH_DELETE_EDGE, "EDGE", 0, "Edges", ""},
553       {MESH_DELETE_FACE, "FACE", 0, "Faces", ""},
554       {MESH_DELETE_EDGE_FACE, "EDGE_FACE", 0, "Only Edges & Faces", ""},
555       {MESH_DELETE_ONLY_FACE, "ONLY_FACE", 0, "Only Faces", ""},
556       {0, NULL, 0, NULL, NULL},
557   };
558
559   /* identifiers */
560   ot->name = "Delete";
561   ot->description = "Delete selected vertices, edges or faces";
562   ot->idname = "MESH_OT_delete";
563
564   /* api callbacks */
565   ot->invoke = WM_menu_invoke;
566   ot->exec = edbm_delete_exec;
567
568   ot->poll = ED_operator_editmesh;
569
570   /* flags */
571   ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
572
573   /* props */
574   ot->prop = RNA_def_enum(ot->srna,
575                           "type",
576                           prop_mesh_delete_types,
577                           MESH_DELETE_VERT,
578                           "Type",
579                           "Method used for deleting mesh data");
580   RNA_def_property_flag(ot->prop, PROP_HIDDEN | PROP_SKIP_SAVE);
581 }
582
583 /** \} */
584
585 /* -------------------------------------------------------------------- */
586 /** \name Delete Loose Operator
587  * \{ */
588
589 static bool bm_face_is_loose(BMFace *f)
590 {
591   BMLoop *l_iter, *l_first;
592
593   l_iter = l_first = BM_FACE_FIRST_LOOP(f);
594   do {
595     if (!BM_edge_is_boundary(l_iter->e)) {
596       return false;
597     }
598   } while ((l_iter = l_iter->next) != l_first);
599
600   return true;
601 }
602
603 static int edbm_delete_loose_exec(bContext *C, wmOperator *op)
604 {
605   ViewLayer *view_layer = CTX_data_view_layer(C);
606   int totelem_old_sel[3];
607   int totelem_old[3];
608
609   uint objects_len = 0;
610   Object **objects = BKE_view_layer_array_from_objects_in_edit_mode_unique_data(
611       view_layer, CTX_wm_view3d(C), &objects_len);
612
613   EDBM_mesh_stats_multi(objects, objects_len, totelem_old, totelem_old_sel);
614
615   const bool use_verts = (RNA_boolean_get(op->ptr, "use_verts") && totelem_old_sel[0]);
616   const bool use_edges = (RNA_boolean_get(op->ptr, "use_edges") && totelem_old_sel[1]);
617   const bool use_faces = (RNA_boolean_get(op->ptr, "use_faces") && totelem_old_sel[2]);
618
619   for (uint ob_index = 0; ob_index < objects_len; ob_index++) {
620     Object *obedit = objects[ob_index];
621
622     BMEditMesh *em = BKE_editmesh_from_object(obedit);
623     BMesh *bm = em->bm;
624     BMIter iter;
625
626     BM_mesh_elem_hflag_disable_all(bm, BM_VERT | BM_EDGE | BM_FACE, BM_ELEM_TAG, false);
627
628     if (use_faces) {
629       BMFace *f;
630
631       BM_ITER_MESH (f, &iter, bm, BM_FACES_OF_MESH) {
632         if (BM_elem_flag_test(f, BM_ELEM_SELECT)) {
633           BM_elem_flag_set(f, BM_ELEM_TAG, bm_face_is_loose(f));
634         }
635       }
636
637       BM_mesh_delete_hflag_context(bm, BM_ELEM_TAG, DEL_FACES);
638     }
639
640     if (use_edges) {
641       BMEdge *e;
642
643       BM_ITER_MESH (e, &iter, bm, BM_EDGES_OF_MESH) {
644         if (BM_elem_flag_test(e, BM_ELEM_SELECT)) {
645           BM_elem_flag_set(e, BM_ELEM_TAG, BM_edge_is_wire(e));
646         }
647       }
648
649       BM_mesh_delete_hflag_context(bm, BM_ELEM_TAG, DEL_EDGES);
650     }
651
652     if (use_verts) {
653       BMVert *v;
654
655       BM_ITER_MESH (v, &iter, bm, BM_VERTS_OF_MESH) {
656         if (BM_elem_flag_test(v, BM_ELEM_SELECT)) {
657           BM_elem_flag_set(v, BM_ELEM_TAG, (v->e == NULL));
658         }
659       }
660
661       BM_mesh_delete_hflag_context(bm, BM_ELEM_TAG, DEL_VERTS);
662     }
663
664     EDBM_flag_disable_all(em, BM_ELEM_SELECT);
665
666     EDBM_update_generic(em, true, true);
667   }
668
669   int totelem_new[3];
670   EDBM_mesh_stats_multi(objects, objects_len, totelem_new, NULL);
671
672   edbm_report_delete_info(op->reports, totelem_old, totelem_new);
673
674   MEM_freeN(objects);
675
676   return OPERATOR_FINISHED;
677 }
678
679 void MESH_OT_delete_loose(wmOperatorType *ot)
680 {
681   /* identifiers */
682   ot->name = "Delete Loose";
683   ot->description = "Delete loose vertices, edges or faces";
684   ot->idname = "MESH_OT_delete_loose";
685
686   /* api callbacks */
687   ot->exec = edbm_delete_loose_exec;
688
689   ot->poll = ED_operator_editmesh;
690
691   /* flags */
692   ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
693
694   /* props */
695   RNA_def_boolean(ot->srna, "use_verts", true, "Vertices", "Remove loose vertices");
696   RNA_def_boolean(ot->srna, "use_edges", true, "Edges", "Remove loose edges");
697   RNA_def_boolean(ot->srna, "use_faces", false, "Faces", "Remove loose faces");
698 }
699
700 /** \} */
701
702 /* -------------------------------------------------------------------- */
703 /** \name Collapse Edge Operator
704  * \{ */
705
706 static int edbm_collapse_edge_exec(bContext *C, wmOperator *op)
707 {
708   ViewLayer *view_layer = CTX_data_view_layer(C);
709   uint objects_len = 0;
710   Object **objects = BKE_view_layer_array_from_objects_in_edit_mode_unique_data(
711       view_layer, CTX_wm_view3d(C), &objects_len);
712   for (uint ob_index = 0; ob_index < objects_len; ob_index++) {
713     Object *obedit = objects[ob_index];
714     BMEditMesh *em = BKE_editmesh_from_object(obedit);
715
716     if (em->bm->totedgesel == 0) {
717       continue;
718     }
719
720     if (!EDBM_op_callf(em, op, "collapse edges=%he uvs=%b", BM_ELEM_SELECT, true)) {
721       continue;
722     }
723
724     EDBM_update_generic(em, true, true);
725   }
726   MEM_freeN(objects);
727
728   return OPERATOR_FINISHED;
729 }
730
731 void MESH_OT_edge_collapse(wmOperatorType *ot)
732 {
733   /* identifiers */
734   ot->name = "Edge Collapse";
735   ot->description = "Collapse selected edges";
736   ot->idname = "MESH_OT_edge_collapse";
737
738   /* api callbacks */
739   ot->exec = edbm_collapse_edge_exec;
740   ot->poll = ED_operator_editmesh;
741
742   /* flags */
743   ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
744 }
745
746 /** \} */
747
748 /* -------------------------------------------------------------------- */
749 /** \name Create Edge/Face Operator
750  * \{ */
751
752 static bool edbm_add_edge_face__smooth_get(BMesh *bm)
753 {
754   BMEdge *e;
755   BMIter iter;
756
757   unsigned int vote_on_smooth[2] = {0, 0};
758
759   BM_ITER_MESH (e, &iter, bm, BM_EDGES_OF_MESH) {
760     if (BM_elem_flag_test(e, BM_ELEM_SELECT) && e->l) {
761       vote_on_smooth[BM_elem_flag_test_bool(e->l->f, BM_ELEM_SMOOTH)]++;
762     }
763   }
764
765   return (vote_on_smooth[0] < vote_on_smooth[1]);
766 }
767
768 #ifdef USE_FACE_CREATE_SEL_EXTEND
769 /**
770  * Function used to get a fixed number of edges linked to a vertex that passes a test function.
771  * This is used so we can request all boundary edges connected to a vertex for eg.
772  */
773 static int edbm_add_edge_face_exec__vert_edge_lookup(
774     BMVert *v, BMEdge *e_used, BMEdge **e_arr, const int e_arr_len, bool (*func)(const BMEdge *))
775 {
776   BMIter iter;
777   BMEdge *e_iter;
778   int i = 0;
779   BM_ITER_ELEM (e_iter, &iter, v, BM_EDGES_OF_VERT) {
780     if (BM_elem_flag_test(e_iter, BM_ELEM_HIDDEN) == false) {
781       if ((e_used == NULL) || (e_used != e_iter)) {
782         if (func(e_iter)) {
783           e_arr[i++] = e_iter;
784           if (i >= e_arr_len) {
785             break;
786           }
787         }
788       }
789     }
790   }
791   return i;
792 }
793
794 static BMElem *edbm_add_edge_face_exec__tricky_extend_sel(BMesh *bm)
795 {
796   BMIter iter;
797   bool found = false;
798
799   if (bm->totvertsel == 1 && bm->totedgesel == 0 && bm->totfacesel == 0) {
800     /* first look for 2 boundary edges */
801     BMVert *v;
802
803     BM_ITER_MESH (v, &iter, bm, BM_VERTS_OF_MESH) {
804       if (BM_elem_flag_test(v, BM_ELEM_SELECT)) {
805         found = true;
806         break;
807       }
808     }
809
810     if (found) {
811       BMEdge *ed_pair[3];
812       if (((edbm_add_edge_face_exec__vert_edge_lookup(v, NULL, ed_pair, 3, BM_edge_is_wire) ==
813             2) &&
814            (BM_edge_share_face_check(ed_pair[0], ed_pair[1]) == false)) ||
815
816           ((edbm_add_edge_face_exec__vert_edge_lookup(v, NULL, ed_pair, 3, BM_edge_is_boundary) ==
817             2) &&
818            (BM_edge_share_face_check(ed_pair[0], ed_pair[1]) == false))) {
819         BMEdge *e_other = BM_edge_exists(BM_edge_other_vert(ed_pair[0], v),
820                                          BM_edge_other_vert(ed_pair[1], v));
821         BM_edge_select_set(bm, ed_pair[0], true);
822         BM_edge_select_set(bm, ed_pair[1], true);
823         if (e_other) {
824           BM_edge_select_set(bm, e_other, true);
825         }
826         return (BMElem *)v;
827       }
828     }
829   }
830   else if (bm->totvertsel == 2 && bm->totedgesel == 1 && bm->totfacesel == 0) {
831     /* first look for 2 boundary edges */
832     BMEdge *e;
833
834     BM_ITER_MESH (e, &iter, bm, BM_EDGES_OF_MESH) {
835       if (BM_elem_flag_test(e, BM_ELEM_SELECT)) {
836         found = true;
837         break;
838       }
839     }
840     if (found) {
841       BMEdge *ed_pair_v1[2];
842       BMEdge *ed_pair_v2[2];
843       if (((edbm_add_edge_face_exec__vert_edge_lookup(e->v1, e, ed_pair_v1, 2, BM_edge_is_wire) ==
844             1) &&
845            (edbm_add_edge_face_exec__vert_edge_lookup(e->v2, e, ed_pair_v2, 2, BM_edge_is_wire) ==
846             1) &&
847            (BM_edge_share_face_check(e, ed_pair_v1[0]) == false) &&
848            (BM_edge_share_face_check(e, ed_pair_v2[0]) == false)) ||
849
850 #  if 1 /* better support mixed cases [#37203] */
851           ((edbm_add_edge_face_exec__vert_edge_lookup(e->v1, e, ed_pair_v1, 2, BM_edge_is_wire) ==
852             1) &&
853            (edbm_add_edge_face_exec__vert_edge_lookup(
854                 e->v2, e, ed_pair_v2, 2, BM_edge_is_boundary) == 1) &&
855            (BM_edge_share_face_check(e, ed_pair_v1[0]) == false) &&
856            (BM_edge_share_face_check(e, ed_pair_v2[0]) == false)) ||
857
858           ((edbm_add_edge_face_exec__vert_edge_lookup(
859                 e->v1, e, ed_pair_v1, 2, BM_edge_is_boundary) == 1) &&
860            (edbm_add_edge_face_exec__vert_edge_lookup(e->v2, e, ed_pair_v2, 2, BM_edge_is_wire) ==
861             1) &&
862            (BM_edge_share_face_check(e, ed_pair_v1[0]) == false) &&
863            (BM_edge_share_face_check(e, ed_pair_v2[0]) == false)) ||
864 #  endif
865
866           ((edbm_add_edge_face_exec__vert_edge_lookup(
867                 e->v1, e, ed_pair_v1, 2, BM_edge_is_boundary) == 1) &&
868            (edbm_add_edge_face_exec__vert_edge_lookup(
869                 e->v2, e, ed_pair_v2, 2, BM_edge_is_boundary) == 1) &&
870            (BM_edge_share_face_check(e, ed_pair_v1[0]) == false) &&
871            (BM_edge_share_face_check(e, ed_pair_v2[0]) == false))) {
872         BMVert *v1_other = BM_edge_other_vert(ed_pair_v1[0], e->v1);
873         BMVert *v2_other = BM_edge_other_vert(ed_pair_v2[0], e->v2);
874         BMEdge *e_other = (v1_other != v2_other) ? BM_edge_exists(v1_other, v2_other) : NULL;
875         BM_edge_select_set(bm, ed_pair_v1[0], true);
876         BM_edge_select_set(bm, ed_pair_v2[0], true);
877         if (e_other) {
878           BM_edge_select_set(bm, e_other, true);
879         }
880         return (BMElem *)e;
881       }
882     }
883   }
884
885   return NULL;
886 }
887 static void edbm_add_edge_face_exec__tricky_finalize_sel(BMesh *bm, BMElem *ele_desel, BMFace *f)
888 {
889   /* now we need to find the edge that isnt connected to this element */
890   BM_select_history_clear(bm);
891
892   /* Notes on hidden geometry:
893    * - Un-hide the face since its possible hidden was copied when copying
894    *   surrounding face attributes.
895    * - Un-hide before adding to select history
896    *   since we may extend into an existing, hidden vert/edge.
897    */
898
899   BM_elem_flag_disable(f, BM_ELEM_HIDDEN);
900   BM_face_select_set(bm, f, false);
901
902   if (ele_desel->head.htype == BM_VERT) {
903     BMLoop *l = BM_face_vert_share_loop(f, (BMVert *)ele_desel);
904     BLI_assert(f->len == 3);
905     BM_vert_select_set(bm, (BMVert *)ele_desel, false);
906     BM_edge_select_set(bm, l->next->e, true);
907     BM_select_history_store(bm, l->next->e);
908   }
909   else {
910     BMLoop *l = BM_face_edge_share_loop(f, (BMEdge *)ele_desel);
911     BLI_assert(f->len == 4 || f->len == 3);
912
913     BM_edge_select_set(bm, (BMEdge *)ele_desel, false);
914     if (f->len == 4) {
915       BMEdge *e_active = l->next->next->e;
916       BM_elem_flag_disable(e_active, BM_ELEM_HIDDEN);
917       BM_edge_select_set(bm, e_active, true);
918       BM_select_history_store(bm, e_active);
919     }
920     else {
921       BMVert *v_active = l->next->next->v;
922       BM_elem_flag_disable(v_active, BM_ELEM_HIDDEN);
923       BM_vert_select_set(bm, v_active, true);
924       BM_select_history_store(bm, v_active);
925     }
926   }
927 }
928 #endif /* USE_FACE_CREATE_SEL_EXTEND */
929
930 static int edbm_add_edge_face_exec(bContext *C, wmOperator *op)
931 {
932   /* when this is used to dissolve we could avoid this, but checking isnt too slow */
933
934   ViewLayer *view_layer = CTX_data_view_layer(C);
935   uint objects_len = 0;
936   Object **objects = BKE_view_layer_array_from_objects_in_edit_mode_unique_data(
937       view_layer, CTX_wm_view3d(C), &objects_len);
938   for (uint ob_index = 0; ob_index < objects_len; ob_index++) {
939     Object *obedit = objects[ob_index];
940     BMEditMesh *em = BKE_editmesh_from_object(obedit);
941
942     if ((em->bm->totvertsel == 0) && (em->bm->totedgesel == 0) && (em->bm->totvertsel == 0)) {
943       continue;
944     }
945
946     bool use_smooth = edbm_add_edge_face__smooth_get(em->bm);
947     int totedge_orig = em->bm->totedge;
948     int totface_orig = em->bm->totface;
949
950     BMOperator bmop;
951 #ifdef USE_FACE_CREATE_SEL_EXTEND
952     BMElem *ele_desel;
953     BMFace *ele_desel_face;
954
955     /* be extra clever, figure out if a partial selection should be extended so we can create
956      * geometry with single vert or single edge selection. */
957     ele_desel = edbm_add_edge_face_exec__tricky_extend_sel(em->bm);
958 #endif
959     if (!EDBM_op_init(em,
960                       &bmop,
961                       op,
962                       "contextual_create geom=%hfev mat_nr=%i use_smooth=%b",
963                       BM_ELEM_SELECT,
964                       em->mat_nr,
965                       use_smooth)) {
966       continue;
967     }
968
969     BMO_op_exec(em->bm, &bmop);
970
971     /* cancel if nothing was done */
972     if ((totedge_orig == em->bm->totedge) && (totface_orig == em->bm->totface)) {
973       EDBM_op_finish(em, &bmop, op, true);
974       continue;
975     }
976 #ifdef USE_FACE_CREATE_SEL_EXTEND
977     /* normally we would want to leave the new geometry selected,
978      * but being able to press F many times to add geometry is too useful! */
979     if (ele_desel && (BMO_slot_buffer_count(bmop.slots_out, "faces.out") == 1) &&
980         (ele_desel_face = BMO_slot_buffer_get_first(bmop.slots_out, "faces.out"))) {
981       edbm_add_edge_face_exec__tricky_finalize_sel(em->bm, ele_desel, ele_desel_face);
982     }
983     else
984 #endif
985     {
986       /* Newly created faces may include existing hidden edges,
987        * copying face data from surrounding, may have copied hidden face flag too.
988        *
989        * Important that faces use flushing since 'edges.out'
990        * wont include hidden edges that already existed.
991        */
992       BMO_slot_buffer_hflag_disable(
993           em->bm, bmop.slots_out, "faces.out", BM_FACE, BM_ELEM_HIDDEN, true);
994       BMO_slot_buffer_hflag_disable(
995           em->bm, bmop.slots_out, "edges.out", BM_EDGE, BM_ELEM_HIDDEN, false);
996
997       BMO_slot_buffer_hflag_enable(
998           em->bm, bmop.slots_out, "faces.out", BM_FACE, BM_ELEM_SELECT, true);
999       BMO_slot_buffer_hflag_enable(
1000           em->bm, bmop.slots_out, "edges.out", BM_EDGE, BM_ELEM_SELECT, true);
1001     }
1002
1003     if (!EDBM_op_finish(em, &bmop, op, true)) {
1004       continue;
1005     }
1006
1007     EDBM_update_generic(em, true, true);
1008   }
1009   MEM_freeN(objects);
1010
1011   return OPERATOR_FINISHED;
1012 }
1013
1014 void MESH_OT_edge_face_add(wmOperatorType *ot)
1015 {
1016   /* identifiers */
1017   ot->name = "Make Edge/Face";
1018   ot->description = "Add an edge or face to selected";
1019   ot->idname = "MESH_OT_edge_face_add";
1020
1021   /* api callbacks */
1022   ot->exec = edbm_add_edge_face_exec;
1023   ot->poll = ED_operator_editmesh;
1024
1025   /* flags */
1026   ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
1027 }
1028
1029 /** \} */
1030
1031 /* -------------------------------------------------------------------- */
1032 /** \name Mark Edge (Seam) Operator
1033  * \{ */
1034
1035 static int edbm_mark_seam_exec(bContext *C, wmOperator *op)
1036 {
1037   Scene *scene = CTX_data_scene(C);
1038   ViewLayer *view_layer = CTX_data_view_layer(C);
1039   BMEdge *eed;
1040   BMIter iter;
1041   const bool clear = RNA_boolean_get(op->ptr, "clear");
1042
1043   uint objects_len = 0;
1044   Object **objects = BKE_view_layer_array_from_objects_in_edit_mode_unique_data(
1045       view_layer, CTX_wm_view3d(C), &objects_len);
1046   for (uint ob_index = 0; ob_index < objects_len; ob_index++) {
1047     Object *obedit = objects[ob_index];
1048     BMEditMesh *em = BKE_editmesh_from_object(obedit);
1049     BMesh *bm = em->bm;
1050
1051     if (bm->totedgesel == 0) {
1052       continue;
1053     }
1054
1055     if (clear) {
1056       BM_ITER_MESH (eed, &iter, bm, BM_EDGES_OF_MESH) {
1057         if (!BM_elem_flag_test(eed, BM_ELEM_SELECT) || BM_elem_flag_test(eed, BM_ELEM_HIDDEN)) {
1058           continue;
1059         }
1060
1061         BM_elem_flag_disable(eed, BM_ELEM_SEAM);
1062       }
1063     }
1064     else {
1065       BM_ITER_MESH (eed, &iter, bm, BM_EDGES_OF_MESH) {
1066         if (!BM_elem_flag_test(eed, BM_ELEM_SELECT) || BM_elem_flag_test(eed, BM_ELEM_HIDDEN)) {
1067           continue;
1068         }
1069         BM_elem_flag_enable(eed, BM_ELEM_SEAM);
1070       }
1071     }
1072   }
1073
1074   ED_uvedit_live_unwrap(scene, objects, objects_len);
1075
1076   for (uint ob_index = 0; ob_index < objects_len; ob_index++) {
1077     Object *obedit = objects[ob_index];
1078     BMEditMesh *em = BKE_editmesh_from_object(obedit);
1079     EDBM_update_generic(em, true, false);
1080   }
1081
1082   MEM_freeN(objects);
1083
1084   return OPERATOR_FINISHED;
1085 }
1086
1087 void MESH_OT_mark_seam(wmOperatorType *ot)
1088 {
1089   PropertyRNA *prop;
1090
1091   /* identifiers */
1092   ot->name = "Mark Seam";
1093   ot->idname = "MESH_OT_mark_seam";
1094   ot->description = "(Un)mark selected edges as a seam";
1095
1096   /* api callbacks */
1097   ot->exec = edbm_mark_seam_exec;
1098   ot->poll = ED_operator_editmesh;
1099
1100   /* flags */
1101   ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
1102
1103   prop = RNA_def_boolean(ot->srna, "clear", 0, "Clear", "");
1104   RNA_def_property_flag(prop, PROP_HIDDEN | PROP_SKIP_SAVE);
1105
1106   WM_operatortype_props_advanced_begin(ot);
1107 }
1108
1109 /** \} */
1110
1111 /* -------------------------------------------------------------------- */
1112 /** \name Mark Edge (Sharp) Operator
1113  * \{ */
1114
1115 static int edbm_mark_sharp_exec(bContext *C, wmOperator *op)
1116 {
1117   BMEdge *eed;
1118   BMIter iter;
1119   const bool clear = RNA_boolean_get(op->ptr, "clear");
1120   const bool use_verts = RNA_boolean_get(op->ptr, "use_verts");
1121   ViewLayer *view_layer = CTX_data_view_layer(C);
1122
1123   uint objects_len = 0;
1124   Object **objects = BKE_view_layer_array_from_objects_in_edit_mode_unique_data(
1125       view_layer, CTX_wm_view3d(C), &objects_len);
1126   for (uint ob_index = 0; ob_index < objects_len; ob_index++) {
1127     Object *obedit = objects[ob_index];
1128     BMEditMesh *em = BKE_editmesh_from_object(obedit);
1129     BMesh *bm = em->bm;
1130
1131     if ((use_verts && bm->totvertsel == 0) || (!use_verts && bm->totedgesel == 0)) {
1132       continue;
1133     }
1134
1135     BM_ITER_MESH (eed, &iter, bm, BM_EDGES_OF_MESH) {
1136       if (use_verts) {
1137         if (!(BM_elem_flag_test(eed->v1, BM_ELEM_SELECT) ||
1138               BM_elem_flag_test(eed->v2, BM_ELEM_SELECT))) {
1139           continue;
1140         }
1141       }
1142       else if (!BM_elem_flag_test(eed, BM_ELEM_SELECT)) {
1143         continue;
1144       }
1145
1146       BM_elem_flag_set(eed, BM_ELEM_SMOOTH, clear);
1147     }
1148
1149     EDBM_update_generic(em, true, false);
1150   }
1151   MEM_freeN(objects);
1152
1153   return OPERATOR_FINISHED;
1154 }
1155
1156 void MESH_OT_mark_sharp(wmOperatorType *ot)
1157 {
1158   PropertyRNA *prop;
1159
1160   /* identifiers */
1161   ot->name = "Mark Sharp";
1162   ot->idname = "MESH_OT_mark_sharp";
1163   ot->description = "(Un)mark selected edges as sharp";
1164
1165   /* api callbacks */
1166   ot->exec = edbm_mark_sharp_exec;
1167   ot->poll = ED_operator_editmesh;
1168
1169   /* flags */
1170   ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
1171
1172   prop = RNA_def_boolean(ot->srna, "clear", false, "Clear", "");
1173   RNA_def_property_flag(prop, PROP_HIDDEN | PROP_SKIP_SAVE);
1174   prop = RNA_def_boolean(
1175       ot->srna,
1176       "use_verts",
1177       false,
1178       "Vertices",
1179       "Consider vertices instead of edges to select which edges to (un)tag as sharp");
1180   RNA_def_property_flag(prop, PROP_SKIP_SAVE);
1181 }
1182
1183 static bool edbm_connect_vert_pair(BMEditMesh *em, wmOperator *op)
1184 {
1185   BMesh *bm = em->bm;
1186   BMOperator bmop;
1187   const int verts_len = bm->totvertsel;
1188   bool is_pair = (verts_len == 2);
1189   int len = 0;
1190   bool check_degenerate = true;
1191
1192   BMVert **verts;
1193   bool checks_succeded = true;
1194
1195   /* sanity check */
1196   if (verts_len < 2) {
1197     return false;
1198   }
1199
1200   verts = MEM_mallocN(sizeof(*verts) * verts_len, __func__);
1201   {
1202     BMIter iter;
1203     BMVert *v;
1204     int i = 0;
1205
1206     BM_ITER_MESH (v, &iter, bm, BM_VERTS_OF_MESH) {
1207       if (BM_elem_flag_test(v, BM_ELEM_SELECT)) {
1208         verts[i++] = v;
1209       }
1210     }
1211
1212     if (BM_vert_pair_share_face_check_cb(
1213             verts[0],
1214             verts[1],
1215             BM_elem_cb_check_hflag_disabled_simple(BMFace *, BM_ELEM_HIDDEN))) {
1216       check_degenerate = false;
1217       is_pair = false;
1218     }
1219   }
1220
1221   if (is_pair) {
1222     if (!EDBM_op_init(em,
1223                       &bmop,
1224                       op,
1225                       "connect_vert_pair verts=%eb verts_exclude=%hv faces_exclude=%hf",
1226                       verts,
1227                       verts_len,
1228                       BM_ELEM_HIDDEN,
1229                       BM_ELEM_HIDDEN)) {
1230       checks_succeded = false;
1231     }
1232   }
1233   else {
1234     if (!EDBM_op_init(em,
1235                       &bmop,
1236                       op,
1237                       "connect_verts verts=%eb faces_exclude=%hf check_degenerate=%b",
1238                       verts,
1239                       verts_len,
1240                       BM_ELEM_HIDDEN,
1241                       check_degenerate)) {
1242       checks_succeded = false;
1243     }
1244   }
1245   if (checks_succeded) {
1246     BMO_op_exec(bm, &bmop);
1247     len = BMO_slot_get(bmop.slots_out, "edges.out")->len;
1248
1249     if (len && is_pair) {
1250       /* new verts have been added, we have to select the edges, not just flush */
1251       BMO_slot_buffer_hflag_enable(
1252           em->bm, bmop.slots_out, "edges.out", BM_EDGE, BM_ELEM_SELECT, true);
1253     }
1254
1255     if (!EDBM_op_finish(em, &bmop, op, true)) {
1256       len = 0;
1257     }
1258     else {
1259       /* so newly created edges get the selection state from the vertex */
1260       EDBM_selectmode_flush(em);
1261
1262       EDBM_update_generic(em, true, true);
1263     }
1264   }
1265   MEM_freeN(verts);
1266
1267   return len;
1268 }
1269
1270 static int edbm_vert_connect_exec(bContext *C, wmOperator *op)
1271 {
1272   ViewLayer *view_layer = CTX_data_view_layer(C);
1273   uint objects_len = 0;
1274   uint failed_objects_len = 0;
1275   Object **objects = BKE_view_layer_array_from_objects_in_edit_mode_unique_data(
1276       view_layer, CTX_wm_view3d(C), &objects_len);
1277
1278   for (uint ob_index = 0; ob_index < objects_len; ob_index++) {
1279     Object *obedit = objects[ob_index];
1280     BMEditMesh *em = BKE_editmesh_from_object(obedit);
1281
1282     if (!edbm_connect_vert_pair(em, op)) {
1283       failed_objects_len++;
1284     }
1285   }
1286   MEM_freeN(objects);
1287   return failed_objects_len == objects_len ? OPERATOR_FINISHED : OPERATOR_CANCELLED;
1288 }
1289
1290 void MESH_OT_vert_connect(wmOperatorType *ot)
1291 {
1292   /* identifiers */
1293   ot->name = "Vertex Connect";
1294   ot->idname = "MESH_OT_vert_connect";
1295   ot->description = "Connect selected vertices of faces, splitting the face";
1296
1297   /* api callbacks */
1298   ot->exec = edbm_vert_connect_exec;
1299   ot->poll = ED_operator_editmesh;
1300
1301   /* flags */
1302   ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
1303 }
1304
1305 /** \} */
1306
1307 /* -------------------------------------------------------------------- */
1308 /** \name Split Concave Faces Operator
1309  * \{ */
1310
1311 /**
1312  * check that endpoints are verts and only have a single selected edge connected.
1313  */
1314 static bool bm_vert_is_select_history_open(BMesh *bm)
1315 {
1316   BMEditSelection *ele_a = bm->selected.first;
1317   BMEditSelection *ele_b = bm->selected.last;
1318   if ((ele_a->htype == BM_VERT) && (ele_b->htype == BM_VERT)) {
1319     if ((BM_iter_elem_count_flag(BM_EDGES_OF_VERT, (BMVert *)ele_a->ele, BM_ELEM_SELECT, true) ==
1320          1) &&
1321         (BM_iter_elem_count_flag(BM_EDGES_OF_VERT, (BMVert *)ele_b->ele, BM_ELEM_SELECT, true) ==
1322          1)) {
1323       return true;
1324     }
1325   }
1326
1327   return false;
1328 }
1329
1330 static bool bm_vert_connect_pair(BMesh *bm, BMVert *v_a, BMVert *v_b)
1331 {
1332   BMOperator bmop;
1333   BMVert **verts;
1334   const int totedge_orig = bm->totedge;
1335
1336   BMO_op_init(bm, &bmop, BMO_FLAG_DEFAULTS, "connect_vert_pair");
1337
1338   verts = BMO_slot_buffer_alloc(&bmop, bmop.slots_in, "verts", 2);
1339   verts[0] = v_a;
1340   verts[1] = v_b;
1341
1342   BM_vert_normal_update(verts[0]);
1343   BM_vert_normal_update(verts[1]);
1344
1345   BMO_op_exec(bm, &bmop);
1346   BMO_slot_buffer_hflag_enable(bm, bmop.slots_out, "edges.out", BM_EDGE, BM_ELEM_SELECT, true);
1347   BMO_op_finish(bm, &bmop);
1348   return (bm->totedge != totedge_orig);
1349 }
1350
1351 static bool bm_vert_connect_select_history(BMesh *bm)
1352 {
1353   /* Logic is as follows:
1354    *
1355    * - If there are any isolated/wire verts - connect as edges.
1356    * - Otherwise connect faces.
1357    * - If all edges have been created already, closed the loop.
1358    */
1359   if (BLI_listbase_count_at_most(&bm->selected, 2) == 2 && (bm->totvertsel > 2)) {
1360     BMEditSelection *ese;
1361     int tot = 0;
1362     bool changed = false;
1363     bool has_wire = false;
1364     // bool all_verts;
1365
1366     /* ensure all verts have history */
1367     for (ese = bm->selected.first; ese; ese = ese->next, tot++) {
1368       BMVert *v;
1369       if (ese->htype != BM_VERT) {
1370         break;
1371       }
1372       v = (BMVert *)ese->ele;
1373       if ((has_wire == false) && ((v->e == NULL) || BM_vert_is_wire(v))) {
1374         has_wire = true;
1375       }
1376     }
1377     // all_verts = (ese == NULL);
1378
1379     if (has_wire == false) {
1380       /* all verts have faces , connect verts via faces! */
1381       if (tot == bm->totvertsel) {
1382         BMEditSelection *ese_last;
1383         ese_last = bm->selected.first;
1384         ese = ese_last->next;
1385
1386         do {
1387
1388           if (BM_edge_exists((BMVert *)ese_last->ele, (BMVert *)ese->ele)) {
1389             /* pass, edge exists (and will be selected) */
1390           }
1391           else {
1392             changed |= bm_vert_connect_pair(bm, (BMVert *)ese_last->ele, (BMVert *)ese->ele);
1393           }
1394         } while ((void)(ese_last = ese), (ese = ese->next));
1395
1396         if (changed) {
1397           return true;
1398         }
1399       }
1400
1401       if (changed == false) {
1402         /* existing loops: close the selection */
1403         if (bm_vert_is_select_history_open(bm)) {
1404           changed |= bm_vert_connect_pair(bm,
1405                                           (BMVert *)((BMEditSelection *)bm->selected.first)->ele,
1406                                           (BMVert *)((BMEditSelection *)bm->selected.last)->ele);
1407
1408           if (changed) {
1409             return true;
1410           }
1411         }
1412       }
1413     }
1414
1415     else {
1416       /* no faces, simply connect the verts by edges */
1417       BMEditSelection *ese_prev;
1418       ese_prev = bm->selected.first;
1419       ese = ese_prev->next;
1420
1421       do {
1422         if (BM_edge_exists((BMVert *)ese_prev->ele, (BMVert *)ese->ele)) {
1423           /* pass, edge exists (and will be selected) */
1424         }
1425         else {
1426           BMEdge *e;
1427           e = BM_edge_create(bm, (BMVert *)ese_prev->ele, (BMVert *)ese->ele, NULL, 0);
1428           BM_edge_select_set(bm, e, true);
1429           changed = true;
1430         }
1431       } while ((void)(ese_prev = ese), (ese = ese->next));
1432
1433       if (changed == false) {
1434         /* existing loops: close the selection */
1435         if (bm_vert_is_select_history_open(bm)) {
1436           BMEdge *e;
1437           ese_prev = bm->selected.first;
1438           ese = bm->selected.last;
1439           e = BM_edge_create(bm, (BMVert *)ese_prev->ele, (BMVert *)ese->ele, NULL, 0);
1440           BM_edge_select_set(bm, e, true);
1441         }
1442       }
1443
1444       return true;
1445     }
1446   }
1447
1448   return false;
1449 }
1450
1451 /**
1452  * Convert an edge selection to a temp vertex selection
1453  * (which must be cleared after use as a path to connect).
1454  */
1455 static bool bm_vert_connect_select_history_edge_to_vert_path(BMesh *bm, ListBase *r_selected)
1456 {
1457   ListBase selected_orig = {NULL, NULL};
1458   BMEditSelection *ese;
1459   int edges_len = 0;
1460   bool side = false;
1461
1462   /* first check all edges are OK */
1463   for (ese = bm->selected.first; ese; ese = ese->next) {
1464     if (ese->htype == BM_EDGE) {
1465       edges_len += 1;
1466     }
1467     else {
1468       return false;
1469     }
1470   }
1471   /* if this is a mixed selection, bail out! */
1472   if (bm->totedgesel != edges_len) {
1473     return false;
1474   }
1475
1476   SWAP(ListBase, bm->selected, selected_orig);
1477
1478   /* convert edge selection into 2 ordered loops (where the first edge ends up in the middle) */
1479   for (ese = selected_orig.first; ese; ese = ese->next) {
1480     BMEdge *e_curr = (BMEdge *)ese->ele;
1481     BMEdge *e_prev = ese->prev ? (BMEdge *)ese->prev->ele : NULL;
1482     BMLoop *l_curr;
1483     BMLoop *l_prev;
1484     BMVert *v;
1485
1486     if (e_prev) {
1487       BMFace *f = BM_edge_pair_share_face_by_len(e_curr, e_prev, &l_curr, &l_prev, true);
1488       if (f) {
1489         if ((e_curr->v1 != l_curr->v) == (e_prev->v1 != l_prev->v)) {
1490           side = !side;
1491         }
1492       }
1493       else if (is_quad_flip_v3(e_curr->v1->co, e_curr->v2->co, e_prev->v2->co, e_prev->v1->co)) {
1494         side = !side;
1495       }
1496     }
1497
1498     v = (&e_curr->v1)[side];
1499     if (!bm->selected.last || (BMVert *)((BMEditSelection *)bm->selected.last)->ele != v) {
1500       BM_select_history_store_notest(bm, v);
1501     }
1502
1503     v = (&e_curr->v1)[!side];
1504     if (!bm->selected.first || (BMVert *)((BMEditSelection *)bm->selected.first)->ele != v) {
1505       BM_select_history_store_head_notest(bm, v);
1506     }
1507
1508     e_prev = e_curr;
1509   }
1510
1511   *r_selected = bm->selected;
1512   bm->selected = selected_orig;
1513
1514   return true;
1515 }
1516
1517 static int edbm_vert_connect_path_exec(bContext *C, wmOperator *op)
1518 {
1519   ViewLayer *view_layer = CTX_data_view_layer(C);
1520   uint objects_len = 0;
1521   uint failed_selection_order_len = 0;
1522   uint failed_connect_len = 0;
1523   Object **objects = BKE_view_layer_array_from_objects_in_edit_mode_unique_data(
1524       view_layer, CTX_wm_view3d(C), &objects_len);
1525
1526   for (uint ob_index = 0; ob_index < objects_len; ob_index++) {
1527     Object *obedit = objects[ob_index];
1528     BMEditMesh *em = BKE_editmesh_from_object(obedit);
1529     BMesh *bm = em->bm;
1530     const bool is_pair = (em->bm->totvertsel == 2);
1531     ListBase selected_orig = {NULL, NULL};
1532
1533     if (bm->totvertsel == 0) {
1534       continue;
1535     }
1536
1537     /* when there is only 2 vertices, we can ignore selection order */
1538     if (is_pair) {
1539       if (!edbm_connect_vert_pair(em, op)) {
1540         failed_connect_len++;
1541       }
1542       continue;
1543     }
1544
1545     if (bm->selected.first) {
1546       BMEditSelection *ese = bm->selected.first;
1547       if (ese->htype == BM_EDGE) {
1548         if (bm_vert_connect_select_history_edge_to_vert_path(bm, &selected_orig)) {
1549           SWAP(ListBase, bm->selected, selected_orig);
1550         }
1551       }
1552     }
1553
1554     if (bm_vert_connect_select_history(bm)) {
1555       EDBM_selectmode_flush(em);
1556       EDBM_update_generic(em, true, true);
1557     }
1558     else {
1559       failed_selection_order_len++;
1560     }
1561
1562     if (!BLI_listbase_is_empty(&selected_orig)) {
1563       BM_select_history_clear(bm);
1564       bm->selected = selected_orig;
1565     }
1566   }
1567
1568   MEM_freeN(objects);
1569
1570   if (failed_selection_order_len == objects_len) {
1571     BKE_report(op->reports, RPT_ERROR, "Invalid selection order");
1572     return OPERATOR_CANCELLED;
1573   }
1574   else if (failed_connect_len == objects_len) {
1575     BKE_report(op->reports, RPT_ERROR, "Could not connect vertices");
1576     return OPERATOR_CANCELLED;
1577   }
1578
1579   return OPERATOR_FINISHED;
1580 }
1581
1582 void MESH_OT_vert_connect_path(wmOperatorType *ot)
1583 {
1584   /* identifiers */
1585   ot->name = "Vertex Connect Path";
1586   ot->idname = "MESH_OT_vert_connect_path";
1587   ot->description = "Connect vertices by their selection order, creating edges, splitting faces";
1588
1589   /* api callbacks */
1590   ot->exec = edbm_vert_connect_path_exec;
1591   ot->poll = ED_operator_editmesh;
1592
1593   /* flags */
1594   ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
1595 }
1596
1597 static int edbm_vert_connect_concave_exec(bContext *C, wmOperator *op)
1598 {
1599   ViewLayer *view_layer = CTX_data_view_layer(C);
1600   uint objects_len = 0;
1601   Object **objects = BKE_view_layer_array_from_objects_in_edit_mode_unique_data(
1602       view_layer, CTX_wm_view3d(C), &objects_len);
1603   for (uint ob_index = 0; ob_index < objects_len; ob_index++) {
1604     Object *obedit = objects[ob_index];
1605     BMEditMesh *em = BKE_editmesh_from_object(obedit);
1606
1607     if (em->bm->totfacesel == 0) {
1608       continue;
1609     }
1610
1611     if (!EDBM_op_call_and_selectf(
1612             em, op, "faces.out", true, "connect_verts_concave faces=%hf", BM_ELEM_SELECT)) {
1613       continue;
1614     }
1615     EDBM_update_generic(em, true, true);
1616   }
1617
1618   MEM_freeN(objects);
1619   return OPERATOR_FINISHED;
1620 }
1621
1622 void MESH_OT_vert_connect_concave(wmOperatorType *ot)
1623 {
1624   /* identifiers */
1625   ot->name = "Split Concave Faces";
1626   ot->idname = "MESH_OT_vert_connect_concave";
1627   ot->description = "Make all faces convex";
1628
1629   /* api callbacks */
1630   ot->exec = edbm_vert_connect_concave_exec;
1631   ot->poll = ED_operator_editmesh;
1632
1633   /* flags */
1634   ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
1635 }
1636
1637 /** \} */
1638
1639 /* -------------------------------------------------------------------- */
1640 /** \name Split Non-Planar Faces Operator
1641  * \{ */
1642
1643 static int edbm_vert_connect_nonplaner_exec(bContext *C, wmOperator *op)
1644 {
1645   ViewLayer *view_layer = CTX_data_view_layer(C);
1646   const float angle_limit = RNA_float_get(op->ptr, "angle_limit");
1647   uint objects_len = 0;
1648   Object **objects = BKE_view_layer_array_from_objects_in_edit_mode_unique_data(
1649       view_layer, CTX_wm_view3d(C), &objects_len);
1650
1651   for (uint ob_index = 0; ob_index < objects_len; ob_index++) {
1652     Object *obedit = objects[ob_index];
1653     BMEditMesh *em = BKE_editmesh_from_object(obedit);
1654
1655     if (em->bm->totfacesel == 0) {
1656       continue;
1657     }
1658
1659     if (!EDBM_op_call_and_selectf(em,
1660                                   op,
1661                                   "faces.out",
1662                                   true,
1663                                   "connect_verts_nonplanar faces=%hf angle_limit=%f",
1664                                   BM_ELEM_SELECT,
1665                                   angle_limit)) {
1666       continue;
1667     }
1668
1669     EDBM_update_generic(em, true, true);
1670   }
1671   MEM_freeN(objects);
1672
1673   return OPERATOR_FINISHED;
1674 }
1675
1676 void MESH_OT_vert_connect_nonplanar(wmOperatorType *ot)
1677 {
1678   PropertyRNA *prop;
1679
1680   /* identifiers */
1681   ot->name = "Split Non-Planar Faces";
1682   ot->idname = "MESH_OT_vert_connect_nonplanar";
1683   ot->description = "Split non-planar faces that exceed the angle threshold";
1684
1685   /* api callbacks */
1686   ot->exec = edbm_vert_connect_nonplaner_exec;
1687   ot->poll = ED_operator_editmesh;
1688
1689   /* flags */
1690   ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
1691
1692   /* props */
1693   prop = RNA_def_float_rotation(ot->srna,
1694                                 "angle_limit",
1695                                 0,
1696                                 NULL,
1697                                 0.0f,
1698                                 DEG2RADF(180.0f),
1699                                 "Max Angle",
1700                                 "Angle limit",
1701                                 0.0f,
1702                                 DEG2RADF(180.0f));
1703   RNA_def_property_float_default(prop, DEG2RADF(5.0f));
1704 }
1705
1706 /** \} */
1707
1708 /* -------------------------------------------------------------------- */
1709 /** \name Make Planar Faces Operator
1710  * \{ */
1711
1712 static int edbm_face_make_planar_exec(bContext *C, wmOperator *op)
1713 {
1714   ViewLayer *view_layer = CTX_data_view_layer(C);
1715   uint objects_len = 0;
1716   Object **objects = BKE_view_layer_array_from_objects_in_edit_mode_unique_data(
1717       view_layer, CTX_wm_view3d(C), &objects_len);
1718
1719   const int repeat = RNA_int_get(op->ptr, "repeat");
1720   const float fac = RNA_float_get(op->ptr, "factor");
1721
1722   for (uint ob_index = 0; ob_index < objects_len; ob_index++) {
1723     Object *obedit = objects[ob_index];
1724     BMEditMesh *em = BKE_editmesh_from_object(obedit);
1725     if (em->bm->totfacesel == 0) {
1726       continue;
1727     }
1728
1729     if (!EDBM_op_callf(em,
1730                        op,
1731                        "planar_faces faces=%hf iterations=%i factor=%f",
1732                        BM_ELEM_SELECT,
1733                        repeat,
1734                        fac)) {
1735       continue;
1736     }
1737
1738     EDBM_update_generic(em, true, true);
1739   }
1740   MEM_freeN(objects);
1741
1742   return OPERATOR_FINISHED;
1743 }
1744
1745 void MESH_OT_face_make_planar(wmOperatorType *ot)
1746 {
1747   /* identifiers */
1748   ot->name = "Make Planar Faces";
1749   ot->idname = "MESH_OT_face_make_planar";
1750   ot->description = "Flatten selected faces";
1751
1752   /* api callbacks */
1753   ot->exec = edbm_face_make_planar_exec;
1754   ot->poll = ED_operator_editmesh;
1755
1756   /* flags */
1757   ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
1758
1759   /* props */
1760   RNA_def_float(ot->srna, "factor", 1.0f, -10.0f, 10.0f, "Factor", "", 0.0f, 1.0f);
1761   RNA_def_int(ot->srna, "repeat", 1, 1, 10000, "Iterations", "", 1, 200);
1762 }
1763
1764 /** \} */
1765
1766 /* -------------------------------------------------------------------- */
1767 /** \name Split Edge Operator
1768  * \{ */
1769
1770 static int edbm_edge_split_exec(bContext *C, wmOperator *op)
1771 {
1772   ViewLayer *view_layer = CTX_data_view_layer(C);
1773   uint objects_len = 0;
1774   Object **objects = BKE_view_layer_array_from_objects_in_edit_mode_unique_data(
1775       view_layer, CTX_wm_view3d(C), &objects_len);
1776   for (uint ob_index = 0; ob_index < objects_len; ob_index++) {
1777     Object *obedit = objects[ob_index];
1778     BMEditMesh *em = BKE_editmesh_from_object(obedit);
1779     if (em->bm->totedgesel == 0) {
1780       continue;
1781     }
1782
1783     if (!EDBM_op_call_and_selectf(
1784             em, op, "edges.out", false, "split_edges edges=%he", BM_ELEM_SELECT)) {
1785       continue;
1786     }
1787
1788     if (em->selectmode == SCE_SELECT_FACE) {
1789       EDBM_select_flush(em);
1790     }
1791
1792     EDBM_update_generic(em, true, true);
1793   }
1794   MEM_freeN(objects);
1795
1796   return OPERATOR_FINISHED;
1797 }
1798
1799 void MESH_OT_edge_split(wmOperatorType *ot)
1800 {
1801   /* identifiers */
1802   ot->name = "Edge Split";
1803   ot->idname = "MESH_OT_edge_split";
1804   ot->description = "Split selected edges so that each neighbor face gets its own copy";
1805
1806   /* api callbacks */
1807   ot->exec = edbm_edge_split_exec;
1808   ot->poll = ED_operator_editmesh;
1809
1810   /* flags */
1811   ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
1812 }
1813
1814 /** \} */
1815
1816 /* -------------------------------------------------------------------- */
1817 /** \name Duplicate Operator
1818  * \{ */
1819
1820 static int edbm_duplicate_exec(bContext *C, wmOperator *op)
1821 {
1822   ViewLayer *view_layer = CTX_data_view_layer(C);
1823   uint objects_len = 0;
1824   Object **objects = BKE_view_layer_array_from_objects_in_edit_mode_unique_data(
1825       view_layer, CTX_wm_view3d(C), &objects_len);
1826
1827   for (uint ob_index = 0; ob_index < objects_len; ob_index++) {
1828     Object *obedit = objects[ob_index];
1829     BMEditMesh *em = BKE_editmesh_from_object(obedit);
1830     if (em->bm->totvertsel == 0) {
1831       continue;
1832     }
1833
1834     BMOperator bmop;
1835     BMesh *bm = em->bm;
1836
1837     EDBM_op_init(em,
1838                  &bmop,
1839                  op,
1840                  "duplicate geom=%hvef use_select_history=%b use_edge_flip_from_face=%b",
1841                  BM_ELEM_SELECT,
1842                  true,
1843                  true);
1844
1845     BMO_op_exec(bm, &bmop);
1846
1847     /* de-select all would clear otherwise */
1848     BM_SELECT_HISTORY_BACKUP(bm);
1849
1850     EDBM_flag_disable_all(em, BM_ELEM_SELECT);
1851
1852     BMO_slot_buffer_hflag_enable(
1853         bm, bmop.slots_out, "geom.out", BM_ALL_NOLOOP, BM_ELEM_SELECT, true);
1854
1855     /* rebuild editselection */
1856     BM_SELECT_HISTORY_RESTORE(bm);
1857
1858     if (!EDBM_op_finish(em, &bmop, op, true)) {
1859       continue;
1860     }
1861     EDBM_update_generic(em, true, true);
1862   }
1863   MEM_freeN(objects);
1864
1865   return OPERATOR_FINISHED;
1866 }
1867
1868 static int edbm_duplicate_invoke(bContext *C, wmOperator *op, const wmEvent *UNUSED(event))
1869 {
1870   WM_cursor_wait(1);
1871   edbm_duplicate_exec(C, op);
1872   WM_cursor_wait(0);
1873
1874   return OPERATOR_FINISHED;
1875 }
1876
1877 void MESH_OT_duplicate(wmOperatorType *ot)
1878 {
1879   /* identifiers */
1880   ot->name = "Duplicate";
1881   ot->description = "Duplicate selected vertices, edges or faces";
1882   ot->idname = "MESH_OT_duplicate";
1883
1884   /* api callbacks */
1885   ot->invoke = edbm_duplicate_invoke;
1886   ot->exec = edbm_duplicate_exec;
1887
1888   ot->poll = ED_operator_editmesh;
1889
1890   /* to give to transform */
1891   RNA_def_int(ot->srna, "mode", TFM_TRANSLATION, 0, INT_MAX, "Mode", "", 0, INT_MAX);
1892 }
1893
1894 /** \} */
1895
1896 /* -------------------------------------------------------------------- */
1897 /** \name Flip Normals Operator
1898  * \{ */
1899 static int edbm_flip_normals_exec(bContext *C, wmOperator *op)
1900 {
1901   ViewLayer *view_layer = CTX_data_view_layer(C);
1902   uint objects_len = 0;
1903   Object **objects = BKE_view_layer_array_from_objects_in_edit_mode_unique_data(
1904       view_layer, CTX_wm_view3d(C), &objects_len);
1905
1906   for (uint ob_index = 0; ob_index < objects_len; ob_index++) {
1907     Object *obedit = objects[ob_index];
1908     BMEditMesh *em = BKE_editmesh_from_object(obedit);
1909
1910     if (em->bm->totfacesel == 0) {
1911       continue;
1912     }
1913
1914     if (!EDBM_op_callf(em, op, "reverse_faces faces=%hf flip_multires=%b", BM_ELEM_SELECT, true)) {
1915       continue;
1916     }
1917
1918     EDBM_update_generic(em, true, false);
1919   }
1920
1921   MEM_freeN(objects);
1922   return OPERATOR_FINISHED;
1923 }
1924
1925 void MESH_OT_flip_normals(wmOperatorType *ot)
1926 {
1927   /* identifiers */
1928   ot->name = "Flip Normals";
1929   ot->description = "Flip the direction of selected faces' normals (and of their vertices)";
1930   ot->idname = "MESH_OT_flip_normals";
1931
1932   /* api callbacks */
1933   ot->exec = edbm_flip_normals_exec;
1934   ot->poll = ED_operator_editmesh;
1935
1936   /* flags */
1937   ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
1938 }
1939
1940 /** \} */
1941
1942 /* -------------------------------------------------------------------- */
1943 /** \name Rotate Edge Operator
1944  * \{ */
1945
1946 /**
1947  * Rotate the edges between selected faces, otherwise rotate the selected edges.
1948  */
1949 static int edbm_edge_rotate_selected_exec(bContext *C, wmOperator *op)
1950 {
1951   BMEdge *eed;
1952   BMIter iter;
1953   const bool use_ccw = RNA_boolean_get(op->ptr, "use_ccw");
1954
1955   int tot_rotate_all = 0, tot_failed_all = 0;
1956   bool no_selected_edges = true, invalid_selected_edges = true;
1957
1958   ViewLayer *view_layer = CTX_data_view_layer(C);
1959   uint objects_len = 0;
1960   Object **objects = BKE_view_layer_array_from_objects_in_edit_mode_unique_data(
1961       view_layer, CTX_wm_view3d(C), &objects_len);
1962   for (uint ob_index = 0; ob_index < objects_len; ob_index++) {
1963     Object *obedit = objects[ob_index];
1964     BMEditMesh *em = BKE_editmesh_from_object(obedit);
1965     int tot = 0;
1966
1967     if (em->bm->totedgesel == 0) {
1968       continue;
1969     }
1970     no_selected_edges = false;
1971
1972     /* first see if we have two adjacent faces */
1973     BM_ITER_MESH (eed, &iter, em->bm, BM_EDGES_OF_MESH) {
1974       BM_elem_flag_disable(eed, BM_ELEM_TAG);
1975       if (BM_elem_flag_test(eed, BM_ELEM_SELECT)) {
1976         BMFace *fa, *fb;
1977         if (BM_edge_face_pair(eed, &fa, &fb)) {
1978           /* if both faces are selected we rotate between them,
1979            * otherwise - rotate between 2 unselected - but not mixed */
1980           if (BM_elem_flag_test(fa, BM_ELEM_SELECT) == BM_elem_flag_test(fb, BM_ELEM_SELECT)) {
1981             BM_elem_flag_enable(eed, BM_ELEM_TAG);
1982             tot++;
1983           }
1984         }
1985       }
1986     }
1987
1988     /* ok, we don't have two adjacent faces, but we do have two selected ones.
1989      * that's an error condition.*/
1990     if (tot == 0) {
1991       continue;
1992     }
1993     invalid_selected_edges = false;
1994
1995     BMOperator bmop;
1996     EDBM_op_init(em, &bmop, op, "rotate_edges edges=%he use_ccw=%b", BM_ELEM_TAG, use_ccw);
1997
1998     /* avoids leaving old verts selected which can be a problem running multiple times,
1999      * since this means the edges become selected around the face
2000      * which then attempt to rotate */
2001     BMO_slot_buffer_hflag_disable(em->bm, bmop.slots_in, "edges", BM_EDGE, BM_ELEM_SELECT, true);
2002
2003     BMO_op_exec(em->bm, &bmop);
2004     /* edges may rotate into hidden vertices, if this does _not_ run we get an illogical state */
2005     BMO_slot_buffer_hflag_disable(
2006         em->bm, bmop.slots_out, "edges.out", BM_EDGE, BM_ELEM_HIDDEN, true);
2007     BMO_slot_buffer_hflag_enable(
2008         em->bm, bmop.slots_out, "edges.out", BM_EDGE, BM_ELEM_SELECT, true);
2009
2010     const int tot_rotate = BMO_slot_buffer_count(bmop.slots_out, "edges.out");
2011     const int tot_failed = tot - tot_rotate;
2012
2013     tot_rotate_all += tot_rotate;
2014     tot_failed_all += tot_failed;
2015
2016     if (tot_failed != 0) {
2017       /* If some edges fail to rotate, we need to re-select them,
2018        * otherwise we can end up with invalid selection
2019        * (unselected edge between 2 selected faces). */
2020       BM_mesh_elem_hflag_enable_test(em->bm, BM_EDGE, BM_ELEM_SELECT, true, false, BM_ELEM_TAG);
2021     }
2022
2023     EDBM_selectmode_flush(em);
2024
2025     if (!EDBM_op_finish(em, &bmop, op, true)) {
2026       continue;
2027     }
2028
2029     EDBM_update_generic(em, true, true);
2030   }
2031   MEM_freeN(objects);
2032
2033   if (no_selected_edges) {
2034     BKE_report(
2035         op->reports, RPT_ERROR, "Select edges or face pairs for edge loops to rotate about");
2036     return OPERATOR_CANCELLED;
2037   }
2038
2039   /* Ok, we don't have two adjacent faces, but we do have two selected ones.
2040    * that's an error condition. */
2041   if (invalid_selected_edges) {
2042     BKE_report(op->reports, RPT_ERROR, "Could not find any selected edges that can be rotated");
2043     return OPERATOR_CANCELLED;
2044   }
2045
2046   if (tot_failed_all != 0) {
2047     BKE_reportf(op->reports, RPT_WARNING, "Unable to rotate %d edge(s)", tot_failed_all);
2048   }
2049
2050   return OPERATOR_FINISHED;
2051 }
2052
2053 void MESH_OT_edge_rotate(wmOperatorType *ot)
2054 {
2055   /* identifiers */
2056   ot->name = "Rotate Selected Edge";
2057   ot->description = "Rotate selected edge or adjoining faces";
2058   ot->idname = "MESH_OT_edge_rotate";
2059
2060   /* api callbacks */
2061   ot->exec = edbm_edge_rotate_selected_exec;
2062   ot->poll = ED_operator_editmesh;
2063
2064   /* flags */
2065   ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
2066
2067   /* props */
2068   RNA_def_boolean(ot->srna, "use_ccw", false, "Counter Clockwise", "");
2069 }
2070
2071 /** \} */
2072
2073 /* -------------------------------------------------------------------- */
2074 /** \name Hide Operator
2075  * \{ */
2076
2077 static int edbm_hide_exec(bContext *C, wmOperator *op)
2078 {
2079   const bool unselected = RNA_boolean_get(op->ptr, "unselected");
2080   ViewLayer *view_layer = CTX_data_view_layer(C);
2081   bool changed = false;
2082
2083   uint objects_len = 0;
2084   Object **objects = BKE_view_layer_array_from_objects_in_edit_mode_unique_data(
2085       view_layer, CTX_wm_view3d(C), &objects_len);
2086   for (uint ob_index = 0; ob_index < objects_len; ob_index++) {
2087     Object *obedit = objects[ob_index];
2088     BMEditMesh *em = BKE_editmesh_from_object(obedit);
2089     BMesh *bm = em->bm;
2090
2091     if (unselected) {
2092       if (bm->totvertsel == bm->totvert) {
2093         continue;
2094       }
2095     }
2096     else {
2097       if (bm->totvertsel == 0) {
2098         continue;
2099       }
2100     }
2101
2102     if (EDBM_mesh_hide(em, unselected)) {
2103       EDBM_update_generic(em, true, false);
2104       changed = true;
2105     }
2106   }
2107   MEM_freeN(objects);
2108
2109   if (!changed) {
2110     return OPERATOR_CANCELLED;
2111   }
2112
2113   return OPERATOR_FINISHED;
2114 }
2115
2116 void MESH_OT_hide(wmOperatorType *ot)
2117 {
2118   /* identifiers */
2119   ot->name = "Hide Selected";
2120   ot->idname = "MESH_OT_hide";
2121   ot->description = "Hide (un)selected vertices, edges or faces";
2122
2123   /* api callbacks */
2124   ot->exec = edbm_hide_exec;
2125   ot->poll = ED_operator_editmesh;
2126
2127   /* flags */
2128   ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
2129
2130   /* props */
2131   RNA_def_boolean(
2132       ot->srna, "unselected", false, "Unselected", "Hide unselected rather than selected");
2133 }
2134
2135 /** \} */
2136
2137 /* -------------------------------------------------------------------- */
2138 /** \name Reveal Operator
2139  * \{ */
2140
2141 static int edbm_reveal_exec(bContext *C, wmOperator *op)
2142 {
2143   const bool select = RNA_boolean_get(op->ptr, "select");
2144   ViewLayer *view_layer = CTX_data_view_layer(C);
2145
2146   uint objects_len = 0;
2147   Object **objects = BKE_view_layer_array_from_objects_in_edit_mode_unique_data(
2148       view_layer, CTX_wm_view3d(C), &objects_len);
2149   for (uint ob_index = 0; ob_index < objects_len; ob_index++) {
2150     Object *obedit = objects[ob_index];
2151     BMEditMesh *em = BKE_editmesh_from_object(obedit);
2152
2153     if (EDBM_mesh_reveal(em, select)) {
2154       EDBM_update_generic(em, true, false);
2155     }
2156   }
2157   MEM_freeN(objects);
2158
2159   return OPERATOR_FINISHED;
2160 }
2161
2162 void MESH_OT_reveal(wmOperatorType *ot)
2163 {
2164   /* identifiers */
2165   ot->name = "Reveal Hidden";
2166   ot->idname = "MESH_OT_reveal";
2167   ot->description = "Reveal all hidden vertices, edges and faces";
2168
2169   /* api callbacks */
2170   ot->exec = edbm_reveal_exec;
2171   ot->poll = ED_operator_editmesh;
2172
2173   /* flags */
2174   ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
2175
2176   RNA_def_boolean(ot->srna, "select", true, "Select", "");
2177 }
2178
2179 /** \} */
2180
2181 /* -------------------------------------------------------------------- */
2182 /** \name Recalculate Normals Operator
2183  * \{ */
2184
2185 static int edbm_normals_make_consistent_exec(bContext *C, wmOperator *op)
2186 {
2187   ViewLayer *view_layer = CTX_data_view_layer(C);
2188
2189   uint objects_len = 0;
2190   Object **objects = BKE_view_layer_array_from_objects_in_edit_mode_unique_data(
2191       view_layer, CTX_wm_view3d(C), &objects_len);
2192   for (uint ob_index = 0; ob_index < objects_len; ob_index++) {
2193     Object *obedit = objects[ob_index];
2194     BMEditMesh *em = BKE_editmesh_from_object(obedit);
2195
2196     if (em->bm->totfacesel == 0) {
2197       continue;
2198     }
2199
2200     if (!EDBM_op_callf(em, op, "recalc_face_normals faces=%hf", BM_ELEM_SELECT)) {
2201       continue;
2202     }
2203     if (RNA_boolean_get(op->ptr, "inside")) {
2204       EDBM_op_callf(em, op, "reverse_faces faces=%hf flip_multires=%b", BM_ELEM_SELECT, true);
2205     }
2206
2207     EDBM_update_generic(em, true, false);
2208   }
2209   MEM_freeN(objects);
2210
2211   return OPERATOR_FINISHED;
2212 }
2213
2214 void MESH_OT_normals_make_consistent(wmOperatorType *ot)
2215 {
2216   /* identifiers */
2217   ot->name = "Recalculate Normals";
2218   ot->description = "Make face and vertex normals point either outside or inside the mesh";
2219   ot->idname = "MESH_OT_normals_make_consistent";
2220
2221   /* api callbacks */
2222   ot->exec = edbm_normals_make_consistent_exec;
2223   ot->poll = ED_operator_editmesh;
2224
2225   /* flags */
2226   ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
2227
2228   RNA_def_boolean(ot->srna, "inside", false, "Inside", "");
2229 }
2230
2231 /** \} */
2232
2233 /* -------------------------------------------------------------------- */
2234 /** \name Smooth Vertices Operator
2235  * \{ */
2236
2237 static int edbm_do_smooth_vertex_exec(bContext *C, wmOperator *op)
2238 {
2239   const float fac = RNA_float_get(op->ptr, "factor");
2240
2241   const bool xaxis = RNA_boolean_get(op->ptr, "xaxis");
2242   const bool yaxis = RNA_boolean_get(op->ptr, "yaxis");
2243   const bool zaxis = RNA_boolean_get(op->ptr, "zaxis");
2244   int repeat = RNA_int_get(op->ptr, "repeat");
2245
2246   if (!repeat) {
2247     repeat = 1;
2248   }
2249
2250   ViewLayer *view_layer = CTX_data_view_layer(C);
2251   uint objects_len = 0;
2252   Object **objects = BKE_view_layer_array_from_objects_in_edit_mode_unique_data(
2253       view_layer, CTX_wm_view3d(C), &objects_len);
2254   for (uint ob_index = 0; ob_index < objects_len; ob_index++) {
2255     Object *obedit = objects[ob_index];
2256     Mesh *me = obedit->data;
2257     BMEditMesh *em = BKE_editmesh_from_object(obedit);
2258     ModifierData *md;
2259     bool mirrx = false, mirry = false, mirrz = false;
2260     int i;
2261     float clip_dist = 0.0f;
2262     const bool use_topology = (me->editflag & ME_EDIT_MIRROR_TOPO) != 0;
2263
2264     if (em->bm->totvertsel == 0) {
2265       continue;
2266     }
2267
2268     /* mirror before smooth */
2269     if (((Mesh *)obedit->data)->editflag & ME_EDIT_MIRROR_X) {
2270       EDBM_verts_mirror_cache_begin(em, 0, false, true, use_topology);
2271     }
2272
2273     /* if there is a mirror modifier with clipping, flag the verts that
2274      * are within tolerance of the plane(s) of reflection
2275      */
2276     for (md = obedit->modifiers.first; md; md = md->next) {
2277       if (md->type == eModifierType_Mirror && (md->mode & eModifierMode_Realtime)) {
2278         MirrorModifierData *mmd = (MirrorModifierData *)md;
2279
2280         if (mmd->flag & MOD_MIR_CLIPPING) {
2281           if (mmd->flag & MOD_MIR_AXIS_X) {
2282             mirrx = true;
2283           }
2284           if (mmd->flag & MOD_MIR_AXIS_Y) {
2285             mirry = true;
2286           }
2287           if (mmd->flag & MOD_MIR_AXIS_Z) {
2288             mirrz = true;
2289           }
2290
2291           clip_dist = mmd->tolerance;
2292         }
2293       }
2294     }
2295
2296     for (i = 0; i < repeat; i++) {
2297       if (!EDBM_op_callf(
2298               em,
2299               op,
2300               "smooth_vert verts=%hv factor=%f mirror_clip_x=%b mirror_clip_y=%b mirror_clip_z=%b "
2301               "clip_dist=%f use_axis_x=%b use_axis_y=%b use_axis_z=%b",
2302               BM_ELEM_SELECT,
2303               fac,
2304               mirrx,
2305               mirry,
2306               mirrz,
2307               clip_dist,
2308               xaxis,
2309               yaxis,
2310               zaxis)) {
2311         continue;
2312       }
2313     }
2314
2315     /* apply mirror */
2316     if (((Mesh *)obedit->data)->editflag & ME_EDIT_MIRROR_X) {
2317       EDBM_verts_mirror_apply(em, BM_ELEM_SELECT, 0);
2318       EDBM_verts_mirror_cache_end(em);
2319     }
2320
2321     EDBM_update_generic(em, true, false);
2322   }
2323   MEM_freeN(objects);
2324
2325   return OPERATOR_FINISHED;
2326 }
2327
2328 void MESH_OT_vertices_smooth(wmOperatorType *ot)
2329 {
2330   /* identifiers */
2331   ot->name = "Smooth Vertices";
2332   ot->description = "Flatten angles of selected vertices";
2333   ot->idname = "MESH_OT_vertices_smooth";
2334
2335   /* api callbacks */
2336   ot->exec = edbm_do_smooth_vertex_exec;
2337   ot->poll = ED_operator_editmesh;
2338
2339   /* flags */
2340   ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
2341
2342   ot->prop = RNA_def_float_factor(
2343       ot->srna, "factor", 0.5f, -10.0f, 10.0f, "Smoothing", "Smoothing factor", 0.0f, 1.0f);
2344   RNA_def_int(
2345       ot->srna, "repeat", 1, 1, 1000, "Repeat", "Number of times to smooth the mesh", 1, 100);
2346
2347   WM_operatortype_props_advanced_begin(ot);
2348
2349   RNA_def_boolean(ot->srna, "xaxis", true, "X-Axis", "Smooth along the X axis");
2350   RNA_def_boolean(ot->srna, "yaxis", true, "Y-Axis", "Smooth along the Y axis");
2351   RNA_def_boolean(ot->srna, "zaxis", true, "Z-Axis", "Smooth along the Z axis");
2352 }
2353
2354 /** \} */
2355
2356 /* -------------------------------------------------------------------- */
2357 /** \name Laplacian Smooth Vertices Operator
2358  * \{ */
2359
2360 static int edbm_do_smooth_laplacian_vertex_exec(bContext *C, wmOperator *op)
2361 {
2362   BMIter fiter;
2363   BMFace *f;
2364   int tot_invalid = 0;
2365   int tot_unselected = 0;
2366   ViewLayer *view_layer = CTX_data_view_layer(C);
2367
2368   const float lambda_factor = RNA_float_get(op->ptr, "lambda_factor");
2369   const float lambda_border = RNA_float_get(op->ptr, "lambda_border");
2370   const bool usex = RNA_boolean_get(op->ptr, "use_x");
2371   const bool usey = RNA_boolean_get(op->ptr, "use_y");
2372   const bool usez = RNA_boolean_get(op->ptr, "use_z");
2373   const bool preserve_volume = RNA_boolean_get(op->ptr, "preserve_volume");
2374   int repeat = RNA_int_get(op->ptr, "repeat");
2375
2376   if (!repeat) {
2377     repeat = 1;
2378   }
2379
2380   uint objects_len = 0;
2381   Object **objects = BKE_view_layer_array_from_objects_in_edit_mode_unique_data(
2382       view_layer, CTX_wm_view3d(C), &objects_len);
2383   for (uint ob_index = 0; ob_index < objects_len; ob_index++) {
2384     Object *obedit = objects[ob_index];
2385     BMEditMesh *em = BKE_editmesh_from_object(obedit);
2386     Mesh *me = obedit->data;
2387     bool use_topology = (me->editflag & ME_EDIT_MIRROR_TOPO) != 0;
2388
2389     if (em->bm->totvertsel == 0) {
2390       tot_unselected++;
2391       tot_invalid++;
2392       continue;
2393     }
2394
2395     bool is_invalid = false;
2396     /* Check if select faces are triangles. */
2397     BM_ITER_MESH (f, &fiter, em->bm, BM_FACES_OF_MESH) {
2398       if (BM_elem_flag_test(f, BM_ELEM_SELECT)) {
2399         if (f->len > 4) {
2400           tot_invalid++;
2401           is_invalid = true;
2402           break;
2403         }
2404       }
2405     }
2406     if (is_invalid) {
2407       continue;
2408     }
2409
2410     /* Mirror before smooth. */
2411     if (((Mesh *)obedit->data)->editflag & ME_EDIT_MIRROR_X) {
2412       EDBM_verts_mirror_cache_begin(em, 0, false, true, use_topology);
2413     }
2414
2415     bool failed_repeat_loop = false;
2416     for (int i = 0; i < repeat; i++) {
2417       if (!EDBM_op_callf(em,
2418                          op,
2419                          "smooth_laplacian_vert verts=%hv lambda_factor=%f lambda_border=%f "
2420                          "use_x=%b use_y=%b use_z=%b preserve_volume=%b",
2421                          BM_ELEM_SELECT,
2422                          lambda_factor,
2423                          lambda_border,
2424                          usex,
2425                          usey,
2426                          usez,
2427                          preserve_volume)) {
2428         failed_repeat_loop = true;
2429         break;
2430       }
2431     }
2432     if (failed_repeat_loop) {
2433       continue;
2434     }
2435
2436     /* Apply mirror. */
2437     if (((Mesh *)obedit->data)->editflag & ME_EDIT_MIRROR_X) {
2438       EDBM_verts_mirror_apply(em, BM_ELEM_SELECT, 0);
2439       EDBM_verts_mirror_cache_end(em);
2440     }
2441
2442     EDBM_update_generic(em, true, false);
2443   }
2444   MEM_freeN(objects);
2445
2446   if (tot_unselected == objects_len) {
2447     BKE_report(op->reports, RPT_WARNING, "No selected vertex");
2448     return OPERATOR_CANCELLED;
2449   }
2450   else if (tot_invalid == objects_len) {
2451     BKE_report(op->reports, RPT_WARNING, "Selected faces must be triangles or quads");
2452     return OPERATOR_CANCELLED;
2453   }
2454
2455   return OPERATOR_FINISHED;
2456 }
2457
2458 void MESH_OT_vertices_smooth_laplacian(wmOperatorType *ot)
2459 {
2460   /* identifiers */
2461   ot->name = "Laplacian Smooth Vertices";
2462   ot->description = "Laplacian smooth of selected vertices";
2463   ot->idname = "MESH_OT_vertices_smooth_laplacian";
2464
2465   /* api callbacks */
2466   ot->exec = edbm_do_smooth_laplacian_vertex_exec;
2467   ot->poll = ED_operator_editmesh;
2468
2469   /* flags */
2470   ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
2471
2472   RNA_def_int(
2473       ot->srna, "repeat", 1, 1, 1000, "Number of iterations to smooth the mesh", "", 1, 200);
2474   RNA_def_float(
2475       ot->srna, "lambda_factor", 1.0f, 1e-7f, 1000.0f, "Lambda factor", "", 1e-7f, 1000.0f);
2476   RNA_def_float(ot->srna,
2477                 "lambda_border",
2478                 5e-5f,
2479                 1e-7f,
2480                 1000.0f,
2481                 "Lambda factor in border",
2482                 "",
2483                 1e-7f,
2484                 1000.0f);
2485
2486   WM_operatortype_props_advanced_begin(ot);
2487
2488   RNA_def_boolean(ot->srna, "use_x", true, "Smooth X Axis", "Smooth object along X axis");
2489   RNA_def_boolean(ot->srna, "use_y", true, "Smooth Y Axis", "Smooth object along Y axis");
2490   RNA_def_boolean(ot->srna, "use_z", true, "Smooth Z Axis", "Smooth object along Z axis");
2491   RNA_def_boolean(ot->srna,
2492                   "preserve_volume",
2493                   true,
2494                   "Preserve Volume",
2495                   "Apply volume preservation after smooth");
2496 }
2497
2498 /** \} */
2499
2500 /* -------------------------------------------------------------------- */
2501 /** \name Set Faces Smooth Shading Operator
2502  * \{ */
2503
2504 static void mesh_set_smooth_faces(BMEditMesh *em, short smooth)
2505 {
2506   BMIter iter;
2507   BMFace *efa;
2508
2509   if (em == NULL) {
2510     return;
2511   }
2512
2513   BM_ITER_MESH (efa, &iter, em->bm, BM_FACES_OF_MESH) {
2514     if (BM_elem_flag_test(efa, BM_ELEM_SELECT)) {
2515       BM_elem_flag_set(efa, BM_ELEM_SMOOTH, smooth);
2516     }
2517   }
2518 }
2519
2520 static int edbm_faces_shade_smooth_exec(bContext *C, wmOperator *UNUSED(op))
2521 {
2522   ViewLayer *view_layer = CTX_data_view_layer(C);
2523   uint objects_len = 0;
2524   Object **objects = BKE_view_layer_array_from_objects_in_edit_mode_unique_data(
2525       view_layer, CTX_wm_view3d(C), &objects_len);
2526   for (uint ob_index = 0; ob_index < objects_len; ob_index++) {
2527     Object *obedit = objects[ob_index];
2528     BMEditMesh *em = BKE_editmesh_from_object(obedit);
2529
2530     if (em->bm->totfacesel == 0) {
2531       continue;
2532     }
2533
2534     mesh_set_smooth_faces(em, 1);
2535     EDBM_update_generic(em, false, false);
2536   }
2537   MEM_freeN(objects);
2538
2539   return OPERATOR_FINISHED;
2540 }
2541
2542 void MESH_OT_faces_shade_smooth(wmOperatorType *ot)
2543 {
2544   /* identifiers */
2545   ot->name = "Shade Smooth";
2546   ot->description = "Display faces smooth (using vertex normals)";
2547   ot->idname = "MESH_OT_faces_shade_smooth";
2548
2549   /* api callbacks */
2550   ot->exec = edbm_faces_shade_smooth_exec;
2551   ot->poll = ED_operator_editmesh;
2552
2553   /* flags */
2554   ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
2555 }
2556
2557 /** \} */
2558
2559 /* -------------------------------------------------------------------- */
2560 /** \name Set Faces Flat Shading Operator
2561  * \{ */
2562
2563 static int edbm_faces_shade_flat_exec(bContext *C, wmOperator *UNUSED(op))
2564 {
2565   ViewLayer *view_layer = CTX_data_view_layer(C);
2566   uint objects_len = 0;
2567   Object **objects = BKE_view_layer_array_from_objects_in_edit_mode_unique_data(
2568       view_layer, CTX_wm_view3d(C), &objects_len);
2569   for (uint ob_index = 0; ob_index < objects_len; ob_index++) {
2570     Object *obedit = objects[ob_index];
2571     BMEditMesh *em = BKE_editmesh_from_object(obedit);
2572
2573     if (em->bm->totfacesel == 0) {
2574       continue;
2575     }
2576
2577     mesh_set_smooth_faces(em, 0);
2578     EDBM_update_generic(em, false, false);
2579   }
2580   MEM_freeN(objects);
2581
2582   return OPERATOR_FINISHED;
2583 }
2584
2585 void MESH_OT_faces_shade_flat(wmOperatorType *ot)
2586 {
2587   /* identifiers */
2588   ot->name = "Shade Flat";
2589   ot->description = "Display faces flat";
2590   ot->idname = "MESH_OT_faces_shade_flat";
2591
2592   /* api callbacks */
2593   ot->exec = edbm_faces_shade_flat_exec;
2594   ot->poll = ED_operator_editmesh;
2595
2596   /* flags */
2597   ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
2598 }
2599
2600 /** \} */
2601
2602 /* -------------------------------------------------------------------- */
2603 /** \name UV/Color Rotate/Reverse Operator
2604  * \{ */
2605
2606 static int edbm_rotate_uvs_exec(bContext *C, wmOperator *op)
2607 {
2608   /* get the direction from RNA */
2609   const bool use_ccw = RNA_boolean_get(op->ptr, "use_ccw");
2610
2611   ViewLayer *view_layer = CTX_data_view_layer(C);
2612   uint objects_len = 0;
2613   Object **objects = BKE_view_layer_array_from_objects_in_edit_mode_unique_data(
2614       view_layer, CTX_wm_view3d(C), &objects_len);
2615   for (uint ob_index = 0; ob_index < objects_len; ob_index++) {
2616     Object *obedit = objects[ob_index];
2617     BMEditMesh *em = BKE_editmesh_from_object(obedit);
2618
2619     if (em->bm->totfacesel == 0) {
2620       continue;
2621     }
2622
2623     BMOperator bmop;
2624
2625     /* initialize the bmop using EDBM api, which does various ui error reporting and other stuff */
2626     EDBM_op_init(em, &bmop, op, "rotate_uvs faces=%hf use_ccw=%b", BM_ELEM_SELECT, use_ccw);
2627
2628     /* execute the operator */
2629     BMO_op_exec(em->bm, &bmop);
2630
2631     if (!EDBM_op_finish(em, &bmop, op, true)) {
2632       continue;
2633     }
2634
2635     EDBM_update_generic(em, false, false);
2636   }
2637
2638   MEM_freeN(objects);
2639   return OPERATOR_FINISHED;
2640 }
2641
2642 static int edbm_reverse_uvs_exec(bContext *C, wmOperator *op)
2643 {
2644   ViewLayer *view_layer = CTX_data_view_layer(C);
2645   uint objects_len = 0;
2646   Object **objects = BKE_view_layer_array_from_objects_in_edit_mode_unique_data(
2647       view_layer, CTX_wm_view3d(C), &objects_len);
2648   for (uint ob_index = 0; ob_index < objects_len; ob_index++) {
2649     Object *obedit = objects[ob_index];
2650     BMEditMesh *em = BKE_editmesh_from_object(obedit);
2651
2652     if (em->bm->totfacesel == 0) {
2653       continue;
2654     }
2655
2656     BMOperator bmop;
2657
2658     /* initialize the bmop using EDBM api, which does various ui error reporting and other stuff */
2659     EDBM_op_init(em, &bmop, op, "reverse_uvs faces=%hf", BM_ELEM_SELECT);
2660
2661     /* execute the operator */
2662     BMO_op_exec(em->bm, &bmop);
2663
2664     /* finish the operator */
2665     if (!EDBM_op_finish(em, &bmop, op, true)) {
2666       continue;
2667     }
2668     EDBM_update_generic(em, false, false);
2669   }
2670
2671   MEM_freeN(objects);
2672   return OPERATOR_FINISHED;
2673 }
2674
2675 static int edbm_rotate_colors_exec(bContext *C, wmOperator *op)
2676 {
2677   /* get the direction from RNA */
2678   const bool use_ccw = RNA_boolean_get(op->ptr, "use_ccw");
2679
2680   ViewLayer *view_layer = CTX_data_view_layer(C);
2681   uint objects_len = 0;
2682   Object **objects = BKE_view_layer_array_from_objects_in_edit_mode_unique_data(
2683       view_layer, CTX_wm_view3d(C), &objects_len);
2684
2685   for (uint ob_index = 0; ob_index < objects_len; ob_index++) {
2686     Object *ob = objects[ob_index];
2687     BMEditMesh *em = BKE_editmesh_from_object(ob);
2688     if (em->bm->totfacesel == 0) {
2689       continue;
2690     }
2691
2692     BMOperator bmop;
2693
2694     /* initialize the bmop using EDBM api, which does various ui error reporting and other stuff */
2695     EDBM_op_init(em, &bmop, op, "rotate_colors faces=%hf use_ccw=%b", BM_ELEM_SELECT, use_ccw);
2696
2697     /* execute the operator */
2698     BMO_op_exec(em->bm, &bmop);
2699
2700     /* finish the operator */
2701     if (!EDBM_op_finish(em, &bmop, op, true)) {
2702       continue;
2703     }
2704
2705     /* dependencies graph and notification stuff */
2706     EDBM_update_generic(em, false, false);
2707   }
2708
2709   MEM_freeN(objects);
2710
2711   return OPERATOR_FINISHED;
2712 }
2713
2714 static int edbm_reverse_colors_exec(bContext *C, wmOperator *op)
2715 {
2716   ViewLayer *view_layer = CTX_data_view_layer(C);
2717   uint objects_len = 0;
2718   Object **objects = BKE_view_layer_array_from_objects_in_edit_mode_unique_data(
2719       view_layer, CTX_wm_view3d(C), &objects_len);
2720
2721   for (uint ob_index = 0; ob_index < objects_len; ob_index++) {
2722     Object *ob = objects[ob_index];
2723     BMEditMesh *em = BKE_editmesh_from_object(ob);
2724
2725     if (em->bm->totfacesel == 0) {
2726       continue;
2727     }
2728
2729     BMOperator bmop;
2730
2731     /* initialize the bmop using EDBM api, which does various ui error reporting and other stuff */
2732     EDBM_op_init(em, &bmop, op, "reverse_colors faces=%hf", BM_ELEM_SELECT);
2733
2734     /* execute the operator */
2735     BMO_op_exec(em->bm, &bmop);
2736
2737     /* finish the operator */
2738     if (!EDBM_op_finish(em, &bmop, op, true)) {
2739       return OPERATOR_CANCELLED;
2740     }
2741
2742     EDBM_update_generic(em, false, false);
2743   }
2744   MEM_freeN(objects);
2745
2746   return OPERATOR_FINISHED;
2747 }
2748
2749 void MESH_OT_uvs_rotate(wmOperatorType *ot)
2750 {
2751   /* identifiers */
2752   ot->name = "Rotate UVs";
2753   ot->idname = "MESH_OT_uvs_rotate";
2754   ot->description = "Rotate UV coordinates inside faces";
2755
2756   /* api callbacks */
2757   ot->exec = edbm_rotate_uvs_exec;
2758   ot->poll = ED_operator_editmesh;
2759
2760   /* flags */
2761   ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
2762
2763   /* props */
2764   RNA_def_boolean(ot->srna, "use_ccw", false, "Counter Clockwise", "");
2765 }
2766
2767 void MESH_OT_uvs_reverse(wmOperatorType *ot)
2768 {
2769   /* identifiers */
2770   ot->name = "Reverse UVs";
2771   ot->idname = "MESH_OT_uvs_reverse";
2772   ot->description = "Flip direction of UV coordinates inside faces";
2773
2774   /* api callbacks */
2775   ot->exec = edbm_reverse_uvs_exec;
2776   ot->poll = ED_operator_editmesh;
2777
2778   /* flags */
2779   ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
2780
2781   /* props */
2782   // RNA_def_enum(ot->srna, "axis", axis_items, DIRECTION_CW, "Axis", "Axis to mirror UVs around");
2783 }
2784
2785 void MESH_OT_colors_rotate(wmOperatorType *ot)
2786 {
2787   /* identifiers */
2788   ot->name = "Rotate Colors";
2789   ot->idname = "MESH_OT_colors_rotate";
2790   ot->description = "Rotate vertex colors inside faces";
2791
2792   /* api callbacks */
2793   ot->exec = edbm_rotate_colors_exec;
2794   ot->poll = ED_operator_editmesh;
2795
2796   /* flags */
2797   ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
2798
2799   /* props */
2800   RNA_def_boolean(ot->srna, "use_ccw", false, "Counter Clockwise", "");
2801 }
2802
2803 void MESH_OT_colors_reverse(wmOperatorType *ot)
2804 {
2805   /* identifiers */
2806   ot->name = "Reverse Colors";
2807   ot->idname = "MESH_OT_colors_reverse";
2808   ot->description = "Flip direction of vertex colors inside faces";
2809
2810   /* api callbacks */
2811   ot->exec = edbm_reverse_colors_exec;
2812   ot->poll = ED_operator_editmesh;
2813
2814   /* flags */
2815   ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
2816
2817   /* props */
2818 #if 0
2819   RNA_def_enum(ot->srna, "axis", axis_items, DIRECTION_CW, "Axis", "Axis to mirror colors around");
2820 #endif
2821 }
2822
2823 /** \} */
2824
2825 /* -------------------------------------------------------------------- */
2826 /** \name Merge Vertices Operator
2827  * \{ */
2828
2829 enum {
2830   MESH_MERGE_LAST = 1,
2831   MESH_MERGE_CENTER = 3,
2832   MESH_MERGE_CURSOR = 4,
2833   MESH_MERGE_COLLAPSE = 5,
2834   MESH_MERGE_FIRST = 6,
2835 };
2836
2837 static bool merge_firstlast(BMEditMesh *em,
2838                             const bool use_first,
2839                             const bool use_uvmerge,
2840                             wmOperator *wmop)
2841 {
2842   BMVert *mergevert;
2843   BMEditSelection *ese;
2844
2845   /* operator could be called directly from shortcut or python,
2846    * so do extra check for data here
2847    */
2848
2849   /* do sanity check in mergemenu in edit.c ?*/
2850   if (use_first == false) {
2851     if (!em->bm->selected.last || ((BMEditSelection *)em->bm->selected.last)->htype != BM_VERT) {
2852       return false;
2853     }
2854
2855     ese = em->bm->selected.last;
2856     mergevert = (BMVert *)ese->ele;
2857   }
2858   else {
2859     if (!em->bm->selected.first || ((BMEditSelection *)em->bm->selected.first)->htype != BM_VERT) {
2860       return false;
2861     }
2862
2863     ese = em->bm->selected.first;
2864     mergevert = (BMVert *)ese->ele;
2865   }
2866
2867   if (!BM_elem_flag_test(mergevert, BM_ELEM_SELECT)) {
2868     return false;
2869   }
2870
2871   if (use_uvmerge) {
2872     if (!EDBM_op_callf(
2873             em, wmop, "pointmerge_facedata verts=%hv vert_snap=%e", BM_ELEM_SELECT, mergevert)) {
2874       return false;
2875     }
2876   }
2877
2878   if (!EDBM_op_callf(
2879           em, wmop, "pointmerge verts=%hv merge_co=%v", BM_ELEM_SELECT, mergevert->co)) {
2880     return false;
2881   }
2882
2883   return true;
2884 }
2885
2886 static bool merge_target(BMEditMesh *em,
2887                          Scene *scene,
2888                          Object *ob,
2889                          const bool use_cursor,
2890                          const bool use_uvmerge,
2891                          wmOperator *wmop)
2892 {
2893   BMIter iter;
2894   BMVert *v;
2895   float co[3], cent[3] = {0.0f, 0.0f, 0.0f};
2896   const float *vco = NULL;
2897
2898   if (use_cursor) {
2899     vco = scene->cursor.location;
2900     copy_v3_v3(co, vco);
2901     invert_m4_m4(ob->imat, ob->obmat);
2902     mul_m4_v3(ob->imat, co);
2903   }
2904   else {
2905     float fac;
2906     int i = 0;
2907     BM_ITER_MESH (v, &iter, em->bm, BM_VERTS_OF_MESH) {
2908       if (!BM_elem_flag_test(v, BM_ELEM_SELECT)) {
2909         continue;
2910       }
2911       add_v3_v3(cent, v->co);
2912       i++;
2913     }
2914
2915     if (!i) {
2916       return false;
2917     }
2918
2919     fac = 1.0f / (float)i;
2920     mul_v3_fl(cent, fac);
2921     copy_v3_v3(co, cent);
2922     vco = co;
2923   }
2924
2925   if (!vco) {
2926     return false;
2927   }
2928
2929   if (use_uvmerge) {
2930     if (!EDBM_op_callf(em, wmop, "average_vert_facedata verts=%hv", BM_ELEM_SELECT)) {
2931       return false;
2932     }
2933   }
2934
2935   if (!EDBM_op_callf(em, wmop, "pointmerge verts=%hv merge_co=%v", BM_ELEM_SELECT, co)) {
2936     return false;
2937   }
2938
2939   return true;
2940 }
2941
2942 static int edbm_merge_exec(bContext *C, wmOperator *op)
2943 {
2944   Scene *scene = CTX_data_scene(C);
2945   ViewLayer *view_layer = CTX_data_view_layer(C);
2946   uint objects_len = 0;
2947   Object **objects = BKE_view_layer_array_from_objects_in_edit_mode_unique_data(
2948       view_layer, CTX_wm_view3d(C), &objects_len);
2949   const int type = RNA_enum_get(op->ptr, "type");
2950   const bool uvs = RNA_boolean_get(op->ptr, "uvs");
2951
2952   for (uint ob_index = 0; ob_index < objects_len; ob_index++) {
2953     Object *obedit = objects[ob_index];
2954     BMEditMesh *em = BKE_editmesh_from_object(obedit);
2955
2956     if (em->bm->totvertsel == 0) {
2957       continue;
2958     }
2959
2960     bool ok = false;
2961     switch (type) {
2962       case MESH_MERGE_CENTER:
2963         ok = merge_target(em, scene, obedit, false, uvs, op);
2964         break;
2965       case MESH_MERGE_CURSOR:
2966         ok = merge_target(em, scene, obedit, true, uvs, op);
2967         break;
2968       case MESH_MERGE_LAST:
2969         ok = merge_firstlast(em, false, uvs, op);
2970         break;
2971       case MESH_MERGE_FIRST:
2972         ok = merge_firstlast(em, true, uvs, op);
2973         break;
2974       case MESH_MERGE_COLLAPSE:
2975         ok = EDBM_op_callf(em, op, "collapse edges=%he uvs=%b", BM_ELEM_SELECT, uvs);
2976         break;
2977       default:
2978         BLI_assert(0);
2979         break;
2980     }
2981
2982     if (!ok) {
2983       continue;
2984     }
2985
2986     EDBM_update_generic(em, true, true);
2987
2988     /* once collapsed, we can't have edge/face selection */
2989     if ((em->selectmode & SCE_SELECT_VERTEX) == 0) {
2990       EDBM_flag_disable_all(em, BM_ELEM_SELECT);
2991     }
2992     /* Only active object supported, see comment below. */
2993     if (ELEM(type, MESH_MERGE_FIRST, MESH_MERGE_LAST)) {
2994       break;
2995     }
2996   }
2997
2998   MEM_freeN(objects);
2999
3000   return OPERATOR_FINISHED;
3001 }
3002
3003 static const EnumPropertyItem merge_type_items[] = {
3004     {MESH_MERGE_FIRST, "FIRST", 0, "At First", ""},
3005     {MESH_MERGE_LAST, "LAST", 0, "At Last", ""},
3006     {MESH_MERGE_CENTER, "CENTER", 0, "At Center", ""},
3007     {MESH_MERGE_CURSOR, "CURSOR", 0, "At Cursor", ""},
3008     {MESH_MERGE_COLLAPSE, "COLLAPSE", 0, "Collapse", ""},
3009     {0, NULL, 0, NULL, NULL},
3010 };
3011
3012 static const EnumPropertyItem *merge_type_itemf(bContext *C,
3013                                                 PointerRNA *UNUSED(ptr),
3014                                                 PropertyRNA *UNUSED(prop),
3015                                                 bool *r_free)
3016 {
3017   Object *obedit;
3018   EnumPropertyItem *item = NULL;
3019   int totitem = 0;
3020
3021   if (!C) { /* needed for docs */
3022     return merge_type_items;
3023   }
3024
3025   obedit = CTX_data_edit_object(C);
3026   if (obedit && obedit->type == OB_MESH) {
3027     BMEditMesh *em = BKE_editmesh_from_object(obedit);
3028
3029     /* Only active object supported:
3030      * In practice it doesn't make sense to run this operation on non-active meshes
3031      * since selecting will activate - we could have own code-path for these but it's a hassle
3032      * for now just apply to the active (first) object. */
3033     if (em->selectmode & SCE_SELECT_VERTEX) {
3034       if (em->bm->selected.first && em->bm->selected.last &&
3035           ((BMEditSelection *)em->bm->selected.first)->htype == BM_VERT &&
3036           ((BMEditSelection *)em->bm->selected.last)->htype == BM_VERT) {
3037         RNA_enum_items_add_value(&item, &totitem, merge_type_items, MESH_MERGE_FIRST);
3038         RNA_enum_items_add_value(&item, &totitem, merge_type_items, MESH_MERGE_LAST);
3039       }
3040       else if (em->bm->selected.first &&
3041                ((BMEditSelection *)em->bm->selected.first)->htype == BM_VERT) {
3042         RNA_enum_items_add_value(&item, &totitem, merge_type_items, MESH_MERGE_FIRST);
3043       }
3044       else if (em->bm->selected.last &&
3045                ((BMEditSelection *)em->bm->selected.last)->htype == BM_VERT) {
3046         RNA_enum_items_add_value(&item, &totitem, merge_type_items, MESH_MERGE_LAST);
3047       }
3048     }
3049
3050     RNA_enum_items_add_value(&item, &totitem, merge_type_items, MESH_MERGE_CENTER);
3051     RNA_enum_items_add_value(&item, &totitem, merge_type_items, MESH_MERGE_CURSOR);
3052     RNA_enum_items_add_value(&item, &totitem, merge_type_items, MESH_MERGE_COLLAPSE);
3053     RNA_enum_item_end(&item, &totitem);
3054
3055     *r_free = true;
3056
3057     return item;
3058   }
3059
3060   /* Get all items e.g. when creating keymap item. */
3061   return merge_type_items;
3062 }
3063
3064 void MESH_OT_merge(wmOperatorType *ot)
3065 {
3066   /* identifiers */
3067   ot->name = "Merge";
3068   ot->description = "Merge selected vertices";
3069   ot->idname = "MESH_OT_merge";
3070
3071   /* api callbacks */
3072   ot->exec = edbm_merge_exec;
3073   ot->invoke = WM_menu_invoke;
3074   ot->poll = ED_operator_editmesh;
3075
3076   /* flags */
3077   ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
3078
3079   /* properties */
3080   ot->prop = RNA_def_enum(
3081       ot->srna, "type", merge_type_items, MESH_MERGE_CENTER, "Type", "Merge method to use");
3082   RNA_def_enum_funcs(ot->prop, merge_type_itemf);
3083
3084   WM_operatortype_props_advanced_begin(ot);
3085
3086   RNA_def_boolean(ot->srna, "uvs", false, "UVs", "Move UVs according to merge");
3087 }
3088
3089 /** \} */
3090
3091 /* -------------------------------------------------------------------- */
3092 /** \name Remove Doubles Operator
3093  * \{ */
3094
3095 static int edbm_remove_doubles_exec(bContext *C, wmOperator *op)
3096 {
3097   const float threshold = RNA_float_get(op->ptr, "threshold");
3098   const bool use_unselected = RNA_boolean_get(op->ptr, "use_unselected");
3099   int count_multi = 0;
3100
3101   ViewLayer *view_layer = CTX_data_view_layer(C);
3102   uint objects_len = 0;
3103   Object **objects = BKE_view_layer_array_from_objects_in_edit_mode_unique_data(
3104       view_layer, CTX_wm_view3d(C), &objects_len);
3105
3106   for (uint ob_index = 0; ob_index < objects_len; ob_index++) {
3107     Object *obedit = objects[ob_index];
3108     BMEditMesh *em = BKE_editmesh_from_object(obedit);
3109
3110     /* Selection used as target with 'use_unselected'. */
3111     if (em->bm->totvertsel == 0) {
3112       continue;
3113     }
3114
3115     BMOperator bmop;
3116     const int totvert_orig = em->bm->totvert;
3117
3118     /* avoid losing selection state (select -> tags) */
3119     char htype_select;
3120     if (em->selectmode & SCE_SELECT_VERTEX) {
3121       htype_select = BM_VERT;
3122     }
3123     else if (em->selectmode & SCE_SELECT_EDGE) {
3124       htype_select = BM_EDGE;
3125     }
3126     else {
3127       htype_select = BM_FACE;
3128     }
3129
3130     /* store selection as tags */
3131     BM_mesh_elem_hflag_enable_test(em->bm, htype_select, BM_ELEM_TAG, true, true, BM_ELEM_SELECT);
3132
3133     if (use_unselected) {
3134       EDBM_automerge(obedit, false, BM_ELEM_SELECT, threshold);
3135     }
3136     else {
3137       EDBM_op_init(em, &bmop, op, "find_doubles verts=%hv dist=%f", BM_ELEM_SELECT, threshold);
3138
3139       BMO_op_exec(em->bm, &bmop);
3140
3141       if (!EDBM_op_callf(em, op, "weld_verts targetmap=%S", &bmop, "targetmap.out")) {
3142         BMO_op_finish(em->bm, &bmop);
3143         continue;
3144       }
3145
3146       if (!EDBM_op_finish(em, &bmop, op, true)) {
3147         continue;
3148       }
3149     }
3150
3151     const int count = (totvert_orig - em->bm->totvert);
3152
3153     /* restore selection from tags */
3154     BM_mesh_elem_hflag_enable_test(em->bm, htype_select, BM_ELEM_SELECT, true, true, BM_ELEM_TAG);
3155     EDBM_selectmode_flush(em);
3156
3157     if (count) {
3158       count_multi += count;
3159       EDBM_update_generic(em, true, true);
3160     }
3161   }
3162   MEM_freeN(objects);
3163
3164   BKE_reportf(op->reports, RPT_INFO, "Removed %d vertice(s)", count_multi);
3165
3166   return OPERATOR_FINISHED;
3167 }
3168
3169 void MESH_OT_remove_doubles(wmOperatorType *ot)
3170 {
3171   /* identifiers */
3172   ot->name = "Merge by Distance";
3173   ot->description = "Merge vertices based on their proximity";
3174   ot->idname = "MESH_OT_remove_doubles";
3175
3176   /* api callbacks */
3177   ot->exec = edbm_remove_doubles_exec;
3178   ot->poll = ED_operator_editmesh;
3179
3180   /* flags */
3181   ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
3182
3183   RNA_def_float_distance(ot->srna,
3184                          "threshold",
3185                          1e-4f,
3186                          1e-6f,
3187                          50.0f,
3188                          "Merge Distance",
3189                          "Maximum distance between elements to merge",
3190                          1e-5f,
3191                          10.0f);
3192   RNA_def_boolean(ot->srna,
3193                   "use_unselected",
3194                   false,
3195                   "Unselected",
3196                   "Merge selected to other unselected vertices");
3197 }
3198
3199 /** \} */
3200
3201 /* -------------------------------------------------------------------- */
3202 /** \name Shape Key Propagate Operator
3203  * \{ */
3204
3205 /* BMESH_TODO this should be properly encapsulated in a bmop.  but later.*/
3206 static bool shape_propagate(BMEditMesh *em)
3207 {
3208   BMIter iter;
3209   BMVert *eve = NULL;
3210   float *co;
3211   int totshape = CustomData_number_of_layers(&em->bm->vdata, CD_SHAPEKEY);
3212
3213   if (!CustomData_has_layer(&em->bm->vdata, CD_SHAPEKEY)) {
3214     return false;
3215   }
3216
3217   BM_ITER_MESH (eve, &iter, em->bm, BM_VERTS_OF_MESH) {
3218     if (!BM_elem_flag_test(eve, BM_ELEM_SELECT) || BM_elem_flag_test(eve, BM_ELEM_HIDDEN)) {
3219       continue;
3220     }
3221
3222     for (int i = 0; i < totshape; i++) {
3223       co = CustomData_bmesh_get_n(&em->bm->vdata, eve->head.data, CD_SHAPEKEY, i);
3224       copy_v3_v3(co, eve->co);
3225     }
3226   }
3227   return true;
3228 }
3229
3230 static int edbm_shape_propagate_to_all_exec(bContext *C, wmOperator *op)
3231 {
3232   ViewLayer *view_layer = CTX_data_view_layer(C);
3233   int tot_shapekeys = 0;
3234   int tot_selected_verts_objects = 0;
3235
3236   uint objects_len = 0;
3237   Object **objects = BKE_view_layer_array_from_objects_in_edit_mode_unique_data(
3238       view_layer, CTX_wm_view3d(C), &objects_len);
3239   for (uint ob_index = 0; ob_index < objects_len; ob_index++) {
3240     Object *obedit = objects[ob_index];
3241     Mesh *me = obedit->data;
3242     BMEditMesh *em = me->edit_mesh;
3243
3244     if (em->bm->totvertsel == 0) {
3245       continue;
3246     }
3247     tot_selected_verts_objects++;
3248
3249     if (shape_propagate(em)) {
3250       tot_shapekeys++;
3251     }
3252
3253     EDBM_update_generic(em, false, false);
3254   }
3255   MEM_freeN(objects);
3256
3257   if (tot_selected_verts_objects == 0) {
3258     BKE_report(op->reports, RPT_ERROR, "No selected vertex");
3259     return OPERATOR_CANCELLED;
3260   }
3261   else if (tot_shapekeys == 0) {
3262     BKE_report(op->reports,
3263                RPT_ERROR,
3264                objects_len > 1 ? "Meshes do not have shape keys" :
3265                                  "Mesh does not have shape keys");
3266     return OPERATOR_CANCELLED;
3267   }
3268
3269   return OPERATOR_FINISHED;
3270 }
3271
3272 void MESH_OT_shape_propagate_to_all(wmOperatorType *ot)
3273 {
3274   /* identifiers */
3275   ot->name = "Shape Propagate";
3276   ot->description = "Apply selected vertex locations to all other shape keys";
3277   ot->idname = "MESH_OT_shape_propagate_to_all";
3278
3279   /* api callbacks */
3280   ot->exec = edbm_shape_propagate_to_all_exec;
3281   ot->poll = ED_operator_editmesh;
3282
3283   /* flags */
3284   ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
3285 }
3286
3287 /** \} */
3288
3289 /* -------------------------------------------------------------------- */
3290 /** \name Blend from Shape Operator
3291  * \{ */
3292
3293 /* BMESH_TODO this should be properly encapsulated in a bmop.  but later.*/
3294 static int edbm_blend_from_shape_exec(bContext *C, wmOperator *op)
3295 {
3296   Object *obedit_ref = CTX_data_edit_object(C);
3297   Mesh *me_ref = obedit_ref->data;
3298   Key *key_ref = me_ref->key;
3299   KeyBlock *kb_ref = NULL;
3300   BMEditMesh *em_ref = me_ref->edit_mesh;
3301   BMVert *eve;
3302   BMIter iter;
3303   ViewLayer *view_layer = CTX_data_view_layer(C);
3304   float co[3], *sco;
3305   int totshape_ref = 0;
3306
3307   const float blend = RNA_float_get(op->ptr, "blend");
3308   int shape_ref = RNA_enum_get(op->ptr, "shape");
3309   const bool use_add = RNA_boolean_get(op->ptr, "add");
3310
3311   /* Sanity check. */
3312   totshape_ref = CustomData_number_of_layers(&em_ref->bm->vdata, CD_SHAPEKEY);
3313
3314   if (totshape_ref == 0 || shape_ref < 0) {
3315     BKE_report(op->reports, RPT_ERROR, "Active mesh does not have shape keys");
3316     return OPERATOR_CANCELLED;
3317   }
3318   else if (shape_ref >= totshape_ref) {
3319     /* This case occurs if operator was used before on object with more keys than current one. */
3320     shape_ref = 0; /* default to basis */
3321   }
3322
3323   /* Get shape key - needed for finding reference shape (for add mode only). */
3324   if (key_ref) {
3325     kb_ref = BLI_findlink(&key_ref->block, shape_ref);
3326   }
3327
3328   int tot_selected_verts_objects = 0;
3329   uint objects_len = 0;
3330   Object **objects = BKE_view_layer_array_from_objects_in_edit_mode_unique_data(
3331       view_layer, CTX_wm_view3d(C), &objects_len);
3332   for (uint ob_index = 0; ob_index < objects_len; ob_index++) {
3333     Object *obedit = objects[ob_index];
3334     Mesh *me = obedit->data;
3335     Key *key = me->key;
3336     KeyBlock *kb = NULL;
3337     BMEditMesh *em = me->edit_mesh;
3338     int shape;
3339
3340     if (em->bm->totvertsel == 0) {
3341       continue;
3342     }
3343     tot_selected_verts_objects++;
3344
3345     if (!key) {
3346       continue;
3347     }
3348     else {
3349       kb = BKE_keyblock_find_name(key, kb_ref->name);
3350       shape = BLI_findindex(&key->block, kb);
3351     }
3352
3353     if (kb) {
3354       /* Perform blending on selected vertices. */
3355       BM_ITER_MESH (eve, &iter, em->bm, BM_VERTS_OF_MESH) {
3356         if (!BM_elem_flag_test(eve, BM_ELEM_SELECT) || BM_elem_flag_test(eve, BM_ELEM_HIDDEN)) {
3357           continue;
3358         }
3359
3360         /* Get coordinates of shapekey we're blending from. */
3361         sco = CustomData_bmesh_get_n(&em->bm->vdata, eve->head.data, CD_SHAPEKEY, shape);
3362         copy_v3_v3(co, sco);
3363
3364         if (use_add) {
3365           /* In add mode, we add relative shape key offset. */
3366           if (kb) {
3367             const float *rco = CustomData_bmesh_get_n(
3368                 &em->bm->vdata, eve->head.data, CD_SHAPEKEY, kb->relative);
3369             sub_v3_v3v3(co, co, rco);
3370           }
3371
3372           madd_v3_v3fl(eve->co, co, blend);
3373         }
3374         else {
3375           /* In blend mode, we interpolate to the shape key. */
3376           interp_v3_v3v3(eve->co, eve->co, co, blend);
3377         }
3378       }
3379       EDBM_update_generic(em, true, false);
3380     }
3381   }
3382   MEM_freeN(objects);
3383
3384   if (tot_selected_verts_objects == 0) {
3385     BKE_report(op->reports, RPT_ERROR, "No selected vertex");
3386     return OPERATOR_CANCELLED;
3387   }
3388
3389   return OPERATOR_FINISHED;
3390 }
3391
3392 static const EnumPropertyItem *shape_itemf(bContext *C,
3393                                            PointerRNA *UNUSED(ptr),
3394                                            PropertyRNA *UNUSED(prop),
3395                                            bool *r_free)
3396 {
3397   Object *obedit = CTX_data_edit_object(C);
3398   BMEditMesh *em;
3399   EnumPropertyItem *item = NULL;
3400   int totitem = 0;
3401
3402   if ((obedit && obedit->type == OB_MESH) && (em = BKE_editmesh_from_object(obedit)) &&
3403       CustomData_has_layer(&em->bm->vdata, CD_SHAPEKEY)) {
3404     EnumPropertyItem tmp = {0, "", 0, "", ""};
3405     int a;
3406
3407     for (a = 0; a < em->bm->vdata.totlayer; a++) {
3408       if (em->bm->vdata.layers[a].type != CD_SHAPEKEY) {
3409         continue;
3410       }
3411
3412       tmp.value = totitem;
3413       tmp.identifier = em->bm->vdata.layers[a].name;
3414       tmp.name = em->bm->vdata.layers[a].name;
3415       /* RNA_enum_item_add sets totitem itself! */
3416       RNA_enum_item_add(&item, &totitem, &tmp);
3417     }
3418   }
3419
3420   RNA_enum_item_end(&item, &totitem);
3421   *r_free = true;
3422
3423   return item;
3424 }
3425
3426 static void edbm_blend_from_shape_ui(bContext *C, wmOperator *op)
3427 {
3428   uiLayout *layout = op->layout;
3429   PointerRNA ptr;
3430   Object *obedit = CTX_data_edit_object(C);
3431   Mesh *me = obedit->data;
3432   PointerRNA ptr_key;
3433
3434   RNA_pointer_create(NULL, op->type->srna, op->properties, &ptr);
3435   RNA_id_pointer_create((ID *)me->key, &ptr_key);
3436
3437   uiItemPointerR(layout, &ptr, "shape", &ptr_key, "key_blocks", "", ICON_SHAPEKEY_DATA);
3438   uiItemR(layout, &ptr, "blend", 0, NULL, ICON_NONE);
3439   uiItemR(layout, &ptr, "add", 0, NULL, ICON_NONE);
3440 }
3441
3442 void MESH_OT_blend_from_shape(wmOperatorType *ot)
3443 {
3444   PropertyRNA *prop;
3445
3446   /* identifiers */
3447   ot->name = "Blend From Shape";
3448   ot->description = "Blend in shape from a shape key";
3449   ot->idname = "MESH_OT_blend_from_shape";
3450
3451   /* api callbacks */
3452   ot->exec = edbm_blend_from_shape_exec;
3453   /* disable because search popup closes too easily */
3454   //  ot->invoke = WM_operator_props_popup_call;
3455   ot->ui = edbm_blend_from_shape_ui;
3456   ot->poll = ED_operator_editmesh;
3457
3458   /* flags */
3459   ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
3460
3461   /* properties */
3462   prop = RNA_def_enum(
3463       ot->srna, "shape", DummyRNA_NULL_items, 0, "Shape", "Shape key to use for blending");
3464   RNA_def_enum_funcs(prop, shape_itemf);
3465   RNA_def_property_flag(prop, PROP_ENUM_NO_TRANSLATE | PROP_NEVER_UNLINK);
3466   RNA_def_float(ot->srna, "blend", 1.0f, -1e3f, 1e3f, "Blend", "Blending factor", -2.0f, 2.0f);
3467   RNA_def_boolean(ot->srna, "add", true, "Add", "Add rather than blend between shapes");
3468 }
3469
3470 /** \} */
3471
3472 /* -------------------------------------------------------------------- */
3473 /** \name Solidify Mesh Operator
3474  * \{ */
3475
3476 static int edbm_solidify_exec(bContext *C, wmOperator *op)
3477 {
3478   const float thickness = RNA_float_get(op->ptr, "thickness");
3479
3480   ViewLayer *view_layer = CTX_data_view_layer(C);
3481   uint objects_len = 0;
3482   Object **objects = BKE_view_layer_array_from_objects_in_edit_mode_unique_data(
3483       view_layer, CTX_wm_view3d(C), &objects_len);
3484   for (uint ob_index = 0; ob_index < objects_len; ob_index++) {
3485     Object *obedit = objects[ob_index];
3486     BMEditMesh *em = BKE_editmesh_from_object(obedit);
3487     BMesh *bm = em->bm;
3488
3489     if (em->bm->totfacesel == 0) {
3490       continue;
3491     }
3492
3493     BMOperator bmop;
3494
3495     if (!EDBM_op_init(
3496             em, &bmop, op, "solidify geom=%hf thickness=%f", BM_ELEM_SELECT, thickness)) {
3497       continue;
3498     }
3499
3500     /* deselect only the faces in the region to be solidified (leave wire
3501      * edges and loose verts selected, as there will be no corresponding
3502      * geometry selected below) */
3503     BMO_slot_buffer_hflag_disable(bm, bmop.slots_in, "geom", BM_FACE, BM_ELEM_SELECT, true);
3504
3505     /* run the solidify operator */
3506     BMO_op_exec(bm, &bmop);
3507
3508     /* select the newly generated faces */
3509     BMO_slot_buffer_hflag_enable(bm, bmop.slots_out, "geom.out", BM_FACE, BM_ELEM_SELECT, true);
3510
3511     if (!EDBM_op_finish(em, &bmop, op, true)) {
3512       continue;
3513     }
3514
3515     EDBM_update_generic(em, true, true);
3516   }
3517
3518   MEM_freeN(objects);
3519   return OPERATOR_FINISHED;
3520 }
3521
3522 void MESH_OT_solidify(wmOperatorType *ot)
3523 {
3524   PropertyRNA *prop;
3525   /* identifiers */
3526   ot->name = "Solidify";
3527   ot->description = "Create a solid skin by extruding, compensating for sharp angles";
3528   ot->idname = "MESH_OT_solidify";
3529
3530   /* api callbacks */
3531   ot->exec = edbm_solidify_exec;
3532   ot->poll = ED_operator_editmesh;
3533
3534   /* flags */
3535   ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
3536
3537   prop = RNA_def_float_distance(
3538       ot->srna, "thickness", 0.01f, -1e4f, 1e4f, "Thickness", "", -10.0f, 10.0f);
3539   RNA_def_property_ui_range(prop, -10.0, 10.0, 0.1, 4);
3540 }
3541
3542 /** \} */
3543
3544 /* -------------------------------------------------------------------- */
3545 /** \name Knife Subdivide Operator
3546  * \{ */
3547
3548 #define KNIFE_EXACT 1
3549 #define KNIFE_MIDPOINT 2
3550 #define KNIFE_MULTICUT 3
3551
3552 static const EnumPropertyItem knife_items[] = {
3553     {KNIFE_EXACT, "EXACT", 0, "Exact", ""},
3554     {KNIFE_MIDPOINT, "MIDPOINTS", 0, "Midpoints", ""},
3555     {KNIFE_MULTICUT, "MULTICUT", 0, "Multicut", ""},
3556     {0, NULL, 0, NULL, NULL},
3557 };
3558
3559 /* bm_edge_seg_isect() Determines if and where a mouse trail intersects an BMEdge */
3560
3561 static float bm_edge_seg_isect(const float sco_a[2],
3562                                const float sco_b[2],
3563                                float (*mouse_path)[2],
3564                                int len,
3565                                char mode,
3566                                int *isected)
3567 {
3568 #define MAXSLOPE 100000
3569   float x11, y11, x12 = 0, y12 = 0, x2max, x2min, y2max;
3570   float y2min, dist, lastdist = 0, xdiff2, xdiff1;
3571   float m1, b1, m2, b2, x21, x22, y21, y22, xi;
3572   float yi, x1min, x1max, y1max, y1min, perc = 0;
3573   float threshold = 0.0;
3574   int i;
3575
3576   // threshold = 0.000001; /* tolerance for vertex intersection */
3577   // XXX threshold = scene->toolsettings->select_thresh / 100;
3578
3579   /* Get screen coords of verts */
3580   x21 = sco_a[0];
3581   y21 = sco_a[1];
3582
3583   x22 = sco_b[0];
3584   y22 = sco_b[1];
3585
3586   xdiff2 = (x22 - x21);
3587   if (xdiff2) {
3588     m2 = (y22 - y21) / xdiff2;
3589     b2 = ((x22 * y21) - (x21 * y22)) / xdiff2;
3590   }
3591   else {
3592     m2 = MAXSLOPE; /* Vertical slope  */
3593     b2 = x22;
3594   }
3595
3596   *isected = 0;
3597
3598   /* check for _exact_ vertex intersection first */
3599   if (mode != KNIFE_MULTICUT) {
3600     for (i = 0; i < len; i++) {
3601       if (i > 0) {
3602         x11 = x12;
3603         y11 = y12;
3604       }
3605       else {
3606         x11 = mouse_path[i][0];
3607         y11 = mouse_path[i][1];
3608       }
3609       x12 = mouse_path[i][0];
3610       y12 = mouse_path[i][1];
3611
3612       /* test e->v1 */
3613       if ((x11 == x21 && y11 == y21) || (x12 == x21 && y12 == y21)) {
3614         perc = 0;
3615         *isected = 1;
3616         return perc;
3617       }
3618       /* test e->v2 */
3619       else if ((x11 == x22 && y11 == y22) || (x12 == x22 && y12 == y22)) {
3620         perc = 0;
3621         *isected = 2;
3622         return perc;
3623       }
3624     }
3625   }
3626
3627   /* now check for edge intersect (may produce vertex intersection as well) */
3628   for (i = 0; i < len; i++) {
3629     if (i > 0) {
3630       x11 = x12;
3631       y11 = y12;
3632     }
3633     else {
3634       x11 = mouse_path[i][0];
3635       y11 = mouse_path[i][1];
3636     }
3637     x12 = mouse_path[i][0];
3638     y12 = mouse_path[i][1];
3639
3640     /* Perp. Distance from point to line */
3641     if (m2 != MAXSLOPE) {
3642       /* sqrt(m2 * m2 + 1); Only looking for change in sign.  Skip extra math .*/
3643       dist = (y12 - m2 * x12 - b2);
3644     }
3645     else {
3646       dist = x22 - x12;
3647     }
3648
3649     if (i == 0) {
3650       lastdist = dist;
3651     }
3652
3653     /* if dist changes sign, and intersect point in edge's Bound Box */
3654     if ((lastdist * dist) <= 0) {
3655       xdiff1 = (x12 - x11); /* Equation of line between last 2 points */
3656       if (xdiff1) {
3657         m1 = (y12 - y11) / xdiff1;
3658         b1 = ((x12 * y11) - (x11 * y12)) / xdiff1;
3659       }
3660       else {
3661         m1 = MAXSLOPE;
3662         b1 = x12;
3663       }
3664       x2max = max_ff(x21, x22) + 0.001f; /* prevent missed edges   */
3665       x2min = min_ff(x21, x22) - 0.001f; /* due to round off error */
3666       y2max = max_ff(y21, y22) + 0.001f;
3667       y2min = min_ff(y21, y22) - 0.001f;
3668
3669       /* Found an intersect,  calc intersect point */
3670       if (m1 == m2) { /* co-incident lines */
3671         /* cut at 50% of overlap area */
3672         x1max = max_ff(x11, x12);
3673         x1min = min_ff(x11, x12);
3674         xi = (min_ff(x2max, x1max) + max_ff(x2min, x1min)) / 2.0f;
3675
3676         y1max = max_ff(y11, y12);
3677         y1min = min_ff(y11, y12);
3678         yi = (min_ff(y2max, y1max) + max_ff(y2min, y1min)) / 2.0f;
3679       }
3680       else if (m2 == MAXSLOPE) {
3681         xi = x22;
3682         yi = m1 * x22 + b1;
3683       }
3684       else if (m1 == MAXSLOPE) {
3685         xi = x12;
3686         yi = m2 * x12 + b2;
3687       }
3688       else {
3689         xi = (b1 - b2) / (m2 - m1);
3690         yi = (b1 * m2 - m1 * b2) / (m2 - m1);
3691       }
3692
3693       /* Intersect inside bounding box of edge?*/
3694       if ((xi >= x2min) && (xi <= x2max) && (yi <= y2max) && (yi >= y2min)) {
3695         /* test for vertex intersect that may be 'close enough'*/
3696         if (mode != KNIFE_MULTICUT) {
3697           if (xi <= (x21 + threshold) && xi >= (x21 - threshold)) {
3698             if (yi <= (y21 + threshold) && yi >= (y21 - threshold)) {
3699               *isected = 1;
3700               perc = 0;
3701               break;
3702             }
3703           }
3704           if (xi <= (x22 + threshold) && xi >= (x22 - threshold)) {
3705             if (yi <= (y22 + threshold) && yi >= (y22 - threshold)) {
3706               *isected = 2;
3707               perc = 0;
3708               break;
3709             }
3710           }
3711         }