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