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