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