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         BMOperator bmop;
861         Object *obedit = CTX_data_edit_object(C);
862         BMEditMesh *em = BKE_editmesh_from_object(obedit);
863         const bool use_smooth = edbm_add_edge_face__smooth_get(em->bm);
864         const int totedge_orig = em->bm->totedge;
865         const int totface_orig = em->bm->totface;
866         /* when this is used to dissolve we could avoid this, but checking isnt too slow */
867
868 #ifdef USE_FACE_CREATE_SEL_EXTEND
869         BMElem *ele_desel;
870         BMFace *ele_desel_face;
871
872         /* be extra clever, figure out if a partial selection should be extended so we can create geometry
873          * with single vert or single edge selection */
874         ele_desel = edbm_add_edge_face_exec__tricky_extend_sel(em->bm);
875 #endif
876
877         if (!EDBM_op_init(
878                     em, &bmop, op,
879                     "contextual_create geom=%hfev mat_nr=%i use_smooth=%b",
880                     BM_ELEM_SELECT, em->mat_nr, use_smooth))
881         {
882                 return OPERATOR_CANCELLED;
883         }
884
885         BMO_op_exec(em->bm, &bmop);
886
887         /* cancel if nothing was done */
888         if ((totedge_orig == em->bm->totedge) &&
889             (totface_orig == em->bm->totface))
890         {
891                 EDBM_op_finish(em, &bmop, op, true);
892                 return OPERATOR_CANCELLED;
893         }
894
895 #ifdef USE_FACE_CREATE_SEL_EXTEND
896         /* normally we would want to leave the new geometry selected,
897          * but being able to press F many times to add geometry is too useful! */
898         if (ele_desel &&
899             (BMO_slot_buffer_count(bmop.slots_out, "faces.out") == 1) &&
900             (ele_desel_face = BMO_slot_buffer_get_first(bmop.slots_out, "faces.out")))
901         {
902                 edbm_add_edge_face_exec__tricky_finalize_sel(em->bm, ele_desel, ele_desel_face);
903         }
904         else
905 #endif
906         {
907                 /* Newly created faces may include existing hidden edges,
908                  * copying face data from surrounding, may have copied hidden face flag too.
909                  *
910                  * Important that faces use flushing since 'edges.out' wont include hidden edges that already existed.
911                  */
912                 BMO_slot_buffer_hflag_disable(em->bm, bmop.slots_out, "faces.out", BM_FACE, BM_ELEM_HIDDEN, true);
913                 BMO_slot_buffer_hflag_disable(em->bm, bmop.slots_out, "edges.out", BM_EDGE, BM_ELEM_HIDDEN, false);
914
915                 BMO_slot_buffer_hflag_enable(em->bm, bmop.slots_out, "faces.out", BM_FACE, BM_ELEM_SELECT, true);
916                 BMO_slot_buffer_hflag_enable(em->bm, bmop.slots_out, "edges.out", BM_EDGE, BM_ELEM_SELECT, true);
917         }
918
919         if (!EDBM_op_finish(em, &bmop, op, true)) {
920                 return OPERATOR_CANCELLED;
921         }
922
923         EDBM_update_generic(em, true, true);
924
925         return OPERATOR_FINISHED;
926 }
927
928 void MESH_OT_edge_face_add(wmOperatorType *ot)
929 {
930         /* identifiers */
931         ot->name = "Make Edge/Face";
932         ot->description = "Add an edge or face to selected";
933         ot->idname = "MESH_OT_edge_face_add";
934
935         /* api callbacks */
936         ot->exec = edbm_add_edge_face_exec;
937         ot->poll = ED_operator_editmesh;
938
939         /* flags */
940         ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
941 }
942
943 /** \} */
944
945 /* -------------------------------------------------------------------- */
946 /** \name Mark Edge (Seam) Operator
947  * \{ */
948
949 static int edbm_mark_seam_exec(bContext *C, wmOperator *op)
950 {
951         Scene *scene = CTX_data_scene(C);
952         ViewLayer *view_layer = CTX_data_view_layer(C);
953         BMEdge *eed;
954         BMIter iter;
955         const bool clear = RNA_boolean_get(op->ptr, "clear");
956
957         uint objects_len = 0;
958         Object **objects = BKE_view_layer_array_from_objects_in_edit_mode_unique_data(view_layer, &objects_len);
959         for (uint ob_index = 0; ob_index < objects_len; ob_index++) {
960                 Object *obedit = objects[ob_index];
961                 BMEditMesh *em = BKE_editmesh_from_object(obedit);
962                 BMesh *bm = em->bm;
963
964                 if (bm->totedgesel == 0) {
965                         continue;
966                 }
967
968                 Mesh *me = ((Mesh *)obedit->data);
969
970                 /* auto-enable seams drawing */
971                 if (clear == 0) {
972                         me->drawflag |= ME_DRAWSEAMS;
973                 }
974
975                 if (clear) {
976                         BM_ITER_MESH (eed, &iter, bm, BM_EDGES_OF_MESH) {
977                                 if (!BM_elem_flag_test(eed, BM_ELEM_SELECT) || BM_elem_flag_test(eed, BM_ELEM_HIDDEN)) {
978                                         continue;
979                                 }
980
981                                 BM_elem_flag_disable(eed, BM_ELEM_SEAM);
982                         }
983                 }
984                 else {
985                         BM_ITER_MESH (eed, &iter, bm, BM_EDGES_OF_MESH) {
986                                 if (!BM_elem_flag_test(eed, BM_ELEM_SELECT) || BM_elem_flag_test(eed, BM_ELEM_HIDDEN)) {
987                                         continue;
988                                 }
989                                 BM_elem_flag_enable(eed, BM_ELEM_SEAM);
990                         }
991                 }
992
993                 ED_uvedit_live_unwrap(scene, obedit);
994                 EDBM_update_generic(em, true, false);
995         }
996         MEM_freeN(objects);
997
998         return OPERATOR_FINISHED;
999 }
1000
1001 void MESH_OT_mark_seam(wmOperatorType *ot)
1002 {
1003         PropertyRNA *prop;
1004
1005         /* identifiers */
1006         ot->name = "Mark Seam";
1007         ot->idname = "MESH_OT_mark_seam";
1008         ot->description = "(Un)mark selected edges as a seam";
1009
1010         /* api callbacks */
1011         ot->exec = edbm_mark_seam_exec;
1012         ot->poll = ED_operator_editmesh;
1013
1014         /* flags */
1015         ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
1016
1017         prop = RNA_def_boolean(ot->srna, "clear", 0, "Clear", "");
1018         RNA_def_property_flag(prop, PROP_SKIP_SAVE);
1019
1020         WM_operatortype_props_advanced_begin(ot);
1021 }
1022
1023 /** \} */
1024
1025 /* -------------------------------------------------------------------- */
1026 /** \name Mark Edge (Sharp) Operator
1027  * \{ */
1028
1029 static int edbm_mark_sharp_exec(bContext *C, wmOperator *op)
1030 {
1031         BMEdge *eed;
1032         BMIter iter;
1033         const bool clear = RNA_boolean_get(op->ptr, "clear");
1034         const bool use_verts = RNA_boolean_get(op->ptr, "use_verts");
1035         ViewLayer *view_layer = CTX_data_view_layer(C);
1036
1037         uint objects_len = 0;
1038         Object **objects = BKE_view_layer_array_from_objects_in_edit_mode_unique_data(view_layer, &objects_len);
1039         for (uint ob_index = 0; ob_index < objects_len; ob_index++) {
1040                 Object *obedit = objects[ob_index];
1041                 BMEditMesh *em = BKE_editmesh_from_object(obedit);
1042                 BMesh *bm = em->bm;
1043                 Mesh *me = ((Mesh *)obedit->data);
1044
1045                 if (bm->totedgesel == 0) {
1046                         continue;
1047                 }
1048
1049                 /* auto-enable sharp edge drawing */
1050                 if (clear == 0) {
1051                         me->drawflag |= ME_DRAWSHARP;
1052                 }
1053
1054                 BM_ITER_MESH (eed, &iter, bm, BM_EDGES_OF_MESH) {
1055                         if (use_verts) {
1056                                 if (!(BM_elem_flag_test(eed->v1, BM_ELEM_SELECT) || BM_elem_flag_test(eed->v2, BM_ELEM_SELECT))) {
1057                                         continue;
1058                                 }
1059                         }
1060                         else if (!BM_elem_flag_test(eed, BM_ELEM_SELECT)) {
1061                                 continue;
1062                         }
1063
1064                         BM_elem_flag_set(eed, BM_ELEM_SMOOTH, clear);
1065                 }
1066
1067                 EDBM_update_generic(em, true, false);
1068         }
1069         MEM_freeN(objects);
1070
1071         return OPERATOR_FINISHED;
1072 }
1073
1074 void MESH_OT_mark_sharp(wmOperatorType *ot)
1075 {
1076         PropertyRNA *prop;
1077
1078         /* identifiers */
1079         ot->name = "Mark Sharp";
1080         ot->idname = "MESH_OT_mark_sharp";
1081         ot->description = "(Un)mark selected edges as sharp";
1082
1083         /* api callbacks */
1084         ot->exec = edbm_mark_sharp_exec;
1085         ot->poll = ED_operator_editmesh;
1086
1087         /* flags */
1088         ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
1089
1090         prop = RNA_def_boolean(ot->srna, "clear", false, "Clear", "");
1091         RNA_def_property_flag(prop, PROP_SKIP_SAVE);
1092         prop = RNA_def_boolean(ot->srna, "use_verts", false, "Vertices",
1093                                "Consider vertices instead of edges to select which edges to (un)tag as sharp");
1094         RNA_def_property_flag(prop, PROP_SKIP_SAVE);
1095 }
1096
1097 static int edbm_vert_connect_exec(bContext *C, wmOperator *op)
1098 {
1099         Object *obedit = CTX_data_edit_object(C);
1100         BMEditMesh *em = BKE_editmesh_from_object(obedit);
1101         BMesh *bm = em->bm;
1102         BMOperator bmop;
1103         bool is_pair = (bm->totvertsel == 2);
1104         int len = 0;
1105         bool check_degenerate = true;
1106         const int verts_len = bm->totvertsel;
1107         BMVert **verts;
1108
1109         verts = MEM_mallocN(sizeof(*verts) * verts_len, __func__);
1110         {
1111                 BMIter iter;
1112                 BMVert *v;
1113                 int i = 0;
1114
1115                 BM_ITER_MESH (v, &iter, bm, BM_VERTS_OF_MESH) {
1116                         if (BM_elem_flag_test(v, BM_ELEM_SELECT)) {
1117                                 verts[i++] = v;
1118                         }
1119                 }
1120
1121                 if (is_pair) {
1122                         if (BM_vert_pair_share_face_check_cb(
1123                                 verts[0], verts[1],
1124                                 BM_elem_cb_check_hflag_disabled_simple(BMFace *, BM_ELEM_HIDDEN)))
1125                         {
1126                                 check_degenerate = false;
1127                                 is_pair = false;
1128                         }
1129                 }
1130         }
1131
1132         if (is_pair) {
1133                 if (!EDBM_op_init(
1134                             em, &bmop, op,
1135                             "connect_vert_pair verts=%eb verts_exclude=%hv faces_exclude=%hf",
1136                             verts, verts_len, BM_ELEM_HIDDEN, BM_ELEM_HIDDEN))
1137                 {
1138                         goto finally;
1139                 }
1140         }
1141         else {
1142                 if (!EDBM_op_init(
1143                             em, &bmop, op,
1144                             "connect_verts verts=%eb faces_exclude=%hf check_degenerate=%b",
1145                             verts, verts_len, BM_ELEM_HIDDEN, check_degenerate))
1146                 {
1147                         goto finally;
1148                 }
1149         }
1150
1151         BMO_op_exec(bm, &bmop);
1152         len = BMO_slot_get(bmop.slots_out, "edges.out")->len;
1153
1154         if (len) {
1155                 if (is_pair) {
1156                         /* new verts have been added, we have to select the edges, not just flush */
1157                         BMO_slot_buffer_hflag_enable(em->bm, bmop.slots_out, "edges.out", BM_EDGE, BM_ELEM_SELECT, true);
1158                 }
1159         }
1160
1161         if (!EDBM_op_finish(em, &bmop, op, true)) {
1162                 len = 0;
1163         }
1164         else {
1165                 EDBM_selectmode_flush(em);  /* so newly created edges get the selection state from the vertex */
1166
1167                 EDBM_update_generic(em, true, true);
1168         }
1169
1170
1171 finally:
1172         MEM_freeN(verts);
1173         return len ? OPERATOR_FINISHED : OPERATOR_CANCELLED;
1174 }
1175
1176 void MESH_OT_vert_connect(wmOperatorType *ot)
1177 {
1178         /* identifiers */
1179         ot->name = "Vertex Connect";
1180         ot->idname = "MESH_OT_vert_connect";
1181         ot->description = "Connect selected vertices of faces, splitting the face";
1182
1183         /* api callbacks */
1184         ot->exec = edbm_vert_connect_exec;
1185         ot->poll = ED_operator_editmesh;
1186
1187         /* flags */
1188         ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
1189 }
1190
1191 /** \} */
1192
1193 /* -------------------------------------------------------------------- */
1194 /** \name Split Concave Faces Operator
1195  * \{ */
1196
1197 /**
1198  * check that endpoints are verts and only have a single selected edge connected.
1199  */
1200 static bool bm_vert_is_select_history_open(BMesh *bm)
1201 {
1202         BMEditSelection *ele_a = bm->selected.first;
1203         BMEditSelection *ele_b = bm->selected.last;
1204         if ((ele_a->htype == BM_VERT) &&
1205             (ele_b->htype == BM_VERT))
1206         {
1207                 if ((BM_iter_elem_count_flag(BM_EDGES_OF_VERT, (BMVert *)ele_a->ele, BM_ELEM_SELECT, true) == 1) &&
1208                     (BM_iter_elem_count_flag(BM_EDGES_OF_VERT, (BMVert *)ele_b->ele, BM_ELEM_SELECT, true) == 1))
1209                 {
1210                         return true;
1211                 }
1212         }
1213
1214         return false;
1215 }
1216
1217 static bool bm_vert_connect_pair(BMesh *bm, BMVert *v_a, BMVert *v_b)
1218 {
1219         BMOperator bmop;
1220         BMVert **verts;
1221         const int totedge_orig = bm->totedge;
1222
1223         BMO_op_init(bm, &bmop, BMO_FLAG_DEFAULTS, "connect_vert_pair");
1224
1225         verts = BMO_slot_buffer_alloc(&bmop, bmop.slots_in, "verts", 2);
1226         verts[0] = v_a;
1227         verts[1] = v_b;
1228
1229         BM_vert_normal_update(verts[0]);
1230         BM_vert_normal_update(verts[1]);
1231
1232         BMO_op_exec(bm, &bmop);
1233         BMO_slot_buffer_hflag_enable(bm, bmop.slots_out, "edges.out", BM_EDGE, BM_ELEM_SELECT, true);
1234         BMO_op_finish(bm, &bmop);
1235         return (bm->totedge != totedge_orig);
1236 }
1237
1238 static bool bm_vert_connect_select_history(BMesh *bm)
1239 {
1240         /* Logic is as follows:
1241          *
1242          * - If there are any isolated/wire verts - connect as edges.
1243          * - Otherwise connect faces.
1244          * - If all edges have been created already, closed the loop.
1245          */
1246         if (BLI_listbase_count_at_most(&bm->selected, 2) == 2 && (bm->totvertsel > 2)) {
1247                 BMEditSelection *ese;
1248                 int tot = 0;
1249                 bool changed = false;
1250                 bool has_wire = false;
1251                 // bool all_verts;
1252
1253                 /* ensure all verts have history */
1254                 for (ese = bm->selected.first; ese; ese = ese->next, tot++) {
1255                         BMVert *v;
1256                         if (ese->htype != BM_VERT) {
1257                                 break;
1258                         }
1259                         v = (BMVert *)ese->ele;
1260                         if ((has_wire == false) && ((v->e == NULL) || BM_vert_is_wire(v))) {
1261                                 has_wire = true;
1262                         }
1263                 }
1264                 // all_verts = (ese == NULL);
1265
1266                 if (has_wire == false) {
1267                         /* all verts have faces , connect verts via faces! */
1268                         if (tot == bm->totvertsel) {
1269                                 BMEditSelection *ese_last;
1270                                 ese_last = bm->selected.first;
1271                                 ese = ese_last->next;
1272
1273                                 do {
1274
1275                                         if (BM_edge_exists((BMVert *)ese_last->ele, (BMVert *)ese->ele)) {
1276                                                 /* pass, edge exists (and will be selected) */
1277                                         }
1278                                         else {
1279                                                 changed |= bm_vert_connect_pair(bm, (BMVert *)ese_last->ele, (BMVert *)ese->ele);
1280                                         }
1281                                 } while ((void)
1282                                          (ese_last = ese),
1283                                          (ese = ese->next));
1284
1285                                 if (changed) {
1286                                         return true;
1287                                 }
1288                         }
1289
1290                         if (changed == false) {
1291                                 /* existing loops: close the selection */
1292                                 if (bm_vert_is_select_history_open(bm)) {
1293                                         changed |= bm_vert_connect_pair(
1294                                                 bm,
1295                                                 (BMVert *)((BMEditSelection *)bm->selected.first)->ele,
1296                                                 (BMVert *)((BMEditSelection *)bm->selected.last)->ele);
1297
1298                                         if (changed) {
1299                                                 return true;
1300                                         }
1301                                 }
1302                         }
1303                 }
1304
1305                 else {
1306                         /* no faces, simply connect the verts by edges */
1307                         BMEditSelection *ese_prev;
1308                         ese_prev = bm->selected.first;
1309                         ese = ese_prev->next;
1310
1311
1312                         do {
1313                                 if (BM_edge_exists((BMVert *)ese_prev->ele, (BMVert *)ese->ele)) {
1314                                         /* pass, edge exists (and will be selected) */
1315                                 }
1316                                 else {
1317                                         BMEdge *e;
1318                                         e = BM_edge_create(bm, (BMVert *)ese_prev->ele, (BMVert *)ese->ele, NULL, 0);
1319                                         BM_edge_select_set(bm, e, true);
1320                                         changed = true;
1321                                 }
1322                         } while ((void)
1323                                  (ese_prev = ese),
1324                                  (ese = ese->next));
1325
1326                         if (changed == false) {
1327                                 /* existing loops: close the selection */
1328                                 if (bm_vert_is_select_history_open(bm)) {
1329                                         BMEdge *e;
1330                                         ese_prev = bm->selected.first;
1331                                         ese = bm->selected.last;
1332                                         e = BM_edge_create(bm, (BMVert *)ese_prev->ele, (BMVert *)ese->ele, NULL, 0);
1333                                         BM_edge_select_set(bm, e, true);
1334                                 }
1335                         }
1336
1337                         return true;
1338                 }
1339         }
1340
1341         return false;
1342 }
1343
1344 /**
1345  * Convert an edge selection to a temp vertex selection
1346  * (which must be cleared after use as a path to connect).
1347  */
1348 static bool bm_vert_connect_select_history_edge_to_vert_path(BMesh *bm, ListBase *r_selected)
1349 {
1350         ListBase selected_orig = {NULL, NULL};
1351         BMEditSelection *ese;
1352         int edges_len = 0;
1353         bool side = false;
1354
1355         /* first check all edges are OK */
1356         for (ese = bm->selected.first; ese; ese = ese->next) {
1357                 if (ese->htype == BM_EDGE) {
1358                         edges_len += 1;
1359                 }
1360                 else {
1361                         return false;
1362                 }
1363         }
1364         /* if this is a mixed selection, bail out! */
1365         if (bm->totedgesel != edges_len) {
1366                 return false;
1367         }
1368
1369         SWAP(ListBase, bm->selected, selected_orig);
1370
1371         /* convert edge selection into 2 ordered loops (where the first edge ends up in the middle) */
1372         for (ese = selected_orig.first; ese; ese = ese->next) {
1373                 BMEdge *e_curr = (BMEdge *)ese->ele;
1374                 BMEdge *e_prev = ese->prev ? (BMEdge *)ese->prev->ele : NULL;
1375                 BMLoop *l_curr;
1376                 BMLoop *l_prev;
1377                 BMVert *v;
1378
1379                 if (e_prev) {
1380                         BMFace *f = BM_edge_pair_share_face_by_len(e_curr, e_prev, &l_curr, &l_prev, true);
1381                         if (f) {
1382                                 if ((e_curr->v1 != l_curr->v) == (e_prev->v1 != l_prev->v)) {
1383                                         side = !side;
1384                                 }
1385                         }
1386                         else if (is_quad_flip_v3(e_curr->v1->co, e_curr->v2->co, e_prev->v2->co, e_prev->v1->co)) {
1387                                 side = !side;
1388                         }
1389                 }
1390
1391                 v = (&e_curr->v1)[side];
1392                 if (!bm->selected.last || (BMVert *)((BMEditSelection *)bm->selected.last)->ele != v) {
1393                         BM_select_history_store_notest(bm, v);
1394                 }
1395
1396                 v = (&e_curr->v1)[!side];
1397                 if (!bm->selected.first || (BMVert *)((BMEditSelection *)bm->selected.first)->ele != v) {
1398                         BM_select_history_store_head_notest(bm, v);
1399                 }
1400
1401                 e_prev = e_curr;
1402         }
1403
1404         *r_selected = bm->selected;
1405         bm->selected = selected_orig;
1406
1407         return true;
1408 }
1409
1410 static int edbm_vert_connect_path_exec(bContext *C, wmOperator *op)
1411 {
1412         Object *obedit = CTX_data_edit_object(C);
1413         BMEditMesh *em = BKE_editmesh_from_object(obedit);
1414         BMesh *bm = em->bm;
1415         bool is_pair = (em->bm->totvertsel == 2);
1416         ListBase selected_orig = {NULL, NULL};
1417         int retval;
1418
1419         /* when there is only 2 vertices, we can ignore selection order */
1420         if (is_pair) {
1421                 return edbm_vert_connect_exec(C, op);
1422         }
1423
1424         if (bm->selected.first) {
1425                 BMEditSelection *ese = bm->selected.first;
1426                 if (ese->htype == BM_EDGE) {
1427                         if (bm_vert_connect_select_history_edge_to_vert_path(bm, &selected_orig)) {
1428                                 SWAP(ListBase, bm->selected, selected_orig);
1429                         }
1430                 }
1431         }
1432
1433         if (bm_vert_connect_select_history(bm)) {
1434                 EDBM_selectmode_flush(em);
1435                 EDBM_update_generic(em, true, true);
1436                 retval = OPERATOR_FINISHED;
1437         }
1438         else {
1439                 BKE_report(op->reports, RPT_ERROR, "Invalid selection order");
1440                 retval = OPERATOR_CANCELLED;
1441         }
1442
1443         if (!BLI_listbase_is_empty(&selected_orig)) {
1444                 BM_select_history_clear(bm);
1445                 bm->selected = selected_orig;
1446         }
1447
1448         return retval;
1449 }
1450
1451 void MESH_OT_vert_connect_path(wmOperatorType *ot)
1452 {
1453         /* identifiers */
1454         ot->name = "Vertex Connect Path";
1455         ot->idname = "MESH_OT_vert_connect_path";
1456         ot->description = "Connect vertices by their selection order, creating edges, splitting faces";
1457
1458         /* api callbacks */
1459         ot->exec = edbm_vert_connect_path_exec;
1460         ot->poll = ED_operator_editmesh;
1461
1462         /* flags */
1463         ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
1464 }
1465
1466 static int edbm_vert_connect_concave_exec(bContext *C, wmOperator *op)
1467 {
1468         Object *obedit = CTX_data_edit_object(C);
1469         BMEditMesh *em = BKE_editmesh_from_object(obedit);
1470
1471         if (!EDBM_op_call_and_selectf(
1472                      em, op,
1473                      "faces.out", true,
1474                      "connect_verts_concave faces=%hf",
1475                      BM_ELEM_SELECT))
1476         {
1477                 return OPERATOR_CANCELLED;
1478         }
1479
1480
1481         EDBM_update_generic(em, true, true);
1482         return OPERATOR_FINISHED;
1483 }
1484
1485 void MESH_OT_vert_connect_concave(wmOperatorType *ot)
1486 {
1487         /* identifiers */
1488         ot->name = "Split Concave Faces";
1489         ot->idname = "MESH_OT_vert_connect_concave";
1490         ot->description = "Make all faces convex";
1491
1492         /* api callbacks */
1493         ot->exec = edbm_vert_connect_concave_exec;
1494         ot->poll = ED_operator_editmesh;
1495
1496         /* flags */
1497         ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
1498 }
1499
1500 /** \} */
1501
1502 /* -------------------------------------------------------------------- */
1503 /** \name Split Non-Planar Faces Operator
1504  * \{ */
1505
1506 static int edbm_vert_connect_nonplaner_exec(bContext *C, wmOperator *op)
1507 {
1508         Object *obedit = CTX_data_edit_object(C);
1509         BMEditMesh *em = BKE_editmesh_from_object(obedit);
1510
1511         const float angle_limit = RNA_float_get(op->ptr, "angle_limit");
1512
1513         if (!EDBM_op_call_and_selectf(
1514                      em, op,
1515                      "faces.out", true,
1516                      "connect_verts_nonplanar faces=%hf angle_limit=%f",
1517                      BM_ELEM_SELECT, angle_limit))
1518         {
1519                 return OPERATOR_CANCELLED;
1520         }
1521
1522
1523         EDBM_update_generic(em, true, true);
1524         return OPERATOR_FINISHED;
1525 }
1526
1527 void MESH_OT_vert_connect_nonplanar(wmOperatorType *ot)
1528 {
1529         PropertyRNA *prop;
1530
1531         /* identifiers */
1532         ot->name = "Split Non-Planar Faces";
1533         ot->idname = "MESH_OT_vert_connect_nonplanar";
1534         ot->description = "Split non-planar faces that exceed the angle threshold";
1535
1536         /* api callbacks */
1537         ot->exec = edbm_vert_connect_nonplaner_exec;
1538         ot->poll = ED_operator_editmesh;
1539
1540         /* flags */
1541         ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
1542
1543         /* props */
1544         prop = RNA_def_float_rotation(ot->srna, "angle_limit", 0, NULL, 0.0f, DEG2RADF(180.0f),
1545                                       "Max Angle", "Angle limit", 0.0f, DEG2RADF(180.0f));
1546         RNA_def_property_float_default(prop, DEG2RADF(5.0f));
1547 }
1548
1549 /** \} */
1550
1551 /* -------------------------------------------------------------------- */
1552 /** \name Make Planar Faces Operator
1553  * \{ */
1554
1555 static int edbm_face_make_planar_exec(bContext *C, wmOperator *op)
1556 {
1557         ViewLayer *view_layer = CTX_data_view_layer(C);
1558         uint objects_len = 0;
1559         Object **objects = BKE_view_layer_array_from_objects_in_edit_mode_unique_data(view_layer, &objects_len);
1560
1561         const int repeat = RNA_int_get(op->ptr, "repeat");
1562         const float fac = RNA_float_get(op->ptr, "factor");
1563
1564         for (uint ob_index = 0; ob_index < objects_len; ob_index++) {
1565                 Object *obedit = objects[ob_index];
1566                 BMEditMesh *em = BKE_editmesh_from_object(obedit);
1567                 if (em->bm->totfacesel == 0) {
1568                         continue;
1569                 }
1570
1571                 if (!EDBM_op_callf(
1572                             em, op, "planar_faces faces=%hf iterations=%i factor=%f",
1573                             BM_ELEM_SELECT, repeat, fac))
1574                 {
1575                         continue;
1576                 }
1577
1578                 EDBM_update_generic(em, true, true);
1579         }
1580         MEM_freeN(objects);
1581
1582         return OPERATOR_FINISHED;
1583 }
1584
1585 void MESH_OT_face_make_planar(wmOperatorType *ot)
1586 {
1587         /* identifiers */
1588         ot->name = "Make Planar Faces";
1589         ot->idname = "MESH_OT_face_make_planar";
1590         ot->description = "Flatten selected faces";
1591
1592         /* api callbacks */
1593         ot->exec = edbm_face_make_planar_exec;
1594         ot->poll = ED_operator_editmesh;
1595
1596         /* flags */
1597         ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
1598
1599         /* props */
1600         RNA_def_float(ot->srna, "factor", 1.0f, -10.0f, 10.0f, "Factor", "", 0.0f, 1.0f);
1601         RNA_def_int(ot->srna, "repeat", 1, 1, 10000, "Iterations", "", 1, 200);
1602 }
1603
1604 /** \} */
1605
1606 /* -------------------------------------------------------------------- */
1607 /** \name Split Edge Operator
1608  * \{ */
1609
1610 static int edbm_edge_split_exec(bContext *C, wmOperator *op)
1611 {
1612         ViewLayer *view_layer = CTX_data_view_layer(C);
1613         uint objects_len = 0;
1614         Object **objects = BKE_view_layer_array_from_objects_in_edit_mode_unique_data(view_layer, &objects_len);
1615         for (uint ob_index = 0; ob_index < objects_len; ob_index++) {
1616                 Object *obedit = objects[ob_index];
1617                 BMEditMesh *em = BKE_editmesh_from_object(obedit);
1618                 if (em->bm->totedgesel == 0) {
1619                         continue;
1620                 }
1621
1622                 if (!EDBM_op_call_and_selectf(
1623                             em, op,
1624                             "edges.out", false,
1625                             "split_edges edges=%he",
1626                             BM_ELEM_SELECT))
1627                 {
1628                         continue;
1629                 }
1630
1631                 if (em->selectmode == SCE_SELECT_FACE) {
1632                         EDBM_select_flush(em);
1633                 }
1634
1635                 EDBM_update_generic(em, true, true);
1636         }
1637         MEM_freeN(objects);
1638
1639         return OPERATOR_FINISHED;
1640 }
1641
1642 void MESH_OT_edge_split(wmOperatorType *ot)
1643 {
1644         /* identifiers */
1645         ot->name = "Edge Split";
1646         ot->idname = "MESH_OT_edge_split";
1647         ot->description = "Split selected edges so that each neighbor face gets its own copy";
1648
1649         /* api callbacks */
1650         ot->exec = edbm_edge_split_exec;
1651         ot->poll = ED_operator_editmesh;
1652
1653         /* flags */
1654         ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
1655 }
1656
1657 /** \} */
1658
1659 /* -------------------------------------------------------------------- */
1660 /** \name Duplicate Operator
1661  * \{ */
1662
1663 static int edbm_duplicate_exec(bContext *C, wmOperator *op)
1664 {
1665         ViewLayer *view_layer = CTX_data_view_layer(C);
1666         uint objects_len = 0;
1667         Object **objects = BKE_view_layer_array_from_objects_in_edit_mode_unique_data(view_layer, &objects_len);
1668
1669         for (uint ob_index = 0; ob_index < objects_len; ob_index++) {
1670                 Object *obedit = objects[ob_index];
1671                 BMEditMesh *em = BKE_editmesh_from_object(obedit);
1672                 if (em->bm->totvertsel == 0) {
1673                         continue;
1674                 }
1675
1676                 BMOperator bmop;
1677                 BMesh *bm = em->bm;
1678
1679                 EDBM_op_init(
1680                         em, &bmop, op,
1681                         "duplicate geom=%hvef use_select_history=%b",
1682                         BM_ELEM_SELECT, true);
1683
1684                 BMO_op_exec(bm, &bmop);
1685
1686                 /* de-select all would clear otherwise */
1687                 BM_SELECT_HISTORY_BACKUP(bm);
1688
1689                 EDBM_flag_disable_all(em, BM_ELEM_SELECT);
1690
1691                 BMO_slot_buffer_hflag_enable(bm, bmop.slots_out, "geom.out", BM_ALL_NOLOOP, BM_ELEM_SELECT, true);
1692
1693                 /* rebuild editselection */
1694                 BM_SELECT_HISTORY_RESTORE(bm);
1695
1696                 if (!EDBM_op_finish(em, &bmop, op, true)) {
1697                         continue;
1698                 }
1699                 EDBM_update_generic(em, true, true);
1700         }
1701         MEM_freeN(objects);
1702
1703         return OPERATOR_FINISHED;
1704 }
1705
1706 static int edbm_duplicate_invoke(bContext *C, wmOperator *op, const wmEvent *UNUSED(event))
1707 {
1708         WM_cursor_wait(1);
1709         edbm_duplicate_exec(C, op);
1710         WM_cursor_wait(0);
1711
1712         return OPERATOR_FINISHED;
1713 }
1714
1715 void MESH_OT_duplicate(wmOperatorType *ot)
1716 {
1717         /* identifiers */
1718         ot->name = "Duplicate";
1719         ot->description = "Duplicate selected vertices, edges or faces";
1720         ot->idname = "MESH_OT_duplicate";
1721
1722         /* api callbacks */
1723         ot->invoke = edbm_duplicate_invoke;
1724         ot->exec = edbm_duplicate_exec;
1725
1726         ot->poll = ED_operator_editmesh;
1727
1728         /* to give to transform */
1729         RNA_def_int(ot->srna, "mode", TFM_TRANSLATION, 0, INT_MAX, "Mode", "", 0, INT_MAX);
1730 }
1731
1732 /** \} */
1733
1734 /* -------------------------------------------------------------------- */
1735 /** \name Flip Normals Operator
1736  * \{ */
1737 static int edbm_flip_normals_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
1747                 if (em->bm->totfacesel == 0) {
1748                         continue;
1749                 }
1750
1751                 if (!EDBM_op_callf(
1752                         em, op, "reverse_faces faces=%hf flip_multires=%b",
1753                         BM_ELEM_SELECT, true))
1754                 {
1755                         continue;
1756                 }
1757
1758                 EDBM_update_generic(em, true, false);
1759         }
1760
1761         MEM_freeN(objects);
1762         return OPERATOR_FINISHED;
1763 }
1764
1765 void MESH_OT_flip_normals(wmOperatorType *ot)
1766 {
1767         /* identifiers */
1768         ot->name = "Flip Normals";
1769         ot->description = "Flip the direction of selected faces' normals (and of their vertices)";
1770         ot->idname = "MESH_OT_flip_normals";
1771
1772         /* api callbacks */
1773         ot->exec = edbm_flip_normals_exec;
1774         ot->poll = ED_operator_editmesh;
1775
1776         /* flags */
1777         ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
1778 }
1779
1780 /** \} */
1781
1782 /* -------------------------------------------------------------------- */
1783 /** \name Rotate Edge Operator
1784  * \{ */
1785
1786 /**
1787  * Rotate the edges between selected faces, otherwise rotate the selected edges.
1788  */
1789 static int edbm_edge_rotate_selected_exec(bContext *C, wmOperator *op)
1790 {
1791         BMEdge *eed;
1792         BMIter iter;
1793         const bool use_ccw = RNA_boolean_get(op->ptr, "use_ccw");
1794
1795         int tot_rotate_all = 0, tot_failed_all = 0;
1796         bool no_selected_edges = true, invalid_selected_edges = true;
1797
1798         ViewLayer *view_layer = CTX_data_view_layer(C);
1799         uint objects_len = 0;
1800         Object **objects = BKE_view_layer_array_from_objects_in_edit_mode_unique_data(view_layer, &objects_len);
1801         for (uint ob_index = 0; ob_index < objects_len; ob_index++) {
1802                 Object *obedit = objects[ob_index];
1803                 BMEditMesh *em = BKE_editmesh_from_object(obedit);
1804                 int tot = 0;
1805
1806                 if (em->bm->totedgesel == 0) {
1807                         continue;
1808                 }
1809                 no_selected_edges = false;
1810
1811                 /* first see if we have two adjacent faces */
1812                 BM_ITER_MESH (eed, &iter, em->bm, BM_EDGES_OF_MESH) {
1813                         BM_elem_flag_disable(eed, BM_ELEM_TAG);
1814                         if (BM_elem_flag_test(eed, BM_ELEM_SELECT)) {
1815                                 BMFace *fa, *fb;
1816                                 if (BM_edge_face_pair(eed, &fa, &fb)) {
1817                                         /* if both faces are selected we rotate between them,
1818                                          * otherwise - rotate between 2 unselected - but not mixed */
1819                                         if (BM_elem_flag_test(fa, BM_ELEM_SELECT) == BM_elem_flag_test(fb, BM_ELEM_SELECT)) {
1820                                                 BM_elem_flag_enable(eed, BM_ELEM_TAG);
1821                                                 tot++;
1822                                         }
1823                                 }
1824                         }
1825                 }
1826
1827                 /* ok, we don't have two adjacent faces, but we do have two selected ones.
1828                  * that's an error condition.*/
1829                 if (tot == 0) {
1830                         continue;
1831                 }
1832                 invalid_selected_edges = false;
1833
1834                 BMOperator bmop;
1835                 EDBM_op_init(em, &bmop, op, "rotate_edges edges=%he use_ccw=%b", BM_ELEM_TAG, use_ccw);
1836
1837                 /* avoids leaving old verts selected which can be a problem running multiple times,
1838                  * since this means the edges become selected around the face which then attempt to rotate */
1839                 BMO_slot_buffer_hflag_disable(em->bm, bmop.slots_in, "edges", BM_EDGE, BM_ELEM_SELECT, true);
1840
1841                 BMO_op_exec(em->bm, &bmop);
1842                 /* edges may rotate into hidden vertices, if this does _not_ run we get an ilogical state */
1843                 BMO_slot_buffer_hflag_disable(em->bm, bmop.slots_out, "edges.out", BM_EDGE, BM_ELEM_HIDDEN, true);
1844                 BMO_slot_buffer_hflag_enable(em->bm, bmop.slots_out, "edges.out", BM_EDGE, BM_ELEM_SELECT, true);
1845
1846                 const int tot_rotate = BMO_slot_buffer_count(bmop.slots_out, "edges.out");
1847                 const int tot_failed = tot - tot_rotate;
1848
1849                 tot_rotate_all += tot_rotate;
1850                 tot_failed_all += tot_failed;
1851
1852                 if (tot_failed != 0) {
1853                         /* If some edges fail to rotate, we need to re-select them,
1854                          * otherwise we can end up with invalid selection
1855                          * (unselected edge between 2 selected faces). */
1856                         BM_mesh_elem_hflag_enable_test(em->bm, BM_EDGE, BM_ELEM_SELECT, true, false, BM_ELEM_TAG);
1857                 }
1858
1859                 EDBM_selectmode_flush(em);
1860
1861                 if (!EDBM_op_finish(em, &bmop, op, true)) {
1862                         continue;
1863                 }
1864
1865                 EDBM_update_generic(em, true, true);
1866         }
1867         MEM_freeN(objects);
1868
1869         if (no_selected_edges) {
1870                 BKE_report(op->reports, RPT_ERROR, "Select edges or face pairs for edge loops to rotate about");
1871                 return OPERATOR_CANCELLED;
1872         }
1873
1874         /* Ok, we don't have two adjacent faces, but we do have two selected ones.
1875          * that's an error condition. */
1876         if (invalid_selected_edges) {
1877                 BKE_report(op->reports, RPT_ERROR, "Could not find any selected edges that can be rotated");
1878                 return OPERATOR_CANCELLED;
1879         }
1880
1881         if (tot_failed_all != 0) {
1882                 BKE_reportf(op->reports, RPT_WARNING, "Unable to rotate %d edge(s)", tot_failed_all);
1883         }
1884
1885         return OPERATOR_FINISHED;
1886 }
1887
1888 void MESH_OT_edge_rotate(wmOperatorType *ot)
1889 {
1890         /* identifiers */
1891         ot->name = "Rotate Selected Edge";
1892         ot->description = "Rotate selected edge or adjoining faces";
1893         ot->idname = "MESH_OT_edge_rotate";
1894
1895         /* api callbacks */
1896         ot->exec = edbm_edge_rotate_selected_exec;
1897         ot->poll = ED_operator_editmesh;
1898
1899         /* flags */
1900         ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
1901
1902         /* props */
1903         RNA_def_boolean(ot->srna, "use_ccw", false, "Counter Clockwise", "");
1904 }
1905
1906 /** \} */
1907
1908 /* -------------------------------------------------------------------- */
1909 /** \name Hide Operator
1910  * \{ */
1911
1912 static int edbm_hide_exec(bContext *C, wmOperator *op)
1913 {
1914         const bool unselected = RNA_boolean_get(op->ptr, "unselected");
1915         ViewLayer *view_layer = CTX_data_view_layer(C);
1916
1917         uint objects_len = 0;
1918         Object **objects = BKE_view_layer_array_from_objects_in_edit_mode_unique_data(view_layer, &objects_len);
1919         for (uint ob_index = 0; ob_index < objects_len; ob_index++) {
1920                 Object *obedit = objects[ob_index];
1921                 BMEditMesh *em = BKE_editmesh_from_object(obedit);
1922                 BMesh *bm = em->bm;
1923
1924                 if ((bm->totvertsel == 0) &&
1925                     (bm->totedgesel == 0) &&
1926                     (bm->totfacesel == 0))
1927                 {
1928                         continue;
1929                 }
1930
1931                 EDBM_mesh_hide(em, unselected);
1932                 EDBM_update_generic(em, true, false);
1933         }
1934
1935         MEM_freeN(objects);
1936         return OPERATOR_FINISHED;
1937 }
1938
1939 void MESH_OT_hide(wmOperatorType *ot)
1940 {
1941         /* identifiers */
1942         ot->name = "Hide Selection";
1943         ot->idname = "MESH_OT_hide";
1944         ot->description = "Hide (un)selected vertices, edges or faces";
1945
1946         /* api callbacks */
1947         ot->exec = edbm_hide_exec;
1948         ot->poll = ED_operator_editmesh;
1949
1950         /* flags */
1951         ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
1952
1953         /* props */
1954         RNA_def_boolean(ot->srna, "unselected", false, "Unselected", "Hide unselected rather than selected");
1955 }
1956
1957 /** \} */
1958
1959 /* -------------------------------------------------------------------- */
1960 /** \name Reveal Operator
1961  * \{ */
1962
1963 static int edbm_reveal_exec(bContext *C, wmOperator *op)
1964 {
1965         const bool select = RNA_boolean_get(op->ptr, "select");
1966         ViewLayer *view_layer = CTX_data_view_layer(C);
1967
1968         uint objects_len = 0;
1969         Object **objects = BKE_view_layer_array_from_objects_in_edit_mode_unique_data(view_layer, &objects_len);
1970         for (uint ob_index = 0; ob_index < objects_len; ob_index++) {
1971                 Object *obedit = objects[ob_index];
1972                 BMEditMesh *em = BKE_editmesh_from_object(obedit);
1973
1974                 EDBM_mesh_reveal(em, select);
1975                 EDBM_update_generic(em, true, false);
1976         }
1977         MEM_freeN(objects);
1978
1979         return OPERATOR_FINISHED;
1980 }
1981
1982 void MESH_OT_reveal(wmOperatorType *ot)
1983 {
1984         /* identifiers */
1985         ot->name = "Reveal Hidden";
1986         ot->idname = "MESH_OT_reveal";
1987         ot->description = "Reveal all hidden vertices, edges and faces";
1988
1989         /* api callbacks */
1990         ot->exec = edbm_reveal_exec;
1991         ot->poll = ED_operator_editmesh;
1992
1993         /* flags */
1994         ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
1995
1996         RNA_def_boolean(ot->srna, "select", true, "Select", "");
1997 }
1998
1999 /** \} */
2000
2001 /* -------------------------------------------------------------------- */
2002 /** \name Recalculate Normals Operator
2003  * \{ */
2004
2005 static int edbm_normals_make_consistent_exec(bContext *C, wmOperator *op)
2006 {
2007         Object *obedit = CTX_data_edit_object(C);
2008         BMEditMesh *em = BKE_editmesh_from_object(obedit);
2009
2010         /* doflip has to do with bmesh_rationalize_normals, it's an internal
2011          * thing */
2012         if (!EDBM_op_callf(em, op, "recalc_face_normals faces=%hf", BM_ELEM_SELECT))
2013                 return OPERATOR_CANCELLED;
2014
2015         if (RNA_boolean_get(op->ptr, "inside")) {
2016                 EDBM_op_callf(em, op, "reverse_faces faces=%hf flip_multires=%b", BM_ELEM_SELECT, true);
2017         }
2018
2019         EDBM_update_generic(em, true, false);
2020
2021         return OPERATOR_FINISHED;
2022 }
2023
2024 void MESH_OT_normals_make_consistent(wmOperatorType *ot)
2025 {
2026         /* identifiers */
2027         ot->name = "Make Normals Consistent";
2028         ot->description = "Make face and vertex normals point either outside or inside the mesh";
2029         ot->idname = "MESH_OT_normals_make_consistent";
2030
2031         /* api callbacks */
2032         ot->exec = edbm_normals_make_consistent_exec;
2033         ot->poll = ED_operator_editmesh;
2034
2035         /* flags */
2036         ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
2037
2038         RNA_def_boolean(ot->srna, "inside", false, "Inside", "");
2039 }
2040
2041 /** \} */
2042
2043 /* -------------------------------------------------------------------- */
2044 /** \name Smooth Vertex Operator
2045  * \{ */
2046
2047 static int edbm_do_smooth_vertex_exec(bContext *C, wmOperator *op)
2048 {
2049         const float fac = RNA_float_get(op->ptr, "factor");
2050
2051         const bool xaxis = RNA_boolean_get(op->ptr, "xaxis");
2052         const bool yaxis = RNA_boolean_get(op->ptr, "yaxis");
2053         const bool zaxis = RNA_boolean_get(op->ptr, "zaxis");
2054         int repeat = RNA_int_get(op->ptr, "repeat");
2055
2056         if (!repeat) {
2057                 repeat = 1;
2058         }
2059
2060         ViewLayer *view_layer = CTX_data_view_layer(C);
2061         uint objects_len = 0;
2062         Object **objects = BKE_view_layer_array_from_objects_in_edit_mode_unique_data(view_layer, &objects_len);
2063         for (uint ob_index = 0; ob_index < objects_len; ob_index++) {
2064                 Object *obedit = objects[ob_index];
2065                 Mesh *me = obedit->data;
2066                 BMEditMesh *em = BKE_editmesh_from_object(obedit);
2067                 ModifierData *md;
2068                 bool mirrx = false, mirry = false, mirrz = false;
2069                 int i;
2070                 float clip_dist = 0.0f;
2071                 const bool use_topology = (me->editflag & ME_EDIT_MIRROR_TOPO) != 0;
2072
2073                 if (em->bm->totvertsel == 0) {
2074                         continue;
2075                 }
2076
2077                 /* mirror before smooth */
2078                 if (((Mesh *)obedit->data)->editflag & ME_EDIT_MIRROR_X) {
2079                         EDBM_verts_mirror_cache_begin(em, 0, false, true, use_topology);
2080                 }
2081
2082                 /* if there is a mirror modifier with clipping, flag the verts that
2083                  * are within tolerance of the plane(s) of reflection
2084                  */
2085                 for (md = obedit->modifiers.first; md; md = md->next) {
2086                         if (md->type == eModifierType_Mirror && (md->mode & eModifierMode_Realtime)) {
2087                                 MirrorModifierData *mmd = (MirrorModifierData *)md;
2088
2089                                 if (mmd->flag & MOD_MIR_CLIPPING) {
2090                                         if (mmd->flag & MOD_MIR_AXIS_X)
2091                                                 mirrx = true;
2092                                         if (mmd->flag & MOD_MIR_AXIS_Y)
2093                                                 mirry = true;
2094                                         if (mmd->flag & MOD_MIR_AXIS_Z)
2095                                                 mirrz = true;
2096
2097                                         clip_dist = mmd->tolerance;
2098                                 }
2099                         }
2100                 }
2101
2102                 for (i = 0; i < repeat; i++) {
2103                         if (!EDBM_op_callf(
2104                                 em, op,
2105                                 "smooth_vert verts=%hv factor=%f mirror_clip_x=%b mirror_clip_y=%b mirror_clip_z=%b "
2106                                 "clip_dist=%f use_axis_x=%b use_axis_y=%b use_axis_z=%b",
2107                                 BM_ELEM_SELECT, fac, mirrx, mirry, mirrz, clip_dist, xaxis, yaxis, zaxis))
2108                         {
2109                                 continue;
2110                         }
2111                 }
2112
2113                 /* apply mirror */
2114                 if (((Mesh *)obedit->data)->editflag & ME_EDIT_MIRROR_X) {
2115                         EDBM_verts_mirror_apply(em, BM_ELEM_SELECT, 0);
2116                         EDBM_verts_mirror_cache_end(em);
2117                 }
2118
2119                 EDBM_update_generic(em, true, false);
2120         }
2121         MEM_freeN(objects);
2122
2123         return OPERATOR_FINISHED;
2124 }
2125
2126 void MESH_OT_vertices_smooth(wmOperatorType *ot)
2127 {
2128         /* identifiers */
2129         ot->name = "Smooth Vertex";
2130         ot->description = "Flatten angles of selected vertices";
2131         ot->idname = "MESH_OT_vertices_smooth";
2132
2133         /* api callbacks */
2134         ot->exec = edbm_do_smooth_vertex_exec;
2135         ot->poll = ED_operator_editmesh;
2136
2137         /* flags */
2138         ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
2139
2140         RNA_def_float(ot->srna, "factor", 0.5f, -10.0f, 10.0f, "Smoothing", "Smoothing factor", 0.0f, 1.0f);
2141         RNA_def_int(ot->srna, "repeat", 1, 1, 1000, "Repeat", "Number of times to smooth the mesh", 1, 100);
2142
2143         WM_operatortype_props_advanced_begin(ot);
2144
2145         RNA_def_boolean(ot->srna, "xaxis", true, "X-Axis", "Smooth along the X axis");
2146         RNA_def_boolean(ot->srna, "yaxis", true, "Y-Axis", "Smooth along the Y axis");
2147         RNA_def_boolean(ot->srna, "zaxis", true, "Z-Axis", "Smooth along the Z axis");
2148 }
2149
2150 /** \} */
2151
2152 /* -------------------------------------------------------------------- */
2153 /** \name Laplacian Vertex Smooth Operator
2154  * \{ */
2155
2156 static int edbm_do_smooth_laplacian_vertex_exec(bContext *C, wmOperator *op)
2157 {
2158         Object *obedit = CTX_data_edit_object(C);
2159         BMEditMesh *em = BKE_editmesh_from_object(obedit);
2160         Mesh *me = obedit->data;
2161         bool use_topology = (me->editflag & ME_EDIT_MIRROR_TOPO) != 0;
2162         bool usex = true, usey = true, usez = true, preserve_volume = true;
2163         int i, repeat;
2164         float lambda_factor;
2165         float lambda_border;
2166         BMIter fiter;
2167         BMFace *f;
2168
2169         /* Check if select faces are triangles */
2170         BM_ITER_MESH (f, &fiter, em->bm, BM_FACES_OF_MESH) {
2171                 if (BM_elem_flag_test(f, BM_ELEM_SELECT)) {
2172                         if (f->len > 4) {
2173                                 BKE_report(op->reports, RPT_WARNING, "Selected faces must be triangles or quads");
2174                                 return OPERATOR_CANCELLED;
2175                         }
2176                 }
2177         }
2178
2179         /* mirror before smooth */
2180         if (((Mesh *)obedit->data)->editflag & ME_EDIT_MIRROR_X) {
2181                 EDBM_verts_mirror_cache_begin(em, 0, false, true, use_topology);
2182         }
2183
2184         repeat = RNA_int_get(op->ptr, "repeat");
2185         lambda_factor = RNA_float_get(op->ptr, "lambda_factor");
2186         lambda_border = RNA_float_get(op->ptr, "lambda_border");
2187         usex = RNA_boolean_get(op->ptr, "use_x");
2188         usey = RNA_boolean_get(op->ptr, "use_y");
2189         usez = RNA_boolean_get(op->ptr, "use_z");
2190         preserve_volume = RNA_boolean_get(op->ptr, "preserve_volume");
2191         if (!repeat)
2192                 repeat = 1;
2193
2194         for (i = 0; i < repeat; i++) {
2195                 if (!EDBM_op_callf(
2196                             em, op,
2197                             "smooth_laplacian_vert verts=%hv lambda_factor=%f lambda_border=%f use_x=%b use_y=%b use_z=%b preserve_volume=%b",
2198                             BM_ELEM_SELECT, lambda_factor, lambda_border, usex, usey, usez, preserve_volume))
2199                 {
2200                         return OPERATOR_CANCELLED;
2201                 }
2202         }
2203
2204         /* apply mirror */
2205         if (((Mesh *)obedit->data)->editflag & ME_EDIT_MIRROR_X) {
2206                 EDBM_verts_mirror_apply(em, BM_ELEM_SELECT, 0);
2207                 EDBM_verts_mirror_cache_end(em);
2208         }
2209
2210         EDBM_update_generic(em, true, false);
2211
2212         return OPERATOR_FINISHED;
2213 }
2214
2215 void MESH_OT_vertices_smooth_laplacian(wmOperatorType *ot)
2216 {
2217         /* identifiers */
2218         ot->name = "Laplacian Smooth Vertex";
2219         ot->description = "Laplacian smooth of selected vertices";
2220         ot->idname = "MESH_OT_vertices_smooth_laplacian";
2221
2222         /* api callbacks */
2223         ot->exec = edbm_do_smooth_laplacian_vertex_exec;
2224         ot->poll = ED_operator_editmesh;
2225
2226         /* flags */
2227         ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
2228
2229         RNA_def_int(ot->srna, "repeat", 1, 1, 1000,
2230                     "Number of iterations to smooth the mesh", "", 1, 200);
2231         RNA_def_float(ot->srna, "lambda_factor", 5e-5f, 1e-7f, 1000.0f,
2232                       "Lambda factor", "", 1e-7f, 1000.0f);
2233         RNA_def_float(ot->srna, "lambda_border", 5e-5f, 1e-7f, 1000.0f,
2234                       "Lambda factor in border", "", 1e-7f, 1000.0f);
2235
2236         WM_operatortype_props_advanced_begin(ot);
2237
2238         RNA_def_boolean(ot->srna, "use_x", true, "Smooth X Axis", "Smooth object along X axis");
2239         RNA_def_boolean(ot->srna, "use_y", true, "Smooth Y Axis", "Smooth object along Y axis");
2240         RNA_def_boolean(ot->srna, "use_z", true, "Smooth Z Axis", "Smooth object along Z axis");
2241         RNA_def_boolean(ot->srna, "preserve_volume", true, "Preserve Volume", "Apply volume preservation after smooth");
2242 }
2243
2244 /** \} */
2245
2246 /* -------------------------------------------------------------------- */
2247 /** \name Set Faces Smooth Shading Operator
2248  * \{ */
2249
2250 static void mesh_set_smooth_faces(BMEditMesh *em, short smooth)
2251 {
2252         BMIter iter;
2253         BMFace *efa;
2254
2255         if (em == NULL) return;
2256
2257         BM_ITER_MESH (efa, &iter, em->bm, BM_FACES_OF_MESH) {
2258                 if (BM_elem_flag_test(efa, BM_ELEM_SELECT)) {
2259                         BM_elem_flag_set(efa, BM_ELEM_SMOOTH, smooth);
2260                 }
2261         }
2262 }
2263
2264 static int edbm_faces_shade_smooth_exec(bContext *C, wmOperator *UNUSED(op))
2265 {
2266         ViewLayer * view_layer = CTX_data_view_layer(C);
2267         uint objects_len = 0;
2268         Object * *objects = BKE_view_layer_array_from_objects_in_edit_mode_unique_data(view_layer, &objects_len);
2269         for (uint ob_index = 0; ob_index < objects_len; ob_index++) {
2270                 Object * obedit = objects[ob_index];
2271                 BMEditMesh * em = BKE_editmesh_from_object(obedit);
2272
2273                 if (em->bm->totfacesel == 0) {
2274                         continue;
2275                 }
2276
2277                 mesh_set_smooth_faces(em, 1);
2278                 EDBM_update_generic(em, false, false);
2279         }
2280         MEM_freeN(objects);
2281
2282         return OPERATOR_FINISHED;
2283 }
2284
2285 void MESH_OT_faces_shade_smooth(wmOperatorType *ot)
2286 {
2287         /* identifiers */
2288         ot->name = "Shade Smooth";
2289         ot->description = "Display faces smooth (using vertex normals)";
2290         ot->idname = "MESH_OT_faces_shade_smooth";
2291
2292         /* api callbacks */
2293         ot->exec = edbm_faces_shade_smooth_exec;
2294         ot->poll = ED_operator_editmesh;
2295
2296         /* flags */
2297         ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
2298 }
2299
2300 /** \} */
2301
2302 /* -------------------------------------------------------------------- */
2303 /** \name Set Faces Flat Shading Operator
2304  * \{ */
2305
2306 static int edbm_faces_shade_flat_exec(bContext *C, wmOperator *UNUSED(op))
2307 {
2308         ViewLayer *view_layer = CTX_data_view_layer(C);
2309         uint objects_len = 0;
2310         Object **objects = BKE_view_layer_array_from_objects_in_edit_mode_unique_data(view_layer, &objects_len);
2311         for (uint ob_index = 0; ob_index < objects_len; ob_index++) {
2312                 Object *obedit = objects[ob_index];
2313                 BMEditMesh *em = BKE_editmesh_from_object(obedit);
2314
2315                 if (em->bm->totfacesel == 0) {
2316                         continue;
2317                 }
2318
2319                 mesh_set_smooth_faces(em, 0);
2320                 EDBM_update_generic(em, false, false);
2321         }
2322         MEM_freeN(objects);
2323
2324         return OPERATOR_FINISHED;
2325 }
2326
2327 void MESH_OT_faces_shade_flat(wmOperatorType *ot)
2328 {
2329         /* identifiers */
2330         ot->name = "Shade Flat";
2331         ot->description = "Display faces flat";
2332         ot->idname = "MESH_OT_faces_shade_flat";
2333
2334         /* api callbacks */
2335         ot->exec = edbm_faces_shade_flat_exec;
2336         ot->poll = ED_operator_editmesh;
2337
2338         /* flags */
2339         ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
2340 }
2341
2342 /** \} */
2343
2344 /* -------------------------------------------------------------------- */
2345 /** \name UV/Color Rotate/Reverse Operator
2346  * \{ */
2347
2348 static int edbm_rotate_uvs_exec(bContext *C, wmOperator *op)
2349 {
2350         /* get the direction from RNA */
2351         const bool use_ccw = RNA_boolean_get(op->ptr, "use_ccw");
2352
2353         ViewLayer *view_layer = CTX_data_view_layer(C);
2354         uint objects_len = 0;
2355         Object **objects = BKE_view_layer_array_from_objects_in_edit_mode_unique_data(view_layer, &objects_len);
2356         for (uint ob_index = 0; ob_index < objects_len; ob_index++) {
2357                 Object *obedit = objects[ob_index];
2358                 BMEditMesh *em = BKE_editmesh_from_object(obedit);
2359
2360                 if (em->bm->totfacesel == 0) {
2361                         continue;
2362                 }
2363
2364                 BMOperator bmop;
2365
2366                 /* initialize the bmop using EDBM api, which does various ui error reporting and other stuff */
2367                 EDBM_op_init(em, &bmop, op, "rotate_uvs faces=%hf use_ccw=%b", BM_ELEM_SELECT, use_ccw);
2368
2369                 /* execute the operator */
2370                 BMO_op_exec(em->bm, &bmop);
2371
2372                 if (!EDBM_op_finish(em, &bmop, op, true)) {
2373                         continue;
2374                 }
2375
2376                 EDBM_update_generic(em, false, false);
2377         }
2378
2379         MEM_freeN(objects);
2380         return OPERATOR_FINISHED;
2381 }
2382
2383 static int edbm_reverse_uvs_exec(bContext *C, wmOperator *op)
2384 {
2385         ViewLayer *view_layer = CTX_data_view_layer(C);
2386         uint objects_len = 0;
2387         Object **objects = BKE_view_layer_array_from_objects_in_edit_mode_unique_data(view_layer, &objects_len);
2388         for (uint ob_index = 0; ob_index < objects_len; ob_index++) {
2389                 Object *obedit = objects[ob_index];
2390                 BMEditMesh *em = BKE_editmesh_from_object(obedit);
2391
2392                 if (em->bm->totfacesel == 0) {
2393                         continue;
2394                 }
2395
2396                 BMOperator bmop;
2397
2398                 /* initialize the bmop using EDBM api, which does various ui error reporting and other stuff */
2399                 EDBM_op_init(em, &bmop, op, "reverse_uvs faces=%hf", BM_ELEM_SELECT);
2400
2401                 /* execute the operator */
2402                 BMO_op_exec(em->bm, &bmop);
2403
2404                 /* finish the operator */
2405                 if (!EDBM_op_finish(em, &bmop, op, true)) {
2406                         continue;
2407                 }
2408                 EDBM_update_generic(em, false, false);
2409         }
2410
2411         MEM_freeN(objects);
2412         return OPERATOR_FINISHED;
2413 }
2414
2415 static int edbm_rotate_colors_exec(bContext *C, wmOperator *op)
2416 {
2417                 /* get the direction from RNA */
2418         const bool use_ccw = RNA_boolean_get(op->ptr, "use_ccw");
2419
2420         ViewLayer *view_layer = CTX_data_view_layer(C);
2421         uint objects_len = 0;
2422         Object **objects = BKE_view_layer_array_from_objects_in_edit_mode_unique_data(view_layer, &objects_len);
2423
2424         for (uint ob_index = 0; ob_index < objects_len; ob_index++) {
2425                 Object *ob = objects[ob_index];
2426                 BMEditMesh *em = BKE_editmesh_from_object(ob);
2427                 if (em->bm->totfacesel == 0) {
2428                         continue;
2429                 }
2430
2431                 BMOperator bmop;
2432
2433                 /* initialize the bmop using EDBM api, which does various ui error reporting and other stuff */
2434                 EDBM_op_init(em, &bmop, op, "rotate_colors faces=%hf use_ccw=%b", BM_ELEM_SELECT, use_ccw);
2435
2436                 /* execute the operator */
2437                 BMO_op_exec(em->bm, &bmop);
2438
2439                 /* finish the operator */
2440                 if (!EDBM_op_finish(em, &bmop, op, true)) {
2441                         continue;
2442                 }
2443
2444                 /* dependencies graph and notification stuff */
2445                 EDBM_update_generic(em, false, false);
2446         }
2447
2448         MEM_freeN(objects);
2449
2450         return OPERATOR_FINISHED;
2451 }
2452
2453
2454 static int edbm_reverse_colors_exec(bContext *C, wmOperator *op)
2455 {
2456         Object *ob = CTX_data_edit_object(C);
2457         BMEditMesh *em = BKE_editmesh_from_object(ob);
2458         BMOperator bmop;
2459
2460         /* initialize the bmop using EDBM api, which does various ui error reporting and other stuff */
2461         EDBM_op_init(em, &bmop, op, "reverse_colors faces=%hf", BM_ELEM_SELECT);
2462
2463         /* execute the operator */
2464         BMO_op_exec(em->bm, &bmop);
2465
2466         /* finish the operator */
2467         if (!EDBM_op_finish(em, &bmop, op, true)) {
2468                 return OPERATOR_CANCELLED;
2469         }
2470
2471         EDBM_update_generic(em, false, false);
2472
2473         return OPERATOR_FINISHED;
2474 }
2475
2476 void MESH_OT_uvs_rotate(wmOperatorType *ot)
2477 {
2478         /* identifiers */
2479         ot->name = "Rotate UVs";
2480         ot->idname = "MESH_OT_uvs_rotate";
2481         ot->description = "Rotate UV coordinates inside faces";
2482
2483         /* api callbacks */
2484         ot->exec = edbm_rotate_uvs_exec;
2485         ot->poll = ED_operator_editmesh;
2486
2487         /* flags */
2488         ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
2489
2490         /* props */
2491         RNA_def_boolean(ot->srna, "use_ccw", false, "Counter Clockwise", "");
2492 }
2493
2494 void MESH_OT_uvs_reverse(wmOperatorType *ot)
2495 {
2496         /* identifiers */
2497         ot->name = "Reverse UVs";
2498         ot->idname = "MESH_OT_uvs_reverse";
2499         ot->description = "Flip direction of UV coordinates inside faces";
2500
2501         /* api callbacks */
2502         ot->exec = edbm_reverse_uvs_exec;
2503         ot->poll = ED_operator_editmesh;
2504
2505         /* flags */
2506         ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
2507
2508         /* props */
2509         //RNA_def_enum(ot->srna, "axis", axis_items, DIRECTION_CW, "Axis", "Axis to mirror UVs around");
2510 }
2511
2512 void MESH_OT_colors_rotate(wmOperatorType *ot)
2513 {
2514         /* identifiers */
2515         ot->name = "Rotate Colors";
2516         ot->idname = "MESH_OT_colors_rotate";
2517         ot->description = "Rotate vertex colors inside faces";
2518
2519         /* api callbacks */
2520         ot->exec = edbm_rotate_colors_exec;
2521         ot->poll = ED_operator_editmesh;
2522
2523         /* flags */
2524         ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
2525
2526         /* props */
2527         RNA_def_boolean(ot->srna, "use_ccw", false, "Counter Clockwise", "");
2528 }
2529
2530 void MESH_OT_colors_reverse(wmOperatorType *ot)
2531 {
2532         /* identifiers */
2533         ot->name = "Reverse Colors";
2534         ot->idname = "MESH_OT_colors_reverse";
2535         ot->description = "Flip direction of vertex colors inside faces";
2536
2537         /* api callbacks */
2538         ot->exec = edbm_reverse_colors_exec;
2539         ot->poll = ED_operator_editmesh;
2540
2541         /* flags */
2542         ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
2543
2544         /* props */
2545         //RNA_def_enum(ot->srna, "axis", axis_items, DIRECTION_CW, "Axis", "Axis to mirror colors around");
2546 }
2547
2548 /** \} */
2549
2550 /* -------------------------------------------------------------------- */
2551 /** \name Merge Vertices Operator
2552  * \{ */
2553
2554 enum {
2555         MESH_MERGE_LAST     = 1,
2556         MESH_MERGE_CENTER   = 3,
2557         MESH_MERGE_CURSOR   = 4,
2558         MESH_MERGE_COLLAPSE = 5,
2559         MESH_MERGE_FIRST    = 6,
2560 };
2561
2562 static bool merge_firstlast(BMEditMesh *em, const bool use_first, const bool use_uvmerge, wmOperator *wmop)
2563 {
2564         BMVert *mergevert;
2565         BMEditSelection *ese;
2566
2567         /* operator could be called directly from shortcut or python,
2568          * so do extra check for data here
2569          */
2570
2571         /* do sanity check in mergemenu in edit.c ?*/
2572         if (use_first == false) {
2573                 if (!em->bm->selected.last || ((BMEditSelection *)em->bm->selected.last)->htype != BM_VERT)
2574                         return false;
2575
2576                 ese = em->bm->selected.last;
2577                 mergevert = (BMVert *)ese->ele;
2578         }
2579         else {
2580                 if (!em->bm->selected.first || ((BMEditSelection *)em->bm->selected.first)->htype != BM_VERT)
2581                         return false;
2582
2583                 ese = em->bm->selected.first;
2584                 mergevert = (BMVert *)ese->ele;
2585         }
2586
2587         if (!BM_elem_flag_test(mergevert, BM_ELEM_SELECT))
2588                 return false;
2589
2590         if (use_uvmerge) {
2591                 if (!EDBM_op_callf(em, wmop, "pointmerge_facedata verts=%hv vert_snap=%e", BM_ELEM_SELECT, mergevert))
2592                         return false;
2593         }
2594
2595         if (!EDBM_op_callf(em, wmop, "pointmerge verts=%hv merge_co=%v", BM_ELEM_SELECT, mergevert->co))
2596                 return false;
2597
2598         return true;
2599 }
2600
2601 static bool merge_target(
2602         BMEditMesh *em, Scene *scene, View3D *v3d, Object *ob,
2603         const bool use_cursor, const bool use_uvmerge, wmOperator *wmop)
2604 {
2605         BMIter iter;
2606         BMVert *v;
2607         float co[3], cent[3] = {0.0f, 0.0f, 0.0f};
2608         const float *vco = NULL;
2609
2610         if (use_cursor) {
2611                 vco = ED_view3d_cursor3d_get(scene, v3d)->location;
2612                 copy_v3_v3(co, vco);
2613                 invert_m4_m4(ob->imat, ob->obmat);
2614                 mul_m4_v3(ob->imat, co);
2615         }
2616         else {
2617                 float fac;
2618                 int i = 0;
2619                 BM_ITER_MESH (v, &iter, em->bm, BM_VERTS_OF_MESH) {
2620                         if (!BM_elem_flag_test(v, BM_ELEM_SELECT))
2621                                 continue;
2622                         add_v3_v3(cent, v->co);
2623                         i++;
2624                 }
2625
2626                 if (!i)
2627                         return false;
2628
2629                 fac = 1.0f / (float)i;
2630                 mul_v3_fl(cent, fac);
2631                 copy_v3_v3(co, cent);
2632                 vco = co;
2633         }
2634
2635         if (!vco)
2636                 return false;
2637
2638         if (use_uvmerge) {
2639                 if (!EDBM_op_callf(em, wmop, "average_vert_facedata verts=%hv", BM_ELEM_SELECT))
2640                         return false;
2641         }
2642
2643         if (!EDBM_op_callf(em, wmop, "pointmerge verts=%hv merge_co=%v", BM_ELEM_SELECT, co))
2644                 return false;
2645
2646         return true;
2647 }
2648
2649 static int edbm_merge_exec(bContext *C, wmOperator *op)
2650 {
2651         Scene *scene = CTX_data_scene(C);
2652         View3D *v3d = CTX_wm_view3d(C);
2653         Object *obedit = CTX_data_edit_object(C);
2654         BMEditMesh *em = BKE_editmesh_from_object(obedit);
2655         const int type = RNA_enum_get(op->ptr, "type");
2656         const bool uvs = RNA_boolean_get(op->ptr, "uvs");
2657         bool ok = false;
2658
2659         switch (type) {
2660                 case MESH_MERGE_CENTER:
2661                         ok = merge_target(em, scene, v3d, obedit, false, uvs, op);
2662                         break;
2663                 case MESH_MERGE_CURSOR:
2664                         ok = merge_target(em, scene, v3d, obedit, true, uvs, op);
2665                         break;
2666                 case MESH_MERGE_LAST:
2667                         ok = merge_firstlast(em, false, uvs, op);
2668                         break;
2669                 case MESH_MERGE_FIRST:
2670                         ok = merge_firstlast(em, true, uvs, op);
2671                         break;
2672                 case MESH_MERGE_COLLAPSE:
2673                         ok = EDBM_op_callf(em, op, "collapse edges=%he uvs=%b", BM_ELEM_SELECT, uvs);
2674                         break;
2675                 default:
2676                         BLI_assert(0);
2677                         break;
2678         }
2679
2680         if (!ok) {
2681                 return OPERATOR_CANCELLED;
2682         }
2683
2684         EDBM_update_generic(em, true, true);
2685
2686         /* once collapsed, we can't have edge/face selection */
2687         if ((em->selectmode & SCE_SELECT_VERTEX) == 0) {
2688                 EDBM_flag_disable_all(em, BM_ELEM_SELECT);
2689         }
2690
2691         return OPERATOR_FINISHED;
2692 }
2693
2694 static const EnumPropertyItem merge_type_items[] = {
2695         {MESH_MERGE_FIRST, "FIRST", 0, "At First", ""},
2696         {MESH_MERGE_LAST, "LAST", 0, "At Last", ""},
2697         {MESH_MERGE_CENTER, "CENTER", 0, "At Center", ""},
2698         {MESH_MERGE_CURSOR, "CURSOR", 0, "At Cursor", ""},
2699         {MESH_MERGE_COLLAPSE, "COLLAPSE", 0, "Collapse", ""},
2700         {0, NULL, 0, NULL, NULL}
2701 };
2702
2703 static const EnumPropertyItem *merge_type_itemf(bContext *C, PointerRNA *UNUSED(ptr),  PropertyRNA *UNUSED(prop), bool *r_free)
2704 {
2705         Object *obedit;
2706         EnumPropertyItem *item = NULL;
2707         int totitem = 0;
2708
2709         if (!C) /* needed for docs */
2710                 return merge_type_items;
2711
2712         obedit = CTX_data_edit_object(C);
2713         if (obedit && obedit->type == OB_MESH) {
2714                 BMEditMesh *em = BKE_editmesh_from_object(obedit);
2715
2716                 if (em->selectmode & SCE_SELECT_VERTEX) {
2717                         if (em->bm->selected.first && em->bm->selected.last &&
2718                             ((BMEditSelection *)em->bm->selected.first)->htype == BM_VERT &&
2719                             ((BMEditSelection *)em->bm->selected.last)->htype == BM_VERT)
2720                         {
2721                                 RNA_enum_items_add_value(&item, &totitem, merge_type_items, MESH_MERGE_FIRST);
2722                                 RNA_enum_items_add_value(&item, &totitem, merge_type_items, MESH_MERGE_LAST);
2723                         }
2724                         else if (em->bm->selected.first && ((BMEditSelection *)em->bm->selected.first)->htype == BM_VERT) {
2725                                 RNA_enum_items_add_value(&item, &totitem, merge_type_items, MESH_MERGE_FIRST);
2726                         }
2727                         else if (em->bm->selected.last && ((BMEditSelection *)em->bm->selected.last)->htype == BM_VERT) {
2728                                 RNA_enum_items_add_value(&item, &totitem, merge_type_items, MESH_MERGE_LAST);
2729                         }
2730                 }
2731
2732                 RNA_enum_items_add_value(&item, &totitem, merge_type_items, MESH_MERGE_CENTER);
2733                 RNA_enum_items_add_value(&item, &totitem, merge_type_items, MESH_MERGE_CURSOR);
2734                 RNA_enum_items_add_value(&item, &totitem, merge_type_items, MESH_MERGE_COLLAPSE);
2735                 RNA_enum_item_end(&item, &totitem);
2736
2737                 *r_free = true;
2738
2739                 return item;
2740         }
2741
2742         return NULL;
2743 }
2744
2745 void MESH_OT_merge(wmOperatorType *ot)
2746 {
2747         /* identifiers */
2748         ot->name = "Merge";
2749         ot->description = "Merge selected vertices";
2750         ot->idname = "MESH_OT_merge";
2751
2752         /* api callbacks */
2753         ot->exec = edbm_merge_exec;
2754         ot->invoke = WM_menu_invoke;
2755         ot->poll = ED_operator_editmesh;
2756
2757         /* flags */
2758         ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
2759
2760         /* properties */
2761         ot->prop = RNA_def_enum(ot->srna, "type", merge_type_items, MESH_MERGE_CENTER, "Type", "Merge method to use");
2762         RNA_def_enum_funcs(ot->prop, merge_type_itemf);
2763
2764         WM_operatortype_props_advanced_begin(ot);
2765
2766         RNA_def_boolean(ot->srna, "uvs", false, "UVs", "Move UVs according to merge");
2767 }
2768
2769 /** \} */
2770
2771 /* -------------------------------------------------------------------- */
2772 /** \name Remove Doubles Operator
2773  * \{ */
2774
2775 static int edbm_remove_doubles_exec(bContext *C, wmOperator *op)
2776 {
2777         const float threshold = RNA_float_get(op->ptr, "threshold");
2778         const bool use_unselected = RNA_boolean_get(op->ptr, "use_unselected");
2779         int count_multi = 0;
2780
2781         ViewLayer *view_layer = CTX_data_view_layer(C);
2782         uint objects_len = 0;
2783         Object **objects = BKE_view_layer_array_from_objects_in_edit_mode_unique_data(view_layer, &objects_len);
2784
2785         for (uint ob_index = 0; ob_index < objects_len; ob_index++) {
2786                 Object *obedit = objects[ob_index];
2787                 BMEditMesh *em = BKE_editmesh_from_object(obedit);
2788
2789                 /* Selection used as target with 'use_unselected'. */
2790                 if (em->bm->totvertsel == 0) {
2791                         continue;
2792                 }
2793
2794                 BMOperator bmop;
2795                 const int totvert_orig = em->bm->totvert;
2796
2797                 /* avoid loosing selection state (select -> tags) */
2798                 char htype_select;
2799                 if      (em->selectmode & SCE_SELECT_VERTEX) htype_select = BM_VERT;
2800                 else if (em->selectmode & SCE_SELECT_EDGE)   htype_select = BM_EDGE;
2801                 else                                         htype_select = BM_FACE;
2802
2803                 /* store selection as tags */
2804                 BM_mesh_elem_hflag_enable_test(em->bm, htype_select, BM_ELEM_TAG, true, true, BM_ELEM_SELECT);
2805
2806
2807                 if (use_unselected) {
2808                         EDBM_op_init(
2809                                 em, &bmop, op,
2810                                 "automerge verts=%hv dist=%f",
2811                                 BM_ELEM_SELECT, threshold);
2812                         BMO_op_exec(em->bm, &bmop);
2813
2814                         if (!EDBM_op_finish(em, &bmop, op, true)) {
2815                                 continue;
2816                         }
2817                 }
2818                 else {
2819                         EDBM_op_init(
2820                                 em, &bmop, op,
2821                                 "find_doubles verts=%hv dist=%f",
2822                                 BM_ELEM_SELECT, threshold);
2823
2824                         BMO_op_exec(em->bm, &bmop);
2825
2826                         if (!EDBM_op_callf(em, op, "weld_verts targetmap=%S", &bmop, "targetmap.out")) {
2827                                 BMO_op_finish(em->bm, &bmop);
2828                                 continue;
2829                         }
2830
2831                         if (!EDBM_op_finish(em, &bmop, op, true)) {
2832                                 continue;
2833                         }
2834                 }
2835
2836                 const int count = (totvert_orig - em->bm->totvert);
2837
2838                 /* restore selection from tags */
2839                 BM_mesh_elem_hflag_enable_test(em->bm, htype_select, BM_ELEM_SELECT, true, true, BM_ELEM_TAG);
2840                 EDBM_selectmode_flush(em);
2841
2842                 if (count) {
2843                         count_multi += count;
2844                         EDBM_update_generic(em, true, true);
2845                 }
2846         }
2847         MEM_freeN(objects);
2848
2849         BKE_reportf(op->reports, RPT_INFO, "Removed %d vertices", count_multi);
2850
2851         return OPERATOR_FINISHED;
2852 }
2853
2854 void MESH_OT_remove_doubles(wmOperatorType *ot)
2855 {
2856         /* identifiers */
2857         ot->name = "Remove Doubles";
2858         ot->description = "Remove duplicate vertices";
2859         ot->idname = "MESH_OT_remove_doubles";
2860
2861         /* api callbacks */
2862         ot->exec = edbm_remove_doubles_exec;
2863         ot->poll = ED_operator_editmesh;
2864
2865         /* flags */
2866         ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
2867
2868         RNA_def_float_distance(ot->srna, "threshold", 1e-4f, 1e-6f, 50.0f, "Merge Distance",
2869                                "Minimum distance between elements to merge", 1e-5f, 10.0f);
2870         RNA_def_boolean(ot->srna, "use_unselected", false, "Unselected", "Merge selected to other unselected vertices");
2871 }
2872
2873 /** \} */
2874
2875 /* -------------------------------------------------------------------- */
2876 /** \name Shape Key Propagate Operator
2877  * \{ */
2878
2879 /* BMESH_TODO this should be properly encapsulated in a bmop.  but later.*/
2880 static void shape_propagate(BMEditMesh *em, wmOperator *op)
2881 {
2882         BMIter iter;
2883         BMVert *eve = NULL;
2884         float *co;
2885         int i, totshape = CustomData_number_of_layers(&em->bm->vdata, CD_SHAPEKEY);
2886
2887         if (!CustomData_has_layer(&em->bm->vdata, CD_SHAPEKEY)) {
2888                 BKE_report(op->reports, RPT_ERROR, "Mesh does not have shape keys");
2889                 return;
2890         }
2891
2892         BM_ITER_MESH (eve, &iter, em->bm, BM_VERTS_OF_MESH) {
2893                 if (!BM_elem_flag_test(eve, BM_ELEM_SELECT) || BM_elem_flag_test(eve, BM_ELEM_HIDDEN))
2894                         continue;
2895
2896                 for (i = 0; i < totshape; i++) {
2897                         co = CustomData_bmesh_get_n(&em->bm->vdata, eve->head.data, CD_SHAPEKEY, i);
2898                         copy_v3_v3(co, eve->co);
2899                 }
2900         }
2901
2902 #if 0
2903         //TAG Mesh Objects that share this data
2904         for (base = scene->base.first; base; base = base->next) {
2905                 if (base->object && base->object->data == me) {
2906                         DEG_id_tag_update(&base->object->id, OB_RECALC_DATA);
2907                 }
2908         }
2909 #endif
2910 }
2911
2912
2913 static int edbm_shape_propagate_to_all_exec(bContext *C, wmOperator *op)
2914 {
2915         Object *obedit = CTX_data_edit_object(C);
2916         Mesh *me = obedit->data;
2917         BMEditMesh *em = me->edit_btmesh;
2918
2919         shape_propagate(em, op);
2920
2921         EDBM_update_generic(em, false, false);
2922
2923         return OPERATOR_FINISHED;
2924 }
2925
2926
2927 void MESH_OT_shape_propagate_to_all(wmOperatorType *ot)
2928 {
2929         /* identifiers */
2930         ot->name = "Shape Propagate";
2931         ot->description = "Apply selected vertex locations to all other shape keys";
2932         ot->idname = "MESH_OT_shape_propagate_to_all";
2933
2934         /* api callbacks */
2935         ot->exec = edbm_shape_propagate_to_all_exec;
2936         ot->poll = ED_operator_editmesh;
2937
2938         /* flags */
2939         ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
2940 }
2941
2942 /** \} */
2943
2944 /* -------------------------------------------------------------------- */
2945 /** \name Blend from Shape Operator
2946  * \{ */
2947
2948 /* BMESH_TODO this should be properly encapsulated in a bmop.  but later.*/
2949 static int edbm_blend_from_shape_exec(bContext *C, wmOperator *op)
2950 {
2951         Object *obedit = CTX_data_edit_object(C);
2952         Mesh *me = obedit->data;
2953         Key *key = me->key;
2954         KeyBlock *kb = NULL;
2955         BMEditMesh *em = me->edit_btmesh;
2956         BMVert *eve;
2957         BMIter iter;
2958         float co[3], *sco;
2959         int totshape;
2960
2961         const float blend = RNA_float_get(op->ptr, "blend");
2962         const int shape = RNA_enum_get(op->ptr, "shape");
2963         const bool use_add = RNA_boolean_get(op->ptr, "add");
2964
2965         /* sanity check */
2966         totshape = CustomData_number_of_layers(&em->bm->vdata, CD_SHAPEKEY);
2967         if (totshape == 0 || shape < 0 || shape >= totshape)
2968                 return OPERATOR_CANCELLED;
2969
2970         /* get shape key - needed for finding reference shape (for add mode only) */
2971         if (key) {
2972                 kb = BLI_findlink(&key->block, shape);
2973         }
2974
2975         /* perform blending on selected vertices*/
2976         BM_ITER_MESH (eve, &iter, em->bm, BM_VERTS_OF_MESH) {
2977                 if (!BM_elem_flag_test(eve, BM_ELEM_SELECT) || BM_elem_flag_test(eve, BM_ELEM_HIDDEN))
2978                         continue;
2979
2980                 /* get coordinates of shapekey we're blending from */
2981                 sco = CustomData_bmesh_get_n(&em->bm->vdata, eve->head.data, CD_SHAPEKEY, shape);
2982                 copy_v3_v3(co, sco);
2983
2984                 if (use_add) {
2985                         /* in add mode, we add relative shape key offset */
2986                         if (kb) {
2987                                 const float *rco = CustomData_bmesh_get_n(&em->bm->vdata, eve->head.data, CD_SHAPEKEY, kb->relative);
2988                                 sub_v3_v3v3(co, co, rco);
2989                         }
2990
2991                         madd_v3_v3fl(eve->co, co, blend);
2992                 }
2993                 else {
2994                         /* in blend mode, we interpolate to the shape key */
2995                         interp_v3_v3v3(eve->co, eve->co, co, blend);
2996                 }
2997         }
2998
2999         EDBM_update_generic(em, true, false);
3000
3001         return OPERATOR_FINISHED;
3002 }
3003
3004 static const EnumPropertyItem *shape_itemf(bContext *C, PointerRNA *UNUSED(ptr),  PropertyRNA *UNUSED(prop), bool *r_free)
3005 {
3006         Object *obedit = CTX_data_edit_object(C);
3007         BMEditMesh *em;
3008         EnumPropertyItem *item = NULL;
3009         int totitem = 0;
3010
3011         if ((obedit && obedit->type == OB_MESH) &&
3012             (em = BKE_editmesh_from_object(obedit)) &&
3013             CustomData_has_layer(&em->bm->vdata, CD_SHAPEKEY))
3014         {
3015                 EnumPropertyItem tmp = {0, "", 0, "", ""};
3016                 int a;
3017
3018                 for (a = 0; a < em->bm->vdata.totlayer; a++) {
3019                         if (em->bm->vdata.layers[a].type != CD_SHAPEKEY)
3020                                 continue;
3021
3022                         tmp.value = totitem;
3023                         tmp.identifier = em->bm->vdata.layers[a].name;
3024                         tmp.name = em->bm->vdata.layers[a].name;
3025                         /* RNA_enum_item_add sets totitem itself! */
3026                         RNA_enum_item_add(&item, &totitem, &tmp);
3027                 }
3028         }
3029
3030         RNA_enum_item_end(&item, &totitem);
3031         *r_free = true;
3032
3033         return item;
3034 }
3035
3036 static void edbm_blend_from_shape_ui(bContext *C, wmOperator *op)
3037 {
3038         uiLayout *layout = op->layout;
3039         PointerRNA ptr;
3040         Object *obedit = CTX_data_edit_object(C);
3041         Mesh *me = obedit->data;
3042         PointerRNA ptr_key;
3043
3044         RNA_pointer_create(NULL, op->type->srna, op->properties, &ptr);
3045         RNA_id_pointer_create((ID *)me->key, &ptr_key);
3046
3047         uiItemPointerR(layout, &ptr, "shape", &ptr_key, "key_blocks", "", ICON_SHAPEKEY_DATA);
3048         uiItemR(layout, &ptr, "blend", 0, NULL, ICON_NONE);
3049         uiItemR(layout, &ptr, "add", 0, NULL, ICON_NONE);
3050 }
3051
3052 void MESH_OT_blend_from_shape(wmOperatorType *ot)
3053 {
3054         PropertyRNA *prop;
3055
3056         /* identifiers */
3057         ot->name = "Blend From Shape";
3058         ot->description = "Blend in shape from a shape key";
3059         ot->idname = "MESH_OT_blend_from_shape";
3060
3061         /* api callbacks */
3062         ot->exec = edbm_blend_from_shape_exec;
3063 //      ot->invoke = WM_operator_props_popup_call;  /* disable because search popup closes too easily */
3064         ot->ui = edbm_blend_from_shape_ui;
3065         ot->poll = ED_operator_editmesh;
3066
3067         /* flags */
3068         ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
3069
3070         /* properties */
3071         prop = RNA_def_enum(ot->srna, "shape", DummyRNA_NULL_items, 0, "Shape", "Shape key to use for blending");
3072         RNA_def_enum_funcs(prop, shape_itemf);
3073         RNA_def_property_flag(prop, PROP_ENUM_NO_TRANSLATE | PROP_NEVER_UNLINK);
3074         RNA_def_float(ot->srna, "blend", 1.0f, -1e3f, 1e3f, "Blend", "Blending factor", -2.0f, 2.0f);
3075         RNA_def_boolean(ot->srna, "add", true, "Add", "Add rather than blend between shapes");
3076 }
3077
3078 /** \} */
3079
3080 /* -------------------------------------------------------------------- */
3081 /** \name Solidify Mesh Operator
3082  * \{ */
3083
3084 static int edbm_solidify_exec(bContext *C, wmOperator *op)
3085 {
3086         const float thickness = RNA_float_get(op->ptr, "thickness");
3087
3088         ViewLayer *view_layer = CTX_data_view_layer(C);
3089         uint objects_len = 0;
3090         Object **objects = BKE_view_layer_array_from_objects_in_edit_mode_unique_data(view_layer, &objects_len);
3091         for (uint ob_index = 0; ob_index < objects_len; ob_index++) {
3092                 Object *obedit = objects[ob_index];
3093                 BMEditMesh *em = BKE_editmesh_from_object(obedit);
3094                 BMesh *bm = em->bm;
3095
3096                 if (em->bm->totfacesel == 0) {
3097                         continue;
3098                 }
3099
3100                 BMOperator bmop;
3101
3102                 if (!EDBM_op_init(em, &bmop, op, "solidify geom=%hf thickness=%f", BM_ELEM_SELECT, thickness)) {
3103                         continue;
3104                 }
3105
3106                 /* deselect only the faces in the region to be solidified (leave wire
3107                  * edges and loose verts selected, as there will be no corresponding
3108                  * geometry selected below) */
3109                 BMO_slot_buffer_hflag_disable(bm, bmop.slots_in, "geom", BM_FACE, BM_ELEM_SELECT, true);
3110
3111                 /* run the solidify operator */
3112                 BMO_op_exec(bm, &bmop);
3113
3114                 /* select the newly generated faces */
3115                 BMO_slot_buffer_hflag_enable(bm, bmop.slots_out, "geom.out", BM_FACE, BM_ELEM_SELECT, true);
3116
3117                 if (!EDBM_op_finish(em, &bmop, op, true)) {
3118                         continue;
3119                 }
3120
3121                 EDBM_update_generic(em, true, true);
3122         }
3123
3124         MEM_freeN(objects);
3125         return OPERATOR_FINISHED;
3126 }
3127
3128 void MESH_OT_solidify(wmOperatorType *ot)
3129 {
3130         PropertyRNA *prop;
3131         /* identifiers */
3132         ot->name = "Solidify";
3133         ot->description = "Create a solid skin by extruding, compensating for sharp angles";
3134         ot->idname = "MESH_OT_solidify";
3135
3136         /* api callbacks */
3137         ot->exec = edbm_solidify_exec;
3138         ot->poll = ED_operator_editmesh;
3139
3140         /* flags */
3141         ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
3142
3143         prop = RNA_def_float_distance(ot->srna, "thickness", 0.01f, -1e4f, 1e4f, "Thickness", "", -10.0f, 10.0f);
3144         RNA_def_property_ui_range(prop, -10.0, 10.0, 0.1, 4);
3145 }
3146
3147 /** \} */
3148
3149 /* -------------------------------------------------------------------- */
3150 /** \name Knife Subdivide Operator
3151  * \{ */
3152
3153 /* ******************************************************************** */
3154 /* Knife Subdivide Tool.  Subdivides edges intersected by a mouse trail
3155  * drawn by user.
3156  *
3157  * Currently mapped to KKey when in MeshEdit mode.
3158  * Usage:
3159  * - Hit Shift K, Select Centers or Exact
3160  * - Hold LMB down to draw path, hit RETKEY.
3161  * - ESC cancels as expected.
3162  *
3163  * Contributed by Robert Wenzlaff (Det. Thorn).
3164  *
3165  * 2.5 Revamp:
3166  *  - non modal (no menu before cutting)
3167  *  - exit on mouse release
3168  *  - polygon/segment drawing can become handled by WM cb later
3169  *
3170  * bmesh port version
3171  */
3172
3173 #define KNIFE_EXACT     1
3174 #define KNIFE_MIDPOINT  2
3175 #define KNIFE_MULTICUT  3
3176
3177 static const EnumPropertyItem knife_items[] = {
3178         {KNIFE_EXACT, "EXACT", 0, "Exact", ""},
3179         {KNIFE_MIDPOINT, "MIDPOINTS", 0, "Midpoints", ""},
3180         {KNIFE_MULTICUT, "MULTICUT", 0, "Multicut", ""},
3181         {0, NULL, 0, NULL, NULL}
3182 };
3183
3184 /* bm_edge_seg_isect() Determines if and where a mouse trail intersects an BMEdge */
3185
3186 static float bm_edge_seg_isect(
3187         const float sco_a[2], const float sco_b[2],
3188         float (*mouse_path)[2], int len, char mode, int *isected)
3189 {
3190 #define MAXSLOPE 100000
3191         float x11, y11, x12 = 0, y12 = 0, x2max, x2min, y2max;
3192         float y2min, dist, lastdist = 0, xdiff2, xdiff1;
3193         float m1, b1, m2, b2, x21, x22, y21, y22, xi;
3194         float yi, x1min, x1max, y1max, y1min, perc = 0;
3195         float threshold = 0.0;
3196         int i;
3197
3198         //threshold = 0.000001; /* tolerance for vertex intersection */
3199         // XXX threshold = scene->toolsettings->select_thresh / 100;
3200
3201         /* Get screen coords of verts */
3202         x21 = sco_a[0];
3203         y21 = sco_a[1];
3204
3205         x22 = sco_b[0];
3206         y22 = sco_b[1];
3207
3208         xdiff2 = (x22 - x21);
3209         if (xdiff2) {
3210                 m2 = (y22 - y21) / xdiff2;
3211                 b2 = ((x22 * y21) - (x21 * y22)) / xdiff2;
3212         }
3213         else {
3214                 m2 = MAXSLOPE;  /* Verticle slope  */
3215                 b2 = x22;
3216         }
3217
3218         *isected = 0;
3219
3220         /* check for _exact_ vertex intersection first */
3221         if (mode != KNIFE_MULTICUT) {
3222                 for (i = 0; i < len; i++) {
3223                         if (i > 0) {
3224                                 x11 = x12;
3225                                 y11 = y12;
3226                         }
3227                         else {
3228                                 x11 = mouse_path[i][0];
3229                                 y11 = mouse_path[i][1];
3230                         }
3231                         x12 = mouse_path[i][0];
3232                         y12 = mouse_path[i][1];
3233
3234                         /* test e->v1 */
3235                         if ((x11 == x21 && y11 == y21) || (x12 == x21 && y12 == y21)) {
3236                                 perc = 0;
3237                                 *isected = 1;
3238                                 return perc;
3239                         }
3240                         /* test e->v2 */
3241                         else if ((x11 == x22 && y11 == y22) || (x12 == x22 && y12 == y22)) {
3242                                 perc = 0;
3243                                 *isected = 2;
3244                                 return perc;
3245                         }
3246                 }
3247         }
3248
3249         /* now check for edge intersect (may produce vertex intersection as well) */
3250         for (i = 0; i < len; i++) {
3251                 if (i > 0) {
3252                         x11 = x12;
3253                         y11 = y12;
3254                 }
3255                 else {
3256                         x11 = mouse_path[i][0];
3257                         y11 = mouse_path[i][1];
3258                 }
3259                 x12 = mouse_path[i][0];
3260                 y12 = mouse_path[i][1];
3261
3262                 /* Perp. Distance from point to line */
3263                 if (m2 != MAXSLOPE) dist = (y12 - m2 * x12 - b2);  /* /sqrt(m2 * m2 + 1); Only looking for */
3264                 /* change in sign.  Skip extra math */
3265                 else dist = x22 - x12;
3266
3267                 if (i == 0) lastdist = dist;
3268
3269                 /* if dist changes sign, and intersect point in edge's Bound Box */
3270                 if ((lastdist * dist) <= 0) {
3271                         xdiff1 = (x12 - x11); /* Equation of line between last 2 points */
3272                         if (xdiff1) {
3273                                 m1 = (y12 - y11) / xdiff1;
3274                                 b1 = ((x12 * y11) - (x11 * y12)) / xdiff1;
3275                         }
3276                         else {
3277                                 m1 = MAXSLOPE;
3278                                 b1 = x12;
3279                         }
3280                         x2max = max_ff(x21, x22) + 0.001f; /* prevent missed edges   */