7abf05044ddec0c90481b5148598251e5be2c138
[blender.git] / source / blender / bmesh / intern / bmesh_opdefines.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  * Contributor(s): Joseph Eagar, Geoffrey Bantle, Campbell Barton
19  *
20  * ***** END GPL LICENSE BLOCK *****
21  */
22
23 /** \file blender/bmesh/intern/bmesh_opdefines.c
24  *  \ingroup bmesh
25  *
26  * BMesh operator definitions.
27  *
28  * This file defines (and documents) all bmesh operators (bmops).
29  *
30  * Do not rename any operator or slot names! otherwise you must go
31  * through the code and find all references to them!
32  *
33  * A word on slot names:
34  *
35  * For geometry input slots, the following are valid names:
36  * - verts
37  * - edges
38  * - faces
39  * - edgefacein
40  * - vertfacein
41  * - vertedgein
42  * - vertfacein
43  * - geom
44  *
45  * The basic rules are, for single-type geometry slots, use the plural of the
46  * type name (e.g. edges).  for double-type slots, use the two type names plus
47  * "in" (e.g. edgefacein).  for three-type slots, use geom.
48  *
49  * for output slots, for single-type geometry slots, use the type name plus "out",
50  * (e.g. verts.out), for double-type slots, use the two type names plus "out",
51  * (e.g. vertfaces.out), for three-type slots, use geom.  note that you can also
52  * use more esoteric names (e.g. geom_skirt.out) so long as the comment next to the
53  * slot definition tells you what types of elements are in it.
54  *
55  */
56
57 #include "BLI_utildefines.h"
58
59 #include "bmesh.h"
60 #include "intern/bmesh_operators_private.h"
61
62 /* The formatting of these bmesh operators is parsed by
63  * 'doc/python_api/rst_from_bmesh_opdefines.py'
64  * for use in python docs, so reStructuredText may be used
65  * rather then doxygen syntax.
66  *
67  * template (py quotes used because nested comments don't work
68  * on all C compilers):
69  *
70  * """
71  * Region Extend.
72  *
73  * paragraph1, Extends bleh bleh bleh.
74  * Bleh Bleh bleh.
75  *
76  * Another paragraph.
77  *
78  * Another paragraph.
79  * """
80  *
81  * so the first line is the "title" of the bmop.
82  * subsequent line blocks separated by blank lines
83  * are paragraphs.  individual descriptions of slots
84  * are extracted from comments next to them.
85  *
86  * eg:
87  *     {BMO_OP_SLOT_ELEMENT_BUF, "geom.out"},  """ output slot, boundary region """
88  *
89  * ... or:
90  *
91  * """ output slot, boundary region """
92  *     {BMO_OP_SLOT_ELEMENT_BUF, "geom.out"},
93  *
94  * Both are acceptable.
95  * note that '//' comments are ignored.
96  */
97
98 /*
99  * Vertex Smooth.
100  *
101  * Smooths vertices by using a basic vertex averaging scheme.
102  */
103 static BMOpDefine bmo_smooth_vert_def = {
104         "smooth_vert",
105         /* slots_in */
106         {{"verts", BMO_OP_SLOT_ELEMENT_BUF, {BM_VERT}},    /* input vertices */
107          {"factor", BMO_OP_SLOT_FLT},           /* smoothing factor */
108          {"mirror_clip_x", BMO_OP_SLOT_BOOL},   /* set vertices close to the x axis before the operation to 0 */
109          {"mirror_clip_y", BMO_OP_SLOT_BOOL},   /* set vertices close to the y axis before the operation to 0 */
110          {"mirror_clip_z", BMO_OP_SLOT_BOOL},   /* set vertices close to the z axis before the operation to 0 */
111          {"clip_dist",  BMO_OP_SLOT_FLT},       /* clipping threshold for the above three slots */
112          {"use_axis_x", BMO_OP_SLOT_BOOL},      /* smooth vertices along X axis */
113          {"use_axis_y", BMO_OP_SLOT_BOOL},      /* smooth vertices along Y axis */
114          {"use_axis_z", BMO_OP_SLOT_BOOL},      /* smooth vertices along Z axis */
115          {{'\0'}},
116         },
117         {{{'\0'}}},  /* no output */
118         bmo_smooth_vert_exec,
119         (BMO_OPTYPE_FLAG_NORMALS_CALC),
120 };
121
122 /*
123  * Vertex Smooth Laplacian.
124  *
125  * Smooths vertices by using Laplacian smoothing propose by.
126  * Desbrun, et al. Implicit Fairing of Irregular Meshes using Diffusion and Curvature Flow.
127  */
128 static BMOpDefine bmo_smooth_laplacian_vert_def = {
129         "smooth_laplacian_vert",
130         /* slots_in */
131         {{"verts", BMO_OP_SLOT_ELEMENT_BUF, {BM_VERT}},    /* input vertices */
132          {"lambda_factor", BMO_OP_SLOT_FLT},           /* lambda param */
133          {"lambda_border", BMO_OP_SLOT_FLT},    /* lambda param in border */
134          {"use_x", BMO_OP_SLOT_BOOL},           /* Smooth object along X axis */
135          {"use_y", BMO_OP_SLOT_BOOL},           /* Smooth object along Y axis */
136          {"use_z", BMO_OP_SLOT_BOOL},           /* Smooth object along Z axis */
137          {"preserve_volume", BMO_OP_SLOT_BOOL}, /* Apply volume preservation after smooth */
138          {{'\0'}},
139         },
140         {{{'\0'}}},  /* no output */
141         bmo_smooth_laplacian_vert_exec,
142         (BMO_OPTYPE_FLAG_NORMALS_CALC),
143 };
144
145 /*
146  * Right-Hand Faces.
147  *
148  * Computes an "outside" normal for the specified input faces.
149  */
150 static BMOpDefine bmo_recalc_face_normals_def = {
151         "recalc_face_normals",
152         /* slots_in */
153         {{"faces", BMO_OP_SLOT_ELEMENT_BUF, {BM_FACE}},
154          {{'\0'}},
155         },
156         {{{'\0'}}},  /* no output */
157         bmo_recalc_face_normals_exec,
158         (BMO_OPTYPE_FLAG_UNTAN_MULTIRES |
159          BMO_OPTYPE_FLAG_NORMALS_CALC),
160 };
161
162 /*
163  * Planar Faces.
164  *
165  * Iteratively flatten faces.
166  */
167 static BMOpDefine bmo_planar_faces_def = {
168         "planar_faces",
169         /* slots_in */
170         {{"faces", BMO_OP_SLOT_ELEMENT_BUF, {BM_FACE}},    /* input geometry. */
171          {"iterations", BMO_OP_SLOT_INT},  /* Number of times to flatten faces (for when connected faces are used) */
172          {"factor", BMO_OP_SLOT_FLT},  /* Influence for making planar each iteration */
173          {{'\0'}},
174         },
175         /* slots_out */
176         {{"geom.out", BMO_OP_SLOT_ELEMENT_BUF, {BM_VERT | BM_EDGE | BM_FACE}}, /* output slot, computed boundary geometry. */
177          {{'\0'}},
178         },
179         bmo_planar_faces_exec,
180         (BMO_OPTYPE_FLAG_SELECT_FLUSH |
181          BMO_OPTYPE_FLAG_SELECT_VALIDATE),
182 };
183
184 /*
185  * Region Extend.
186  *
187  * used to implement the select more/less tools.
188  * this puts some geometry surrounding regions of
189  * geometry in geom into geom.out.
190  *
191  * if use_faces is 0 then geom.out spits out verts and edges,
192  * otherwise it spits out faces.
193  */
194 static BMOpDefine bmo_region_extend_def = {
195         "region_extend",
196         /* slots_in */
197         {{"geom", BMO_OP_SLOT_ELEMENT_BUF, {BM_VERT | BM_EDGE | BM_FACE}},     /* input geometry */
198          {"use_contract", BMO_OP_SLOT_BOOL},    /* find boundary inside the regions, not outside. */
199          {"use_faces", BMO_OP_SLOT_BOOL},       /* extend from faces instead of edges */
200          {"use_face_step", BMO_OP_SLOT_BOOL},   /* step over connected faces */
201          {{'\0'}},
202         },
203         /* slots_out */
204         {{"geom.out", BMO_OP_SLOT_ELEMENT_BUF, {BM_VERT | BM_EDGE | BM_FACE}}, /* output slot, computed boundary geometry. */
205          {{'\0'}},
206         },
207         bmo_region_extend_exec,
208         (BMO_OPTYPE_FLAG_SELECT_FLUSH |
209          BMO_OPTYPE_FLAG_SELECT_VALIDATE),
210 };
211
212 /*
213  * Edge Rotate.
214  *
215  * Rotates edges topologically.  Also known as "spin edge" to some people.
216  * Simple example: ``[/] becomes [|] then [\]``.
217  */
218 static BMOpDefine bmo_rotate_edges_def = {
219         "rotate_edges",
220         /* slots_in */
221         {{"edges", BMO_OP_SLOT_ELEMENT_BUF, {BM_EDGE}},    /* input edges */
222          {"use_ccw", BMO_OP_SLOT_BOOL},         /* rotate edge counter-clockwise if true, otherwise clockwise */
223          {{'\0'}},
224         },
225         /* slots_out */
226         {{"edges.out", BMO_OP_SLOT_ELEMENT_BUF, {BM_EDGE}}, /* newly spun edges */
227          {{'\0'}},
228         },
229         bmo_rotate_edges_exec,
230         (BMO_OPTYPE_FLAG_UNTAN_MULTIRES |
231          BMO_OPTYPE_FLAG_NORMALS_CALC |
232          BMO_OPTYPE_FLAG_SELECT_FLUSH |
233          BMO_OPTYPE_FLAG_SELECT_VALIDATE),
234 };
235
236 /*
237  * Reverse Faces.
238  *
239  * Reverses the winding (vertex order) of faces.
240  * This has the effect of flipping the normal.
241  */
242 static BMOpDefine bmo_reverse_faces_def = {
243         "reverse_faces",
244         /* slots_in */
245         {{"faces", BMO_OP_SLOT_ELEMENT_BUF, {BM_FACE}},    /* input faces */
246          {"flip_multires", BMO_OP_SLOT_BOOL},  /* maintain multi-res offset */
247          {{'\0'}},
248         },
249         {{{'\0'}}},  /* no output */
250         bmo_reverse_faces_exec,
251         (BMO_OPTYPE_FLAG_UNTAN_MULTIRES |
252          BMO_OPTYPE_FLAG_NORMALS_CALC),
253 };
254
255 /*
256  * Edge Bisect.
257  *
258  * Splits input edges (but doesn't do anything else).
259  * This creates a 2-valence vert.
260  */
261 static BMOpDefine bmo_bisect_edges_def = {
262         "bisect_edges",
263         /* slots_in */
264         {{"edges", BMO_OP_SLOT_ELEMENT_BUF, {BM_EDGE}}, /* input edges */
265          {"cuts", BMO_OP_SLOT_INT}, /* number of cuts */
266          {"edge_percents", BMO_OP_SLOT_MAPPING, {(int)BMO_OP_SLOT_SUBTYPE_MAP_FLT}},
267          {{'\0'}},
268         },
269         /* slots_out */
270         {{"geom_split.out", BMO_OP_SLOT_ELEMENT_BUF, {BM_VERT | BM_EDGE | BM_FACE}}, /* newly created vertices and edges */
271          {{'\0'}},
272         },
273         bmo_bisect_edges_exec,
274         (BMO_OPTYPE_FLAG_UNTAN_MULTIRES |
275          BMO_OPTYPE_FLAG_NORMALS_CALC |
276          BMO_OPTYPE_FLAG_SELECT_FLUSH |
277          BMO_OPTYPE_FLAG_SELECT_VALIDATE),
278 };
279
280 /*
281  * Mirror.
282  *
283  * Mirrors geometry along an axis.  The resulting geometry is welded on using
284  * merge_dist.  Pairs of original/mirrored vertices are welded using the merge_dist
285  * parameter (which defines the minimum distance for welding to happen).
286  */
287 static BMOpDefine bmo_mirror_def = {
288         "mirror",
289         /* slots_in */
290         {{"geom", BMO_OP_SLOT_ELEMENT_BUF, {BM_VERT | BM_EDGE | BM_FACE}},     /* input geometry */
291          {"matrix",          BMO_OP_SLOT_MAT},   /* matrix defining the mirror transformation */
292          {"merge_dist",      BMO_OP_SLOT_FLT},   /* maximum distance for merging.  does no merging if 0. */
293          {"axis",            BMO_OP_SLOT_INT},   /* the axis to use, 0, 1, or 2 for x, y, z */
294          {"mirror_u",        BMO_OP_SLOT_BOOL},  /* mirror UVs across the u axis */
295          {"mirror_v",        BMO_OP_SLOT_BOOL},  /* mirror UVs across the v axis */
296          {{'\0'}},
297         },
298         /* slots_out */
299         {{"geom.out", BMO_OP_SLOT_ELEMENT_BUF, {BM_VERT | BM_EDGE | BM_FACE}}, /* output geometry, mirrored */
300          {{'\0'}},
301         },
302         bmo_mirror_exec,
303         (BMO_OPTYPE_FLAG_NORMALS_CALC |
304          BMO_OPTYPE_FLAG_SELECT_FLUSH |
305          BMO_OPTYPE_FLAG_SELECT_VALIDATE),
306 };
307
308 /*
309  * Find Doubles.
310  *
311  * Takes input verts and find vertices they should weld to.
312  * Outputs a mapping slot suitable for use with the weld verts bmop.
313  *
314  * If keep_verts is used, vertices outside that set can only be merged
315  * with vertices in that set.
316  */
317 static BMOpDefine bmo_find_doubles_def = {
318         "find_doubles",
319         /* slots_in */
320         {{"verts", BMO_OP_SLOT_ELEMENT_BUF, {BM_VERT}}, /* input vertices */
321          {"keep_verts", BMO_OP_SLOT_ELEMENT_BUF, {BM_VERT}}, /* list of verts to keep */
322          {"dist",         BMO_OP_SLOT_FLT}, /* minimum distance */
323          {{'\0'}},
324         },
325         /* slots_out */
326         {{"targetmap.out", BMO_OP_SLOT_MAPPING, {(int)BMO_OP_SLOT_SUBTYPE_MAP_ELEM}},
327          {{'\0'}},
328         },
329         bmo_find_doubles_exec,
330         (BMO_OPTYPE_FLAG_NOP),
331 };
332
333 /*
334  * Remove Doubles.
335  *
336  * Finds groups of vertices closer then dist and merges them together,
337  * using the weld verts bmop.
338  */
339 static BMOpDefine bmo_remove_doubles_def = {
340         "remove_doubles",
341         /* slots_in */
342         {{"verts", BMO_OP_SLOT_ELEMENT_BUF, {BM_VERT}}, /* input verts */
343          {"dist",         BMO_OP_SLOT_FLT}, /* minimum distance */
344          {{'\0'}},
345         },
346         {{{'\0'}}},  /* no output */
347         bmo_remove_doubles_exec,
348         (BMO_OPTYPE_FLAG_UNTAN_MULTIRES |
349          BMO_OPTYPE_FLAG_NORMALS_CALC |
350          BMO_OPTYPE_FLAG_SELECT_FLUSH |
351          BMO_OPTYPE_FLAG_SELECT_VALIDATE),
352 };
353
354 /*
355  * Auto Merge.
356  *
357  * Finds groups of vertices closer then **dist** and merges them together,
358  * using the weld verts bmop.  The merges must go from a vert not in
359  * **verts** to one in **verts**.
360  */
361 static BMOpDefine bmo_automerge_def = {
362         "automerge",
363         /* slots_in */
364         {{"verts", BMO_OP_SLOT_ELEMENT_BUF, {BM_VERT}}, /* input verts */
365          {"dist",         BMO_OP_SLOT_FLT}, /* minimum distance */
366          {{'\0'}},
367         },
368         {{{'\0'}}},  /* no output */
369         bmo_automerge_exec,
370         (BMO_OPTYPE_FLAG_UNTAN_MULTIRES |
371          BMO_OPTYPE_FLAG_NORMALS_CALC |
372          BMO_OPTYPE_FLAG_SELECT_FLUSH |
373          BMO_OPTYPE_FLAG_SELECT_VALIDATE),
374 };
375
376 /*
377  * Collapse Connected.
378  *
379  * Collapses connected vertices
380  */
381 static BMOpDefine bmo_collapse_def = {
382         "collapse",
383         /* slots_in */
384         {{"edges", BMO_OP_SLOT_ELEMENT_BUF, {BM_EDGE}}, /* input edges */
385          {"uvs", BMO_OP_SLOT_BOOL}, /* also collapse UVs and such */
386          {{'\0'}},
387         },
388         {{{'\0'}}},  /* no output */
389         bmo_collapse_exec,
390         (BMO_OPTYPE_FLAG_UNTAN_MULTIRES |
391          BMO_OPTYPE_FLAG_NORMALS_CALC |
392          BMO_OPTYPE_FLAG_SELECT_FLUSH |
393          BMO_OPTYPE_FLAG_SELECT_VALIDATE),
394 };
395
396 /*
397  * Face-Data Point Merge.
398  *
399  * Merge uv/vcols at a specific vertex.
400  */
401 static BMOpDefine bmo_pointmerge_facedata_def = {
402         "pointmerge_facedata",
403         /* slots_in */
404         {{"verts", BMO_OP_SLOT_ELEMENT_BUF, {BM_VERT}},    /* input vertices */
405          {"vert_snap", BMO_OP_SLOT_ELEMENT_BUF, {BM_VERT | (int)BMO_OP_SLOT_SUBTYPE_ELEM_IS_SINGLE}},    /* snap vertex */
406          {{'\0'}},
407         },
408         {{{'\0'}}},  /* no output */
409         bmo_pointmerge_facedata_exec,
410         (BMO_OPTYPE_FLAG_NOP),
411 };
412
413 /*
414  * Average Vertices Facevert Data.
415  *
416  * Merge uv/vcols associated with the input vertices at
417  * the bounding box center. (I know, it's not averaging but
418  * the vert_snap_to_bb_center is just too long).
419  */
420 static BMOpDefine bmo_average_vert_facedata_def = {
421         "average_vert_facedata",
422         /* slots_in */
423         {{"verts", BMO_OP_SLOT_ELEMENT_BUF, {BM_VERT}}, /* input vertices */
424          {{'\0'}},
425         },
426         {{{'\0'}}},  /* no output */
427         bmo_average_vert_facedata_exec,
428         (BMO_OPTYPE_FLAG_NOP),
429 };
430
431 /*
432  * Point Merge.
433  *
434  * Merge verts together at a point.
435  */
436 static BMOpDefine bmo_pointmerge_def = {
437         "pointmerge",
438         /* slots_in */
439         {{"verts", BMO_OP_SLOT_ELEMENT_BUF, {BM_VERT}}, /* input vertices (all verts will be merged into the first). */
440          {"merge_co", BMO_OP_SLOT_VEC},  /* Position to merge at. */
441          {{'\0'}},
442         },
443         {{{'\0'}}},  /* no output */
444         bmo_pointmerge_exec,
445         (BMO_OPTYPE_FLAG_UNTAN_MULTIRES |
446          BMO_OPTYPE_FLAG_NORMALS_CALC |
447          BMO_OPTYPE_FLAG_SELECT_FLUSH |
448          BMO_OPTYPE_FLAG_SELECT_VALIDATE),
449 };
450
451 /*
452  * Collapse Connected UV's.
453  *
454  * Collapses connected UV vertices.
455  */
456 static BMOpDefine bmo_collapse_uvs_def = {
457         "collapse_uvs",
458         /* slots_in */
459         {{"edges", BMO_OP_SLOT_ELEMENT_BUF, {BM_EDGE}}, /* input edges */
460          {{'\0'}},
461         },
462         {{{'\0'}}},  /* no output */
463         bmo_collapse_uvs_exec,
464         (BMO_OPTYPE_FLAG_NOP),
465 };
466
467 /*
468  * Weld Verts.
469  *
470  * Welds verts together (kind-of like remove doubles, merge, etc, all of which
471  * use or will use this bmop).  You pass in mappings from vertices to the vertices
472  * they weld with.
473  */
474 static BMOpDefine bmo_weld_verts_def = {
475         "weld_verts",
476         /* slots_in */
477         /* maps welded vertices to verts they should weld to */
478         {{"targetmap", BMO_OP_SLOT_MAPPING, {(int)BMO_OP_SLOT_SUBTYPE_MAP_ELEM}},
479          {{'\0'}},
480         },
481         {{{'\0'}}},  /* no output */
482         bmo_weld_verts_exec,
483         (BMO_OPTYPE_FLAG_UNTAN_MULTIRES |
484          BMO_OPTYPE_FLAG_NORMALS_CALC |
485          BMO_OPTYPE_FLAG_SELECT_FLUSH |
486          BMO_OPTYPE_FLAG_SELECT_VALIDATE),
487 };
488
489 /*
490  * Make Vertex.
491  *
492  * Creates a single vertex; this bmop was necessary
493  * for click-create-vertex.
494  */
495 static BMOpDefine bmo_create_vert_def = {
496         "create_vert",
497         /* slots_in */
498         {{"co", BMO_OP_SLOT_VEC},  /* the coordinate of the new vert */
499          {{'\0'}},
500         },
501         /* slots_out */
502         {{"vert.out", BMO_OP_SLOT_ELEMENT_BUF, {BM_VERT}},  /* the new vert */
503          {{'\0'}},
504         },
505         bmo_create_vert_exec,
506         (BMO_OPTYPE_FLAG_NOP),
507 };
508
509 /*
510  * Join Triangles.
511  *
512  * Tries to intelligently join triangles according
513  * to angle threshold and delimiters.
514  */
515 static BMOpDefine bmo_join_triangles_def = {
516         "join_triangles",
517         /* slots_in */
518         {{"faces", BMO_OP_SLOT_ELEMENT_BUF, {BM_FACE}},    /* input geometry. */
519          {"cmp_seam", BMO_OP_SLOT_BOOL},
520          {"cmp_sharp", BMO_OP_SLOT_BOOL},
521          {"cmp_uvs", BMO_OP_SLOT_BOOL},
522          {"cmp_vcols", BMO_OP_SLOT_BOOL},
523          {"cmp_materials", BMO_OP_SLOT_BOOL},
524          {"angle_face_threshold", BMO_OP_SLOT_FLT},
525          {"angle_shape_threshold", BMO_OP_SLOT_FLT},
526          {{'\0'}},
527         },
528         /* slots_out */
529         {{"faces.out", BMO_OP_SLOT_ELEMENT_BUF, {BM_FACE}},  /* joined faces */
530          {{'\0'}},
531         },
532         bmo_join_triangles_exec,
533         (BMO_OPTYPE_FLAG_UNTAN_MULTIRES |
534          BMO_OPTYPE_FLAG_NORMALS_CALC |
535          BMO_OPTYPE_FLAG_SELECT_FLUSH |
536          BMO_OPTYPE_FLAG_SELECT_VALIDATE),
537 };
538
539 /*
540  * Contextual Create.
541  *
542  * This is basically F-key, it creates
543  * new faces from vertices, makes stuff from edge nets,
544  * makes wire edges, etc.  It also dissolves faces.
545  *
546  * Three verts become a triangle, four become a quad.  Two
547  * become a wire edge.
548  */
549 static BMOpDefine bmo_contextual_create_def = {
550         "contextual_create",
551         /* slots_in */
552         {{"geom", BMO_OP_SLOT_ELEMENT_BUF, {BM_VERT | BM_EDGE | BM_FACE}},     /* input geometry. */
553          {"mat_nr",         BMO_OP_SLOT_INT},   /* material to use */
554          {"use_smooth",        BMO_OP_SLOT_BOOL}, /* smooth to use */
555          {{'\0'}},
556         },
557         /* slots_out */
558         {{"faces.out", BMO_OP_SLOT_ELEMENT_BUF, {BM_FACE}}, /* newly-made face(s) */
559         /* note, this is for stand-alone edges only, not edges which are apart of newly created faces */
560          {"edges.out", BMO_OP_SLOT_ELEMENT_BUF, {BM_EDGE}}, /* newly-made edge(s) */
561          {{'\0'}},
562         },
563         bmo_contextual_create_exec,
564         (BMO_OPTYPE_FLAG_UNTAN_MULTIRES |
565          BMO_OPTYPE_FLAG_NORMALS_CALC |
566          BMO_OPTYPE_FLAG_SELECT_FLUSH |
567          BMO_OPTYPE_FLAG_SELECT_VALIDATE),
568 };
569
570 /*
571  * Bridge edge loops with faces.
572  */
573 static BMOpDefine bmo_bridge_loops_def = {
574         "bridge_loops",
575         /* slots_in */
576         {{"edges", BMO_OP_SLOT_ELEMENT_BUF, {BM_EDGE}}, /* input edges */
577          {"use_pairs",          BMO_OP_SLOT_BOOL},
578          {"use_cyclic",         BMO_OP_SLOT_BOOL},
579          {"use_merge",          BMO_OP_SLOT_BOOL},
580          {"merge_factor",       BMO_OP_SLOT_FLT},
581          {"twist_offset",       BMO_OP_SLOT_INT},
582          {{'\0'}},
583         },
584         /* slots_out */
585         {{"faces.out", BMO_OP_SLOT_ELEMENT_BUF, {BM_FACE}}, /* new faces */
586          {"edges.out", BMO_OP_SLOT_ELEMENT_BUF, {BM_EDGE}}, /* new edges */
587          {{'\0'}},
588         },
589         bmo_bridge_loops_exec,
590         (BMO_OPTYPE_FLAG_NORMALS_CALC |
591          BMO_OPTYPE_FLAG_SELECT_FLUSH |
592          BMO_OPTYPE_FLAG_SELECT_VALIDATE),
593 };
594
595 /*
596  * Grid Fill.
597  *
598  * Create faces defined by 2 disconnected edge loops (which share edges).
599  */
600 static BMOpDefine bmo_grid_fill_def = {
601         "grid_fill",
602         /* slots_in */
603         {{"edges", BMO_OP_SLOT_ELEMENT_BUF, {BM_EDGE}}, /* input edges */
604         /* restricts edges to groups.  maps edges to integer */
605          {"mat_nr",         BMO_OP_SLOT_INT},      /* material to use */
606          {"use_smooth",     BMO_OP_SLOT_BOOL},     /* smooth state to use */
607          {"use_interp_simple", BMO_OP_SLOT_BOOL},  /* use simple interpolation */
608          {{'\0'}},
609         },
610         /* slots_out */
611         /* maps new faces to the group numbers they came from */
612         {{"faces.out", BMO_OP_SLOT_ELEMENT_BUF, {BM_FACE}},     /* new faces */
613          {{'\0'}},
614         },
615         bmo_grid_fill_exec,
616         (BMO_OPTYPE_FLAG_NORMALS_CALC |
617          BMO_OPTYPE_FLAG_SELECT_FLUSH),
618 };
619
620
621 /*
622  * Fill Holes.
623  *
624  * Fill boundary edges with faces, copying surrounding customdata.
625  */
626 static BMOpDefine bmo_holes_fill_def = {
627         "holes_fill",
628         /* slots_in */
629         {{"edges", BMO_OP_SLOT_ELEMENT_BUF, {BM_EDGE}}, /* input edges */
630          {"sides",          BMO_OP_SLOT_INT},   /* number of face sides to fill */
631          {{'\0'}},
632         },
633         /* slots_out */
634         /* maps new faces to the group numbers they came from */
635         {{"faces.out", BMO_OP_SLOT_ELEMENT_BUF, {BM_FACE}},     /* new faces */
636          {{'\0'}},
637         },
638         bmo_holes_fill_exec,
639         (BMO_OPTYPE_FLAG_NORMALS_CALC |
640          BMO_OPTYPE_FLAG_SELECT_FLUSH),
641 };
642
643
644 /*
645  * Face Attribute Fill.
646  *
647  * Fill in faces with data from adjacent faces.
648  */
649 static BMOpDefine bmo_face_attribute_fill_def = {
650         "face_attribute_fill",
651         /* slots_in */
652         {{"faces", BMO_OP_SLOT_ELEMENT_BUF, {BM_FACE}},     /* input faces */
653          {"use_normals",        BMO_OP_SLOT_BOOL},  /* copy face winding */
654          {"use_data",           BMO_OP_SLOT_BOOL},  /* copy face data */
655          {{'\0'}},
656         },
657         /* slots_out */
658         /* maps new faces to the group numbers they came from */
659         {{"faces_fail.out", BMO_OP_SLOT_ELEMENT_BUF, {BM_FACE}},     /* faces that could not be handled */
660          {{'\0'}},
661         },
662         bmo_face_attribute_fill_exec,
663         (BMO_OPTYPE_FLAG_NORMALS_CALC),
664 };
665
666 /*
667  * Edge Loop Fill.
668  *
669  * Create faces defined by one or more non overlapping edge loops.
670  */
671 static BMOpDefine bmo_edgeloop_fill_def = {
672         "edgeloop_fill",
673         /* slots_in */
674         {{"edges", BMO_OP_SLOT_ELEMENT_BUF, {BM_EDGE}}, /* input edges */
675         /* restricts edges to groups.  maps edges to integer */
676          {"mat_nr",         BMO_OP_SLOT_INT},      /* material to use */
677          {"use_smooth",        BMO_OP_SLOT_BOOL},  /* smooth state to use */
678          {{'\0'}},
679         },
680         /* slots_out */
681         /* maps new faces to the group numbers they came from */
682         {{"faces.out", BMO_OP_SLOT_ELEMENT_BUF, {BM_FACE}},     /* new faces */
683          {{'\0'}},
684         },
685         bmo_edgeloop_fill_exec,
686         (BMO_OPTYPE_FLAG_NORMALS_CALC |
687          BMO_OPTYPE_FLAG_SELECT_FLUSH),
688 };
689
690
691 /*
692  * Edge Net Fill.
693  *
694  * Create faces defined by enclosed edges.
695  */
696 static BMOpDefine bmo_edgenet_fill_def = {
697         "edgenet_fill",
698         /* slots_in */
699         {{"edges", BMO_OP_SLOT_ELEMENT_BUF, {BM_EDGE}}, /* input edges */
700          {"mat_nr",          BMO_OP_SLOT_INT},  /* material to use */
701          {"use_smooth",      BMO_OP_SLOT_BOOL}, /* smooth state to use */
702          {"sides",           BMO_OP_SLOT_INT},  /* number of sides */
703          {{'\0'}},
704         },
705         /* slots_out */
706         /* maps new faces to the group numbers they came from */
707         {{"faces.out", BMO_OP_SLOT_ELEMENT_BUF, {BM_FACE}},  /* new faces */
708          {{'\0'}},
709         },
710         bmo_edgenet_fill_exec,
711         (BMO_OPTYPE_FLAG_NORMALS_CALC |
712          BMO_OPTYPE_FLAG_SELECT_FLUSH),
713 };
714
715 /*
716  * Edgenet Prepare.
717  *
718  * Identifies several useful edge loop cases and modifies them so
719  * they'll become a face when edgenet_fill is called.  The cases covered are:
720  *
721  * - One single loop; an edge is added to connect the ends
722  * - Two loops; two edges are added to connect the endpoints (based on the
723  *   shortest distance between each endpont).
724  */
725 static BMOpDefine bmo_edgenet_prepare_def = {
726         "edgenet_prepare",
727         /* slots_in */
728         {{"edges", BMO_OP_SLOT_ELEMENT_BUF, {BM_EDGE}},    /* input edges */
729          {{'\0'}},
730         },
731         /* slots_out */
732         {{"edges.out", BMO_OP_SLOT_ELEMENT_BUF, {BM_EDGE}},  /* new edges */
733          {{'\0'}},
734         },
735         bmo_edgenet_prepare_exec,
736         (BMO_OPTYPE_FLAG_NOP),
737 };
738
739 /*
740  * Rotate.
741  *
742  * Rotate vertices around a center, using a 3x3 rotation matrix.
743  */
744 static BMOpDefine bmo_rotate_def = {
745         "rotate",
746         /* slots_in */
747         {{"cent",            BMO_OP_SLOT_VEC},  /* center of rotation */
748          {"matrix",          BMO_OP_SLOT_MAT},  /* matrix defining rotation */
749          {"verts",           BMO_OP_SLOT_ELEMENT_BUF, {BM_VERT}},  /* input vertices */
750          {"space",           BMO_OP_SLOT_MAT},  /* matrix to define the space (typically object matrix) */
751          {{'\0'}},
752         },
753         {{{'\0'}}},  /* no output */
754         bmo_rotate_exec,
755         (BMO_OPTYPE_FLAG_NORMALS_CALC),
756 };
757
758 /*
759  * Translate.
760  *
761  * Translate vertices by an offset.
762  */
763 static BMOpDefine bmo_translate_def = {
764         "translate",
765         /* slots_in */
766         {{"vec", BMO_OP_SLOT_VEC},  /* translation offset */
767          {"space", BMO_OP_SLOT_MAT},  /* matrix to define the space (typically object matrix) */
768          {"verts", BMO_OP_SLOT_ELEMENT_BUF, {BM_VERT}},  /* input vertices */
769          {{'\0'}},
770         },
771         {{{'\0'}}},  /* no output */
772         bmo_translate_exec,
773         (BMO_OPTYPE_FLAG_NORMALS_CALC),
774 };
775
776 /*
777  * Scale.
778  *
779  * Scales vertices by an offset.
780  */
781 static BMOpDefine bmo_scale_def = {
782         "scale",
783         /* slots_in */
784         {{"vec", BMO_OP_SLOT_VEC},  /* scale factor */
785          {"space", BMO_OP_SLOT_MAT},  /* matrix to define the space (typically object matrix) */
786          {"verts", BMO_OP_SLOT_ELEMENT_BUF, {BM_VERT}},  /* input vertices */
787          {{'\0'}},
788         },
789         {{{'\0'}}},  /* no output */
790         bmo_scale_exec,
791         (BMO_OPTYPE_FLAG_NORMALS_CALC),
792 };
793
794
795 /*
796  * Transform.
797  *
798  * Transforms a set of vertices by a matrix.  Multiplies
799  * the vertex coordinates with the matrix.
800  */
801 static BMOpDefine bmo_transform_def = {
802         "transform",
803         /* slots_in */
804         {{"matrix",          BMO_OP_SLOT_MAT},  /* transform matrix */
805          {"space",           BMO_OP_SLOT_MAT},  /* matrix to define the space (typically object matrix) */
806          {"verts",           BMO_OP_SLOT_ELEMENT_BUF, {BM_VERT}},  /* input vertices */
807          {{'\0'}},
808         },
809         {{{'\0'}}},  /* no output */
810         bmo_transform_exec,
811         (BMO_OPTYPE_FLAG_NORMALS_CALC),
812 };
813
814 /*
815  * Object Load BMesh.
816  *
817  * Loads a bmesh into an object/mesh.  This is a "private"
818  * bmop.
819  */
820 static BMOpDefine bmo_object_load_bmesh_def = {
821         "object_load_bmesh",
822         /* slots_in */
823         {{"scene", BMO_OP_SLOT_PTR, {(int)BMO_OP_SLOT_SUBTYPE_PTR_SCENE}},
824          {"object", BMO_OP_SLOT_PTR, {(int)BMO_OP_SLOT_SUBTYPE_PTR_OBJECT}},
825          {{'\0'}},
826         },
827         {{{'\0'}}},  /* no output */
828         bmo_object_load_bmesh_exec,
829         (BMO_OPTYPE_FLAG_NOP),
830 };
831
832
833 /*
834  * BMesh to Mesh.
835  *
836  * Converts a bmesh to a Mesh.  This is reserved for exiting editmode.
837  */
838 static BMOpDefine bmo_bmesh_to_mesh_def = {
839         "bmesh_to_mesh",
840         /* slots_in */
841         {
842          /* pointer to a mesh structure to fill in */
843          {"mesh", BMO_OP_SLOT_PTR, {(int)BMO_OP_SLOT_SUBTYPE_PTR_MESH}},
844         /* pointer to an object structure */
845          {"object", BMO_OP_SLOT_PTR, {(int)BMO_OP_SLOT_SUBTYPE_PTR_OBJECT}},
846          {{'\0'}},
847         },
848         {{{'\0'}}},  /* no output */
849         bmo_bmesh_to_mesh_exec,
850         (BMO_OPTYPE_FLAG_NOP),
851 };
852
853 /*
854  * Mesh to BMesh.
855  *
856  * Load the contents of a mesh into the bmesh.  this bmop is private, it's
857  * reserved exclusively for entering editmode.
858  */
859 static BMOpDefine bmo_mesh_to_bmesh_def = {
860         "mesh_to_bmesh",
861         /* slots_in */
862         {
863          /* pointer to a Mesh structure */
864          {"mesh", BMO_OP_SLOT_PTR, {(int)BMO_OP_SLOT_SUBTYPE_PTR_MESH}},
865         /* pointer to an Object structure */
866          {"object", BMO_OP_SLOT_PTR, {(int)BMO_OP_SLOT_SUBTYPE_PTR_OBJECT}},
867          {"use_shapekey", BMO_OP_SLOT_BOOL},  /* load active shapekey coordinates into verts */
868          {{'\0'}},
869         },
870         {{{'\0'}}},  /* no output */
871         bmo_mesh_to_bmesh_exec,
872         (BMO_OPTYPE_FLAG_NOP),
873 };
874
875 /*
876  * Individual Face Extrude.
877  *
878  * Extrudes faces individually.
879  */
880 static BMOpDefine bmo_extrude_discrete_faces_def = {
881         "extrude_discrete_faces",
882         /* slots_in */
883         {{"faces", BMO_OP_SLOT_ELEMENT_BUF, {BM_FACE}},     /* input faces */
884          {"use_normal_flip", BMO_OP_SLOT_BOOL},  /* Create faces with reversed direction. */
885          {"use_select_history", BMO_OP_SLOT_BOOL},  /* pass to duplicate */
886          {{'\0'}},
887         },
888         /* slots_out */
889         {{"faces.out", BMO_OP_SLOT_ELEMENT_BUF, {BM_FACE}},   /* output faces */
890          {{'\0'}},
891         },
892         bmo_extrude_discrete_faces_exec,
893         (BMO_OPTYPE_FLAG_NORMALS_CALC),
894 };
895
896 /*
897  * Extrude Only Edges.
898  *
899  * Extrudes Edges into faces, note that this is very simple, there's no fancy
900  * winged extrusion.
901  */
902 static BMOpDefine bmo_extrude_edge_only_def = {
903         "extrude_edge_only",
904         /* slots_in */
905         {{"edges", BMO_OP_SLOT_ELEMENT_BUF, {BM_EDGE}},    /* input vertices */
906          {"use_normal_flip", BMO_OP_SLOT_BOOL},  /* Create faces with reversed direction. */
907          {"use_select_history", BMO_OP_SLOT_BOOL},  /* pass to duplicate */
908          {{'\0'}},
909         },
910         /* slots_out */
911         {{"geom.out", BMO_OP_SLOT_ELEMENT_BUF, {BM_VERT | BM_EDGE | BM_FACE}},  /* output geometry */
912          {{'\0'}},
913         },
914         bmo_extrude_edge_only_exec,
915         (BMO_OPTYPE_FLAG_NORMALS_CALC),
916 };
917
918 /*
919  * Individual Vertex Extrude.
920  *
921  * Extrudes wire edges from vertices.
922  */
923 static BMOpDefine bmo_extrude_vert_indiv_def = {
924         "extrude_vert_indiv",
925         /* slots_in */
926         {{"verts", BMO_OP_SLOT_ELEMENT_BUF, {BM_VERT}},    /* input vertices */
927          {"use_select_history", BMO_OP_SLOT_BOOL},  /* pass to duplicate */
928          {{'\0'}},
929         },
930         /* slots_out */
931         {{"edges.out", BMO_OP_SLOT_ELEMENT_BUF, {BM_EDGE}},  /* output wire edges */
932          {"verts.out", BMO_OP_SLOT_ELEMENT_BUF, {BM_VERT}},  /* output vertices */
933          {{'\0'}},
934         },
935         bmo_extrude_vert_indiv_exec,
936         (BMO_OPTYPE_FLAG_SELECT_FLUSH),
937 };
938
939 /*
940  * Connect Verts.
941  *
942  * Split faces by adding edges that connect **verts**.
943  */
944 static BMOpDefine bmo_connect_verts_def = {
945         "connect_verts",
946         /* slots_in */
947         {{"verts", BMO_OP_SLOT_ELEMENT_BUF, {BM_VERT}},
948          {"faces_exclude", BMO_OP_SLOT_ELEMENT_BUF, {BM_FACE}},
949          {"check_degenerate", BMO_OP_SLOT_BOOL},  /* prevent splits with overlaps & intersections */
950          {{'\0'}},
951         },
952         /* slots_out */
953         {{"edges.out", BMO_OP_SLOT_ELEMENT_BUF, {BM_EDGE}},
954          {{'\0'}},
955         },
956         bmo_connect_verts_exec,
957         (BMO_OPTYPE_FLAG_UNTAN_MULTIRES |
958          BMO_OPTYPE_FLAG_NORMALS_CALC |
959          BMO_OPTYPE_FLAG_SELECT_FLUSH),
960 };
961
962 /*
963  * Connect Verts to form Convex Faces.
964  *
965  * Ensures all faces are convex **faces**.
966  */
967 static BMOpDefine bmo_connect_verts_concave_def = {
968         "connect_verts_concave",
969         /* slots_in */
970         {{"faces", BMO_OP_SLOT_ELEMENT_BUF, {BM_FACE}},
971          {{'\0'}},
972         },
973         /* slots_out */
974         {{"edges.out", BMO_OP_SLOT_ELEMENT_BUF, {BM_EDGE}},
975          {"faces.out", BMO_OP_SLOT_ELEMENT_BUF, {BM_FACE}},
976          {{'\0'}},
977         },
978         bmo_connect_verts_concave_exec,
979         (BMO_OPTYPE_FLAG_UNTAN_MULTIRES |
980          BMO_OPTYPE_FLAG_NORMALS_CALC |
981          BMO_OPTYPE_FLAG_SELECT_FLUSH),
982 };
983
984 /*
985  * Connect Verts Across non Planer Faces.
986  *
987  * Split faces by connecting edges along non planer **faces**.
988  */
989 static BMOpDefine bmo_connect_verts_nonplanar_def = {
990         "connect_verts_nonplanar",
991         /* slots_in */
992         {{"angle_limit", BMO_OP_SLOT_FLT}, /* total rotation angle (radians) */
993          {"faces", BMO_OP_SLOT_ELEMENT_BUF, {BM_FACE}},
994          {{'\0'}},
995         },
996         /* slots_out */
997         {{"edges.out", BMO_OP_SLOT_ELEMENT_BUF, {BM_EDGE}},
998          {"faces.out", BMO_OP_SLOT_ELEMENT_BUF, {BM_FACE}},
999          {{'\0'}},
1000         },
1001         bmo_connect_verts_nonplanar_exec,
1002         (BMO_OPTYPE_FLAG_UNTAN_MULTIRES |
1003          BMO_OPTYPE_FLAG_NORMALS_CALC |
1004          BMO_OPTYPE_FLAG_SELECT_FLUSH),
1005 };
1006
1007 /*
1008  * Connect Verts.
1009  *
1010  * Split faces by adding edges that connect **verts**.
1011  */
1012 static BMOpDefine bmo_connect_vert_pair_def = {
1013         "connect_vert_pair",
1014         /* slots_in */
1015         {{"verts", BMO_OP_SLOT_ELEMENT_BUF, {BM_VERT}},
1016          {"verts_exclude", BMO_OP_SLOT_ELEMENT_BUF, {BM_VERT}},
1017          {"faces_exclude", BMO_OP_SLOT_ELEMENT_BUF, {BM_FACE}},
1018          {{'\0'}},
1019         },
1020         /* slots_out */
1021         {{"edges.out", BMO_OP_SLOT_ELEMENT_BUF, {BM_EDGE}},
1022          {{'\0'}},
1023         },
1024         bmo_connect_vert_pair_exec,
1025         (BMO_OPTYPE_FLAG_UNTAN_MULTIRES |
1026          BMO_OPTYPE_FLAG_NORMALS_CALC |
1027          BMO_OPTYPE_FLAG_SELECT_FLUSH),
1028 };
1029
1030
1031 /*
1032  * Extrude Faces.
1033  *
1034  * Extrude operator (does not transform)
1035  */
1036 static BMOpDefine bmo_extrude_face_region_def = {
1037         "extrude_face_region",
1038         /* slots_in */
1039         {{"geom", BMO_OP_SLOT_ELEMENT_BUF, {BM_VERT | BM_EDGE | BM_FACE}},     /* edges and faces */
1040          {"edges_exclude", BMO_OP_SLOT_MAPPING, {(int)BMO_OP_SLOT_SUBTYPE_MAP_EMPTY}},
1041          {"use_keep_orig", BMO_OP_SLOT_BOOL},   /* keep original geometry (requires ``geom`` to include edges). */
1042          {"use_normal_flip", BMO_OP_SLOT_BOOL},  /* Create faces with reversed direction. */
1043          {"use_select_history", BMO_OP_SLOT_BOOL},  /* pass to duplicate */
1044          {{'\0'}},
1045         },
1046         /* slots_out */
1047         {{"geom.out", BMO_OP_SLOT_ELEMENT_BUF, {BM_VERT | BM_EDGE | BM_FACE}},
1048          {{'\0'}},
1049         },
1050         bmo_extrude_face_region_exec,
1051         (BMO_OPTYPE_FLAG_NORMALS_CALC),
1052 };
1053
1054 /*
1055  * Dissolve Verts.
1056  */
1057 static BMOpDefine bmo_dissolve_verts_def = {
1058         "dissolve_verts",
1059         /* slots_in */
1060         {{"verts", BMO_OP_SLOT_ELEMENT_BUF, {BM_VERT}},
1061          {"use_face_split", BMO_OP_SLOT_BOOL},
1062          {"use_boundary_tear", BMO_OP_SLOT_BOOL},
1063          {{'\0'}},
1064         },
1065         {{{'\0'}}},  /* no output */
1066         bmo_dissolve_verts_exec,
1067         (BMO_OPTYPE_FLAG_UNTAN_MULTIRES |
1068          BMO_OPTYPE_FLAG_NORMALS_CALC |
1069          BMO_OPTYPE_FLAG_SELECT_FLUSH |
1070          BMO_OPTYPE_FLAG_SELECT_VALIDATE),
1071 };
1072
1073 /*
1074  * Dissolve Edges.
1075  */
1076 static BMOpDefine bmo_dissolve_edges_def = {
1077         "dissolve_edges",
1078         /* slots_in */
1079         {{"edges", BMO_OP_SLOT_ELEMENT_BUF, {BM_EDGE}},
1080          {"use_verts", BMO_OP_SLOT_BOOL},  /* dissolve verts left between only 2 edges. */
1081          {"use_face_split", BMO_OP_SLOT_BOOL},
1082          {{'\0'}},
1083         },
1084         /* slots_out */
1085         {{"region.out", BMO_OP_SLOT_ELEMENT_BUF, {BM_FACE}},
1086          {{'\0'}},
1087         },
1088         bmo_dissolve_edges_exec,
1089         (BMO_OPTYPE_FLAG_UNTAN_MULTIRES |
1090          BMO_OPTYPE_FLAG_NORMALS_CALC |
1091          BMO_OPTYPE_FLAG_SELECT_FLUSH |
1092          BMO_OPTYPE_FLAG_SELECT_VALIDATE),
1093 };
1094
1095 /*
1096  * Dissolve Faces.
1097  */
1098 static BMOpDefine bmo_dissolve_faces_def = {
1099         "dissolve_faces",
1100         /* slots_in */
1101         {{"faces", BMO_OP_SLOT_ELEMENT_BUF, {BM_FACE}},
1102          {"use_verts", BMO_OP_SLOT_BOOL},  /* dissolve verts left between only 2 edges. */
1103          {{'\0'}},
1104         },
1105         /* slots_out */
1106         {{"region.out", BMO_OP_SLOT_ELEMENT_BUF, {BM_FACE}},
1107          {{'\0'}},
1108         },
1109         bmo_dissolve_faces_exec,
1110         (BMO_OPTYPE_FLAG_UNTAN_MULTIRES |
1111          BMO_OPTYPE_FLAG_NORMALS_CALC |
1112          BMO_OPTYPE_FLAG_SELECT_FLUSH |
1113          BMO_OPTYPE_FLAG_SELECT_VALIDATE),
1114 };
1115
1116 /*
1117  * Limited Dissolve.
1118  *
1119  * Dissolve planar faces and co-linear edges.
1120  */
1121 static BMOpDefine bmo_dissolve_limit_def = {
1122         "dissolve_limit",
1123         /* slots_in */
1124         {{"angle_limit", BMO_OP_SLOT_FLT}, /* total rotation angle (radians) */
1125          {"use_dissolve_boundaries", BMO_OP_SLOT_BOOL},
1126          {"verts", BMO_OP_SLOT_ELEMENT_BUF, {BM_VERT}},
1127          {"edges", BMO_OP_SLOT_ELEMENT_BUF, {BM_EDGE}},
1128          {"delimit", BMO_OP_SLOT_INT},
1129          {{'\0'}},
1130         },
1131         /* slots_out */
1132         {{"region.out", BMO_OP_SLOT_ELEMENT_BUF, {BM_FACE}},
1133          {{'\0'}}},
1134         bmo_dissolve_limit_exec,
1135         (BMO_OPTYPE_FLAG_UNTAN_MULTIRES |
1136          BMO_OPTYPE_FLAG_NORMALS_CALC |
1137          BMO_OPTYPE_FLAG_SELECT_FLUSH |
1138          BMO_OPTYPE_FLAG_SELECT_VALIDATE),
1139 };
1140
1141 /*
1142  * Degenerate Dissolve.
1143  *
1144  * Dissolve edges with no length, faces with no area.
1145  */
1146 static BMOpDefine bmo_dissolve_degenerate_def = {
1147         "dissolve_degenerate",
1148         /* slots_in */
1149         {{"dist", BMO_OP_SLOT_FLT}, /* minimum distance to consider degenerate */
1150          {"edges", BMO_OP_SLOT_ELEMENT_BUF, {BM_EDGE}},
1151          {{'\0'}},
1152         },
1153         /* slots_out */
1154         {{{'\0'}}},
1155         bmo_dissolve_degenerate_exec,
1156         (BMO_OPTYPE_FLAG_UNTAN_MULTIRES |
1157          BMO_OPTYPE_FLAG_NORMALS_CALC |
1158          BMO_OPTYPE_FLAG_SELECT_FLUSH |
1159          BMO_OPTYPE_FLAG_SELECT_VALIDATE),
1160 };
1161
1162 /*
1163  * Triangulate.
1164  */
1165 static BMOpDefine bmo_triangulate_def = {
1166         "triangulate",
1167         /* slots_in */
1168         {{"faces", BMO_OP_SLOT_ELEMENT_BUF, {BM_FACE}},
1169          {"quad_method", BMO_OP_SLOT_INT},
1170          {"ngon_method", BMO_OP_SLOT_INT},
1171          {{'\0'}},
1172         },
1173         /* slots_out */
1174         {{"edges.out", BMO_OP_SLOT_ELEMENT_BUF, {BM_EDGE}},
1175          {"faces.out", BMO_OP_SLOT_ELEMENT_BUF, {BM_FACE}},
1176          {"face_map.out", BMO_OP_SLOT_MAPPING, {(int)BMO_OP_SLOT_SUBTYPE_MAP_ELEM}},
1177          {"face_map_double.out", BMO_OP_SLOT_MAPPING, {(int)BMO_OP_SLOT_SUBTYPE_MAP_ELEM}},  /* duplicate faces */
1178          {{'\0'}},
1179         },
1180         bmo_triangulate_exec,
1181         (BMO_OPTYPE_FLAG_UNTAN_MULTIRES |
1182          BMO_OPTYPE_FLAG_NORMALS_CALC |
1183          BMO_OPTYPE_FLAG_SELECT_FLUSH),
1184 };
1185
1186 /*
1187  * Un-Subdivide.
1188  *
1189  * Reduce detail in geometry containing grids.
1190  */
1191 static BMOpDefine bmo_unsubdivide_def = {
1192         "unsubdivide",
1193         /* slots_in */
1194         {{"verts", BMO_OP_SLOT_ELEMENT_BUF, {BM_VERT}}, /* input vertices */
1195          {"iterations", BMO_OP_SLOT_INT},
1196          {{'\0'}},
1197         },
1198         {{{'\0'}}},  /* no output */
1199         bmo_unsubdivide_exec,
1200         (BMO_OPTYPE_FLAG_UNTAN_MULTIRES |
1201          BMO_OPTYPE_FLAG_NORMALS_CALC |
1202          BMO_OPTYPE_FLAG_SELECT_FLUSH |
1203          BMO_OPTYPE_FLAG_SELECT_VALIDATE),
1204 };
1205
1206 /*
1207  * Subdivide Edges.
1208  *
1209  * Advanced operator for subdividing edges
1210  * with options for face patterns, smoothing and randomization.
1211  */
1212 static BMOpDefine bmo_subdivide_edges_def = {
1213         "subdivide_edges",
1214         /* slots_in */
1215         {{"edges", BMO_OP_SLOT_ELEMENT_BUF, {BM_EDGE}},
1216          {"smooth", BMO_OP_SLOT_FLT},
1217          {"smooth_falloff", BMO_OP_SLOT_INT}, /* SUBD_FALLOFF_ROOT and friends */
1218          {"fractal", BMO_OP_SLOT_FLT},
1219          {"along_normal", BMO_OP_SLOT_FLT},
1220          {"cuts", BMO_OP_SLOT_INT},
1221          {"seed", BMO_OP_SLOT_INT},
1222          {"custom_patterns", BMO_OP_SLOT_MAPPING, {(int)BMO_OP_SLOT_SUBTYPE_MAP_INTERNAL}},  /* uses custom pointers */
1223          {"edge_percents", BMO_OP_SLOT_MAPPING, {(int)BMO_OP_SLOT_SUBTYPE_MAP_FLT}},
1224
1225          {"quad_corner_type",  BMO_OP_SLOT_INT}, /* quad corner type, see bmesh_operators.h */
1226          {"use_grid_fill", BMO_OP_SLOT_BOOL},   /* fill in fully-selected faces with a grid */
1227          {"use_single_edge", BMO_OP_SLOT_BOOL}, /* tessellate the case of one edge selected in a quad or triangle */
1228          {"use_only_quads", BMO_OP_SLOT_BOOL},  /* only subdivide quads (for loopcut) */
1229          {"use_sphere", BMO_OP_SLOT_BOOL},     /* for making new primitives only */
1230          {"use_smooth_even", BMO_OP_SLOT_BOOL},  /* maintain even offset when smoothing */
1231          {{'\0'}},
1232         },
1233         /* slots_out */
1234         {/* these next three can have multiple types of elements in them */
1235          {"geom_inner.out", BMO_OP_SLOT_ELEMENT_BUF, {BM_VERT | BM_EDGE | BM_FACE}},
1236          {"geom_split.out", BMO_OP_SLOT_ELEMENT_BUF, {BM_VERT | BM_EDGE | BM_FACE}},
1237          {"geom.out", BMO_OP_SLOT_ELEMENT_BUF, {BM_VERT | BM_EDGE | BM_FACE}}, /* contains all output geometry */
1238          {{'\0'}},
1239         },
1240         bmo_subdivide_edges_exec,
1241         (BMO_OPTYPE_FLAG_UNTAN_MULTIRES |
1242          BMO_OPTYPE_FLAG_NORMALS_CALC |
1243          BMO_OPTYPE_FLAG_SELECT_FLUSH |
1244          BMO_OPTYPE_FLAG_SELECT_VALIDATE),
1245 };
1246
1247 /*
1248  * Subdivide Edge-Ring.
1249  *
1250  * Take an edge-ring, and subdivide with interpolation options.
1251  */
1252 static BMOpDefine bmo_subdivide_edgering_def = {
1253         "subdivide_edgering",
1254         /* slots_in */
1255         {{"edges", BMO_OP_SLOT_ELEMENT_BUF, {BM_EDGE}}, /* input vertices */
1256          {"interp_mode", BMO_OP_SLOT_INT},
1257          {"smooth", BMO_OP_SLOT_FLT},
1258          {"cuts", BMO_OP_SLOT_INT},
1259          {"profile_shape", BMO_OP_SLOT_INT},
1260          {"profile_shape_factor", BMO_OP_SLOT_FLT},
1261          {{'\0'}},
1262         },
1263         {{"faces.out", BMO_OP_SLOT_ELEMENT_BUF, {BM_FACE}}, /* output faces */
1264          {{'\0'}}},
1265         bmo_subdivide_edgering_exec,
1266         (BMO_OPTYPE_FLAG_UNTAN_MULTIRES |
1267          BMO_OPTYPE_FLAG_NORMALS_CALC |
1268          BMO_OPTYPE_FLAG_SELECT_FLUSH |
1269          BMO_OPTYPE_FLAG_SELECT_VALIDATE),
1270 };
1271
1272 /*
1273  * Bisect Plane.
1274  *
1275  * Bisects the mesh by a plane (cut the mesh in half).
1276  */
1277 static BMOpDefine bmo_bisect_plane_def = {
1278         "bisect_plane",
1279         /* slots_in */
1280         {{"geom", BMO_OP_SLOT_ELEMENT_BUF, {BM_VERT | BM_EDGE | BM_FACE}},
1281          {"dist",         BMO_OP_SLOT_FLT},     /* minimum distance when testing if a vert is exactly on the plane */
1282          {"plane_co", BMO_OP_SLOT_VEC},         /* point on the plane */
1283          {"plane_no", BMO_OP_SLOT_VEC},         /* direction of the plane */
1284          {"use_snap_center", BMO_OP_SLOT_BOOL},  /* snap axis aligned verts to the center */
1285          {"clear_outer",   BMO_OP_SLOT_BOOL},    /* when enabled. remove all geometry on the positive side of the plane */
1286          {"clear_inner",   BMO_OP_SLOT_BOOL},    /* when enabled. remove all geometry on the negative side of the plane */
1287          {{'\0'}},
1288         },
1289         {{"geom_cut.out", BMO_OP_SLOT_ELEMENT_BUF, {BM_VERT | BM_EDGE}},  /* output geometry aligned with the plane (new and existing) */
1290          {"geom.out",     BMO_OP_SLOT_ELEMENT_BUF, {BM_VERT | BM_EDGE | BM_FACE}},  /* input and output geometry (result of cut)  */
1291          {{'\0'}}},
1292         bmo_bisect_plane_exec,
1293         (BMO_OPTYPE_FLAG_UNTAN_MULTIRES |
1294          BMO_OPTYPE_FLAG_NORMALS_CALC |
1295          BMO_OPTYPE_FLAG_SELECT_FLUSH |
1296          BMO_OPTYPE_FLAG_SELECT_VALIDATE),
1297 };
1298
1299 /*
1300  * Delete Geometry.
1301  *
1302  * Utility operator to delete geometry.
1303  */
1304 static BMOpDefine bmo_delete_def = {
1305         "delete",
1306         /* slots_in */
1307         {{"geom", BMO_OP_SLOT_ELEMENT_BUF, {BM_VERT | BM_EDGE | BM_FACE}},
1308          {"context", BMO_OP_SLOT_INT},  /* enum DEL_VERTS ... */
1309          {{'\0'}},
1310         },
1311         {{{'\0'}}},  /* no output */
1312         bmo_delete_exec,
1313         (BMO_OPTYPE_FLAG_NORMALS_CALC |
1314          BMO_OPTYPE_FLAG_SELECT_FLUSH |
1315          BMO_OPTYPE_FLAG_SELECT_VALIDATE),
1316 };
1317
1318 /*
1319  * Duplicate Geometry.
1320  *
1321  * Utility operator to duplicate geometry,
1322  * optionally into a destination mesh.
1323  */
1324 static BMOpDefine bmo_duplicate_def = {
1325         "duplicate",
1326         /* slots_in */
1327         {{"geom", BMO_OP_SLOT_ELEMENT_BUF, {BM_VERT | BM_EDGE | BM_FACE}},
1328         /* destination bmesh, if NULL will use current on */
1329          {"dest", BMO_OP_SLOT_PTR, {(int)BMO_OP_SLOT_SUBTYPE_PTR_BMESH}},
1330          {"use_select_history", BMO_OP_SLOT_BOOL},
1331          {{'\0'}},
1332         },
1333         /* slots_out */
1334         {{"geom_orig.out", BMO_OP_SLOT_ELEMENT_BUF, {BM_VERT | BM_EDGE | BM_FACE}},
1335          {"geom.out", BMO_OP_SLOT_ELEMENT_BUF, {BM_VERT | BM_EDGE | BM_FACE}},
1336         /* facemap maps from source faces to dupe
1337          * faces, and from dupe faces to source faces */
1338          {"vert_map.out", BMO_OP_SLOT_MAPPING, {(int)BMO_OP_SLOT_SUBTYPE_MAP_ELEM}},
1339          {"edge_map.out", BMO_OP_SLOT_MAPPING, {(int)BMO_OP_SLOT_SUBTYPE_MAP_ELEM}},
1340          {"face_map.out", BMO_OP_SLOT_MAPPING, {(int)BMO_OP_SLOT_SUBTYPE_MAP_ELEM}},
1341          {"boundary_map.out", BMO_OP_SLOT_MAPPING, {(int)BMO_OP_SLOT_SUBTYPE_MAP_ELEM}},
1342          {"isovert_map.out", BMO_OP_SLOT_MAPPING, {(int)BMO_OP_SLOT_SUBTYPE_MAP_ELEM}},
1343          {{'\0'}},
1344         },
1345         bmo_duplicate_exec,
1346         (BMO_OPTYPE_FLAG_NORMALS_CALC |
1347          BMO_OPTYPE_FLAG_SELECT_FLUSH),
1348 };
1349
1350 /*
1351  * Split Off Geometry.
1352  *
1353  * Disconnect geometry from adjacent edges and faces,
1354  * optionally into a destination mesh.
1355  */
1356 static BMOpDefine bmo_split_def = {
1357         "split",
1358         /* slots_in */
1359         {{"geom", BMO_OP_SLOT_ELEMENT_BUF, {BM_VERT | BM_EDGE | BM_FACE}},
1360         /* destination bmesh, if NULL will use current one */
1361          {"dest", BMO_OP_SLOT_PTR, {(int)BMO_OP_SLOT_SUBTYPE_PTR_BMESH}},
1362          {"use_only_faces", BMO_OP_SLOT_BOOL},  /* when enabled. don't duplicate loose verts/edges */
1363          {{'\0'}},
1364         },
1365         /* slots_out */
1366         {{"geom.out", BMO_OP_SLOT_ELEMENT_BUF, {BM_VERT | BM_EDGE | BM_FACE}},
1367          {"boundary_map.out", BMO_OP_SLOT_MAPPING, {(int)BMO_OP_SLOT_SUBTYPE_MAP_ELEM}},
1368          {"isovert_map.out", BMO_OP_SLOT_MAPPING, {(int)BMO_OP_SLOT_SUBTYPE_MAP_ELEM}},
1369          {{'\0'}},
1370         },
1371         bmo_split_exec,
1372         (BMO_OPTYPE_FLAG_NORMALS_CALC |
1373          BMO_OPTYPE_FLAG_SELECT_FLUSH),
1374 };
1375
1376 /*
1377  * Spin.
1378  *
1379  * Extrude or duplicate geometry a number of times,
1380  * rotating and possibly translating after each step
1381  */
1382 static BMOpDefine bmo_spin_def = {
1383         "spin",
1384         /* slots_in */
1385         {{"geom", BMO_OP_SLOT_ELEMENT_BUF, {BM_VERT | BM_EDGE | BM_FACE}},
1386          {"cent", BMO_OP_SLOT_VEC},             /* rotation center */
1387          {"axis", BMO_OP_SLOT_VEC},             /* rotation axis */
1388          {"dvec", BMO_OP_SLOT_VEC},             /* translation delta per step */
1389          {"angle", BMO_OP_SLOT_FLT},            /* total rotation angle (radians) */
1390          {"space", BMO_OP_SLOT_MAT},            /* matrix to define the space (typically object matrix) */
1391          {"steps", BMO_OP_SLOT_INT},            /* number of steps */
1392          {"use_merge", BMO_OP_SLOT_BOOL},       /* Merge first/last when the angle is a full revolution. */
1393          {"use_normal_flip", BMO_OP_SLOT_BOOL}, /* Create faces with reversed direction. */
1394          {"use_duplicate", BMO_OP_SLOT_BOOL},   /* duplicate or extrude? */
1395          {{'\0'}},
1396         },
1397         /* slots_out */
1398         {{"geom_last.out", BMO_OP_SLOT_ELEMENT_BUF, {BM_VERT | BM_EDGE | BM_FACE}}, /* result of last step */
1399          {{'\0'}},
1400         },
1401         bmo_spin_exec,
1402         (BMO_OPTYPE_FLAG_NORMALS_CALC |
1403          BMO_OPTYPE_FLAG_SELECT_FLUSH),
1404 };
1405
1406
1407 /*
1408  * Similar Faces Search.
1409  *
1410  * Find similar faces (area/material/perimeter, ...).
1411  */
1412 static BMOpDefine bmo_similar_faces_def = {
1413         "similar_faces",
1414         /* slots_in */
1415         {{"faces", BMO_OP_SLOT_ELEMENT_BUF, {BM_FACE}},    /* input faces */
1416          {"type", BMO_OP_SLOT_INT},             /* type of selection */
1417          {"thresh", BMO_OP_SLOT_FLT},           /* threshold of selection */
1418          {"compare", BMO_OP_SLOT_INT},          /* comparison method */
1419          {{'\0'}},
1420         },
1421         /* slots_out */
1422         {{"faces.out", BMO_OP_SLOT_ELEMENT_BUF, {BM_FACE}},  /* output faces */
1423          {{'\0'}},
1424         },
1425         bmo_similar_faces_exec,
1426         (BMO_OPTYPE_FLAG_SELECT_FLUSH),
1427 };
1428
1429 /*
1430  * Similar Edges Search.
1431  *
1432  * Find similar edges (length, direction, edge, seam, ...).
1433  */
1434 static BMOpDefine bmo_similar_edges_def = {
1435         "similar_edges",
1436         /* slots_in */
1437         {{"edges", BMO_OP_SLOT_ELEMENT_BUF, {BM_EDGE}},    /* input edges */
1438          {"type", BMO_OP_SLOT_INT},             /* type of selection */
1439          {"thresh", BMO_OP_SLOT_FLT},           /* threshold of selection */
1440          {"compare", BMO_OP_SLOT_INT},          /* comparison method */
1441          {{'\0'}},
1442         },
1443         /* slots_out */
1444         {{"edges.out", BMO_OP_SLOT_ELEMENT_BUF, {BM_EDGE}},  /* output edges */
1445          {{'\0'}},
1446         },
1447         bmo_similar_edges_exec,
1448         (BMO_OPTYPE_FLAG_SELECT_FLUSH),
1449 };
1450
1451 /*
1452  * Similar Verts Search.
1453  *
1454  * Find similar vertices (normal, face, vertex group, ...).
1455  */
1456 static BMOpDefine bmo_similar_verts_def = {
1457         "similar_verts",
1458         /* slots_in */
1459         {{"verts", BMO_OP_SLOT_ELEMENT_BUF, {BM_VERT}},    /* input vertices */
1460          {"type", BMO_OP_SLOT_INT},             /* type of selection */
1461          {"thresh", BMO_OP_SLOT_FLT},           /* threshold of selection */
1462          {"compare", BMO_OP_SLOT_INT},          /* comparison method */
1463          {{'\0'}},
1464         },
1465         /* slots_out */
1466         {{"verts.out", BMO_OP_SLOT_ELEMENT_BUF, {BM_VERT}},  /* output vertices */
1467          {{'\0'}},
1468         },
1469         bmo_similar_verts_exec,
1470         (BMO_OPTYPE_FLAG_SELECT_FLUSH),
1471 };
1472
1473 /*
1474  * UV Rotation.
1475  *
1476  * Cycle the loop UV's
1477  */
1478 static BMOpDefine bmo_rotate_uvs_def = {
1479         "rotate_uvs",
1480         /* slots_in */
1481         {{"faces", BMO_OP_SLOT_ELEMENT_BUF, {BM_FACE}},    /* input faces */
1482          {"use_ccw", BMO_OP_SLOT_BOOL},         /* rotate counter-clockwise if true, otherwise clockwise */
1483          {{'\0'}},
1484         },
1485         {{{'\0'}}},  /* no output */
1486         bmo_rotate_uvs_exec,
1487         (BMO_OPTYPE_FLAG_NOP),
1488 };
1489
1490 /*
1491  * UV Reverse.
1492  *
1493  * Reverse the UV's
1494  */
1495 static BMOpDefine bmo_reverse_uvs_def = {
1496         "reverse_uvs",
1497         /* slots_in */
1498         {{"faces", BMO_OP_SLOT_ELEMENT_BUF, {BM_FACE}},    /* input faces */
1499          {{'\0'}},
1500         },
1501         {{{'\0'}}},  /* no output */
1502         bmo_reverse_uvs_exec,
1503         (BMO_OPTYPE_FLAG_NOP),
1504 };
1505
1506 /*
1507  * Color Rotation.
1508  *
1509  * Cycle the loop colors
1510  */
1511 static BMOpDefine bmo_rotate_colors_def = {
1512         "rotate_colors",
1513         /* slots_in */
1514         {{"faces", BMO_OP_SLOT_ELEMENT_BUF, {BM_FACE}},    /* input faces */
1515          {"use_ccw", BMO_OP_SLOT_BOOL},         /* rotate counter-clockwise if true, otherwise clockwise */
1516          {{'\0'}},
1517         },
1518         {{{'\0'}}},  /* no output */
1519         bmo_rotate_colors_exec,
1520         (BMO_OPTYPE_FLAG_NOP),
1521 };
1522
1523 /*
1524  * Color Reverse
1525  *
1526  * Reverse the loop colors.
1527  */
1528 static BMOpDefine bmo_reverse_colors_def = {
1529         "reverse_colors",
1530         /* slots_in */
1531         {{"faces", BMO_OP_SLOT_ELEMENT_BUF, {BM_FACE}},    /* input faces */
1532          {{'\0'}},
1533         },
1534         {{{'\0'}}},  /* no output */
1535         bmo_reverse_colors_exec,
1536         (BMO_OPTYPE_FLAG_NOP),
1537 };
1538
1539 /*
1540  * Edge Split.
1541  *
1542  * Disconnects faces along input edges.
1543  */
1544 static BMOpDefine bmo_split_edges_def = {
1545         "split_edges",
1546         /* slots_in */
1547         {{"edges", BMO_OP_SLOT_ELEMENT_BUF, {BM_EDGE}},    /* input edges */
1548          /* needed for vertex rip so we can rip only half an edge at a boundary wich would otherwise split off */
1549          {"verts", BMO_OP_SLOT_ELEMENT_BUF, {BM_VERT}},    /* optional tag verts, use to have greater control of splits */
1550          {"use_verts",        BMO_OP_SLOT_BOOL}, /* use 'verts' for splitting, else just find verts to split from edges */
1551          {{'\0'}},
1552         },
1553         /* slots_out */
1554         {{"edges.out", BMO_OP_SLOT_ELEMENT_BUF, {BM_EDGE}}, /* old output disconnected edges */
1555          {{'\0'}},
1556         },
1557         bmo_split_edges_exec,
1558         (BMO_OPTYPE_FLAG_UNTAN_MULTIRES |
1559          BMO_OPTYPE_FLAG_NORMALS_CALC |
1560          BMO_OPTYPE_FLAG_SELECT_FLUSH),
1561 };
1562
1563 /*
1564  * Create Grid.
1565  *
1566  * Creates a grid with a variable number of subdivisions
1567  */
1568 static BMOpDefine bmo_create_grid_def = {
1569         "create_grid",
1570         /* slots_in */
1571         {{"x_segments",      BMO_OP_SLOT_INT},  /* number of x segments */
1572          {"y_segments",      BMO_OP_SLOT_INT},  /* number of y segments */
1573          {"size",            BMO_OP_SLOT_FLT},  /* size of the grid */
1574          {"matrix",          BMO_OP_SLOT_MAT},  /* matrix to multiply the new geometry with */
1575          {"calc_uvs",        BMO_OP_SLOT_BOOL}, /* calculate default UVs */
1576          {{'\0'}},
1577         },
1578         /* slots_out */
1579         {{"verts.out", BMO_OP_SLOT_ELEMENT_BUF, {BM_VERT}}, /* output verts */
1580          {{'\0'}},
1581         },
1582         bmo_create_grid_exec,
1583         (BMO_OPTYPE_FLAG_NORMALS_CALC |
1584          BMO_OPTYPE_FLAG_SELECT_FLUSH),
1585 };
1586
1587 /*
1588  * Create UV Sphere.
1589  *
1590  * Creates a grid with a variable number of subdivisions
1591  */
1592 static BMOpDefine bmo_create_uvsphere_def = {
1593         "create_uvsphere",
1594         /* slots_in */
1595         {{"u_segments",      BMO_OP_SLOT_INT}, /* number of u segments */
1596          {"v_segments",      BMO_OP_SLOT_INT}, /* number of v segment */
1597          {"diameter",        BMO_OP_SLOT_FLT}, /* diameter */
1598          {"matrix",          BMO_OP_SLOT_MAT}, /* matrix to multiply the new geometry with */
1599          {"calc_uvs",        BMO_OP_SLOT_BOOL}, /* calculate default UVs */
1600          {{'\0'}},
1601         },
1602         /* slots_out */
1603         {{"verts.out", BMO_OP_SLOT_ELEMENT_BUF, {BM_VERT}}, /* output verts */
1604          {{'\0'}},
1605         },
1606         bmo_create_uvsphere_exec,
1607         (BMO_OPTYPE_FLAG_NORMALS_CALC |
1608          BMO_OPTYPE_FLAG_SELECT_FLUSH),
1609 };
1610
1611 /*
1612  * Create Ico-Sphere.
1613  *
1614  * Creates a grid with a variable number of subdivisions
1615  */
1616 static BMOpDefine bmo_create_icosphere_def = {
1617         "create_icosphere",
1618         /* slots_in */
1619         {{"subdivisions",    BMO_OP_SLOT_INT}, /* how many times to recursively subdivide the sphere */
1620          {"diameter",        BMO_OP_SLOT_FLT}, /* diameter */
1621          {"matrix",          BMO_OP_SLOT_MAT}, /* matrix to multiply the new geometry with */
1622          {"calc_uvs",        BMO_OP_SLOT_BOOL}, /* calculate default UVs */
1623          {{'\0'}},
1624         },
1625         /* slots_out */
1626         {{"verts.out", BMO_OP_SLOT_ELEMENT_BUF, {BM_VERT}}, /* output verts */
1627          {{'\0'}},
1628         },
1629         bmo_create_icosphere_exec,
1630         (BMO_OPTYPE_FLAG_NORMALS_CALC |
1631          BMO_OPTYPE_FLAG_SELECT_FLUSH),
1632 };
1633
1634 /*
1635  * Create Suzanne.
1636  *
1637  * Creates a monkey (standard blender primitive).
1638  */
1639 static BMOpDefine bmo_create_monkey_def = {
1640         "create_monkey",
1641         /* slots_in */
1642         {{"matrix",    BMO_OP_SLOT_MAT},  /* matrix to multiply the new geometry with */
1643          {"calc_uvs",  BMO_OP_SLOT_BOOL}, /* calculate default UVs */
1644          {{'\0'}},
1645         },
1646         /* slots_out */
1647         {{"verts.out", BMO_OP_SLOT_ELEMENT_BUF, {BM_VERT}}, /* output verts */
1648          {{'\0'}},
1649         },
1650         bmo_create_monkey_exec,
1651         (BMO_OPTYPE_FLAG_NORMALS_CALC |
1652          BMO_OPTYPE_FLAG_SELECT_FLUSH),
1653 };
1654
1655 /*
1656  * Create Cone.
1657  *
1658  * Creates a cone with variable depth at both ends
1659  */
1660 static BMOpDefine bmo_create_cone_def = {
1661         "create_cone",
1662         /* slots_in */
1663         {{"cap_ends",        BMO_OP_SLOT_BOOL},  /* whether or not to fill in the ends with faces */
1664          {"cap_tris",        BMO_OP_SLOT_BOOL},  /* fill ends with triangles instead of ngons */
1665          {"segments",        BMO_OP_SLOT_INT},
1666          {"diameter1",       BMO_OP_SLOT_FLT},  /* diameter of one end */
1667          {"diameter2",       BMO_OP_SLOT_FLT},  /* diameter of the opposite */
1668          {"depth",           BMO_OP_SLOT_FLT},  /* distance between ends */
1669          {"matrix",          BMO_OP_SLOT_MAT},  /* matrix to multiply the new geometry with */
1670          {"calc_uvs",        BMO_OP_SLOT_BOOL}, /* calculate default UVs */
1671          {{'\0'}},
1672         },
1673         /* slots_out */
1674         {{"verts.out", BMO_OP_SLOT_ELEMENT_BUF, {BM_VERT}}, /* output verts */
1675          {{'\0'}},
1676         },
1677         bmo_create_cone_exec,
1678         (BMO_OPTYPE_FLAG_NORMALS_CALC |
1679          BMO_OPTYPE_FLAG_SELECT_FLUSH),
1680 };
1681
1682 /*
1683  * Creates a Circle.
1684  */
1685 static BMOpDefine bmo_create_circle_def = {
1686         "create_circle",
1687         /* slots_in */
1688         {{"cap_ends",        BMO_OP_SLOT_BOOL},  /* whether or not to fill in the ends with faces */
1689          {"cap_tris",        BMO_OP_SLOT_BOOL},  /* fill ends with triangles instead of ngons */
1690          {"segments",        BMO_OP_SLOT_INT},
1691          {"radius",          BMO_OP_SLOT_FLT},  /* Radius of the circle. */
1692          {"matrix",          BMO_OP_SLOT_MAT},  /* matrix to multiply the new geometry with */
1693          {"calc_uvs",        BMO_OP_SLOT_BOOL}, /* calculate default UVs */
1694          {{'\0'}},
1695         },
1696         /* slots_out */
1697         {{"verts.out", BMO_OP_SLOT_ELEMENT_BUF, {BM_VERT}}, /* output verts */
1698          {{'\0'}},
1699         },
1700         bmo_create_circle_exec,
1701         (BMO_OPTYPE_FLAG_NORMALS_CALC |
1702          BMO_OPTYPE_FLAG_SELECT_FLUSH),
1703 };
1704
1705 /*
1706  * Create Cube
1707  *
1708  * Creates a cube.
1709  */
1710 static BMOpDefine bmo_create_cube_def = {
1711         "create_cube",
1712         /* slots_in */
1713         {{"size",            BMO_OP_SLOT_FLT},  /* size of the cube */
1714          {"matrix",          BMO_OP_SLOT_MAT},  /* matrix to multiply the new geometry with */
1715          {"calc_uvs",        BMO_OP_SLOT_BOOL}, /* calculate default UVs */
1716          {{'\0'}},
1717         },
1718         /* slots_out */
1719         {{"verts.out", BMO_OP_SLOT_ELEMENT_BUF, {BM_VERT}}, /* output verts */
1720          {{'\0'}},
1721         },
1722         bmo_create_cube_exec,
1723         (BMO_OPTYPE_FLAG_NORMALS_CALC |
1724          BMO_OPTYPE_FLAG_SELECT_FLUSH),
1725 };
1726
1727 /*
1728  * Bevel.
1729  *
1730  * Bevels edges and vertices
1731  */
1732 static BMOpDefine bmo_bevel_def = {
1733         "bevel",
1734         /* slots_in */
1735         {{"geom", BMO_OP_SLOT_ELEMENT_BUF, {BM_VERT | BM_EDGE | BM_FACE}},     /* input edges and vertices */
1736          {"offset", BMO_OP_SLOT_FLT},           /* amount to offset beveled edge */
1737          {"offset_type", BMO_OP_SLOT_INT},      /* how to measure offset (enum) */
1738          {"segments", BMO_OP_SLOT_INT},         /* number of segments in bevel */
1739          {"profile", BMO_OP_SLOT_FLT},          /* profile shape, 0->1 (.5=>round) */
1740          {"vertex_only", BMO_OP_SLOT_BOOL},     /* only bevel vertices, not edges */
1741          {"clamp_overlap", BMO_OP_SLOT_BOOL},   /* do not allow beveled edges/vertices to overlap each other */
1742          {"material", BMO_OP_SLOT_INT},         /* material for bevel faces, -1 means get from adjacent faces */
1743          {"loop_slide", BMO_OP_SLOT_BOOL},      /* prefer to slide along edges to having even widths */
1744          {{'\0'}},
1745         },
1746         /* slots_out */
1747         {{"faces.out", BMO_OP_SLOT_ELEMENT_BUF, {BM_FACE}}, /* output faces */
1748          {"edges.out", BMO_OP_SLOT_ELEMENT_BUF, {BM_EDGE}}, /* output edges */
1749          {"verts.out", BMO_OP_SLOT_ELEMENT_BUF, {BM_VERT}}, /* output verts */
1750          {{'\0'}},
1751         },
1752
1753         bmo_bevel_exec,
1754         (BMO_OPTYPE_FLAG_UNTAN_MULTIRES |
1755          BMO_OPTYPE_FLAG_NORMALS_CALC |
1756          BMO_OPTYPE_FLAG_SELECT_FLUSH |
1757          BMO_OPTYPE_FLAG_SELECT_VALIDATE),
1758 };
1759
1760 /*
1761  * Beautify Fill.
1762  *
1763  * Rotate edges to create more evenly spaced triangles.
1764  */
1765 static BMOpDefine bmo_beautify_fill_def = {
1766         "beautify_fill",
1767         /* slots_in */
1768         {{"faces", BMO_OP_SLOT_ELEMENT_BUF, {BM_FACE}}, /* input faces */
1769          {"edges", BMO_OP_SLOT_ELEMENT_BUF, {BM_EDGE}}, /* edges that can be flipped */
1770          {"use_restrict_tag", BMO_OP_SLOT_BOOL}, /* restrict edge rotation to mixed tagged vertices */
1771          {"method", BMO_OP_SLOT_INT}, /* method to define what is beautiful */
1772          {{'\0'}},
1773         },
1774         /* slots_out */
1775         {{"geom.out", BMO_OP_SLOT_ELEMENT_BUF, {BM_VERT | BM_EDGE | BM_FACE}}, /* new flipped faces and edges */
1776          {{'\0'}},
1777         },
1778         bmo_beautify_fill_exec,
1779         (BMO_OPTYPE_FLAG_UNTAN_MULTIRES |
1780          BMO_OPTYPE_FLAG_NORMALS_CALC |
1781          BMO_OPTYPE_FLAG_SELECT_FLUSH |
1782          BMO_OPTYPE_FLAG_SELECT_VALIDATE),
1783 };
1784
1785 /*
1786  * Triangle Fill.
1787  *
1788  * Fill edges with triangles
1789  */
1790 static BMOpDefine bmo_triangle_fill_def = {
1791         "triangle_fill",
1792         /* slots_in */
1793         {{"use_beauty", BMO_OP_SLOT_BOOL},
1794          {"use_dissolve", BMO_OP_SLOT_BOOL},  /* dissolve resulting faces */
1795          {"edges", BMO_OP_SLOT_ELEMENT_BUF, {BM_EDGE}},    /* input edges */
1796          {"normal", BMO_OP_SLOT_VEC},  /* optionally pass the fill normal to use */
1797          {{'\0'}},
1798         },
1799         /* slots_out */
1800         {{"geom.out", BMO_OP_SLOT_ELEMENT_BUF, {BM_VERT | BM_EDGE | BM_FACE}}, /* new faces and edges */
1801          {{'\0'}},
1802         },
1803         bmo_triangle_fill_exec,
1804         (BMO_OPTYPE_FLAG_UNTAN_MULTIRES |
1805          BMO_OPTYPE_FLAG_NORMALS_CALC |
1806          BMO_OPTYPE_FLAG_SELECT_FLUSH),
1807 };
1808
1809 /*
1810  * Solidify.
1811  *
1812  * Turns a mesh into a shell with thickness
1813  */
1814 static BMOpDefine bmo_solidify_def = {
1815         "solidify",
1816         /* slots_in */
1817         {{"geom", BMO_OP_SLOT_ELEMENT_BUF, {BM_VERT | BM_EDGE | BM_FACE}},
1818          {"thickness", BMO_OP_SLOT_FLT},
1819          {{'\0'}},
1820         },
1821         /* slots_out */
1822         {{"geom.out", BMO_OP_SLOT_ELEMENT_BUF, {BM_VERT | BM_EDGE | BM_FACE}},
1823          {{'\0'}},
1824         },
1825         bmo_solidify_face_region_exec,
1826         (BMO_OPTYPE_FLAG_NORMALS_CALC |
1827          BMO_OPTYPE_FLAG_SELECT_FLUSH),
1828 };
1829
1830 /*
1831  * Face Inset (Individual).
1832  *
1833  * Insets individual faces.
1834  */
1835 static BMOpDefine bmo_inset_individual_def = {
1836         "inset_individual",
1837         /* slots_in */
1838         {{"faces", BMO_OP_SLOT_ELEMENT_BUF, {BM_FACE}},    /* input faces */
1839          {"thickness", BMO_OP_SLOT_FLT},
1840          {"depth", BMO_OP_SLOT_FLT},
1841          {"use_even_offset", BMO_OP_SLOT_BOOL},
1842          {"use_interpolate", BMO_OP_SLOT_BOOL},
1843          {"use_relative_offset", BMO_OP_SLOT_BOOL},
1844          {{'\0'}},
1845         },
1846         /* slots_out */
1847         {{"faces.out", BMO_OP_SLOT_ELEMENT_BUF, {BM_FACE}}, /* output faces */
1848          {{'\0'}},
1849         },
1850         bmo_inset_individual_exec,
1851         /* caller needs to handle BMO_OPTYPE_FLAG_SELECT_FLUSH */
1852         (BMO_OPTYPE_FLAG_NORMALS_CALC),
1853 };
1854
1855 /*
1856  * Face Inset (Regions).
1857  *
1858  * Inset or outset face regions.
1859  */
1860 static BMOpDefine bmo_inset_region_def = {
1861         "inset_region",
1862         /* slots_in */
1863         {{"faces", BMO_OP_SLOT_ELEMENT_BUF, {BM_FACE}},    /* input faces */
1864          {"faces_exclude", BMO_OP_SLOT_ELEMENT_BUF, {BM_FACE}},
1865          {"use_boundary", BMO_OP_SLOT_BOOL},
1866          {"use_even_offset", BMO_OP_SLOT_BOOL},
1867          {"use_interpolate", BMO_OP_SLOT_BOOL},
1868          {"use_relative_offset", BMO_OP_SLOT_BOOL},
1869          {"use_edge_rail", BMO_OP_SLOT_BOOL},
1870          {"thickness", BMO_OP_SLOT_FLT},
1871          {"depth", BMO_OP_SLOT_FLT},
1872          {"use_outset", BMO_OP_SLOT_BOOL},
1873          {{'\0'}},
1874         },
1875         /* slots_out */
1876         {{"faces.out", BMO_OP_SLOT_ELEMENT_BUF, {BM_FACE}}, /* output faces */
1877          {{'\0'}},
1878         },
1879         bmo_inset_region_exec,
1880         (BMO_OPTYPE_FLAG_NORMALS_CALC |
1881          BMO_OPTYPE_FLAG_SELECT_FLUSH),
1882 };
1883
1884 /*
1885  * Edgeloop Offset.
1886  *
1887  * Creates edge loops based on simple edge-outset method.
1888  */
1889 static BMOpDefine bmo_offset_edgeloops_def = {
1890         "offset_edgeloops",
1891         /* slots_in */
1892         {{"edges", BMO_OP_SLOT_ELEMENT_BUF, {BM_EDGE}},    /* input faces */
1893          {"use_cap_endpoint", BMO_OP_SLOT_BOOL},
1894          {{'\0'}},
1895         },
1896         /* slots_out */
1897         {{"edges.out", BMO_OP_SLOT_ELEMENT_BUF, {BM_EDGE}}, /* output faces */
1898          {{'\0'}},
1899         },
1900         bmo_offset_edgeloops_exec,
1901         (BMO_OPTYPE_FLAG_NORMALS_CALC |
1902          BMO_OPTYPE_FLAG_SELECT_FLUSH),
1903 };
1904
1905 /*
1906  * Wire Frame.
1907  *
1908  * Makes a wire-frame copy of faces.
1909  */
1910 static BMOpDefine bmo_wireframe_def = {
1911         "wireframe",
1912         /* slots_in */
1913         {{"faces", BMO_OP_SLOT_ELEMENT_BUF, {BM_FACE}},   /* input faces */
1914          {"thickness", BMO_OP_SLOT_FLT},
1915          {"offset", BMO_OP_SLOT_FLT},
1916          {"use_replace", BMO_OP_SLOT_BOOL},
1917          {"use_boundary", BMO_OP_SLOT_BOOL},
1918          {"use_even_offset", BMO_OP_SLOT_BOOL},
1919          {"use_crease", BMO_OP_SLOT_BOOL},
1920          {"crease_weight", BMO_OP_SLOT_FLT},
1921          {"use_relative_offset", BMO_OP_SLOT_BOOL},
1922          {"material_offset", BMO_OP_SLOT_INT},
1923          {{'\0'}},
1924         },
1925         /* slots_out */
1926         {{"faces.out", BMO_OP_SLOT_ELEMENT_BUF, {BM_FACE}}, /* output faces */
1927          {{'\0'}},
1928         },
1929         bmo_wireframe_exec,
1930         (BMO_OPTYPE_FLAG_NORMALS_CALC |
1931          BMO_OPTYPE_FLAG_SELECT_FLUSH |
1932          BMO_OPTYPE_FLAG_SELECT_VALIDATE),
1933 };
1934
1935 /*
1936  * Pokes a face.
1937  *
1938  * Splits a face into a triangle fan.
1939  */
1940 static BMOpDefine bmo_poke_def = {
1941         "poke",
1942         /* slots_in */
1943         {{"faces", BMO_OP_SLOT_ELEMENT_BUF, {BM_FACE}},   /* input faces */
1944          {"offset", BMO_OP_SLOT_FLT}, /* center vertex offset along normal */
1945          {"center_mode", BMO_OP_SLOT_INT}, /* calculation mode for center vertex */
1946          {"use_relative_offset", BMO_OP_SLOT_BOOL}, /* apply offset */
1947          {{'\0'}},
1948         },
1949         /* slots_out */
1950         {{"verts.out", BMO_OP_SLOT_ELEMENT_BUF, {BM_VERT}}, /* output verts */
1951          {"faces.out", BMO_OP_SLOT_ELEMENT_BUF, {BM_FACE}}, /* output faces */
1952          {{'\0'}},
1953         },
1954         bmo_poke_exec,
1955         (BMO_OPTYPE_FLAG_NORMALS_CALC |
1956          BMO_OPTYPE_FLAG_SELECT_FLUSH |
1957          BMO_OPTYPE_FLAG_SELECT_VALIDATE),
1958 };
1959
1960 #ifdef WITH_BULLET
1961 /*
1962  * Convex Hull
1963  *
1964  * Builds a convex hull from the vertices in 'input'.
1965  *
1966  * If 'use_existing_faces' is true, the hull will not output triangles
1967  * that are covered by a pre-existing face.
1968  *
1969  * All hull vertices, faces, and edges are added to 'geom.out'. Any
1970  * input elements that end up inside the hull (i.e. are not used by an
1971  * output face) are added to the 'interior_geom' slot. The
1972  * 'unused_geom' slot will contain all interior geometry that is
1973  * completely unused. Lastly, 'holes_geom' contains edges and faces
1974  * that were in the input and are part of the hull.
1975  */
1976 static BMOpDefine bmo_convex_hull_def = {
1977         "convex_hull",
1978         /* slots_in */
1979         {{"input", BMO_OP_SLOT_ELEMENT_BUF, {BM_VERT | BM_EDGE | BM_FACE}},
1980          {"use_existing_faces", BMO_OP_SLOT_BOOL},
1981          {{'\0'}},
1982         },
1983         /* slots_out */
1984         {{"geom.out", BMO_OP_SLOT_ELEMENT_BUF, {BM_VERT | BM_EDGE | BM_FACE}},
1985          {"geom_interior.out", BMO_OP_SLOT_ELEMENT_BUF, {BM_VERT | BM_EDGE | BM_FACE}},
1986          {"geom_unused.out", BMO_OP_SLOT_ELEMENT_BUF, {BM_VERT | BM_EDGE | BM_FACE}},
1987          {"geom_holes.out", BMO_OP_SLOT_ELEMENT_BUF, {BM_VERT | BM_EDGE | BM_FACE}},
1988          {{'\0'}},
1989         },
1990         bmo_convex_hull_exec,
1991         (BMO_OPTYPE_FLAG_NORMALS_CALC |
1992          BMO_OPTYPE_FLAG_SELECT_FLUSH |
1993          BMO_OPTYPE_FLAG_SELECT_VALIDATE),
1994 };
1995 #endif
1996
1997 /*
1998  * Symmetrize.
1999  *
2000  * Makes the mesh elements in the "input" slot symmetrical. Unlike
2001  * normal mirroring, it only copies in one direction, as specified by
2002  * the "direction" slot. The edges and faces that cross the plane of
2003  * symmetry are split as needed to enforce symmetry.
2004  *
2005  * All new vertices, edges, and faces are added to the "geom.out" slot.
2006  */
2007 static BMOpDefine bmo_symmetrize_def = {
2008         "symmetrize",
2009         /* slots_in */
2010         {{"input", BMO_OP_SLOT_ELEMENT_BUF, {BM_VERT | BM_EDGE | BM_FACE}},
2011          {"direction", BMO_OP_SLOT_INT},
2012          {"dist", BMO_OP_SLOT_FLT}, /* minimum distance */
2013          {{'\0'}},
2014         },
2015         /* slots_out */
2016         {{"geom.out", BMO_OP_SLOT_ELEMENT_BUF, {BM_VERT | BM_EDGE | BM_FACE}},
2017          {{'\0'}},
2018         },
2019         bmo_symmetrize_exec,
2020         (BMO_OPTYPE_FLAG_NORMALS_CALC |
2021          BMO_OPTYPE_FLAG_SELECT_FLUSH |
2022          BMO_OPTYPE_FLAG_SELECT_VALIDATE),
2023 };
2024
2025 const BMOpDefine *bmo_opdefines[] = {
2026         &bmo_automerge_def,
2027         &bmo_average_vert_facedata_def,
2028         &bmo_beautify_fill_def,
2029         &bmo_bevel_def,
2030         &bmo_bisect_edges_def,
2031         &bmo_bmesh_to_mesh_def,
2032         &bmo_bridge_loops_def,
2033         &bmo_collapse_def,
2034         &bmo_collapse_uvs_def,
2035         &bmo_connect_verts_def,
2036         &bmo_connect_verts_concave_def,
2037         &bmo_connect_verts_nonplanar_def,
2038         &bmo_connect_vert_pair_def,
2039         &bmo_contextual_create_def,
2040 #ifdef WITH_BULLET
2041         &bmo_convex_hull_def,
2042 #endif
2043         &bmo_create_circle_def,
2044         &bmo_create_cone_def,
2045         &bmo_create_cube_def,
2046         &bmo_create_grid_def,
2047         &bmo_create_icosphere_def,
2048         &bmo_create_monkey_def,
2049         &bmo_create_uvsphere_def,
2050         &bmo_create_vert_def,
2051         &bmo_delete_def,
2052         &bmo_dissolve_edges_def,
2053         &bmo_dissolve_faces_def,
2054         &bmo_dissolve_verts_def,
2055         &bmo_dissolve_limit_def,
2056         &bmo_dissolve_degenerate_def,
2057         &bmo_duplicate_def,
2058         &bmo_holes_fill_def,
2059         &bmo_face_attribute_fill_def,
2060         &bmo_offset_edgeloops_def,
2061         &bmo_edgeloop_fill_def,
2062         &bmo_edgenet_fill_def,
2063         &bmo_edgenet_prepare_def,
2064         &bmo_extrude_discrete_faces_def,
2065         &bmo_extrude_edge_only_def,
2066         &bmo_extrude_face_region_def,
2067         &bmo_extrude_vert_indiv_def,
2068         &bmo_find_doubles_def,
2069         &bmo_grid_fill_def,
2070         &bmo_inset_individual_def,
2071         &bmo_inset_region_def,
2072         &bmo_join_triangles_def,
2073         &bmo_mesh_to_bmesh_def,
2074         &bmo_mirror_def,
2075         &bmo_object_load_bmesh_def,
2076         &bmo_pointmerge_def,
2077         &bmo_pointmerge_facedata_def,
2078         &bmo_poke_def,
2079         &bmo_recalc_face_normals_def,
2080         &bmo_planar_faces_def,
2081         &bmo_region_extend_def,
2082         &bmo_remove_doubles_def,
2083         &bmo_reverse_colors_def,
2084         &bmo_reverse_faces_def,
2085         &bmo_reverse_uvs_def,
2086         &bmo_rotate_colors_def,
2087         &bmo_rotate_def,
2088         &bmo_rotate_edges_def,
2089         &bmo_rotate_uvs_def,
2090         &bmo_scale_def,
2091         &bmo_similar_edges_def,
2092         &bmo_similar_faces_def,
2093         &bmo_similar_verts_def,
2094         &bmo_smooth_vert_def,
2095         &bmo_smooth_laplacian_vert_def,
2096         &bmo_solidify_def,
2097         &bmo_spin_def,
2098         &bmo_split_def,
2099         &bmo_split_edges_def,
2100         &bmo_subdivide_edges_def,
2101         &bmo_subdivide_edgering_def,
2102         &bmo_bisect_plane_def,
2103         &bmo_symmetrize_def,
2104         &bmo_transform_def,
2105         &bmo_translate_def,
2106         &bmo_triangle_fill_def,
2107         &bmo_triangulate_def,
2108         &bmo_unsubdivide_def,
2109         &bmo_weld_verts_def,
2110         &bmo_wireframe_def,
2111 };
2112
2113 const int bmo_opdefines_total = ARRAY_SIZE(bmo_opdefines);