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