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