bmesh inset: outset option
[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. vertout), for double-type slots, use the two type names plus "out",
51  * (e.g. vertfaceout), for three-type slots, use geom.  note that you can also
52  * use more esohteric names (e.g. skirtout) 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 "bmesh.h"
58 #include "intern/bmesh_private.h"
59
60 /* ok, I'm going to write a little docgen script. so all
61  * bmop comments must conform to the following template/rules:
62  *
63  * template (py quotes used because nested comments don't work
64  * on all C compilers):
65  *
66  * """
67  * Region Extend.
68  *
69  * paragraph1, Extends bleh bleh bleh.
70  * Bleh Bleh bleh.
71  *
72  * Another paragraph.
73  *
74  * Another paragraph.
75  * """
76  *
77  * so the first line is the "title" of the bmop.
78  * subsequent line blocks separated by blank lines
79  * are paragraphs.  individual descriptions of slots
80  * would be extracted from comments
81  * next to them, e.g.
82  *
83  * {BMO_OP_SLOT_ELEMENT_BUF, "geomout"}, //output slot, boundary region
84  *
85  * the doc generator would automatically detect the presence of "output slot"
86  * and flag the slot as an output.  the same happens for "input slot".  also
87  * note that "edges", "faces", "verts", "loops", and "geometry" are valid
88  * substitutions for "slot".
89  *
90  * note that slots default to being input slots.
91  */
92
93 /*
94  * Vertex Smooth
95  *
96  * Smooths vertices by using a basic vertex averaging scheme.
97  */
98 static BMOpDefine bmo_vertexsmooth_def = {
99         "vertexsmooth",
100         {{BMO_OP_SLOT_ELEMENT_BUF, "verts"}, //input vertices
101          {BMO_OP_SLOT_BOOL, "mirror_clip_x"}, //set vertices close to the x axis before the operation to 0
102          {BMO_OP_SLOT_BOOL, "mirror_clip_y"}, //set vertices close to the y axis before the operation to 0
103          {BMO_OP_SLOT_BOOL, "mirror_clip_z"}, //set vertices close to the z axis before the operation to 0
104          {BMO_OP_SLOT_FLT, "clipdist"}, //clipping threshod for the above three slots
105         {0} /* null-terminating sentine */,
106         },
107         bmo_vertexsmooth_exec,
108         0
109 };
110
111 /*
112  * Right-Hand Faces
113  *
114  * Computes an "outside" normal for the specified input faces.
115  */
116
117 static BMOpDefine bmo_righthandfaces_def = {
118         "righthandfaces",
119         {{BMO_OP_SLOT_ELEMENT_BUF, "faces"},
120          {BMO_OP_SLOT_BOOL, "do_flip"}, //internal flag, used by bmesh_rationalize_normals
121          {0} /* null-terminating sentine */,
122         },
123         bmo_righthandfaces_exec,
124         BMO_OP_FLAG_UNTAN_MULTIRES,
125 };
126
127 /*
128  * Region Extend
129  *
130  * used to implement the select more/less tools.
131  * this puts some geometry surrounding regions of
132  * geometry in geom into geomout.
133  *
134  * if usefaces is 0 then geomout spits out verts and edges,
135  * otherwise it spits out faces.
136  */
137 static BMOpDefine bmo_regionextend_def = {
138         "regionextend",
139         {{BMO_OP_SLOT_ELEMENT_BUF, "geom"}, //input geometry
140          {BMO_OP_SLOT_ELEMENT_BUF, "geomout"}, //output slot, computed boundary geometry.
141          {BMO_OP_SLOT_BOOL, "constrict"}, //find boundary inside the regions, not outside.
142          {BMO_OP_SLOT_BOOL, "use_faces"}, //extend from faces instead of edges
143          {0} /* null-terminating sentine */,
144         },
145         bmo_regionextend_exec,
146         0
147 };
148
149 /*
150  * Edge Rotate
151  *
152  * Rotates edges topologically.  Also known as "spin edge" to some people.
153  * Simple example: [/] becomes [|] then [\].
154  */
155 static BMOpDefine bmo_edgerotate_def = {
156         "edgerotate",
157         {{BMO_OP_SLOT_ELEMENT_BUF, "edges"}, //input edges
158          {BMO_OP_SLOT_ELEMENT_BUF, "edgeout"}, //newly spun edges
159          {BMO_OP_SLOT_BOOL, "ccw"}, //rotate edge counter-clockwise if true, othewise clockwise
160          {0} /* null-terminating sentine */,
161         },
162         bmo_edgerotate_exec,
163         BMO_OP_FLAG_UNTAN_MULTIRES
164 };
165
166 /*
167  * Reverse Faces
168  *
169  * Reverses the winding (vertex order) of faces.  This has the effect of
170  * flipping the normal.
171  */
172 static BMOpDefine bmo_reversefaces_def = {
173         "reversefaces",
174         {{BMO_OP_SLOT_ELEMENT_BUF, "faces"}, //input faces
175          {0} /* null-terminating sentine */,
176         },
177         bmo_reversefaces_exec,
178         BMO_OP_FLAG_UNTAN_MULTIRES,
179 };
180
181 /*
182  * Edge Bisect
183  *
184  * Splits input edges (but doesn't do anything else).
185  * This creates a 2-valence vert.
186  */
187 static BMOpDefine bmo_edgebisect_def = {
188         "edgebisect",
189         {{BMO_OP_SLOT_ELEMENT_BUF, "edges"}, //input edges
190          {BMO_OP_SLOT_INT, "numcuts"}, //number of cuts
191          {BMO_OP_SLOT_ELEMENT_BUF, "outsplit"}, //newly created vertices and edges
192          {0} /* null-terminating sentine */,
193         },
194         bmo_edgebisect_exec,
195         BMO_OP_FLAG_UNTAN_MULTIRES
196 };
197
198 /*
199  * Mirror
200  *
201  * Mirrors geometry along an axis.  The resulting geometry is welded on using
202  * mergedist.  Pairs of original/mirrored vertices are welded using the mergedist
203  * parameter (which defines the minimum distance for welding to happen).
204  */
205
206 static BMOpDefine bmo_mirror_def = {
207         "mirror",
208         {{BMO_OP_SLOT_ELEMENT_BUF, "geom"}, //input geometry
209          {BMO_OP_SLOT_MAT, "mat"}, //matrix defining the mirror transformation
210          {BMO_OP_SLOT_FLT, "mergedist"}, //maximum distance for merging.  does no merging if 0.
211          {BMO_OP_SLOT_ELEMENT_BUF, "newout"}, //output geometry, mirrored
212          {BMO_OP_SLOT_INT,         "axis"}, //the axis to use, 0, 1, or 2 for x, y, z
213          {BMO_OP_SLOT_BOOL,        "mirror_u"}, //mirror UVs across the u axis
214          {BMO_OP_SLOT_BOOL,        "mirror_v"}, //mirror UVs across the v axis
215          {0, /* null-terminating sentine */}},
216         bmo_mirror_exec,
217         0,
218 };
219
220 /*
221  * Find Doubles
222  *
223  * Takes input verts and find vertices they should weld to.  Outputs a
224  * mapping slot suitable for use with the weld verts bmop.
225  */
226 static BMOpDefine bmo_finddoubles_def = {
227         "finddoubles",
228         {{BMO_OP_SLOT_ELEMENT_BUF, "verts"}, //input vertices
229          {BMO_OP_SLOT_ELEMENT_BUF, "keepverts"}, //list of verts to keep
230          {BMO_OP_SLOT_FLT,         "dist"}, //minimum distance
231          {BMO_OP_SLOT_MAPPING, "targetmapout"},
232          {0, /* null-terminating sentine */}},
233         bmo_finddoubles_exec,
234         0,
235 };
236
237 /*
238  * Remove Doubles
239  *
240  * Finds groups of vertices closer then dist and merges them together,
241  * using the weld verts bmop.
242  */
243 static BMOpDefine bmo_removedoubles_def = {
244         "removedoubles",
245         {{BMO_OP_SLOT_ELEMENT_BUF, "verts"}, //input verts
246          {BMO_OP_SLOT_FLT,         "dist"}, //minimum distance
247          {0, /* null-terminating sentine */}},
248         bmo_removedoubles_exec,
249         BMO_OP_FLAG_UNTAN_MULTIRES,
250 };
251
252 /*
253  * Auto Merge
254  *
255  * Finds groups of vertices closer then dist and merges them together,
256  * using the weld verts bmop.  The merges must go from a vert not in
257  * verts to one in verts.
258  */
259 static BMOpDefine bmo_automerge_def = {
260         "automerge",
261         {{BMO_OP_SLOT_ELEMENT_BUF, "verts"}, //input verts
262          {BMO_OP_SLOT_FLT,         "dist"}, //minimum distance
263          {0, /* null-terminating sentine */}},
264         bmo_automerge_exec,
265         BMO_OP_FLAG_UNTAN_MULTIRES,
266 };
267
268 /*
269  * Collapse Connected
270  *
271  * Collapses connected vertices
272  */
273 static BMOpDefine bmo_collapse_def = {
274         "collapse",
275         {{BMO_OP_SLOT_ELEMENT_BUF, "edges"}, /* input edge */
276          {0, /* null-terminating sentine */}},
277         bmo_collapse_exec,
278         BMO_OP_FLAG_UNTAN_MULTIRES,
279 };
280
281
282 /*
283  * Facedata point Merge
284  *
285  * Merge uv/vcols at a specific vertex.
286  */
287 static BMOpDefine bmo_pointmerge_facedata_def = {
288         "pointmerge_facedata",
289         {{BMO_OP_SLOT_ELEMENT_BUF, "verts"}, /* input vertice */
290          {BMO_OP_SLOT_ELEMENT_BUF, "snapv"}, /* snap verte */
291          {0, /* null-terminating sentine */}},
292         bmo_pointmerge_facedata_exec,
293         0,
294 };
295
296 /*
297  * Average Vertices Facevert Data
298  *
299  * Merge uv/vcols associated with the input vertices at
300  * the bounding box center. (I know, it's not averaging but
301  * the vert_snap_to_bb_center is just too long).
302  */
303 static BMOpDefine bmo_vert_average_facedata_def = {
304         "vert_average_facedata",
305         {{BMO_OP_SLOT_ELEMENT_BUF, "verts"}, /* input vertice */
306          {0, /* null-terminating sentine */}},
307         bmo_vert_average_facedata_exec,
308         0,
309 };
310
311 /*
312  * Point Merge
313  *
314  * Merge verts together at a point.
315  */
316 static BMOpDefine bmo_pointmerge_def = {
317         "pointmerge",
318         {{BMO_OP_SLOT_ELEMENT_BUF, "verts"}, /* input vertice */
319          {BMO_OP_SLOT_VEC,         "mergeco"},
320          {0, /* null-terminating sentine */}},
321         bmo_pointmerge_exec,
322         BMO_OP_FLAG_UNTAN_MULTIRES,
323 };
324
325 /*
326  * Collapse Connected UVs
327  *
328  * Collapses connected UV vertices.
329  */
330 static BMOpDefine bmo_collapse_uvs_def = {
331         "collapse_uvs",
332         {{BMO_OP_SLOT_ELEMENT_BUF, "edges"}, /* input edge */
333          {0, /* null-terminating sentine */}},
334         bmo_collapse_uvs_exec,
335         0,
336 };
337
338 /*
339  * Weld Verts
340  *
341  * Welds verts together (kindof like remove doubles, merge, etc, all of which
342  * use or will use this bmop).  You pass in mappings from vertices to the vertices
343  * they weld with.
344  */
345 static BMOpDefine bmo_weldverts_def = {
346         "weldverts",
347         {{BMO_OP_SLOT_MAPPING, "targetmap"}, /* maps welded vertices to verts they should weld to */
348          {0, /* null-terminating sentine */}},
349         bmo_weldverts_exec,
350         BMO_OP_FLAG_UNTAN_MULTIRES,
351 };
352
353 /*
354  * Make Vertex
355  *
356  * Creates a single vertex; this bmop was necessary
357  * for click-create-vertex.
358  */
359 static BMOpDefine bmo_makevert_def = {
360         "makevert",
361         {{BMO_OP_SLOT_VEC, "co"}, //the coordinate of the new vert
362          {BMO_OP_SLOT_ELEMENT_BUF, "newvertout"}, //the new vert
363          {0, /* null-terminating sentine */}},
364         bmo_makevert_exec,
365         0,
366 };
367
368 /*
369  * Join Triangles
370  *
371  * Tries to intelligently join triangles according
372  * to various settings and stuff.
373  */
374 static BMOpDefine bmo_join_triangles_def = {
375         "join_triangles",
376         {{BMO_OP_SLOT_ELEMENT_BUF, "faces"}, //input geometry.
377          {BMO_OP_SLOT_ELEMENT_BUF, "faceout"}, //joined faces
378          {BMO_OP_SLOT_BOOL, "cmp_sharp"},
379          {BMO_OP_SLOT_BOOL, "cmp_uvs"},
380          {BMO_OP_SLOT_BOOL, "cmp_vcols"},
381          {BMO_OP_SLOT_BOOL, "cmp_materials"},
382          {BMO_OP_SLOT_FLT, "limit"},
383          {0, /* null-terminating sentine */}},
384         bmo_join_triangles_exec,
385         BMO_OP_FLAG_UNTAN_MULTIRES,
386 };
387
388 /*
389  * Contextual Create
390  *
391  * This is basically fkey, it creates
392  * new faces from vertices, makes stuff from edge nets,
393  * makes wire edges, etc.  It also dissolves
394  * faces.
395  *
396  * Three verts become a triangle, four become a quad.  Two
397  * become a wire edge.
398  */
399 static BMOpDefine bmo_contextual_create_def = {
400         "contextual_create",
401         {{BMO_OP_SLOT_ELEMENT_BUF, "geom"}, //input geometry.
402          {BMO_OP_SLOT_ELEMENT_BUF, "faceout"}, //newly-made face(s)
403          {0, /* null-terminating sentine */}},
404         bmo_contextual_create_exec,
405         BMO_OP_FLAG_UNTAN_MULTIRES,
406 };
407
408 /*
409  * Bridge edge loops with faces
410  */
411 static BMOpDefine bmo_bridge_loops_def = {
412         "bridge_loops",
413         {{BMO_OP_SLOT_ELEMENT_BUF, "edges"}, /* input edge */
414          {BMO_OP_SLOT_ELEMENT_BUF, "faceout"}, /* new face */
415          {0, /* null-terminating sentine */}},
416         bmo_bridge_loops_exec,
417         0,
418 };
419
420 static BMOpDefine bmo_edgenet_fill_def = {
421         "edgenet_fill",
422         {{BMO_OP_SLOT_ELEMENT_BUF, "edges"}, /* input edge */
423          {BMO_OP_SLOT_MAPPING,     "restrict"}, /* restricts edges to groups.  maps edges to integer */
424          {BMO_OP_SLOT_BOOL,        "use_restrict"},
425          {BMO_OP_SLOT_BOOL,        "use_fill_check"},
426          {BMO_OP_SLOT_ELEMENT_BUF, "excludefaces"}, /* list of faces to ignore for manifold check */
427          {BMO_OP_SLOT_MAPPING,     "faceout_groupmap"}, /* maps new faces to the group numbers they came fro */
428          {BMO_OP_SLOT_ELEMENT_BUF, "faceout"}, /* new face */
429          {0, /* null-terminating sentine */}},
430         bmo_edgenet_fill_exec,
431         0,
432 };
433
434 /*
435  * Edgenet Prepare
436  *
437  * Identifies several useful edge loop cases and modifies them so
438  * they'll become a face when edgenet_fill is called.  The cases covered are:
439  *
440  * - One single loop; an edge is added to connect the ends
441  * - Two loops; two edges are added to connect the endpoints (based on the
442  *   shortest distance between each endpont).
443  */
444 static BMOpDefine bmo_edgenet_prepare_def = {
445         "edgenet_prepare",
446         {{BMO_OP_SLOT_ELEMENT_BUF, "edges"}, //input edges
447          {BMO_OP_SLOT_ELEMENT_BUF, "edgeout"}, //new edges
448          {0, /* null-terminating sentine */}},
449         bmo_edgenet_prepare,
450         0,
451 };
452
453 /*
454  * Rotate
455  *
456  * Rotate vertices around a center, using a 3x3 rotation
457  * matrix.  Equivalent of the old rotateflag function.
458  */
459 static BMOpDefine bmo_rotate_def = {
460         "rotate",
461         {{BMO_OP_SLOT_VEC, "cent"}, //center of rotation
462          {BMO_OP_SLOT_MAT, "mat"}, //matrix defining rotation
463          {BMO_OP_SLOT_ELEMENT_BUF, "verts"}, //input vertices
464          {0, /* null-terminating sentine */}},
465         bmo_rotate_exec,
466         0,
467 };
468
469 /*
470  * Translate
471  *
472  * Translate vertices by an offset.  Equivalent of the
473  * old translateflag function.
474  */
475 static BMOpDefine bmo_translate_def = {
476         "translate",
477         {{BMO_OP_SLOT_VEC, "vec"}, //translation offset
478          {BMO_OP_SLOT_ELEMENT_BUF, "verts"}, //input vertices
479          {0, /* null-terminating sentine */}},
480         bmo_translate_exec,
481         0,
482 };
483
484 /*
485  * Scale
486  *
487  * Scales vertices by an offset.
488  */
489 static BMOpDefine bmo_scale_def = {
490         "scale",
491         {{BMO_OP_SLOT_VEC, "vec"}, //scale factor
492          {BMO_OP_SLOT_ELEMENT_BUF, "verts"}, //input vertices
493          {0, /* null-terminating sentine */}},
494         bmo_scale_exec,
495         0,
496 };
497
498
499 /*
500  * Transform
501  *
502  * Transforms a set of vertices by a matrix.  Multiplies
503  * the vertex coordinates with the matrix.
504  */
505 static BMOpDefine bmo_transform_def = {
506         "transform",
507         {{BMO_OP_SLOT_MAT, "mat"}, //transform matrix
508          {BMO_OP_SLOT_ELEMENT_BUF, "verts"}, //input vertices
509          {0, /* null-terminating sentine */}},
510         bmo_transform_exec,
511         0,
512 };
513
514 /*
515  * Object Load BMesh
516  *
517  * Loads a bmesh into an object/mesh.  This is a "private"
518  * bmop.
519  */
520 static BMOpDefine bmo_object_load_bmesh_def = {
521         "object_load_bmesh",
522         {{BMO_OP_SLOT_PNT, "scene"},
523          {BMO_OP_SLOT_PNT, "object"},
524          {0, /* null-terminating sentine */}},
525         bmo_object_load_bmesh_exec,
526         0,
527 };
528
529
530 /*
531  * BMesh to Mesh
532  *
533  * Converts a bmesh to a Mesh.  This is reserved for exiting editmode.
534  */
535 static BMOpDefine bmo_bmesh_to_mesh_def = {
536         "bmesh_to_mesh",
537         {{BMO_OP_SLOT_PNT, "mesh"}, //pointer to a mesh structure to fill in
538          {BMO_OP_SLOT_PNT, "object"}, //pointer to an object structure
539          {BMO_OP_SLOT_BOOL, "notessellation"}, //don't calculate mfaces
540          {0, /* null-terminating sentine */}},
541         bmo_bmesh_to_mesh_exec,
542         0,
543 };
544
545 /*
546  * Mesh to BMesh
547  *
548  * Load the contents of a mesh into the bmesh.  this bmop is private, it's
549  * reserved exclusively for entering editmode.
550  */
551 static BMOpDefine bmo_mesh_to_bmesh_def = {
552         "mesh_to_bmesh",
553         {{BMO_OP_SLOT_PNT, "mesh"}, //pointer to a Mesh structure
554          {BMO_OP_SLOT_PNT, "object"}, //pointer to an Object structure
555          {BMO_OP_SLOT_BOOL, "set_shapekey"}, //load active shapekey coordinates into verts
556          {0, /* null-terminating sentine */}},
557         bmo_mesh_to_bmesh_exec,
558         0
559 };
560
561 /*
562  * Individual Face Extrude
563  *
564  * Extrudes faces individually.
565  */
566 static BMOpDefine bmo_extrude_indivface_def = {
567         "extrude_face_indiv",
568         {{BMO_OP_SLOT_ELEMENT_BUF, "faces"}, //input faces
569          {BMO_OP_SLOT_ELEMENT_BUF, "faceout"}, //output faces
570          {BMO_OP_SLOT_ELEMENT_BUF, "skirtout"}, //output skirt geometry, faces and edges
571          {0} /* null-terminating sentine */},
572         bmo_extrude_face_indiv_exec,
573         0
574 };
575
576 /*
577  * Extrude Only Edges
578  *
579  * Extrudes Edges into faces, note that this is very simple, there's no fancy
580  * winged extrusion.
581  */
582 static BMOpDefine bmo_extrude_edge_only_def = {
583         "extrude_edge_only",
584         {{BMO_OP_SLOT_ELEMENT_BUF, "edges"}, //input vertices
585          {BMO_OP_SLOT_ELEMENT_BUF, "geomout"}, //output geometry
586          {0} /* null-terminating sentine */},
587         bmo_extrude_edge_only_exec,
588         0
589 };
590
591 /*
592  * Individual Vertex Extrude
593  *
594  * Extrudes wire edges from vertices.
595  */
596 static BMOpDefine bmo_extrude_vert_indiv_def = {
597         "extrude_vert_indiv",
598         {{BMO_OP_SLOT_ELEMENT_BUF, "verts"}, //input vertices
599          {BMO_OP_SLOT_ELEMENT_BUF, "edgeout"}, //output wire edges
600          {BMO_OP_SLOT_ELEMENT_BUF, "vertout"}, //output vertices
601          {0} /* null-terminating sentine */},
602         bmo_extrude_vert_indiv_exec,
603         0
604 };
605
606 static BMOpDefine bmo_connectverts_def = {
607         "connectverts",
608         {{BMO_OP_SLOT_ELEMENT_BUF, "verts"},
609          {BMO_OP_SLOT_ELEMENT_BUF, "edgeout"},
610          {0} /* null-terminating sentine */},
611         bmo_connectverts_exec,
612         BMO_OP_FLAG_UNTAN_MULTIRES
613 };
614
615 static BMOpDefine bmo_extrude_face_region_def = {
616         "extrude_face_region",
617         {{BMO_OP_SLOT_ELEMENT_BUF, "edgefacein"},
618          {BMO_OP_SLOT_MAPPING, "exclude"},
619          {BMO_OP_SLOT_BOOL, "alwayskeeporig"},
620          {BMO_OP_SLOT_ELEMENT_BUF, "geomout"},
621          {0} /* null-terminating sentine */},
622         bmo_extrude_face_region_exec,
623         0
624 };
625
626 static BMOpDefine bmo_dissolve_verts_def = {
627         "dissolve_verts",
628         {{BMO_OP_SLOT_ELEMENT_BUF, "verts"},
629          {0} /* null-terminating sentine */},
630         bmo_dissolve_verts_exec,
631         BMO_OP_FLAG_UNTAN_MULTIRES
632 };
633
634 static BMOpDefine bmo_dissolve_edges_def = {
635         "dissolve_edges",
636         {{BMO_OP_SLOT_ELEMENT_BUF, "edges"},
637          {BMO_OP_SLOT_ELEMENT_BUF, "regionout"},
638          {BMO_OP_SLOT_BOOL, "use_verts"}, // dissolve verts left between only 2 edges.
639          {0} /* null-terminating sentine */},
640         bmo_dissolve_edges_exec,
641         BMO_OP_FLAG_UNTAN_MULTIRES
642 };
643
644 static BMOpDefine bmo_dissolve_edge_loop_def = {
645         "dissolve_edge_loop",
646         {{BMO_OP_SLOT_ELEMENT_BUF, "edges"},
647          {BMO_OP_SLOT_ELEMENT_BUF, "regionout"},
648          {0} /* null-terminating sentine */},
649         bmo_dissolve_edgeloop_exec,
650         BMO_OP_FLAG_UNTAN_MULTIRES
651 };
652
653 static BMOpDefine bmo_dissolve_faces_def = {
654         "dissolve_faces",
655         {{BMO_OP_SLOT_ELEMENT_BUF, "faces"},
656          {BMO_OP_SLOT_ELEMENT_BUF, "regionout"},
657          {BMO_OP_SLOT_BOOL, "use_verts"}, // dissolve verts left between only 2 edges.
658          {0} /* null-terminating sentine */},
659         bmo_dissolve_faces_exec,
660         BMO_OP_FLAG_UNTAN_MULTIRES
661 };
662
663 static BMOpDefine bmo_dissolve_limit_def = {
664         "dissolve_limit",
665         {{BMO_OP_SLOT_FLT, "angle_limit"}, /* total rotation angle (degrees) */
666          {BMO_OP_SLOT_ELEMENT_BUF, "verts"},
667          {BMO_OP_SLOT_ELEMENT_BUF, "edges"},
668          {0} /* null-terminating sentine */},
669         bmo_dissolve_limit_exec,
670         BMO_OP_FLAG_UNTAN_MULTIRES
671 };
672
673 static BMOpDefine bmo_triangulate_def = {
674         "triangulate",
675         {{BMO_OP_SLOT_ELEMENT_BUF, "faces"},
676          {BMO_OP_SLOT_ELEMENT_BUF, "edgeout"},
677          {BMO_OP_SLOT_ELEMENT_BUF, "faceout"},
678          {BMO_OP_SLOT_MAPPING, "facemap"},
679          {BMO_OP_SLOT_BOOL, "use_beauty"},
680          {0} /* null-terminating sentine */},
681         bmo_triangulate_exec,
682         BMO_OP_FLAG_UNTAN_MULTIRES
683 };
684
685 static BMOpDefine bmo_esubd_def = {
686         "esubd",
687         {{BMO_OP_SLOT_ELEMENT_BUF, "edges"},
688          {BMO_OP_SLOT_INT, "numcuts"},
689          {BMO_OP_SLOT_FLT, "smooth"},
690          {BMO_OP_SLOT_FLT, "fractal"},
691          {BMO_OP_SLOT_INT, "beauty"},
692          {BMO_OP_SLOT_INT, "seed"},
693          {BMO_OP_SLOT_MAPPING, "custompatterns"},
694          {BMO_OP_SLOT_MAPPING, "edgepercents"},
695
696         /* these next three can have multiple types of elements in them */
697          {BMO_OP_SLOT_ELEMENT_BUF, "outinner"},
698          {BMO_OP_SLOT_ELEMENT_BUF, "outsplit"},
699          {BMO_OP_SLOT_ELEMENT_BUF, "geomout"}, /* contains all output geometr */
700
701          {BMO_OP_SLOT_INT,  "quadcornertype"}, //quad corner type, see bmesh_operators.h
702          {BMO_OP_SLOT_BOOL, "gridfill"}, //fill in fully-selected faces with a grid
703          {BMO_OP_SLOT_BOOL, "singleedge"}, //tesselate the case of one edge selected in a quad or triangle
704
705          {0} /* null-terminating sentine */,
706         },
707         bmo_esubd_exec,
708         BMO_OP_FLAG_UNTAN_MULTIRES
709 };
710
711 static BMOpDefine bmo_del_def = {
712         "del",
713         {{BMO_OP_SLOT_ELEMENT_BUF, "geom"},
714          {BMO_OP_SLOT_INT, "context"},
715          {0} /* null-terminating sentine */},
716         bmo_del_exec,
717         0
718 };
719
720 static BMOpDefine bmo_dupe_def = {
721         "dupe",
722         {{BMO_OP_SLOT_ELEMENT_BUF, "geom"},
723          {BMO_OP_SLOT_ELEMENT_BUF, "origout"},
724          {BMO_OP_SLOT_ELEMENT_BUF, "newout"},
725         /* facemap maps from source faces to dupe
726          * faces, and from dupe faces to source faces */
727          {BMO_OP_SLOT_MAPPING, "facemap"},
728          {BMO_OP_SLOT_MAPPING, "boundarymap"},
729          {BMO_OP_SLOT_MAPPING, "isovertmap"},
730          {BMO_OP_SLOT_PNT, "dest"}, /* destination bmesh, if NULL will use current on */
731          {0} /* null-terminating sentine */},
732         bmo_dupe_exec,
733         0
734 };
735
736 static BMOpDefine bmo_split_def = {
737         "split",
738         {{BMO_OP_SLOT_ELEMENT_BUF, "geom"},
739          {BMO_OP_SLOT_ELEMENT_BUF, "geomout"},
740          {BMO_OP_SLOT_MAPPING, "boundarymap"},
741          {BMO_OP_SLOT_MAPPING, "isovertmap"},
742          {BMO_OP_SLOT_PNT, "dest"}, /* destination bmesh, if NULL will use current on */
743          {BMO_OP_SLOT_BOOL, "use_only_faces"}, /* when enabled. don't duplicate loose verts/edges */
744          {0} /* null-terminating sentine */},
745         bmo_split_exec,
746         0
747 };
748
749 /*
750  * Spin
751  *
752  * Extrude or duplicate geometry a number of times,
753  * rotating and possibly translating after each step
754  */
755 static BMOpDefine bmo_spin_def = {
756         "spin",
757         {{BMO_OP_SLOT_ELEMENT_BUF, "geom"},
758          {BMO_OP_SLOT_ELEMENT_BUF, "lastout"}, /* result of last step */
759          {BMO_OP_SLOT_VEC, "cent"}, /* rotation center */
760          {BMO_OP_SLOT_VEC, "axis"}, /* rotation axis */
761          {BMO_OP_SLOT_VEC, "dvec"}, /* translation delta per step */
762          {BMO_OP_SLOT_FLT, "ang"}, /* total rotation angle (degrees) */
763          {BMO_OP_SLOT_INT, "steps"}, /* number of steps */
764          {BMO_OP_SLOT_BOOL, "do_dupli"}, /* duplicate or extrude? */
765          {0} /* null-terminating sentine */},
766         bmo_spin_exec,
767         0
768 };
769
770
771 /*
772  * Similar faces search
773  *
774  * Find similar faces (area/material/perimeter, ...).
775  */
776 static BMOpDefine bmo_similarfaces_def = {
777         "similarfaces",
778         {{BMO_OP_SLOT_ELEMENT_BUF, "faces"}, /* input faces */
779          {BMO_OP_SLOT_ELEMENT_BUF, "faceout"}, /* output faces */
780          {BMO_OP_SLOT_INT, "type"},                     /* type of selection */
781          {BMO_OP_SLOT_FLT, "thresh"},           /* threshold of selection */
782          {0} /* null-terminating sentine */},
783         bmo_similarfaces_exec,
784         0
785 };
786
787 /*
788  * Similar edges search
789  *
790  *  Find similar edges (length, direction, edge, seam, ...).
791  */
792 static BMOpDefine bmo_similaredges_def = {
793         "similaredges",
794         {{BMO_OP_SLOT_ELEMENT_BUF, "edges"}, /* input edges */
795          {BMO_OP_SLOT_ELEMENT_BUF, "edgeout"}, /* output edges */
796          {BMO_OP_SLOT_INT, "type"},                     /* type of selection */
797          {BMO_OP_SLOT_FLT, "thresh"},           /* threshold of selection */
798          {0} /* null-terminating sentine */},
799         bmo_similaredges_exec,
800         0
801 };
802
803 /*
804  * Similar vertices search
805  *
806  * Find similar vertices (normal, face, vertex group, ...).
807  */
808 static BMOpDefine bmo_similarverts_def = {
809         "similarverts",
810         {{BMO_OP_SLOT_ELEMENT_BUF, "verts"}, /* input vertices */
811          {BMO_OP_SLOT_ELEMENT_BUF, "vertout"}, /* output vertices */
812          {BMO_OP_SLOT_INT, "type"},                     /* type of selection */
813          {BMO_OP_SLOT_FLT, "thresh"},           /* threshold of selection */
814          {0} /* null-terminating sentine */},
815         bmo_similarverts_exec,
816         0
817 };
818
819 /*
820  * uv rotation
821  * cycle the uvs
822  */
823 static BMOpDefine bmo_face_rotateuvs_def = {
824         "face_rotateuvs",
825         {{BMO_OP_SLOT_ELEMENT_BUF, "faces"}, /* input faces */
826          {BMO_OP_SLOT_INT, "dir"},                      /* direction */
827          {0} /* null-terminating sentine */},
828         bmo_face_rotateuvs_exec,
829         0
830 };
831
832 /*
833  * uv reverse
834  * reverse the uvs
835  */
836 static BMOpDefine bmo_face_reverseuvs_def = {
837         "face_reverseuvs",
838         {{BMO_OP_SLOT_ELEMENT_BUF, "faces"}, /* input faces */
839          {0} /* null-terminating sentine */},
840         bmo_face_reverseuvs_exec,
841         0
842 };
843
844 /*
845  * color rotation
846  * cycle the colors
847  */
848 static BMOpDefine bmo_face_rotatecolors_def = {
849         "face_rotatecolors",
850         {{BMO_OP_SLOT_ELEMENT_BUF, "faces"}, /* input faces */
851          {BMO_OP_SLOT_INT, "dir"},                      /* direction */
852          {0} /* null-terminating sentine */},
853         bmo_rotatecolors_exec,
854         0
855 };
856
857 /*
858  * color reverse
859  * reverse the colors
860  */
861 static BMOpDefine bmo_face_reversecolors_def = {
862         "face_reversecolors",
863         {{BMO_OP_SLOT_ELEMENT_BUF, "faces"}, /* input faces */
864          {0} /* null-terminating sentine */},
865         bmo_face_reversecolors_exec,
866         0
867 };
868
869 /*
870  * Similar vertices search
871  *
872  * Find similar vertices (normal, face, vertex group, ...).
873  */
874 static BMOpDefine bmo_vertexshortestpath_def = {
875         "vertexshortestpath",
876         {{BMO_OP_SLOT_ELEMENT_BUF, "startv"}, /* start vertex */
877          {BMO_OP_SLOT_ELEMENT_BUF, "endv"}, /* end vertex */
878          {BMO_OP_SLOT_ELEMENT_BUF, "vertout"}, /* output vertices */
879          {BMO_OP_SLOT_INT, "type"},                     /* type of selection */
880          {0} /* null-terminating sentine */},
881         bmo_vertexshortestpath_exec,
882         0
883 };
884
885 /*
886  * Edge Split
887  *
888  * Disconnects faces along input edges.
889  */
890 static BMOpDefine bmo_edgesplit_def = {
891         "edgesplit",
892         {{BMO_OP_SLOT_ELEMENT_BUF, "edges"}, /* input edges */
893          {BMO_OP_SLOT_ELEMENT_BUF, "edgeout"}, /* old output disconnected edges */
894          {0} /* null-terminating sentine */},
895         bmo_edgesplit_exec,
896         BMO_OP_FLAG_UNTAN_MULTIRES
897 };
898
899 /*
900  * Create Grid
901  *
902  * Creates a grid with a variable number of subdivisions
903  */
904 static BMOpDefine bmo_create_grid_def = {
905         "create_grid",
906         {{BMO_OP_SLOT_ELEMENT_BUF, "vertout"}, //output verts
907          {BMO_OP_SLOT_INT,         "xsegments"}, //number of x segments
908          {BMO_OP_SLOT_INT,         "ysegments"}, //number of y segments
909          {BMO_OP_SLOT_FLT,         "size"}, //size of the grid
910          {BMO_OP_SLOT_MAT,         "mat"}, //matrix to multiply the new geometry with
911          {0, /* null-terminating sentine */}},
912         bmo_create_grid_exec,
913         0,
914 };
915
916 /*
917  * Create UV Sphere
918  *
919  * Creates a grid with a variable number of subdivisions
920  */
921 static BMOpDefine bmo_create_uvsphere_def = {
922         "create_uvsphere",
923         {{BMO_OP_SLOT_ELEMENT_BUF, "vertout"}, //output verts
924          {BMO_OP_SLOT_INT,         "segments"}, //number of u segments
925          {BMO_OP_SLOT_INT,         "revolutions"}, //number of v segment
926          {BMO_OP_SLOT_FLT,         "diameter"}, //diameter
927          {BMO_OP_SLOT_MAT,         "mat"}, //matrix to multiply the new geometry with--
928          {0, /* null-terminating sentine */}},
929         bmo_create_uvsphere_exec,
930         0,
931 };
932
933 /*
934  * Create Ico Sphere
935  *
936  * Creates a grid with a variable number of subdivisions
937  */
938 static BMOpDefine bmo_create_icosphere_def = {
939         "create_icosphere",
940         {{BMO_OP_SLOT_ELEMENT_BUF, "vertout"}, //output verts
941          {BMO_OP_SLOT_INT,         "subdivisions"}, //how many times to recursively subdivide the sphere
942          {BMO_OP_SLOT_FLT,         "diameter"}, //diameter
943          {BMO_OP_SLOT_MAT,         "mat"}, //matrix to multiply the new geometry with
944          {0, /* null-terminating sentine */}},
945         bmo_create_icosphere_exec,
946         0,
947 };
948
949 /*
950  * Create Suzanne
951  *
952  * Creates a monkey.  Be wary.
953  */
954 static BMOpDefine bmo_create_monkey_def = {
955         "create_monkey",
956         {{BMO_OP_SLOT_ELEMENT_BUF, "vertout"}, //output verts
957          {BMO_OP_SLOT_MAT, "mat"}, //matrix to multiply the new geometry with--
958          {0, /* null-terminating sentine */}},
959         bmo_create_monkey_exec,
960         0,
961 };
962
963 /*
964  * Create Cone
965  *
966  * Creates a cone with variable depth at both ends
967  */
968 static BMOpDefine bmo_create_cone_def = {
969         "create_cone",
970         {{BMO_OP_SLOT_ELEMENT_BUF, "vertout"}, //output verts
971          {BMO_OP_SLOT_BOOL, "cap_ends"}, //wheter or not to fill in the ends with faces
972          {BMO_OP_SLOT_BOOL, "cap_tris"}, //fill ends with triangles instead of ngons
973          {BMO_OP_SLOT_INT, "segments"},
974          {BMO_OP_SLOT_FLT, "diameter1"}, //diameter of one end
975          {BMO_OP_SLOT_FLT, "diameter2"}, //diameter of the opposite
976          {BMO_OP_SLOT_FLT, "depth"}, //distance between ends
977          {BMO_OP_SLOT_MAT, "mat"}, //matrix to multiply the new geometry with--
978          {0, /* null-terminating sentine */}},
979         bmo_create_cone_exec,
980         0,
981 };
982
983 /*
984  * Creates a circle
985  */
986 static BMOpDefine bmo_create_circle_def = {
987         "create_circle",
988         {{BMO_OP_SLOT_ELEMENT_BUF, "vertout"}, //output verts
989          {BMO_OP_SLOT_BOOL, "cap_ends"}, //wheter or not to fill in the ends with faces
990          {BMO_OP_SLOT_BOOL, "cap_tris"}, //fill ends with triangles instead of ngons
991          {BMO_OP_SLOT_INT, "segments"},
992          {BMO_OP_SLOT_FLT, "diameter"}, //diameter of one end
993          {BMO_OP_SLOT_MAT, "mat"}, //matrix to multiply the new geometry with--
994          {0, /* null-terminating sentine */}},
995         bmo_create_circle_exec,
996         0,
997 };
998
999 /*
1000  * Create Cone
1001  *
1002  * Creates a cone with variable depth at both ends
1003  */
1004 static BMOpDefine bmo_create_cube_def = {
1005         "create_cube",
1006         {{BMO_OP_SLOT_ELEMENT_BUF, "vertout"}, //output verts
1007          {BMO_OP_SLOT_FLT, "size"}, //size of the cube
1008          {BMO_OP_SLOT_MAT, "mat"}, //matrix to multiply the new geometry with--
1009          {0, /* null-terminating sentine */}},
1010         bmo_create_cube_exec,
1011         0,
1012 };
1013
1014 /*
1015  * Bevel
1016  *
1017  * Bevels edges and vertices
1018  */
1019 static BMOpDefine bmo_bevel_def = {
1020         "bevel",
1021         {{BMO_OP_SLOT_ELEMENT_BUF, "geom"}, /* input edges and vertices */
1022          {BMO_OP_SLOT_ELEMENT_BUF, "face_spans"}, /* new geometry */
1023          {BMO_OP_SLOT_ELEMENT_BUF, "face_holes"}, /* new geometry */
1024          {BMO_OP_SLOT_BOOL, "use_lengths"}, /* grab edge lengths from a PROP_FLT customdata laye */
1025          {BMO_OP_SLOT_BOOL, "use_even"}, /* corner vert placement: use shell/angle calculations  */
1026          {BMO_OP_SLOT_BOOL, "use_dist"}, /* corner vert placement: evaluate percent as a distance,
1027                                           * modifier uses this. We could do this as another float setting */
1028          {BMO_OP_SLOT_INT, "lengthlayer"}, /* which PROP_FLT layer to us */
1029          {BMO_OP_SLOT_FLT, "percent"}, /* percentage to expand bevelled edge */
1030          {0} /* null-terminating sentine */},
1031         bmo_bevel_exec,
1032         BMO_OP_FLAG_UNTAN_MULTIRES
1033 };
1034
1035 /*
1036  * Beautify Fill
1037  *
1038  * Makes triangle a bit nicer
1039  */
1040 static BMOpDefine bmo_beautify_fill_def = {
1041         "beautify_fill",
1042         {{BMO_OP_SLOT_ELEMENT_BUF, "faces"}, /* input faces */
1043          {BMO_OP_SLOT_ELEMENT_BUF, "constrain_edges"}, /* edges that can't be flipped */
1044          {BMO_OP_SLOT_ELEMENT_BUF, "geomout"}, /* new flipped faces and edges */
1045          {0} /* null-terminating sentine */},
1046         bmo_beautify_fill_exec,
1047         BMO_OP_FLAG_UNTAN_MULTIRES
1048 };
1049
1050 /*
1051  * Triangle Fill
1052  *
1053  * Fill edges with triangles
1054  */
1055 static BMOpDefine bmo_triangle_fill_def = {
1056         "triangle_fill",
1057         {{BMO_OP_SLOT_ELEMENT_BUF, "edges"}, /* input edges */
1058          {BMO_OP_SLOT_ELEMENT_BUF, "geomout"}, /* new faces and edges */
1059          {0} /* null-terminating sentine */},
1060         bmo_triangle_fill_exec,
1061         BMO_OP_FLAG_UNTAN_MULTIRES
1062 };
1063
1064 /*
1065  * Solidify
1066  *
1067  * Turns a mesh into a shell with thickness
1068  */
1069 static BMOpDefine bmo_solidify_def = {
1070         "solidify",
1071         {{BMO_OP_SLOT_ELEMENT_BUF, "geom"},
1072          {BMO_OP_SLOT_FLT, "thickness"},
1073          {BMO_OP_SLOT_ELEMENT_BUF, "geomout"},
1074          {0}},
1075         bmo_solidify_face_region_exec,
1076         0
1077 };
1078
1079 /*
1080  * Face Inset
1081  *
1082  * Extrudes faces individually.
1083  */
1084 static BMOpDefine bmo_inset_def = {
1085         "inset",
1086         {{BMO_OP_SLOT_ELEMENT_BUF, "faces"},   /* input faces */
1087          {BMO_OP_SLOT_ELEMENT_BUF, "faceout"}, /* output faces */
1088          {BMO_OP_SLOT_BOOL, "use_boundary"},
1089          {BMO_OP_SLOT_BOOL, "use_even_offset"},
1090          {BMO_OP_SLOT_BOOL, "use_relative_offset"},
1091          {BMO_OP_SLOT_FLT, "thickness"},
1092          {BMO_OP_SLOT_BOOL, "use_outset"},
1093          {0} /* null-terminating sentine */},
1094         bmo_inset_exec,
1095         0
1096 };
1097
1098 BMOpDefine *opdefines[] = {
1099         &bmo_split_def,
1100         &bmo_spin_def,
1101         &bmo_dupe_def,
1102         &bmo_del_def,
1103         &bmo_esubd_def,
1104         &bmo_triangulate_def,
1105         &bmo_dissolve_faces_def,
1106         &bmo_dissolve_edges_def,
1107         &bmo_dissolve_edge_loop_def,
1108         &bmo_dissolve_verts_def,
1109         &bmo_dissolve_limit_def,
1110         &bmo_extrude_face_region_def,
1111         &bmo_connectverts_def,
1112         &bmo_extrude_vert_indiv_def,
1113         &bmo_mesh_to_bmesh_def,
1114         &bmo_object_load_bmesh_def,
1115         &bmo_transform_def,
1116         &bmo_translate_def,
1117         &bmo_rotate_def,
1118         &bmo_edgenet_fill_def,
1119         &bmo_contextual_create_def,
1120         &bmo_makevert_def,
1121         &bmo_weldverts_def,
1122         &bmo_removedoubles_def,
1123         &bmo_finddoubles_def,
1124         &bmo_mirror_def,
1125         &bmo_edgebisect_def,
1126         &bmo_reversefaces_def,
1127         &bmo_edgerotate_def,
1128         &bmo_regionextend_def,
1129         &bmo_righthandfaces_def,
1130         &bmo_vertexsmooth_def,
1131         &bmo_extrude_edge_only_def,
1132         &bmo_extrude_indivface_def,
1133         &bmo_collapse_uvs_def,
1134         &bmo_pointmerge_def,
1135         &bmo_collapse_def,
1136         &bmo_similarfaces_def,
1137         &bmo_similaredges_def,
1138         &bmo_similarverts_def,
1139         &bmo_pointmerge_facedata_def,
1140         &bmo_vert_average_facedata_def,
1141         &bmo_face_rotateuvs_def,
1142         &bmo_bmesh_to_mesh_def,
1143         &bmo_face_reverseuvs_def,
1144         &bmo_edgenet_prepare_def,
1145         &bmo_face_rotatecolors_def,
1146         &bmo_face_reversecolors_def,
1147         &bmo_vertexshortestpath_def,
1148         &bmo_scale_def,
1149         &bmo_edgesplit_def,
1150         &bmo_automerge_def,
1151         &bmo_create_uvsphere_def,
1152         &bmo_create_grid_def,
1153         &bmo_create_icosphere_def,
1154         &bmo_create_monkey_def,
1155         &bmo_create_cube_def,
1156         &bmo_create_circle_def,
1157         &bmo_create_cone_def,
1158         &bmo_join_triangles_def,
1159         &bmo_bevel_def,
1160         &bmo_beautify_fill_def,
1161         &bmo_triangle_fill_def,
1162         &bmo_bridge_loops_def,
1163         &bmo_solidify_def,
1164         &bmo_inset_def,
1165 };
1166
1167 int bmesh_total_ops = (sizeof(opdefines) / sizeof(void *));