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