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