Fix T60099: Inconsistent normals from spin tool
[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_normal_from_adjacent", BMO_OP_SLOT_BOOL},  /* Use winding from surrounding faces instead of this region. */
1044          {"use_select_history", BMO_OP_SLOT_BOOL},  /* pass to duplicate */
1045          {{'\0'}},
1046         },
1047         /* slots_out */
1048         {{"geom.out", BMO_OP_SLOT_ELEMENT_BUF, {BM_VERT | BM_EDGE | BM_FACE}},
1049          {{'\0'}},
1050         },
1051         bmo_extrude_face_region_exec,
1052         (BMO_OPTYPE_FLAG_NORMALS_CALC),
1053 };
1054
1055 /*
1056  * Dissolve Verts.
1057  */
1058 static BMOpDefine bmo_dissolve_verts_def = {
1059         "dissolve_verts",
1060         /* slots_in */
1061         {{"verts", BMO_OP_SLOT_ELEMENT_BUF, {BM_VERT}},
1062          {"use_face_split", BMO_OP_SLOT_BOOL},
1063          {"use_boundary_tear", BMO_OP_SLOT_BOOL},
1064          {{'\0'}},
1065         },
1066         {{{'\0'}}},  /* no output */
1067         bmo_dissolve_verts_exec,
1068         (BMO_OPTYPE_FLAG_UNTAN_MULTIRES |
1069          BMO_OPTYPE_FLAG_NORMALS_CALC |
1070          BMO_OPTYPE_FLAG_SELECT_FLUSH |
1071          BMO_OPTYPE_FLAG_SELECT_VALIDATE),
1072 };
1073
1074 /*
1075  * Dissolve Edges.
1076  */
1077 static BMOpDefine bmo_dissolve_edges_def = {
1078         "dissolve_edges",
1079         /* slots_in */
1080         {{"edges", BMO_OP_SLOT_ELEMENT_BUF, {BM_EDGE}},
1081          {"use_verts", BMO_OP_SLOT_BOOL},  /* dissolve verts left between only 2 edges. */
1082          {"use_face_split", BMO_OP_SLOT_BOOL},
1083          {{'\0'}},
1084         },
1085         /* slots_out */
1086         {{"region.out", BMO_OP_SLOT_ELEMENT_BUF, {BM_FACE}},
1087          {{'\0'}},
1088         },
1089         bmo_dissolve_edges_exec,
1090         (BMO_OPTYPE_FLAG_UNTAN_MULTIRES |
1091          BMO_OPTYPE_FLAG_NORMALS_CALC |
1092          BMO_OPTYPE_FLAG_SELECT_FLUSH |
1093          BMO_OPTYPE_FLAG_SELECT_VALIDATE),
1094 };
1095
1096 /*
1097  * Dissolve Faces.
1098  */
1099 static BMOpDefine bmo_dissolve_faces_def = {
1100         "dissolve_faces",
1101         /* slots_in */
1102         {{"faces", BMO_OP_SLOT_ELEMENT_BUF, {BM_FACE}},
1103          {"use_verts", BMO_OP_SLOT_BOOL},  /* dissolve verts left between only 2 edges. */
1104          {{'\0'}},
1105         },
1106         /* slots_out */
1107         {{"region.out", BMO_OP_SLOT_ELEMENT_BUF, {BM_FACE}},
1108          {{'\0'}},
1109         },
1110         bmo_dissolve_faces_exec,
1111         (BMO_OPTYPE_FLAG_UNTAN_MULTIRES |
1112          BMO_OPTYPE_FLAG_NORMALS_CALC |
1113          BMO_OPTYPE_FLAG_SELECT_FLUSH |
1114          BMO_OPTYPE_FLAG_SELECT_VALIDATE),
1115 };
1116
1117 /*
1118  * Limited Dissolve.
1119  *
1120  * Dissolve planar faces and co-linear edges.
1121  */
1122 static BMOpDefine bmo_dissolve_limit_def = {
1123         "dissolve_limit",
1124         /* slots_in */
1125         {{"angle_limit", BMO_OP_SLOT_FLT}, /* total rotation angle (radians) */
1126          {"use_dissolve_boundaries", BMO_OP_SLOT_BOOL},
1127          {"verts", BMO_OP_SLOT_ELEMENT_BUF, {BM_VERT}},
1128          {"edges", BMO_OP_SLOT_ELEMENT_BUF, {BM_EDGE}},
1129          {"delimit", BMO_OP_SLOT_INT},
1130          {{'\0'}},
1131         },
1132         /* slots_out */
1133         {{"region.out", BMO_OP_SLOT_ELEMENT_BUF, {BM_FACE}},
1134          {{'\0'}}},
1135         bmo_dissolve_limit_exec,
1136         (BMO_OPTYPE_FLAG_UNTAN_MULTIRES |
1137          BMO_OPTYPE_FLAG_NORMALS_CALC |
1138          BMO_OPTYPE_FLAG_SELECT_FLUSH |
1139          BMO_OPTYPE_FLAG_SELECT_VALIDATE),
1140 };
1141
1142 /*
1143  * Degenerate Dissolve.
1144  *
1145  * Dissolve edges with no length, faces with no area.
1146  */
1147 static BMOpDefine bmo_dissolve_degenerate_def = {
1148         "dissolve_degenerate",
1149         /* slots_in */
1150         {{"dist", BMO_OP_SLOT_FLT}, /* minimum distance to consider degenerate */
1151          {"edges", BMO_OP_SLOT_ELEMENT_BUF, {BM_EDGE}},
1152          {{'\0'}},
1153         },
1154         /* slots_out */
1155         {{{'\0'}}},
1156         bmo_dissolve_degenerate_exec,
1157         (BMO_OPTYPE_FLAG_UNTAN_MULTIRES |
1158          BMO_OPTYPE_FLAG_NORMALS_CALC |
1159          BMO_OPTYPE_FLAG_SELECT_FLUSH |
1160          BMO_OPTYPE_FLAG_SELECT_VALIDATE),
1161 };
1162
1163 /*
1164  * Triangulate.
1165  */
1166 static BMOpDefine bmo_triangulate_def = {
1167         "triangulate",
1168         /* slots_in */
1169         {{"faces", BMO_OP_SLOT_ELEMENT_BUF, {BM_FACE}},
1170          {"quad_method", BMO_OP_SLOT_INT},
1171          {"ngon_method", BMO_OP_SLOT_INT},
1172          {{'\0'}},
1173         },
1174         /* slots_out */
1175         {{"edges.out", BMO_OP_SLOT_ELEMENT_BUF, {BM_EDGE}},
1176          {"faces.out", BMO_OP_SLOT_ELEMENT_BUF, {BM_FACE}},
1177          {"face_map.out", BMO_OP_SLOT_MAPPING, {(int)BMO_OP_SLOT_SUBTYPE_MAP_ELEM}},
1178          {"face_map_double.out", BMO_OP_SLOT_MAPPING, {(int)BMO_OP_SLOT_SUBTYPE_MAP_ELEM}},  /* duplicate faces */
1179          {{'\0'}},
1180         },
1181         bmo_triangulate_exec,
1182         (BMO_OPTYPE_FLAG_UNTAN_MULTIRES |
1183          BMO_OPTYPE_FLAG_NORMALS_CALC |
1184          BMO_OPTYPE_FLAG_SELECT_FLUSH),
1185 };
1186
1187 /*
1188  * Un-Subdivide.
1189  *
1190  * Reduce detail in geometry containing grids.
1191  */
1192 static BMOpDefine bmo_unsubdivide_def = {
1193         "unsubdivide",
1194         /* slots_in */
1195         {{"verts", BMO_OP_SLOT_ELEMENT_BUF, {BM_VERT}}, /* input vertices */
1196          {"iterations", BMO_OP_SLOT_INT},
1197          {{'\0'}},
1198         },
1199         {{{'\0'}}},  /* no output */
1200         bmo_unsubdivide_exec,
1201         (BMO_OPTYPE_FLAG_UNTAN_MULTIRES |
1202          BMO_OPTYPE_FLAG_NORMALS_CALC |
1203          BMO_OPTYPE_FLAG_SELECT_FLUSH |
1204          BMO_OPTYPE_FLAG_SELECT_VALIDATE),
1205 };
1206
1207 /*
1208  * Subdivide Edges.
1209  *
1210  * Advanced operator for subdividing edges
1211  * with options for face patterns, smoothing and randomization.
1212  */
1213 static BMOpDefine bmo_subdivide_edges_def = {
1214         "subdivide_edges",
1215         /* slots_in */
1216         {{"edges", BMO_OP_SLOT_ELEMENT_BUF, {BM_EDGE}},
1217          {"smooth", BMO_OP_SLOT_FLT},
1218          {"smooth_falloff", BMO_OP_SLOT_INT}, /* SUBD_FALLOFF_ROOT and friends */
1219          {"fractal", BMO_OP_SLOT_FLT},
1220          {"along_normal", BMO_OP_SLOT_FLT},
1221          {"cuts", BMO_OP_SLOT_INT},
1222          {"seed", BMO_OP_SLOT_INT},
1223          {"custom_patterns", BMO_OP_SLOT_MAPPING, {(int)BMO_OP_SLOT_SUBTYPE_MAP_INTERNAL}},  /* uses custom pointers */
1224          {"edge_percents", BMO_OP_SLOT_MAPPING, {(int)BMO_OP_SLOT_SUBTYPE_MAP_FLT}},
1225
1226          {"quad_corner_type",  BMO_OP_SLOT_INT}, /* quad corner type, see bmesh_operators.h */
1227          {"use_grid_fill", BMO_OP_SLOT_BOOL},   /* fill in fully-selected faces with a grid */
1228          {"use_single_edge", BMO_OP_SLOT_BOOL}, /* tessellate the case of one edge selected in a quad or triangle */
1229          {"use_only_quads", BMO_OP_SLOT_BOOL},  /* only subdivide quads (for loopcut) */
1230          {"use_sphere", BMO_OP_SLOT_BOOL},     /* for making new primitives only */
1231          {"use_smooth_even", BMO_OP_SLOT_BOOL},  /* maintain even offset when smoothing */
1232          {{'\0'}},
1233         },
1234         /* slots_out */
1235         {/* these next three can have multiple types of elements in them */
1236          {"geom_inner.out", BMO_OP_SLOT_ELEMENT_BUF, {BM_VERT | BM_EDGE | BM_FACE}},
1237          {"geom_split.out", BMO_OP_SLOT_ELEMENT_BUF, {BM_VERT | BM_EDGE | BM_FACE}},
1238          {"geom.out", BMO_OP_SLOT_ELEMENT_BUF, {BM_VERT | BM_EDGE | BM_FACE}}, /* contains all output geometry */
1239          {{'\0'}},
1240         },
1241         bmo_subdivide_edges_exec,
1242         (BMO_OPTYPE_FLAG_UNTAN_MULTIRES |
1243          BMO_OPTYPE_FLAG_NORMALS_CALC |
1244          BMO_OPTYPE_FLAG_SELECT_FLUSH |
1245          BMO_OPTYPE_FLAG_SELECT_VALIDATE),
1246 };
1247
1248 /*
1249  * Subdivide Edge-Ring.
1250  *
1251  * Take an edge-ring, and subdivide with interpolation options.
1252  */
1253 static BMOpDefine bmo_subdivide_edgering_def = {
1254         "subdivide_edgering",
1255         /* slots_in */
1256         {{"edges", BMO_OP_SLOT_ELEMENT_BUF, {BM_EDGE}}, /* input vertices */
1257          {"interp_mode", BMO_OP_SLOT_INT},
1258          {"smooth", BMO_OP_SLOT_FLT},
1259          {"cuts", BMO_OP_SLOT_INT},
1260          {"profile_shape", BMO_OP_SLOT_INT},
1261          {"profile_shape_factor", BMO_OP_SLOT_FLT},
1262          {{'\0'}},
1263         },
1264         {{"faces.out", BMO_OP_SLOT_ELEMENT_BUF, {BM_FACE}}, /* output faces */
1265          {{'\0'}}},
1266         bmo_subdivide_edgering_exec,
1267         (BMO_OPTYPE_FLAG_UNTAN_MULTIRES |
1268          BMO_OPTYPE_FLAG_NORMALS_CALC |
1269          BMO_OPTYPE_FLAG_SELECT_FLUSH |
1270          BMO_OPTYPE_FLAG_SELECT_VALIDATE),
1271 };
1272
1273 /*
1274  * Bisect Plane.
1275  *
1276  * Bisects the mesh by a plane (cut the mesh in half).
1277  */
1278 static BMOpDefine bmo_bisect_plane_def = {
1279         "bisect_plane",
1280         /* slots_in */
1281         {{"geom", BMO_OP_SLOT_ELEMENT_BUF, {BM_VERT | BM_EDGE | BM_FACE}},
1282          {"dist",         BMO_OP_SLOT_FLT},     /* minimum distance when testing if a vert is exactly on the plane */
1283          {"plane_co", BMO_OP_SLOT_VEC},         /* point on the plane */
1284          {"plane_no", BMO_OP_SLOT_VEC},         /* direction of the plane */
1285          {"use_snap_center", BMO_OP_SLOT_BOOL},  /* snap axis aligned verts to the center */
1286          {"clear_outer",   BMO_OP_SLOT_BOOL},    /* when enabled. remove all geometry on the positive side of the plane */
1287          {"clear_inner",   BMO_OP_SLOT_BOOL},    /* when enabled. remove all geometry on the negative side of the plane */
1288          {{'\0'}},
1289         },
1290         {{"geom_cut.out", BMO_OP_SLOT_ELEMENT_BUF, {BM_VERT | BM_EDGE}},  /* output geometry aligned with the plane (new and existing) */
1291          {"geom.out",     BMO_OP_SLOT_ELEMENT_BUF, {BM_VERT | BM_EDGE | BM_FACE}},  /* input and output geometry (result of cut)  */
1292          {{'\0'}}},
1293         bmo_bisect_plane_exec,
1294         (BMO_OPTYPE_FLAG_UNTAN_MULTIRES |
1295          BMO_OPTYPE_FLAG_NORMALS_CALC |
1296          BMO_OPTYPE_FLAG_SELECT_FLUSH |
1297          BMO_OPTYPE_FLAG_SELECT_VALIDATE),
1298 };
1299
1300 /*
1301  * Delete Geometry.
1302  *
1303  * Utility operator to delete geometry.
1304  */
1305 static BMOpDefine bmo_delete_def = {
1306         "delete",
1307         /* slots_in */
1308         {{"geom", BMO_OP_SLOT_ELEMENT_BUF, {BM_VERT | BM_EDGE | BM_FACE}},
1309          {"context", BMO_OP_SLOT_INT},  /* enum DEL_VERTS ... */
1310          {{'\0'}},
1311         },
1312         {{{'\0'}}},  /* no output */
1313         bmo_delete_exec,
1314         (BMO_OPTYPE_FLAG_NORMALS_CALC |
1315          BMO_OPTYPE_FLAG_SELECT_FLUSH |
1316          BMO_OPTYPE_FLAG_SELECT_VALIDATE),
1317 };
1318
1319 /*
1320  * Duplicate Geometry.
1321  *
1322  * Utility operator to duplicate geometry,
1323  * optionally into a destination mesh.
1324  */
1325 static BMOpDefine bmo_duplicate_def = {
1326         "duplicate",
1327         /* slots_in */
1328         {{"geom", BMO_OP_SLOT_ELEMENT_BUF, {BM_VERT | BM_EDGE | BM_FACE}},
1329         /* destination bmesh, if NULL will use current on */
1330          {"dest", BMO_OP_SLOT_PTR, {(int)BMO_OP_SLOT_SUBTYPE_PTR_BMESH}},
1331          {"use_select_history", BMO_OP_SLOT_BOOL},
1332          {{'\0'}},
1333         },
1334         /* slots_out */
1335         {{"geom_orig.out", BMO_OP_SLOT_ELEMENT_BUF, {BM_VERT | BM_EDGE | BM_FACE}},
1336          {"geom.out", BMO_OP_SLOT_ELEMENT_BUF, {BM_VERT | BM_EDGE | BM_FACE}},
1337         /* facemap maps from source faces to dupe
1338          * faces, and from dupe faces to source faces */
1339          {"vert_map.out", BMO_OP_SLOT_MAPPING, {(int)BMO_OP_SLOT_SUBTYPE_MAP_ELEM}},
1340          {"edge_map.out", BMO_OP_SLOT_MAPPING, {(int)BMO_OP_SLOT_SUBTYPE_MAP_ELEM}},
1341          {"face_map.out", BMO_OP_SLOT_MAPPING, {(int)BMO_OP_SLOT_SUBTYPE_MAP_ELEM}},
1342          {"boundary_map.out", BMO_OP_SLOT_MAPPING, {(int)BMO_OP_SLOT_SUBTYPE_MAP_ELEM}},
1343          {"isovert_map.out", BMO_OP_SLOT_MAPPING, {(int)BMO_OP_SLOT_SUBTYPE_MAP_ELEM}},
1344          {{'\0'}},
1345         },
1346         bmo_duplicate_exec,
1347         (BMO_OPTYPE_FLAG_NORMALS_CALC |
1348          BMO_OPTYPE_FLAG_SELECT_FLUSH),
1349 };
1350
1351 /*
1352  * Split Off Geometry.
1353  *
1354  * Disconnect geometry from adjacent edges and faces,
1355  * optionally into a destination mesh.
1356  */
1357 static BMOpDefine bmo_split_def = {
1358         "split",
1359         /* slots_in */
1360         {{"geom", BMO_OP_SLOT_ELEMENT_BUF, {BM_VERT | BM_EDGE | BM_FACE}},
1361         /* destination bmesh, if NULL will use current one */
1362          {"dest", BMO_OP_SLOT_PTR, {(int)BMO_OP_SLOT_SUBTYPE_PTR_BMESH}},
1363          {"use_only_faces", BMO_OP_SLOT_BOOL},  /* when enabled. don't duplicate loose verts/edges */
1364          {{'\0'}},
1365         },
1366         /* slots_out */
1367         {{"geom.out", BMO_OP_SLOT_ELEMENT_BUF, {BM_VERT | BM_EDGE | BM_FACE}},
1368          {"boundary_map.out", BMO_OP_SLOT_MAPPING, {(int)BMO_OP_SLOT_SUBTYPE_MAP_ELEM}},
1369          {"isovert_map.out", BMO_OP_SLOT_MAPPING, {(int)BMO_OP_SLOT_SUBTYPE_MAP_ELEM}},
1370          {{'\0'}},
1371         },
1372         bmo_split_exec,
1373         (BMO_OPTYPE_FLAG_NORMALS_CALC |
1374          BMO_OPTYPE_FLAG_SELECT_FLUSH),
1375 };
1376
1377 /*
1378  * Spin.
1379  *
1380  * Extrude or duplicate geometry a number of times,
1381  * rotating and possibly translating after each step
1382  */
1383 static BMOpDefine bmo_spin_def = {
1384         "spin",
1385         /* slots_in */
1386         {{"geom", BMO_OP_SLOT_ELEMENT_BUF, {BM_VERT | BM_EDGE | BM_FACE}},
1387          {"cent", BMO_OP_SLOT_VEC},             /* rotation center */
1388          {"axis", BMO_OP_SLOT_VEC},             /* rotation axis */
1389          {"dvec", BMO_OP_SLOT_VEC},             /* translation delta per step */
1390          {"angle", BMO_OP_SLOT_FLT},            /* total rotation angle (radians) */
1391          {"space", BMO_OP_SLOT_MAT},            /* matrix to define the space (typically object matrix) */
1392          {"steps", BMO_OP_SLOT_INT},            /* number of steps */
1393          {"use_merge", BMO_OP_SLOT_BOOL},       /* Merge first/last when the angle is a full revolution. */
1394          {"use_normal_flip", BMO_OP_SLOT_BOOL}, /* Create faces with reversed direction. */
1395          {"use_duplicate", BMO_OP_SLOT_BOOL},   /* duplicate or extrude? */
1396          {{'\0'}},
1397         },
1398         /* slots_out */
1399         {{"geom_last.out", BMO_OP_SLOT_ELEMENT_BUF, {BM_VERT | BM_EDGE | BM_FACE}}, /* result of last step */
1400          {{'\0'}},
1401         },
1402         bmo_spin_exec,
1403         (BMO_OPTYPE_FLAG_NORMALS_CALC |
1404          BMO_OPTYPE_FLAG_SELECT_FLUSH),
1405 };
1406
1407
1408 /*
1409  * Similar Faces Search.
1410  *
1411  * Find similar faces (area/material/perimeter, ...).
1412  */
1413 static BMOpDefine bmo_similar_faces_def = {
1414         "similar_faces",
1415         /* slots_in */
1416         {{"faces", BMO_OP_SLOT_ELEMENT_BUF, {BM_FACE}},    /* input faces */
1417          {"type", BMO_OP_SLOT_INT},             /* type of selection */
1418          {"thresh", BMO_OP_SLOT_FLT},           /* threshold of selection */
1419          {"compare", BMO_OP_SLOT_INT},          /* comparison method */
1420          {{'\0'}},
1421         },
1422         /* slots_out */
1423         {{"faces.out", BMO_OP_SLOT_ELEMENT_BUF, {BM_FACE}},  /* output faces */
1424          {{'\0'}},
1425         },
1426         bmo_similar_faces_exec,
1427         (BMO_OPTYPE_FLAG_SELECT_FLUSH),
1428 };
1429
1430 /*
1431  * Similar Edges Search.
1432  *
1433  * Find similar edges (length, direction, edge, seam, ...).
1434  */
1435 static BMOpDefine bmo_similar_edges_def = {
1436         "similar_edges",
1437         /* slots_in */
1438         {{"edges", BMO_OP_SLOT_ELEMENT_BUF, {BM_EDGE}},    /* input edges */
1439          {"type", BMO_OP_SLOT_INT},             /* type of selection */
1440          {"thresh", BMO_OP_SLOT_FLT},           /* threshold of selection */
1441          {"compare", BMO_OP_SLOT_INT},          /* comparison method */
1442          {{'\0'}},
1443         },
1444         /* slots_out */
1445         {{"edges.out", BMO_OP_SLOT_ELEMENT_BUF, {BM_EDGE}},  /* output edges */
1446          {{'\0'}},
1447         },
1448         bmo_similar_edges_exec,
1449         (BMO_OPTYPE_FLAG_SELECT_FLUSH),
1450 };
1451
1452 /*
1453  * Similar Verts Search.
1454  *
1455  * Find similar vertices (normal, face, vertex group, ...).
1456  */
1457 static BMOpDefine bmo_similar_verts_def = {
1458         "similar_verts",
1459         /* slots_in */
1460         {{"verts", BMO_OP_SLOT_ELEMENT_BUF, {BM_VERT}},    /* input vertices */
1461          {"type", BMO_OP_SLOT_INT},             /* type of selection */
1462          {"thresh", BMO_OP_SLOT_FLT},           /* threshold of selection */
1463          {"compare", BMO_OP_SLOT_INT},          /* comparison method */
1464          {{'\0'}},
1465         },
1466         /* slots_out */
1467         {{"verts.out", BMO_OP_SLOT_ELEMENT_BUF, {BM_VERT}},  /* output vertices */
1468          {{'\0'}},
1469         },
1470         bmo_similar_verts_exec,
1471         (BMO_OPTYPE_FLAG_SELECT_FLUSH),
1472 };
1473
1474 /*
1475  * UV Rotation.
1476  *
1477  * Cycle the loop UV's
1478  */
1479 static BMOpDefine bmo_rotate_uvs_def = {
1480         "rotate_uvs",
1481         /* slots_in */
1482         {{"faces", BMO_OP_SLOT_ELEMENT_BUF, {BM_FACE}},    /* input faces */
1483          {"use_ccw", BMO_OP_SLOT_BOOL},         /* rotate counter-clockwise if true, otherwise clockwise */
1484          {{'\0'}},
1485         },
1486         {{{'\0'}}},  /* no output */
1487         bmo_rotate_uvs_exec,
1488         (BMO_OPTYPE_FLAG_NOP),
1489 };
1490
1491 /*
1492  * UV Reverse.
1493  *
1494  * Reverse the UV's
1495  */
1496 static BMOpDefine bmo_reverse_uvs_def = {
1497         "reverse_uvs",
1498         /* slots_in */
1499         {{"faces", BMO_OP_SLOT_ELEMENT_BUF, {BM_FACE}},    /* input faces */
1500          {{'\0'}},
1501         },
1502         {{{'\0'}}},  /* no output */
1503         bmo_reverse_uvs_exec,
1504         (BMO_OPTYPE_FLAG_NOP),
1505 };
1506
1507 /*
1508  * Color Rotation.
1509  *
1510  * Cycle the loop colors
1511  */
1512 static BMOpDefine bmo_rotate_colors_def = {
1513         "rotate_colors",
1514         /* slots_in */
1515         {{"faces", BMO_OP_SLOT_ELEMENT_BUF, {BM_FACE}},    /* input faces */
1516          {"use_ccw", BMO_OP_SLOT_BOOL},         /* rotate counter-clockwise if true, otherwise clockwise */
1517          {{'\0'}},
1518         },
1519         {{{'\0'}}},  /* no output */
1520         bmo_rotate_colors_exec,
1521         (BMO_OPTYPE_FLAG_NOP),
1522 };
1523
1524 /*
1525  * Color Reverse
1526  *
1527  * Reverse the loop colors.
1528  */
1529 static BMOpDefine bmo_reverse_colors_def = {
1530         "reverse_colors",
1531         /* slots_in */
1532         {{"faces", BMO_OP_SLOT_ELEMENT_BUF, {BM_FACE}},    /* input faces */
1533          {{'\0'}},
1534         },
1535         {{{'\0'}}},  /* no output */
1536         bmo_reverse_colors_exec,
1537         (BMO_OPTYPE_FLAG_NOP),
1538 };
1539
1540 /*
1541  * Edge Split.
1542  *
1543  * Disconnects faces along input edges.
1544  */
1545 static BMOpDefine bmo_split_edges_def = {
1546         "split_edges",
1547         /* slots_in */
1548         {{"edges", BMO_OP_SLOT_ELEMENT_BUF, {BM_EDGE}},    /* input edges */
1549          /* needed for vertex rip so we can rip only half an edge at a boundary wich would otherwise split off */
1550          {"verts", BMO_OP_SLOT_ELEMENT_BUF, {BM_VERT}},    /* optional tag verts, use to have greater control of splits */
1551          {"use_verts",        BMO_OP_SLOT_BOOL}, /* use 'verts' for splitting, else just find verts to split from edges */
1552          {{'\0'}},
1553         },
1554         /* slots_out */
1555         {{"edges.out", BMO_OP_SLOT_ELEMENT_BUF, {BM_EDGE}}, /* old output disconnected edges */
1556          {{'\0'}},
1557         },
1558         bmo_split_edges_exec,
1559         (BMO_OPTYPE_FLAG_UNTAN_MULTIRES |
1560          BMO_OPTYPE_FLAG_NORMALS_CALC |
1561          BMO_OPTYPE_FLAG_SELECT_FLUSH),
1562 };
1563
1564 /*
1565  * Create Grid.
1566  *
1567  * Creates a grid with a variable number of subdivisions
1568  */
1569 static BMOpDefine bmo_create_grid_def = {
1570         "create_grid",
1571         /* slots_in */
1572         {{"x_segments",      BMO_OP_SLOT_INT},  /* number of x segments */
1573          {"y_segments",      BMO_OP_SLOT_INT},  /* number of y segments */
1574          {"size",            BMO_OP_SLOT_FLT},  /* size of the grid */
1575          {"matrix",          BMO_OP_SLOT_MAT},  /* matrix to multiply the new geometry with */
1576          {"calc_uvs",        BMO_OP_SLOT_BOOL}, /* calculate default UVs */
1577          {{'\0'}},
1578         },
1579         /* slots_out */
1580         {{"verts.out", BMO_OP_SLOT_ELEMENT_BUF, {BM_VERT}}, /* output verts */
1581          {{'\0'}},
1582         },
1583         bmo_create_grid_exec,
1584         (BMO_OPTYPE_FLAG_NORMALS_CALC |
1585          BMO_OPTYPE_FLAG_SELECT_FLUSH),
1586 };
1587
1588 /*
1589  * Create UV Sphere.
1590  *
1591  * Creates a grid with a variable number of subdivisions
1592  */
1593 static BMOpDefine bmo_create_uvsphere_def = {
1594         "create_uvsphere",
1595         /* slots_in */
1596         {{"u_segments",      BMO_OP_SLOT_INT}, /* number of u segments */
1597          {"v_segments",      BMO_OP_SLOT_INT}, /* number of v segment */
1598          {"diameter",        BMO_OP_SLOT_FLT}, /* diameter */
1599          {"matrix",          BMO_OP_SLOT_MAT}, /* matrix to multiply the new geometry with */
1600          {"calc_uvs",        BMO_OP_SLOT_BOOL}, /* calculate default UVs */
1601          {{'\0'}},
1602         },
1603         /* slots_out */
1604         {{"verts.out", BMO_OP_SLOT_ELEMENT_BUF, {BM_VERT}}, /* output verts */
1605          {{'\0'}},
1606         },
1607         bmo_create_uvsphere_exec,
1608         (BMO_OPTYPE_FLAG_NORMALS_CALC |
1609          BMO_OPTYPE_FLAG_SELECT_FLUSH),
1610 };
1611
1612 /*
1613  * Create Ico-Sphere.
1614  *
1615  * Creates a grid with a variable number of subdivisions
1616  */
1617 static BMOpDefine bmo_create_icosphere_def = {
1618         "create_icosphere",
1619         /* slots_in */
1620         {{"subdivisions",    BMO_OP_SLOT_INT}, /* how many times to recursively subdivide the sphere */
1621          {"diameter",        BMO_OP_SLOT_FLT}, /* diameter */
1622          {"matrix",          BMO_OP_SLOT_MAT}, /* matrix to multiply the new geometry with */
1623          {"calc_uvs",        BMO_OP_SLOT_BOOL}, /* calculate default UVs */
1624          {{'\0'}},
1625         },
1626         /* slots_out */
1627         {{"verts.out", BMO_OP_SLOT_ELEMENT_BUF, {BM_VERT}}, /* output verts */
1628          {{'\0'}},
1629         },
1630         bmo_create_icosphere_exec,
1631         (BMO_OPTYPE_FLAG_NORMALS_CALC |
1632          BMO_OPTYPE_FLAG_SELECT_FLUSH),
1633 };
1634
1635 /*
1636  * Create Suzanne.
1637  *
1638  * Creates a monkey (standard blender primitive).
1639  */
1640 static BMOpDefine bmo_create_monkey_def = {
1641         "create_monkey",
1642         /* slots_in */
1643         {{"matrix",    BMO_OP_SLOT_MAT},  /* matrix to multiply the new geometry with */
1644          {"calc_uvs",  BMO_OP_SLOT_BOOL}, /* calculate default UVs */
1645          {{'\0'}},
1646         },
1647         /* slots_out */
1648         {{"verts.out", BMO_OP_SLOT_ELEMENT_BUF, {BM_VERT}}, /* output verts */
1649          {{'\0'}},
1650         },
1651         bmo_create_monkey_exec,
1652         (BMO_OPTYPE_FLAG_NORMALS_CALC |
1653          BMO_OPTYPE_FLAG_SELECT_FLUSH),
1654 };
1655
1656 /*
1657  * Create Cone.
1658  *
1659  * Creates a cone with variable depth at both ends
1660  */
1661 static BMOpDefine bmo_create_cone_def = {
1662         "create_cone",
1663         /* slots_in */
1664         {{"cap_ends",        BMO_OP_SLOT_BOOL},  /* whether or not to fill in the ends with faces */
1665          {"cap_tris",        BMO_OP_SLOT_BOOL},  /* fill ends with triangles instead of ngons */
1666          {"segments",        BMO_OP_SLOT_INT},
1667          {"diameter1",       BMO_OP_SLOT_FLT},  /* diameter of one end */
1668          {"diameter2",       BMO_OP_SLOT_FLT},  /* diameter of the opposite */
1669          {"depth",           BMO_OP_SLOT_FLT},  /* distance between ends */
1670          {"matrix",          BMO_OP_SLOT_MAT},  /* matrix to multiply the new geometry with */
1671          {"calc_uvs",        BMO_OP_SLOT_BOOL}, /* calculate default UVs */
1672          {{'\0'}},
1673         },
1674         /* slots_out */
1675         {{"verts.out", BMO_OP_SLOT_ELEMENT_BUF, {BM_VERT}}, /* output verts */
1676          {{'\0'}},
1677         },
1678         bmo_create_cone_exec,
1679         (BMO_OPTYPE_FLAG_NORMALS_CALC |
1680          BMO_OPTYPE_FLAG_SELECT_FLUSH),
1681 };
1682
1683 /*
1684  * Creates a Circle.
1685  */
1686 static BMOpDefine bmo_create_circle_def = {
1687         "create_circle",
1688         /* slots_in */
1689         {{"cap_ends",        BMO_OP_SLOT_BOOL},  /* whether or not to fill in the ends with faces */
1690          {"cap_tris",        BMO_OP_SLOT_BOOL},  /* fill ends with triangles instead of ngons */
1691          {"segments",        BMO_OP_SLOT_INT},
1692          {"radius",          BMO_OP_SLOT_FLT},  /* Radius of the circle. */
1693          {"matrix",          BMO_OP_SLOT_MAT},  /* matrix to multiply the new geometry with */
1694          {"calc_uvs",        BMO_OP_SLOT_BOOL}, /* calculate default UVs */
1695          {{'\0'}},
1696         },
1697         /* slots_out */
1698         {{"verts.out", BMO_OP_SLOT_ELEMENT_BUF, {BM_VERT}}, /* output verts */
1699          {{'\0'}},
1700         },
1701         bmo_create_circle_exec,
1702         (BMO_OPTYPE_FLAG_NORMALS_CALC |
1703          BMO_OPTYPE_FLAG_SELECT_FLUSH),
1704 };
1705
1706 /*
1707  * Create Cube
1708  *
1709  * Creates a cube.
1710  */
1711 static BMOpDefine bmo_create_cube_def = {
1712         "create_cube",
1713         /* slots_in */
1714         {{"size",            BMO_OP_SLOT_FLT},  /* size of the cube */
1715          {"matrix",          BMO_OP_SLOT_MAT},  /* matrix to multiply the new geometry with */
1716          {"calc_uvs",        BMO_OP_SLOT_BOOL}, /* calculate default UVs */
1717          {{'\0'}},
1718         },
1719         /* slots_out */
1720         {{"verts.out", BMO_OP_SLOT_ELEMENT_BUF, {BM_VERT}}, /* output verts */
1721          {{'\0'}},
1722         },
1723         bmo_create_cube_exec,
1724         (BMO_OPTYPE_FLAG_NORMALS_CALC |
1725          BMO_OPTYPE_FLAG_SELECT_FLUSH),
1726 };
1727
1728 /*
1729  * Bevel.
1730  *
1731  * Bevels edges and vertices
1732  */
1733 static BMOpDefine bmo_bevel_def = {
1734         "bevel",
1735         /* slots_in */
1736         {{"geom", BMO_OP_SLOT_ELEMENT_BUF, {BM_VERT | BM_EDGE | BM_FACE}},     /* input edges and vertices */
1737          {"offset", BMO_OP_SLOT_FLT},           /* amount to offset beveled edge */
1738          {"offset_type", BMO_OP_SLOT_INT},      /* how to measure offset (enum) */
1739          {"segments", BMO_OP_SLOT_INT},         /* number of segments in bevel */
1740          {"profile", BMO_OP_SLOT_FLT},          /* profile shape, 0->1 (.5=>round) */
1741          {"vertex_only", BMO_OP_SLOT_BOOL},     /* only bevel vertices, not edges */
1742          {"clamp_overlap", BMO_OP_SLOT_BOOL},   /* do not allow beveled edges/vertices to overlap each other */
1743          {"material", BMO_OP_SLOT_INT},         /* material for bevel faces, -1 means get from adjacent faces */
1744          {"loop_slide", BMO_OP_SLOT_BOOL},      /* prefer to slide along edges to having even widths */
1745          {{'\0'}},
1746         },
1747         /* slots_out */
1748         {{"faces.out", BMO_OP_SLOT_ELEMENT_BUF, {BM_FACE}}, /* output faces */
1749          {"edges.out", BMO_OP_SLOT_ELEMENT_BUF, {BM_EDGE}}, /* output edges */
1750          {"verts.out", BMO_OP_SLOT_ELEMENT_BUF, {BM_VERT}}, /* output verts */
1751          {{'\0'}},
1752         },
1753
1754         bmo_bevel_exec,
1755         (BMO_OPTYPE_FLAG_UNTAN_MULTIRES |
1756          BMO_OPTYPE_FLAG_NORMALS_CALC |
1757          BMO_OPTYPE_FLAG_SELECT_FLUSH |
1758          BMO_OPTYPE_FLAG_SELECT_VALIDATE),
1759 };
1760
1761 /*
1762  * Beautify Fill.
1763  *
1764  * Rotate edges to create more evenly spaced triangles.
1765  */
1766 static BMOpDefine bmo_beautify_fill_def = {
1767         "beautify_fill",
1768         /* slots_in */
1769         {{"faces", BMO_OP_SLOT_ELEMENT_BUF, {BM_FACE}}, /* input faces */
1770          {"edges", BMO_OP_SLOT_ELEMENT_BUF, {BM_EDGE}}, /* edges that can be flipped */
1771          {"use_restrict_tag", BMO_OP_SLOT_BOOL}, /* restrict edge rotation to mixed tagged vertices */
1772          {"method", BMO_OP_SLOT_INT}, /* method to define what is beautiful */
1773          {{'\0'}},
1774         },
1775         /* slots_out */
1776         {{"geom.out", BMO_OP_SLOT_ELEMENT_BUF, {BM_VERT | BM_EDGE | BM_FACE}}, /* new flipped faces and edges */
1777          {{'\0'}},
1778         },
1779         bmo_beautify_fill_exec,
1780         (BMO_OPTYPE_FLAG_UNTAN_MULTIRES |
1781          BMO_OPTYPE_FLAG_NORMALS_CALC |
1782          BMO_OPTYPE_FLAG_SELECT_FLUSH |
1783          BMO_OPTYPE_FLAG_SELECT_VALIDATE),
1784 };
1785
1786 /*
1787  * Triangle Fill.
1788  *
1789  * Fill edges with triangles
1790  */
1791 static BMOpDefine bmo_triangle_fill_def = {
1792         "triangle_fill",
1793         /* slots_in */
1794         {{"use_beauty", BMO_OP_SLOT_BOOL},
1795          {"use_dissolve", BMO_OP_SLOT_BOOL},  /* dissolve resulting faces */
1796          {"edges", BMO_OP_SLOT_ELEMENT_BUF, {BM_EDGE}},    /* input edges */
1797          {"normal", BMO_OP_SLOT_VEC},  /* optionally pass the fill normal to use */
1798          {{'\0'}},
1799         },
1800         /* slots_out */
1801         {{"geom.out", BMO_OP_SLOT_ELEMENT_BUF, {BM_VERT | BM_EDGE | BM_FACE}}, /* new faces and edges */
1802          {{'\0'}},
1803         },
1804         bmo_triangle_fill_exec,
1805         (BMO_OPTYPE_FLAG_UNTAN_MULTIRES |
1806          BMO_OPTYPE_FLAG_NORMALS_CALC |
1807          BMO_OPTYPE_FLAG_SELECT_FLUSH),
1808 };
1809
1810 /*
1811  * Solidify.
1812  *
1813  * Turns a mesh into a shell with thickness
1814  */
1815 static BMOpDefine bmo_solidify_def = {
1816         "solidify",
1817         /* slots_in */
1818         {{"geom", BMO_OP_SLOT_ELEMENT_BUF, {BM_VERT | BM_EDGE | BM_FACE}},
1819          {"thickness", BMO_OP_SLOT_FLT},
1820          {{'\0'}},
1821         },
1822         /* slots_out */
1823         {{"geom.out", BMO_OP_SLOT_ELEMENT_BUF, {BM_VERT | BM_EDGE | BM_FACE}},
1824          {{'\0'}},
1825         },
1826         bmo_solidify_face_region_exec,
1827         (BMO_OPTYPE_FLAG_NORMALS_CALC |
1828          BMO_OPTYPE_FLAG_SELECT_FLUSH),
1829 };
1830
1831 /*
1832  * Face Inset (Individual).
1833  *
1834  * Insets individual faces.
1835  */
1836 static BMOpDefine bmo_inset_individual_def = {
1837         "inset_individual",
1838         /* slots_in */
1839         {{"faces", BMO_OP_SLOT_ELEMENT_BUF, {BM_FACE}},    /* input faces */
1840          {"thickness", BMO_OP_SLOT_FLT},
1841          {"depth", BMO_OP_SLOT_FLT},
1842          {"use_even_offset", BMO_OP_SLOT_BOOL},
1843          {"use_interpolate", BMO_OP_SLOT_BOOL},
1844          {"use_relative_offset", BMO_OP_SLOT_BOOL},
1845          {{'\0'}},
1846         },
1847         /* slots_out */
1848         {{"faces.out", BMO_OP_SLOT_ELEMENT_BUF, {BM_FACE}}, /* output faces */
1849          {{'\0'}},
1850         },
1851         bmo_inset_individual_exec,
1852         /* caller needs to handle BMO_OPTYPE_FLAG_SELECT_FLUSH */
1853         (BMO_OPTYPE_FLAG_NORMALS_CALC),
1854 };
1855
1856 /*
1857  * Face Inset (Regions).
1858  *
1859  * Inset or outset face regions.
1860  */
1861 static BMOpDefine bmo_inset_region_def = {
1862         "inset_region",
1863         /* slots_in */
1864         {{"faces", BMO_OP_SLOT_ELEMENT_BUF, {BM_FACE}},    /* input faces */
1865          {"faces_exclude", BMO_OP_SLOT_ELEMENT_BUF, {BM_FACE}},
1866          {"use_boundary", BMO_OP_SLOT_BOOL},
1867          {"use_even_offset", BMO_OP_SLOT_BOOL},
1868          {"use_interpolate", BMO_OP_SLOT_BOOL},
1869          {"use_relative_offset", BMO_OP_SLOT_BOOL},
1870          {"use_edge_rail", BMO_OP_SLOT_BOOL},
1871          {"thickness", BMO_OP_SLOT_FLT},
1872          {"depth", BMO_OP_SLOT_FLT},
1873          {"use_outset", BMO_OP_SLOT_BOOL},
1874          {{'\0'}},
1875         },
1876         /* slots_out */
1877         {{"faces.out", BMO_OP_SLOT_ELEMENT_BUF, {BM_FACE}}, /* output faces */
1878          {{'\0'}},
1879         },
1880         bmo_inset_region_exec,
1881         (BMO_OPTYPE_FLAG_NORMALS_CALC |
1882          BMO_OPTYPE_FLAG_SELECT_FLUSH),
1883 };
1884
1885 /*
1886  * Edgeloop Offset.
1887  *
1888  * Creates edge loops based on simple edge-outset method.
1889  */
1890 static BMOpDefine bmo_offset_edgeloops_def = {
1891         "offset_edgeloops",
1892         /* slots_in */
1893         {{"edges", BMO_OP_SLOT_ELEMENT_BUF, {BM_EDGE}},    /* input faces */
1894          {"use_cap_endpoint", BMO_OP_SLOT_BOOL},
1895          {{'\0'}},
1896         },
1897         /* slots_out */
1898         {{"edges.out", BMO_OP_SLOT_ELEMENT_BUF, {BM_EDGE}}, /* output faces */
1899          {{'\0'}},
1900         },
1901         bmo_offset_edgeloops_exec,
1902         (BMO_OPTYPE_FLAG_NORMALS_CALC |
1903          BMO_OPTYPE_FLAG_SELECT_FLUSH),
1904 };
1905
1906 /*
1907  * Wire Frame.
1908  *
1909  * Makes a wire-frame copy of faces.
1910  */
1911 static BMOpDefine bmo_wireframe_def = {
1912         "wireframe",
1913         /* slots_in */
1914         {{"faces", BMO_OP_SLOT_ELEMENT_BUF, {BM_FACE}},   /* input faces */
1915          {"thickness", BMO_OP_SLOT_FLT},
1916          {"offset", BMO_OP_SLOT_FLT},
1917          {"use_replace", BMO_OP_SLOT_BOOL},
1918          {"use_boundary", BMO_OP_SLOT_BOOL},
1919          {"use_even_offset", BMO_OP_SLOT_BOOL},
1920          {"use_crease", BMO_OP_SLOT_BOOL},
1921          {"crease_weight", BMO_OP_SLOT_FLT},
1922          {"use_relative_offset", BMO_OP_SLOT_BOOL},
1923          {"material_offset", BMO_OP_SLOT_INT},
1924          {{'\0'}},
1925         },
1926         /* slots_out */
1927         {{"faces.out", BMO_OP_SLOT_ELEMENT_BUF, {BM_FACE}}, /* output faces */
1928          {{'\0'}},
1929         },
1930         bmo_wireframe_exec,
1931         (BMO_OPTYPE_FLAG_NORMALS_CALC |
1932          BMO_OPTYPE_FLAG_SELECT_FLUSH |
1933          BMO_OPTYPE_FLAG_SELECT_VALIDATE),
1934 };
1935
1936 /*
1937  * Pokes a face.
1938  *
1939  * Splits a face into a triangle fan.
1940  */
1941 static BMOpDefine bmo_poke_def = {
1942         "poke",
1943         /* slots_in */
1944         {{"faces", BMO_OP_SLOT_ELEMENT_BUF, {BM_FACE}},   /* input faces */
1945          {"offset", BMO_OP_SLOT_FLT}, /* center vertex offset along normal */
1946          {"center_mode", BMO_OP_SLOT_INT}, /* calculation mode for center vertex */
1947          {"use_relative_offset", BMO_OP_SLOT_BOOL}, /* apply offset */
1948          {{'\0'}},
1949         },
1950         /* slots_out */
1951         {{"verts.out", BMO_OP_SLOT_ELEMENT_BUF, {BM_VERT}}, /* output verts */
1952          {"faces.out", BMO_OP_SLOT_ELEMENT_BUF, {BM_FACE}}, /* output faces */
1953          {{'\0'}},
1954         },
1955         bmo_poke_exec,
1956         (BMO_OPTYPE_FLAG_NORMALS_CALC |
1957          BMO_OPTYPE_FLAG_SELECT_FLUSH |
1958          BMO_OPTYPE_FLAG_SELECT_VALIDATE),
1959 };
1960
1961 #ifdef WITH_BULLET
1962 /*
1963  * Convex Hull
1964  *
1965  * Builds a convex hull from the vertices in 'input'.
1966  *
1967  * If 'use_existing_faces' is true, the hull will not output triangles
1968  * that are covered by a pre-existing face.
1969  *
1970  * All hull vertices, faces, and edges are added to 'geom.out'. Any
1971  * input elements that end up inside the hull (i.e. are not used by an
1972  * output face) are added to the 'interior_geom' slot. The
1973  * 'unused_geom' slot will contain all interior geometry that is
1974  * completely unused. Lastly, 'holes_geom' contains edges and faces
1975  * that were in the input and are part of the hull.
1976  */
1977 static BMOpDefine bmo_convex_hull_def = {
1978         "convex_hull",
1979         /* slots_in */
1980         {{"input", BMO_OP_SLOT_ELEMENT_BUF, {BM_VERT | BM_EDGE | BM_FACE}},
1981          {"use_existing_faces", BMO_OP_SLOT_BOOL},
1982          {{'\0'}},
1983         },
1984         /* slots_out */
1985         {{"geom.out", BMO_OP_SLOT_ELEMENT_BUF, {BM_VERT | BM_EDGE | BM_FACE}},
1986          {"geom_interior.out", BMO_OP_SLOT_ELEMENT_BUF, {BM_VERT | BM_EDGE | BM_FACE}},
1987          {"geom_unused.out", BMO_OP_SLOT_ELEMENT_BUF, {BM_VERT | BM_EDGE | BM_FACE}},
1988          {"geom_holes.out", BMO_OP_SLOT_ELEMENT_BUF, {BM_VERT | BM_EDGE | BM_FACE}},
1989          {{'\0'}},
1990         },
1991         bmo_convex_hull_exec,
1992         (BMO_OPTYPE_FLAG_NORMALS_CALC |
1993          BMO_OPTYPE_FLAG_SELECT_FLUSH |
1994          BMO_OPTYPE_FLAG_SELECT_VALIDATE),
1995 };
1996 #endif
1997
1998 /*
1999  * Symmetrize.
2000  *
2001  * Makes the mesh elements in the "input" slot symmetrical. Unlike
2002  * normal mirroring, it only copies in one direction, as specified by
2003  * the "direction" slot. The edges and faces that cross the plane of
2004  * symmetry are split as needed to enforce symmetry.
2005  *
2006  * All new vertices, edges, and faces are added to the "geom.out" slot.
2007  */
2008 static BMOpDefine bmo_symmetrize_def = {
2009         "symmetrize",
2010         /* slots_in */
2011         {{"input", BMO_OP_SLOT_ELEMENT_BUF, {BM_VERT | BM_EDGE | BM_FACE}},
2012          {"direction", BMO_OP_SLOT_INT},
2013          {"dist", BMO_OP_SLOT_FLT}, /* minimum distance */
2014          {{'\0'}},
2015         },
2016         /* slots_out */
2017         {{"geom.out", BMO_OP_SLOT_ELEMENT_BUF, {BM_VERT | BM_EDGE | BM_FACE}},
2018          {{'\0'}},
2019         },
2020         bmo_symmetrize_exec,
2021         (BMO_OPTYPE_FLAG_NORMALS_CALC |
2022          BMO_OPTYPE_FLAG_SELECT_FLUSH |
2023          BMO_OPTYPE_FLAG_SELECT_VALIDATE),
2024 };
2025
2026 const BMOpDefine *bmo_opdefines[] = {
2027         &bmo_automerge_def,
2028         &bmo_average_vert_facedata_def,
2029         &bmo_beautify_fill_def,
2030         &bmo_bevel_def,
2031         &bmo_bisect_edges_def,
2032         &bmo_bmesh_to_mesh_def,
2033         &bmo_bridge_loops_def,
2034         &bmo_collapse_def,
2035         &bmo_collapse_uvs_def,
2036         &bmo_connect_verts_def,
2037         &bmo_connect_verts_concave_def,
2038         &bmo_connect_verts_nonplanar_def,
2039         &bmo_connect_vert_pair_def,
2040         &bmo_contextual_create_def,
2041 #ifdef WITH_BULLET
2042         &bmo_convex_hull_def,
2043 #endif
2044         &bmo_create_circle_def,
2045         &bmo_create_cone_def,
2046         &bmo_create_cube_def,
2047         &bmo_create_grid_def,
2048         &bmo_create_icosphere_def,
2049         &bmo_create_monkey_def,
2050         &bmo_create_uvsphere_def,
2051         &bmo_create_vert_def,
2052         &bmo_delete_def,
2053         &bmo_dissolve_edges_def,
2054         &bmo_dissolve_faces_def,
2055         &bmo_dissolve_verts_def,
2056         &bmo_dissolve_limit_def,
2057         &bmo_dissolve_degenerate_def,
2058         &bmo_duplicate_def,
2059         &bmo_holes_fill_def,
2060         &bmo_face_attribute_fill_def,
2061         &bmo_offset_edgeloops_def,
2062         &bmo_edgeloop_fill_def,
2063         &bmo_edgenet_fill_def,
2064         &bmo_edgenet_prepare_def,
2065         &bmo_extrude_discrete_faces_def,
2066         &bmo_extrude_edge_only_def,
2067         &bmo_extrude_face_region_def,
2068         &bmo_extrude_vert_indiv_def,
2069         &bmo_find_doubles_def,
2070         &bmo_grid_fill_def,
2071         &bmo_inset_individual_def,
2072         &bmo_inset_region_def,
2073         &bmo_join_triangles_def,
2074         &bmo_mesh_to_bmesh_def,
2075         &bmo_mirror_def,
2076         &bmo_object_load_bmesh_def,
2077         &bmo_pointmerge_def,
2078         &bmo_pointmerge_facedata_def,
2079         &bmo_poke_def,
2080         &bmo_recalc_face_normals_def,
2081         &bmo_planar_faces_def,
2082         &bmo_region_extend_def,
2083         &bmo_remove_doubles_def,
2084         &bmo_reverse_colors_def,
2085         &bmo_reverse_faces_def,
2086         &bmo_reverse_uvs_def,
2087         &bmo_rotate_colors_def,
2088         &bmo_rotate_def,
2089         &bmo_rotate_edges_def,
2090         &bmo_rotate_uvs_def,
2091         &bmo_scale_def,
2092         &bmo_similar_edges_def,
2093         &bmo_similar_faces_def,
2094         &bmo_similar_verts_def,
2095         &bmo_smooth_vert_def,
2096         &bmo_smooth_laplacian_vert_def,
2097         &bmo_solidify_def,
2098         &bmo_spin_def,
2099         &bmo_split_def,
2100         &bmo_split_edges_def,
2101         &bmo_subdivide_edges_def,
2102         &bmo_subdivide_edgering_def,
2103         &bmo_bisect_plane_def,
2104         &bmo_symmetrize_def,
2105         &bmo_transform_def,
2106         &bmo_translate_def,
2107         &bmo_triangle_fill_def,
2108         &bmo_triangulate_def,
2109         &bmo_unsubdivide_def,
2110         &bmo_weld_verts_def,
2111         &bmo_wireframe_def,
2112 };
2113
2114 const int bmo_opdefines_total = ARRAY_SIZE(bmo_opdefines);