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