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