PyAPI: add utilities PyTuple_SET_ITEMS, Py_INCREF_RET
[blender.git] / source / blender / python / bmesh / bmesh_py_utils.c
1 /*
2  * ***** BEGIN GPL LICENSE BLOCK *****
3  *
4  * This program is free software; you can redistribute it and/or
5  * modify it under the terms of the GNU General Public License
6  * as published by the Free Software Foundation; either version 2
7  * of the License, or (at your option) any later version.
8  *
9  * This program is distributed in the hope that it will be useful,
10  * but WITHOUT ANY WARRANTY; without even the implied warranty of
11  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
12  * GNU General Public License for more details.
13  *
14  * You should have received a copy of the GNU General Public License
15  * along with this program; if not, write to the Free Software Foundation,
16  * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
17  *
18  * The Original Code is Copyright (C) 2012 Blender Foundation.
19  * All rights reserved.
20  *
21  * Contributor(s): Campbell Barton
22  *
23  * ***** END GPL LICENSE BLOCK *****
24  */
25
26 /** \file blender/python/bmesh/bmesh_py_utils.c
27  *  \ingroup pybmesh
28  *
29  * This file defines the 'bmesh.utils' module.
30  * Utility functions for operating on 'bmesh.types'
31  */
32
33 #include <Python.h>
34
35 #include "BLI_utildefines.h"
36
37 #include "MEM_guardedalloc.h"
38
39 #include "../mathutils/mathutils.h"
40
41 #include "bmesh.h"
42 #include "bmesh_py_types.h"
43 #include "bmesh_py_utils.h" /* own include */
44
45 #include "../generic/python_utildefines.h"
46
47
48 PyDoc_STRVAR(bpy_bm_utils_vert_collapse_edge_doc,
49 ".. method:: vert_collapse_edge(vert, edge)\n"
50 "\n"
51 "   Collapse a vertex into an edge.\n"
52 "\n"
53 "   :arg vert: The vert that will be collapsed.\n"
54 "   :type vert: :class:`bmesh.types.BMVert`\n"
55 "   :arg edge: The edge to collapse into.\n"
56 "   :type edge: :class:`bmesh.types.BMEdge`\n"
57 "   :return: The resulting edge from the collapse operation.\n"
58 "   :rtype: :class:`bmesh.types.BMEdge`\n"
59 );
60 static PyObject *bpy_bm_utils_vert_collapse_edge(PyObject *UNUSED(self), PyObject *args)
61 {
62         BPy_BMEdge *py_edge;
63         BPy_BMVert *py_vert;
64
65         BMesh *bm;
66         BMEdge *e_new = NULL;
67
68         if (!PyArg_ParseTuple(args, "O!O!:vert_collapse_edge",
69                               &BPy_BMVert_Type, &py_vert,
70                               &BPy_BMEdge_Type, &py_edge))
71         {
72                 return NULL;
73         }
74
75         BPY_BM_CHECK_OBJ(py_edge);
76         BPY_BM_CHECK_OBJ(py_vert);
77
78         /* this doubles for checking that the verts are in the same mesh */
79         if (!(py_edge->e->v1 == py_vert->v ||
80               py_edge->e->v2 == py_vert->v))
81         {
82                 PyErr_SetString(PyExc_ValueError,
83                                 "vert_collapse_edge(vert, edge): the vertex is not found in the edge");
84                 return NULL;
85         }
86
87         if (BM_vert_edge_count(py_vert->v) > 2) {
88                 PyErr_SetString(PyExc_ValueError,
89                                 "vert_collapse_edge(vert, edge): vert has more than 2 connected edges");
90                 return NULL;
91         }
92
93         bm = py_edge->bm;
94
95         e_new = BM_vert_collapse_edge(bm, py_edge->e, py_vert->v, true, true);
96
97         if (e_new) {
98                 return BPy_BMEdge_CreatePyObject(bm, e_new);
99         }
100         else {
101                 PyErr_SetString(PyExc_ValueError,
102                                 "vert_collapse_edge(vert, edge): no new edge created, internal error");
103                 return NULL;
104         }
105 }
106
107
108 PyDoc_STRVAR(bpy_bm_utils_vert_collapse_faces_doc,
109 ".. method:: vert_collapse_faces(vert, edge, fac, join_faces)\n"
110 "\n"
111 "   Collapses a vertex that has only two manifold edges onto a vertex it shares an edge with.\n"
112 "\n"
113 "   :arg vert: The vert that will be collapsed.\n"
114 "   :type vert: :class:`bmesh.types.BMVert`\n"
115 "   :arg edge: The edge to collapse into.\n"
116 "   :type edge: :class:`bmesh.types.BMEdge`\n"
117 "   :arg fac: The factor to use when merging customdata [0 - 1].\n"
118 "   :type fac: float\n"
119 "   :return: The resulting edge from the collapse operation.\n"
120 "   :rtype: :class:`bmesh.types.BMEdge`\n"
121 );
122 static PyObject *bpy_bm_utils_vert_collapse_faces(PyObject *UNUSED(self), PyObject *args)
123 {
124         BPy_BMEdge *py_edge;
125         BPy_BMVert *py_vert;
126
127         float fac;
128         int do_join_faces;
129
130         BMesh *bm;
131         BMEdge *e_new = NULL;
132
133         if (!PyArg_ParseTuple(args, "O!O!fi:vert_collapse_faces",
134                               &BPy_BMVert_Type, &py_vert,
135                               &BPy_BMEdge_Type, &py_edge,
136                               &fac, &do_join_faces))
137         {
138                 return NULL;
139         }
140
141         BPY_BM_CHECK_OBJ(py_edge);
142         BPY_BM_CHECK_OBJ(py_vert);
143
144         /* this doubles for checking that the verts are in the same mesh */
145         if (!(py_edge->e->v1 == py_vert->v ||
146               py_edge->e->v2 == py_vert->v))
147         {
148                 PyErr_SetString(PyExc_ValueError,
149                                 "vert_collapse_faces(vert, edge): the vertex is not found in the edge");
150                 return NULL;
151         }
152
153         if (BM_vert_edge_count(py_vert->v) > 2) {
154                 PyErr_SetString(PyExc_ValueError,
155                                 "vert_collapse_faces(vert, edge): vert has more than 2 connected edges");
156                 return NULL;
157         }
158
159         bm = py_edge->bm;
160
161         e_new = BM_vert_collapse_faces(bm, py_edge->e, py_vert->v, CLAMPIS(fac, 0.0f, 1.0f), true, do_join_faces, true);
162
163         if (e_new) {
164                 return BPy_BMEdge_CreatePyObject(bm, e_new);
165         }
166         else {
167                 PyErr_SetString(PyExc_ValueError,
168                                 "vert_collapse_faces(vert, edge): no new edge created, internal error");
169                 return NULL;
170         }
171 }
172
173
174 PyDoc_STRVAR(bpy_bm_utils_vert_dissolve_doc,
175 ".. method:: vert_dissolve(vert)\n"
176 "\n"
177 "   Dissolve this vertex (will be removed).\n"
178 "\n"
179 "   :arg vert: The vert to be dissolved.\n"
180 "   :type vert: :class:`bmesh.types.BMVert`\n"
181 "   :return: True when the vertex dissolve is successful.\n"
182 "   :rtype: boolean\n"
183 );
184 static PyObject *bpy_bm_utils_vert_dissolve(PyObject *UNUSED(self), PyObject *args)
185 {
186         BPy_BMVert *py_vert;
187
188         BMesh *bm;
189
190         if (!PyArg_ParseTuple(args, "O!:vert_dissolve",
191                               &BPy_BMVert_Type, &py_vert))
192         {
193                 return NULL;
194         }
195
196         BPY_BM_CHECK_OBJ(py_vert);
197
198         bm = py_vert->bm;
199
200         return PyBool_FromLong((BM_vert_dissolve(bm, py_vert->v)));
201 }
202
203 PyDoc_STRVAR(bpy_bm_utils_vert_splice_doc,
204 ".. method:: vert_splice(vert, vert_target)\n"
205 "\n"
206 "   Splice vert into vert_target.\n"
207 "\n"
208 "   :arg vert: The vertex to be removed.\n"
209 "   :type vert: :class:`bmesh.types.BMVert`\n"
210 "   :arg vert_target: The vertex to use.\n"
211 "   :type vert_target: :class:`bmesh.types.BMVert`\n"
212 "\n"
213 "   .. note:: The verts mustn't share an edge or face.\n"
214 );
215 static PyObject *bpy_bm_utils_vert_splice(PyObject *UNUSED(self), PyObject *args)
216 {
217         BPy_BMVert *py_vert;
218         BPy_BMVert *py_vert_target;
219
220         BMesh *bm;
221
222         bool ok;
223
224         if (!PyArg_ParseTuple(args, "O!O!:vert_splice",
225                               &BPy_BMVert_Type, &py_vert,
226                               &BPy_BMVert_Type, &py_vert_target))
227         {
228                 return NULL;
229         }
230
231         BPY_BM_CHECK_OBJ(py_vert);
232         BPY_BM_CHECK_OBJ(py_vert_target);
233
234         bm = py_vert->bm;
235         BPY_BM_CHECK_SOURCE_OBJ(bm, "vert_splice", py_vert_target);
236
237         if (py_vert->v == py_vert_target->v) {
238                 PyErr_SetString(PyExc_ValueError,
239                                 "vert_splice(...): vert arguments match");
240                 return NULL;
241         }
242
243         if (BM_edge_exists(py_vert->v, py_vert_target->v)) {
244                 PyErr_SetString(PyExc_ValueError,
245                                 "vert_splice(...): verts can't share an edge");
246                 return NULL;
247         }
248
249         if (BM_vert_pair_share_face_check(py_vert->v, py_vert_target->v)) {
250                 PyErr_SetString(PyExc_ValueError,
251                                 "vert_splice(...): verts can't share a face");
252                 return NULL;
253         }
254
255         /* should always succeed */
256         ok = BM_vert_splice(bm, py_vert->v, py_vert_target->v);
257         BLI_assert(ok == true);
258
259         Py_RETURN_NONE;
260 }
261
262 PyDoc_STRVAR(bpy_bm_utils_vert_separate_doc,
263 ".. method:: vert_separate(vert, edges)\n"
264 "\n"
265 "   Separate this vertex at every edge.\n"
266 "\n"
267 "   :arg vert: The vert to be separated.\n"
268 "   :type vert: :class:`bmesh.types.BMVert`\n"
269 "   :arg edges: The edges to separated.\n"
270 "   :type edges: :class:`bmesh.types.BMEdge`\n"
271 "   :return: The newly separated verts (including the vertex passed).\n"
272 "   :rtype: tuple of :class:`bmesh.types.BMVert`\n"
273 );
274 static PyObject *bpy_bm_utils_vert_separate(PyObject *UNUSED(self), PyObject *args)
275 {
276         BPy_BMVert *py_vert;
277         PyObject *edge_seq;
278
279         BMesh *bm;
280         BMVert **elem;
281         int elem_len;
282
283         /* edges to split */
284         BMEdge **edge_array;
285         Py_ssize_t edge_array_len;
286
287         PyObject *ret;
288
289
290         if (!PyArg_ParseTuple(args, "O!O:vert_separate",
291                               &BPy_BMVert_Type, &py_vert,
292                               &edge_seq))
293         {
294                 return NULL;
295         }
296
297         BPY_BM_CHECK_OBJ(py_vert);
298
299         bm = py_vert->bm;
300
301         edge_array = BPy_BMElem_PySeq_As_Array(&bm, edge_seq, 0, PY_SSIZE_T_MAX,
302                                                &edge_array_len, BM_EDGE,
303                                                true, true, "vert_separate(...)");
304
305         if (edge_array == NULL) {
306                 return NULL;
307         }
308
309         BM_vert_separate(bm, py_vert->v, &elem, &elem_len, edge_array, edge_array_len);
310         /* return collected verts */
311         ret = BPy_BMVert_Array_As_Tuple(bm, elem, elem_len);
312         MEM_freeN(elem);
313
314         PyMem_FREE(edge_array);
315
316         return ret;
317 }
318
319
320 PyDoc_STRVAR(bpy_bm_utils_edge_split_doc,
321 ".. method:: edge_split(edge, vert, fac)\n"
322 "\n"
323 "   Split an edge, return the newly created data.\n"
324 "\n"
325 "   :arg edge: The edge to split.\n"
326 "   :type edge: :class:`bmesh.types.BMEdge`\n"
327 "   :arg vert: One of the verts on the edge, defines the split direction.\n"
328 "   :type vert: :class:`bmesh.types.BMVert`\n"
329 "   :arg fac: The point on the edge where the new vert will be created [0 - 1].\n"
330 "   :type fac: float\n"
331 "   :return: The newly created (edge, vert) pair.\n"
332 "   :rtype: tuple\n"
333 );
334 static PyObject *bpy_bm_utils_edge_split(PyObject *UNUSED(self), PyObject *args)
335 {
336         BPy_BMEdge *py_edge;
337         BPy_BMVert *py_vert;
338         float fac;
339
340         BMesh *bm;
341         BMVert *v_new = NULL;
342         BMEdge *e_new = NULL;
343
344         if (!PyArg_ParseTuple(args, "O!O!f:edge_split",
345                               &BPy_BMEdge_Type, &py_edge,
346                               &BPy_BMVert_Type, &py_vert,
347                               &fac))
348         {
349                 return NULL;
350         }
351
352         BPY_BM_CHECK_OBJ(py_edge);
353         BPY_BM_CHECK_OBJ(py_vert);
354
355         /* this doubles for checking that the verts are in the same mesh */
356         if (!(py_edge->e->v1 == py_vert->v ||
357               py_edge->e->v2 == py_vert->v))
358         {
359                 PyErr_SetString(PyExc_ValueError,
360                                 "edge_split(edge, vert): the vertex is not found in the edge");
361                 return NULL;
362         }
363
364         bm = py_edge->bm;
365
366         v_new = BM_edge_split(bm, py_edge->e, py_vert->v, &e_new, CLAMPIS(fac, 0.0f, 1.0f));
367
368         if (v_new && e_new) {
369                 PyObject *ret = PyTuple_New(2);
370                 PyTuple_SET_ITEMS(ret,
371                         BPy_BMEdge_CreatePyObject(bm, e_new),
372                         BPy_BMVert_CreatePyObject(bm, v_new));
373                 return ret;
374         }
375         else {
376                 PyErr_SetString(PyExc_ValueError,
377                                 "edge_split(edge, vert): couldn't split the edge, internal error");
378                 return NULL;
379         }
380 }
381
382
383 PyDoc_STRVAR(bpy_bm_utils_edge_rotate_doc,
384 ".. method:: edge_rotate(edge, ccw=False)\n"
385 "\n"
386 "   Rotate the edge and return the newly created edge.\n"
387 "   If rotating the edge fails, None will be returned.\n"
388 "\n"
389 "   :arg edge: The edge to rotate.\n"
390 "   :type edge: :class:`bmesh.types.BMEdge`\n"
391 "   :arg ccw: When True the edge will be rotated counter clockwise.\n"
392 "   :type ccw: boolean\n"
393 "   :return: The newly rotated edge.\n"
394 "   :rtype: :class:`bmesh.types.BMEdge`\n"
395 );
396 static PyObject *bpy_bm_utils_edge_rotate(PyObject *UNUSED(self), PyObject *args)
397 {
398         BPy_BMEdge *py_edge;
399         int do_ccw = false;
400
401         BMesh *bm;
402         BMEdge *e_new = NULL;
403
404         if (!PyArg_ParseTuple(args, "O!|i:edge_rotate",
405                               &BPy_BMEdge_Type, &py_edge,
406                               &do_ccw))
407         {
408                 return NULL;
409         }
410
411         BPY_BM_CHECK_OBJ(py_edge);
412
413         bm = py_edge->bm;
414
415         e_new = BM_edge_rotate(bm, py_edge->e, do_ccw, 0);
416
417         if (e_new) {
418                 return BPy_BMEdge_CreatePyObject(bm, e_new);
419         }
420         else {
421                 Py_RETURN_NONE;
422         }
423 }
424
425
426 PyDoc_STRVAR(bpy_bm_utils_face_split_doc,
427 ".. method:: face_split(face, vert_a, vert_b, coords=(), use_exist=True, example=None)\n"
428 "\n"
429 "   Face split with optional intermediate points.\n"
430 "\n"
431 "   :arg face: The face to cut.\n"
432 "   :type face: :class:`bmesh.types.BMFace`\n"
433 "   :arg vert_a: First vertex to cut in the face (face must contain the vert).\n"
434 "   :type vert_a: :class:`bmesh.types.BMVert`\n"
435 "   :arg vert_b: Second vertex to cut in the face (face must contain the vert).\n"
436 "   :type vert_b: :class:`bmesh.types.BMVert`\n"
437 "   :arg coords: Optional argument to define points inbetween *vert_a* and *vert_b*.\n"
438 "   :type coords: sequence of float triplets\n"
439 "   :arg use_exist: .Use an existing edge if it exists (Only used when *coords* argument is empty or omitted)\n"
440 "   :type use_exist: boolean\n"
441 "   :arg example: Newly created edge will copy settings from this one.\n"
442 "   :type example: :class:`bmesh.types.BMEdge`\n"
443 "   :return: The newly created face or None on failure.\n"
444 "   :rtype: (:class:`bmesh.types.BMFace`, :class:`bmesh.types.BMLoop`) pair\n"
445 );
446 static PyObject *bpy_bm_utils_face_split(PyObject *UNUSED(self), PyObject *args, PyObject *kw)
447 {
448         static const char *kwlist[] = {"face", "vert_a", "vert_b",
449                                        "coords", "use_exist", "example", NULL};
450
451         BPy_BMFace *py_face;
452         BPy_BMVert *py_vert_a;
453         BPy_BMVert *py_vert_b;
454
455         /* optional */
456         PyObject *py_coords = NULL;
457         int edge_exists = true;
458         BPy_BMEdge *py_edge_example = NULL;
459
460         float *coords;
461         int ncoords = 0;
462
463         BMesh *bm;
464         BMFace *f_new = NULL;
465         BMLoop *l_new = NULL;
466         BMLoop *l_a, *l_b;
467
468         if (!PyArg_ParseTupleAndKeywords(args, kw, "O!O!O!|OiO!:face_split", (char **)kwlist,
469                                          &BPy_BMFace_Type, &py_face,
470                                          &BPy_BMVert_Type, &py_vert_a,
471                                          &BPy_BMVert_Type, &py_vert_b,
472                                          &py_coords,
473                                          &edge_exists,
474                                          &BPy_BMEdge_Type, &py_edge_example))
475         {
476                 return NULL;
477         }
478
479         BPY_BM_CHECK_OBJ(py_face);
480         BPY_BM_CHECK_OBJ(py_vert_a);
481         BPY_BM_CHECK_OBJ(py_vert_b);
482
483         if (py_edge_example) {
484                 BPY_BM_CHECK_OBJ(py_edge_example);
485         }
486
487         /* this doubles for checking that the verts are in the same mesh */
488         if ((l_a = BM_face_vert_share_loop(py_face->f, py_vert_a->v)) &&
489             (l_b = BM_face_vert_share_loop(py_face->f, py_vert_b->v)))
490         {
491                 /* pass */
492         }
493         else {
494                 PyErr_SetString(PyExc_ValueError,
495                                 "face_split(...): one of the verts passed is not found in the face");
496                 return NULL;
497         }
498
499         if (py_vert_a->v == py_vert_b->v) {
500                 PyErr_SetString(PyExc_ValueError,
501                                 "face_split(...): vert arguments must differ");
502                 return NULL;
503         }
504
505         if (py_coords) {
506                 ncoords = mathutils_array_parse_alloc_v(&coords, 3, py_coords, "face_split(...): ");
507                 if (ncoords == -1) {
508                         return NULL;
509                 }
510         }
511
512         /* --- main function body --- */
513         bm = py_face->bm;
514
515         if (ncoords) {
516                 f_new = BM_face_split_n(bm, py_face->f,
517                                         l_a, l_b,
518                                         (float (*)[3])coords, ncoords,
519                                         &l_new, py_edge_example ? py_edge_example->e : NULL);
520                 PyMem_Free(coords);
521         }
522         else {
523                 f_new = BM_face_split(bm, py_face->f,
524                                       l_a, l_b,
525                                       &l_new, py_edge_example ? py_edge_example->e : NULL, edge_exists);
526         }
527
528         if (f_new && l_new) {
529                 PyObject *ret = PyTuple_New(2);
530                 PyTuple_SET_ITEMS(ret,
531                         BPy_BMFace_CreatePyObject(bm, f_new),
532                         BPy_BMLoop_CreatePyObject(bm, l_new));
533                 return ret;
534         }
535         else {
536                 PyErr_SetString(PyExc_ValueError,
537                                 "face_split(...): couldn't split the face, internal error");
538                 return NULL;
539         }
540 }
541
542
543 PyDoc_STRVAR(bpy_bm_utils_face_split_edgenet_doc,
544 ".. method:: face_split_edgenet(face, edgenet)\n"
545 "\n"
546 "   Splits a face into any number of regions defined by an edgenet.\n"
547 "\n"
548 "   :arg face: The face to split.\n"
549 "   :type face: :class:`bmesh.types.BMFace`\n"
550 "   :arg face: The face to split.\n"
551 "   :type face: :class:`bmesh.types.BMFace`\n"
552 "   :arg edgenet: Sequence of edges.\n"
553 "   :type edgenet: :class:`bmesh.types.BMEdge`\n"
554 "   :return: The newly created faces.\n"
555 "   :rtype: tuple of (:class:`bmesh.types.BMFace`)\n"
556 );
557 static PyObject *bpy_bm_utils_face_split_edgenet(PyObject *UNUSED(self), PyObject *args, PyObject *kw)
558 {
559         static const char *kwlist[] = {"face", "edgenet", NULL};
560
561         BPy_BMFace *py_face;
562         PyObject *edge_seq;
563
564         BMEdge **edge_array;
565         Py_ssize_t edge_array_len;
566
567         BMesh *bm;
568
569         BMFace **face_arr;
570         int face_arr_len;
571         bool ok;
572
573
574         if (!PyArg_ParseTupleAndKeywords(args, kw, "O!O:face_split_edgenet", (char **)kwlist,
575                                          &BPy_BMFace_Type, &py_face,
576                                          &edge_seq))
577         {
578                 return NULL;
579         }
580
581         BPY_BM_CHECK_OBJ(py_face);
582
583         bm = py_face->bm;
584
585         edge_array = BPy_BMElem_PySeq_As_Array(&bm, edge_seq, 1, PY_SSIZE_T_MAX,
586                                                &edge_array_len, BM_EDGE,
587                                                true, true, "face_split_edgenet(...)");
588
589         if (edge_array == NULL) {
590                 return NULL;
591         }
592
593         /* --- main function body --- */
594
595         ok = BM_face_split_edgenet(bm, py_face->f, edge_array, edge_array_len,
596                                    &face_arr, &face_arr_len);
597
598         PyMem_FREE(edge_array);
599
600         if (ok) {
601                 PyObject *ret = BPy_BMFace_Array_As_Tuple(bm, face_arr, face_arr_len);
602                 if (face_arr) {
603                         MEM_freeN(face_arr);
604                 }
605                 return ret;
606         }
607         else {
608                 PyErr_SetString(PyExc_ValueError,
609                                 "face_split_edgenet(...): couldn't split the face, internal error");
610                 return NULL;
611         }
612 }
613
614
615 PyDoc_STRVAR(bpy_bm_utils_face_join_doc,
616 ".. method:: face_join(faces, remove=True)\n"
617 "\n"
618 "   Joins a sequence of faces.\n"
619 "\n"
620 "   :arg faces: Sequence of faces.\n"
621 "   :type faces: :class:`bmesh.types.BMFace`\n"
622 "   :arg remove: Remove the edges and vertices between the faces.\n"
623 "   :type remove: boolean\n"
624 "   :return: The newly created face or None on failure.\n"
625 "   :rtype: :class:`bmesh.types.BMFace`\n"
626 );
627 static PyObject *bpy_bm_utils_face_join(PyObject *UNUSED(self), PyObject *args)
628 {
629         BMesh *bm = NULL;
630         PyObject *py_face_array;
631         BMFace **face_array;
632         Py_ssize_t face_seq_len = 0;
633         BMFace *f_new;
634         int do_remove = true;
635
636         if (!PyArg_ParseTuple(args, "O|i:face_join", &py_face_array, &do_remove)) {
637                 return NULL;
638         }
639
640         face_array = BPy_BMElem_PySeq_As_Array(&bm, py_face_array, 2, PY_SSIZE_T_MAX,
641                                                &face_seq_len, BM_FACE,
642                                                true, true, "face_join(...)");
643
644         if (face_array == NULL) {
645                 return NULL; /* error will be set */
646         }
647
648         /* Go ahead and join the face!
649          * --------------------------- */
650         f_new = BM_faces_join(bm, face_array, (int)face_seq_len, do_remove);
651
652         PyMem_FREE(face_array);
653
654         if (f_new) {
655                 return BPy_BMFace_CreatePyObject(bm, f_new);
656         }
657         else {
658                 Py_RETURN_NONE;
659         }
660 }
661
662
663 PyDoc_STRVAR(bpy_bm_utils_face_vert_separate_doc,
664 ".. method:: face_vert_separate(face, vert)\n"
665 "\n"
666 "   Rip a vertex in a face away and add a new vertex.\n"
667 "\n"
668 "   :arg face: The face to separate.\n"
669 "   :type face: :class:`bmesh.types.BMFace`\n"
670 "   :arg vert: A vertex in the face to separate.\n"
671 "   :type vert: :class:`bmesh.types.BMVert`\n"
672 "   :return vert: The newly created vertex or None of failure.\n"
673 "   :rtype vert: :class:`bmesh.types.BMVert`\n"
674 "\n"
675 "   .. note::\n"
676 "\n"
677 "      This is the same as loop_separate, and has only been added for convenience.\n"
678 );
679 static PyObject *bpy_bm_utils_face_vert_separate(PyObject *UNUSED(self), PyObject *args)
680 {
681         BPy_BMFace *py_face;
682         BPy_BMVert *py_vert;
683
684         BMesh *bm;
685         BMLoop *l;
686         BMVert *v_old, *v_new;
687
688         if (!PyArg_ParseTuple(args, "O!O!:face_vert_separate",
689                               &BPy_BMFace_Type, &py_face,
690                               &BPy_BMVert_Type, &py_vert))
691         {
692                 return NULL;
693         }
694
695         bm = py_face->bm;
696
697         BPY_BM_CHECK_OBJ(py_face);
698         BPY_BM_CHECK_SOURCE_OBJ(bm, "face_vert_separate()", py_vert);
699
700         l = BM_face_vert_share_loop(py_face->f, py_vert->v);
701
702         if (l == NULL) {
703                 PyErr_SetString(PyExc_ValueError,
704                                 "vertex not found in face");
705                 return NULL;
706         }
707
708         v_old = l->v;
709         v_new = BM_face_loop_separate(bm, l);
710
711         if (v_new != v_old) {
712                 return BPy_BMVert_CreatePyObject(bm, v_new);
713         }
714         else {
715                 Py_RETURN_NONE;
716         }
717 }
718
719
720 PyDoc_STRVAR(bpy_bm_utils_face_flip_doc,
721 ".. method:: face_flip(faces)\n"
722 "\n"
723 "   Flip the faces direction.\n"
724 "\n"
725 "   :arg face: Face to flip.\n"
726 "   :type face: :class:`bmesh.types.BMFace`\n"
727 );
728 static PyObject *bpy_bm_utils_face_flip(PyObject *UNUSED(self), BPy_BMFace *value)
729 {
730         if (!BPy_BMFace_Check(value)) {
731                 PyErr_Format(PyExc_TypeError,
732                              "face_flip(face): BMFace expected, not '%.200s'",
733                              Py_TYPE(value)->tp_name);
734                 return NULL;
735         }
736
737         BPY_BM_CHECK_OBJ(value);
738
739         BM_face_normal_flip(value->bm, value->f);
740
741         Py_RETURN_NONE;
742 }
743
744
745
746 PyDoc_STRVAR(bpy_bm_utils_loop_separate_doc,
747 ".. method:: loop_separate(loop)\n"
748 "\n"
749 "   Rip a vertex in a face away and add a new vertex.\n"
750 "\n"
751 "   :arg loop: The to separate.\n"
752 "   :type loop: :class:`bmesh.types.BMFace`\n"
753 "   :return vert: The newly created vertex or None of failure.\n"
754 "   :rtype vert: :class:`bmesh.types.BMVert`\n"
755 );
756 static PyObject *bpy_bm_utils_loop_separate(PyObject *UNUSED(self), BPy_BMLoop *value)
757 {
758         BMesh *bm;
759         BMLoop *l;
760         BMVert *v_old, *v_new;
761
762         if (!BPy_BMLoop_Check(value)) {
763                 PyErr_Format(PyExc_TypeError,
764                              "loop_separate(loop): BMLoop expected, not '%.200s'",
765                              Py_TYPE(value)->tp_name);
766                 return NULL;
767         }
768
769         BPY_BM_CHECK_OBJ(value);
770
771         bm = value->bm;
772         l = value->l;
773
774         v_old = l->v;
775         v_new = BM_face_loop_separate(bm, l);
776
777         if (v_new != v_old) {
778                 return BPy_BMVert_CreatePyObject(bm, v_new);
779         }
780         else {
781                 Py_RETURN_NONE;
782         }
783 }
784
785
786 static struct PyMethodDef BPy_BM_utils_methods[] = {
787         {"vert_collapse_edge",  (PyCFunction)bpy_bm_utils_vert_collapse_edge,  METH_VARARGS, bpy_bm_utils_vert_collapse_edge_doc},
788         {"vert_collapse_faces", (PyCFunction)bpy_bm_utils_vert_collapse_faces, METH_VARARGS, bpy_bm_utils_vert_collapse_faces_doc},
789         {"vert_dissolve",       (PyCFunction)bpy_bm_utils_vert_dissolve,       METH_VARARGS, bpy_bm_utils_vert_dissolve_doc}, /* could use METH_O */
790         {"vert_splice",         (PyCFunction)bpy_bm_utils_vert_splice,         METH_VARARGS, bpy_bm_utils_vert_splice_doc},
791         {"vert_separate",       (PyCFunction)bpy_bm_utils_vert_separate,       METH_VARARGS, bpy_bm_utils_vert_separate_doc},
792         {"edge_split",          (PyCFunction)bpy_bm_utils_edge_split,          METH_VARARGS, bpy_bm_utils_edge_split_doc},
793         {"edge_rotate",         (PyCFunction)bpy_bm_utils_edge_rotate,         METH_VARARGS, bpy_bm_utils_edge_rotate_doc},
794         {"face_split",          (PyCFunction)bpy_bm_utils_face_split,          METH_VARARGS | METH_KEYWORDS, bpy_bm_utils_face_split_doc},
795         {"face_split_edgenet",  (PyCFunction)bpy_bm_utils_face_split_edgenet,  METH_VARARGS | METH_KEYWORDS, bpy_bm_utils_face_split_edgenet_doc},
796         {"face_join",           (PyCFunction)bpy_bm_utils_face_join,           METH_VARARGS, bpy_bm_utils_face_join_doc},
797         {"face_vert_separate",  (PyCFunction)bpy_bm_utils_face_vert_separate,  METH_VARARGS, bpy_bm_utils_face_vert_separate_doc},
798         {"face_flip",           (PyCFunction)bpy_bm_utils_face_flip,           METH_O,       bpy_bm_utils_face_flip_doc},
799         {"loop_separate",       (PyCFunction)bpy_bm_utils_loop_separate,       METH_O,       bpy_bm_utils_loop_separate_doc},
800         {NULL, NULL, 0, NULL}
801 };
802
803
804 PyDoc_STRVAR(BPy_BM_utils_doc,
805 "This module provides access to blenders bmesh data structures."
806 );
807 static struct PyModuleDef BPy_BM_utils_module_def = {
808         PyModuleDef_HEAD_INIT,
809         "bmesh.utils",  /* m_name */
810         BPy_BM_utils_doc,  /* m_doc */
811         0,  /* m_size */
812         BPy_BM_utils_methods,  /* m_methods */
813         NULL,  /* m_reload */
814         NULL,  /* m_traverse */
815         NULL,  /* m_clear */
816         NULL,  /* m_free */
817 };
818
819
820 PyObject *BPyInit_bmesh_utils(void)
821 {
822         PyObject *submodule;
823
824         submodule = PyModule_Create(&BPy_BM_utils_module_def);
825
826         return submodule;
827 }