bmesh py api, new functions:
[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_api.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 "bmesh.h"
36
37 #include "bmesh_py_types.h"
38
39 #include "BLI_utildefines.h"
40
41 #include "bmesh_py_utils.h" /* own include */
42
43
44 PyDoc_STRVAR(bpy_bm_utils_vert_collapse_edge_doc,
45 ".. method:: vert_collapse_edge(vert, edge)\n"
46 "\n"
47 "   Collapse a vertex into an edge.\n"
48 "\n"
49 "   :arg vert: The vert that will be collapsed.\n"
50 "   :type vert: :class:`BMVert`\n"
51 "   :arg edge: The edge to collapse into.\n"
52 "   :type edge: :class:`BMEdge`\n"
53 "   :return: The resulting edge from the collapse operation.\n"
54 "   :rtype: :class:`BMEdge`\n"
55 );
56 static PyObject *bpy_bm_utils_vert_collapse_edge(PyObject *UNUSED(self), PyObject *args)
57 {
58         BPy_BMEdge *py_edge;
59         BPy_BMVert *py_vert;
60
61         BMesh *bm;
62         BMEdge *e_new = NULL;
63
64         if (!PyArg_ParseTuple(args, "O!O!:vert_collapse_edge",
65                               &BPy_BMVert_Type, &py_vert,
66                               &BPy_BMEdge_Type, &py_edge))
67         {
68                 return NULL;
69         }
70
71         BPY_BM_CHECK_OBJ(py_edge);
72         BPY_BM_CHECK_OBJ(py_vert);
73
74         /* this doubles for checking that the verts are in the same mesh */
75         if (!(py_edge->e->v1 == py_vert->v ||
76               py_edge->e->v2 == py_vert->v))
77         {
78                 PyErr_SetString(PyExc_ValueError,
79                                 "vert_collapse_edge(vert, edge): the vertex is not found in the edge");
80                 return NULL;
81         }
82
83         if (BM_vert_edge_count(py_vert->v) > 2) {
84                 PyErr_SetString(PyExc_ValueError,
85                                 "vert_collapse_edge(vert, edge): vert has more then 2 connected edges");
86                 return NULL;
87         }
88
89         bm = py_edge->bm;
90
91         e_new = BM_vert_collapse_edge(bm, py_edge->e, py_vert->v, TRUE);
92
93         if (e_new) {
94                 return BPy_BMEdge_CreatePyObject(bm, e_new);
95         }
96         else {
97                 PyErr_SetString(PyExc_ValueError,
98                                 "vert_collapse_edge(vert, edge): no new edge created, internal error");
99                 return NULL;
100         }
101 }
102
103
104 PyDoc_STRVAR(bpy_bm_utils_vert_collapse_faces_doc,
105 ".. method:: vert_collapse_faces(vert, edge, fac, join_faces)\n"
106 "\n"
107 "   Split an edge, return the newly created data.\n"
108 "\n"
109 "   :arg vert: The vert that will be collapsed.\n"
110 "   :type vert: :class:`BMVert`\n"
111 "   :arg edge: The edge to collapse into.\n"
112 "   :type edge: :class:`BMEdge`\n"
113 "   :arg fac: The factor to use when merging customdata [0 - 1].\n"
114 "   :type fac: float\n"
115 "   :return: The resulting edge from the collapse operation.\n"
116 "   :rtype: :class:`BMEdge`\n"
117 );
118 static PyObject *bpy_bm_utils_vert_collapse_faces(PyObject *UNUSED(self), PyObject *args)
119 {
120         BPy_BMEdge *py_edge;
121         BPy_BMVert *py_vert;
122
123         float fac;
124         int do_join_faces;
125
126         BMesh *bm;
127         BMEdge *e_new = NULL;
128
129         if (!PyArg_ParseTuple(args, "O!O!fi:vert_collapse_faces",
130                               &BPy_BMVert_Type, &py_vert,
131                               &BPy_BMEdge_Type, &py_edge,
132                               &fac, &do_join_faces))
133         {
134                 return NULL;
135         }
136
137         BPY_BM_CHECK_OBJ(py_edge);
138         BPY_BM_CHECK_OBJ(py_vert);
139
140         /* this doubles for checking that the verts are in the same mesh */
141         if (!(py_edge->e->v1 == py_vert->v ||
142               py_edge->e->v2 == py_vert->v))
143         {
144                 PyErr_SetString(PyExc_ValueError,
145                                 "vert_collapse_faces(vert, edge): the vertex is not found in the edge");
146                 return NULL;
147         }
148
149         if (BM_vert_edge_count(py_vert->v) > 2) {
150                 PyErr_SetString(PyExc_ValueError,
151                                 "vert_collapse_faces(vert, edge): vert has more then 2 connected edges");
152                 return NULL;
153         }
154
155         bm = py_edge->bm;
156
157         e_new = BM_vert_collapse_faces(bm, py_edge->e, py_vert->v, CLAMPIS(fac, 0.0f, 1.0f), do_join_faces, TRUE);
158
159         if (e_new) {
160                 return BPy_BMEdge_CreatePyObject(bm, e_new);
161         }
162         else {
163                 PyErr_SetString(PyExc_ValueError,
164                                 "vert_collapse_edge(vert, edge): no new edge created, internal error");
165                 return NULL;
166         }
167 }
168
169
170 PyDoc_STRVAR(bpy_bm_utils_vert_dissolve_doc,
171 ".. method:: vert_dissolve(vert)\n"
172 "\n"
173 "   Dissolve this vertex (will be removed).\n"
174 "\n"
175 "   :arg vert: The vert to be dissolved.\n"
176 "   :type vert: :class:`BMVert`\n"
177 "   :return: True when the vertex dissolve is successful.\n"
178 "   :rtype: boolean\n"
179 );
180 static PyObject *bpy_bm_utils_vert_dissolve(PyObject *UNUSED(self), PyObject *args)
181 {
182         BPy_BMVert *py_vert;
183
184         BMesh *bm;
185
186         if (!PyArg_ParseTuple(args, "O!:vert_dissolve",
187                               &BPy_BMVert_Type, &py_vert))
188         {
189                 return NULL;
190         }
191
192         BPY_BM_CHECK_OBJ(py_vert);
193
194         bm = py_vert->bm;
195
196         return PyBool_FromLong((BM_vert_dissolve(bm, py_vert->v)));
197 }
198
199
200 PyDoc_STRVAR(bpy_bm_utils_edge_split_doc,
201 ".. method:: edge_split(edge, vert, fac)\n"
202 "\n"
203 "   Split an edge, return the newly created data.\n"
204 "\n"
205 "   :arg edge: The edge to split.\n"
206 "   :type edge: :class:`BMEdge`\n"
207 "   :arg vert: One of the verts on the edge, defines the split direction.\n"
208 "   :type vert: :class:`BMVert`\n"
209 "   :arg fac: The point on the edge where the new vert will be created [0 - 1].\n"
210 "   :type fac: float\n"
211 "   :return: The newly created (edge, vert) pair.\n"
212 "   :rtype: tuple\n"
213 );
214 static PyObject *bpy_bm_utils_edge_split(PyObject *UNUSED(self), PyObject *args)
215 {
216         BPy_BMEdge *py_edge;
217         BPy_BMVert *py_vert;
218         float fac;
219
220         BMesh *bm;
221         BMVert *v_new = NULL;
222         BMEdge *e_new = NULL;
223
224         if (!PyArg_ParseTuple(args, "O!O!f:edge_split",
225                               &BPy_BMEdge_Type, &py_edge,
226                               &BPy_BMVert_Type, &py_vert,
227                               &fac))
228         {
229                 return NULL;
230         }
231
232         BPY_BM_CHECK_OBJ(py_edge);
233         BPY_BM_CHECK_OBJ(py_vert);
234
235         /* this doubles for checking that the verts are in the same mesh */
236         if (!(py_edge->e->v1 == py_vert->v ||
237               py_edge->e->v2 == py_vert->v))
238         {
239                 PyErr_SetString(PyExc_ValueError,
240                                 "edge_split(edge, vert): the vertex is not found in the edge");
241                 return NULL;
242         }
243
244         bm = py_edge->bm;
245
246         v_new = BM_edge_split(bm, py_edge->e, py_vert->v, &e_new, CLAMPIS(fac, 0.0f, 1.0f));
247
248         if (v_new && e_new) {
249                 PyObject *ret = PyTuple_New(2);
250                 PyTuple_SET_ITEM(ret, 0, BPy_BMEdge_CreatePyObject(bm, e_new));
251                 PyTuple_SET_ITEM(ret, 1, BPy_BMVert_CreatePyObject(bm, v_new));
252                 return ret;
253         }
254         else {
255                 PyErr_SetString(PyExc_ValueError,
256                                 "edge_split(edge, vert): couldn't split the edge, internal error");
257                 return NULL;
258         }
259 }
260
261
262 PyDoc_STRVAR(bpy_bm_utils_edge_rotate_doc,
263 ".. method:: edge_rotate(edge, ccw=False)\n"
264 "\n"
265 "   Rotate the edge and return the newly created edge.\n"
266 "   If rotating the edge fails, None will be returned.\n"
267 "\n"
268 "   :arg edge: The edge to rotate.\n"
269 "   :type edge: :class:`BMEdge`\n"
270 "   :arg ccw: When True the edge will be rotated counter clockwise.\n"
271 "   :type ccw: boolean\n"
272 "   :return: The newly rotated edge.\n"
273 "   :rtype: :class:`BMEdge`\n"
274 );
275 static PyObject *bpy_bm_utils_edge_rotate(PyObject *UNUSED(self), PyObject *args)
276 {
277         BPy_BMEdge *py_edge;
278         int do_ccw = FALSE;
279
280         BMesh *bm;
281         BMEdge *e_new = NULL;
282
283         if (!PyArg_ParseTuple(args, "O!|i:edge_rotate",
284                               &BPy_BMEdge_Type, &py_edge,
285                               &do_ccw))
286         {
287                 return NULL;
288         }
289
290         BPY_BM_CHECK_OBJ(py_edge);
291
292         bm = py_edge->bm;
293
294         e_new = BM_edge_rotate(bm, py_edge->e, do_ccw, 0); /* BMESH_TODO - expose to API */
295
296         if (e_new) {
297                 return BPy_BMEdge_CreatePyObject(bm, e_new);
298         }
299         else {
300                 Py_RETURN_NONE;
301         }
302 }
303
304
305 PyDoc_STRVAR(bpy_bm_utils_face_split_doc,
306 ".. method:: face_split(face, vert, vert_a, vert_b, edge_example)\n"
307 "\n"
308 "   Split an edge, return the newly created data.\n"
309 "\n"
310 "   :arg face: The face to cut.\n"
311 "   :type face: :class:`BMFace`\n"
312 "   :arg vert_a: First vertex to cut in the face (face must contain the vert).\n"
313 "   :type vert_a: :class:`BMVert`\n"
314 "   :arg vert_b: Second vertex to cut in the face (face must contain the vert).\n"
315 "   :type vert_b: :class:`BMVert`\n"
316 "   :arg edge_example: Optional edge argument, newly created edge will copy settings from this one.\n"
317 "   :type edge_example: :class:`BMEdge`\n"
318 );
319 static PyObject *bpy_bm_utils_face_split(PyObject *UNUSED(self), PyObject *args)
320 {
321         BPy_BMFace *py_face;
322         BPy_BMVert *py_vert_a;
323         BPy_BMVert *py_vert_b;
324         BPy_BMEdge *py_edge_example = NULL; /* optional */
325
326         BMesh *bm;
327         BMFace *f_new = NULL;
328         BMLoop *l_new = NULL;
329
330         if (!PyArg_ParseTuple(args, "O!O!O!|O!:face_split",
331                               &BPy_BMFace_Type, &py_face,
332                               &BPy_BMVert_Type, &py_vert_a,
333                               &BPy_BMVert_Type, &py_vert_b,
334                               &BPy_BMEdge_Type, &py_edge_example))
335         {
336                 return NULL;
337         }
338
339         BPY_BM_CHECK_OBJ(py_face);
340         BPY_BM_CHECK_OBJ(py_vert_a);
341         BPY_BM_CHECK_OBJ(py_vert_b);
342
343         if (py_edge_example) {
344                 BPY_BM_CHECK_OBJ(py_edge_example);
345         }
346
347         /* this doubles for checking that the verts are in the same mesh */
348         if (BM_vert_in_face(py_face->f, py_vert_a->v) == FALSE ||
349             BM_vert_in_face(py_face->f, py_vert_b->v) == FALSE)
350         {
351                 PyErr_SetString(PyExc_ValueError,
352                                 "face_split(...): one of the verts passed is not found in the face");
353                 return NULL;
354         }
355
356         if (py_vert_a->v == py_vert_b->v) {
357                 PyErr_SetString(PyExc_ValueError,
358                                 "face_split(...): vert arguments must differ");
359                 return NULL;
360         }
361
362         bm = py_face->bm;
363
364         f_new = BM_face_split(bm, py_face->f,
365                               py_vert_a->v, py_vert_b->v,
366                               &l_new, py_edge_example ? py_edge_example->e : NULL, FALSE); /* BMESH_TODO, make arg */
367
368         if (f_new && l_new) {
369                 PyObject *ret = PyTuple_New(2);
370                 PyTuple_SET_ITEM(ret, 0, BPy_BMFace_CreatePyObject(bm, f_new));
371                 PyTuple_SET_ITEM(ret, 1, BPy_BMLoop_CreatePyObject(bm, l_new));
372                 return ret;
373         }
374         else {
375                 PyErr_SetString(PyExc_ValueError,
376                                 "face_split(...): couldn't split the face, internal error");
377                 return NULL;
378         }
379 }
380
381
382 PyDoc_STRVAR(bpy_bm_utils_face_join_doc,
383 ".. method:: face_join(faces)\n"
384 "\n"
385 "   Joins a sequence of faces.\n"
386 "\n"
387 "   :arg faces: Sequence of faces.\n"
388 "   :type faces: :class:`BMFace`\n"
389 "   :return: The newly created face or None on failure.\n"
390 "   :rtype: :class:`BMFace`\n"
391 );
392 static PyObject *bpy_bm_utils_face_join(PyObject *UNUSED(self), PyObject *value)
393 {
394         BMesh *bm = NULL;
395         BMFace **face_array;
396         Py_ssize_t face_seq_len = 0;
397         BMFace *f_new;
398
399         face_array = BPy_BMElem_PySeq_As_Array(&bm, value, 2, PY_SSIZE_T_MAX,
400                                                &face_seq_len, &BPy_BMFace_Type,
401                                                TRUE, TRUE, "face_join(...)");
402
403         if (face_array == NULL) {
404                 return NULL; /* error will be set */
405         }
406
407         /* Go ahead and join the face!
408          * --------------------------- */
409         f_new = BM_faces_join(bm, face_array, (int)face_seq_len);
410
411         if (f_new) {
412                 return BPy_BMFace_CreatePyObject(bm, f_new);
413         }
414         else {
415                 Py_RETURN_NONE;
416         }
417 }
418
419
420 PyDoc_STRVAR(bpy_bm_utils_face_vert_rip_doc,
421 ".. method:: face_vert_rip(face, vert)\n"
422 "\n"
423 "   Rip a vertex in a face away and add a new vertex.\n"
424 "\n"
425 "   :arg face: The face to rip.\n"
426 "   :type face: :class:`BMFace`\n"
427 "   :arg vert: A vertex in the face to rip.\n"
428 "   :type vert: :class:`BMVert`\n"
429 "   :return vert: The newly created vertex or None of failure.\n"
430 "   :rtype vert: :class:`BMVert`\n"
431 "\n"
432 "   .. note::\n"
433 "\n"
434 "      This is the same as loop_rip, and has only been added for convenience.\n"
435 );
436 static PyObject *bpy_bm_utils_face_vert_rip(PyObject *UNUSED(self), PyObject *args)
437 {
438         BPy_BMFace *py_face;
439         BPy_BMVert *py_vert;
440
441         BMesh *bm;
442         BMLoop *l;
443         BMVert *v_new;
444
445         if (!PyArg_ParseTuple(args, "O!O!:face_vert_rip",
446                               &BPy_BMFace_Type, &py_face,
447                               &BPy_BMVert_Type, &py_vert))
448         {
449                 return NULL;
450         }
451
452         BPY_BM_CHECK_OBJ(py_face);
453         BPY_BM_CHECK_OBJ(py_vert);
454
455         bm = py_face->bm;
456
457         if (bm != py_vert->bm) {
458                 PyErr_SetString(PyExc_ValueError,
459                                 "mesh elements are from different meshes");
460                 return NULL;
461         }
462
463         l = BM_face_vert_share_loop(py_face->f, py_vert->v);
464
465         if (l == NULL) {
466                 PyErr_SetString(PyExc_ValueError,
467                                 "vertex not found in face");
468                 return NULL;
469         }
470
471         v_new = BM_face_loop_rip(bm, l);
472
473         if (v_new != l->v) {
474                 return BPy_BMVert_CreatePyObject(bm, v_new);
475         }
476         else {
477                 Py_RETURN_NONE;
478         }
479 }
480
481
482 PyDoc_STRVAR(bpy_bm_utils_face_flip_doc,
483 ".. method:: face_flip(faces)\n"
484 "\n"
485 "   Flip the faces direction.\n"
486 "\n"
487 "   :arg face: Face to flip.\n"
488 "   :type face: :class:`BMFace`\n"
489 );
490 static PyObject *bpy_bm_utils_face_flip(PyObject *UNUSED(self), BPy_BMFace *value)
491 {
492         if (!BPy_BMFace_Check(value)) {
493                 PyErr_Format(PyExc_TypeError,
494                              "face_flip(face): BMFace expected, not '%.200s'",
495                              Py_TYPE(value)->tp_name);
496                 return NULL;
497         }
498
499         BPY_BM_CHECK_OBJ(value);
500
501         BM_face_normal_flip(value->bm, value->f);
502
503         Py_RETURN_NONE;
504 }
505
506
507
508 PyDoc_STRVAR(bpy_bm_utils_loop_rip_doc,
509 ".. method:: loop_rip(loop)\n"
510 "\n"
511 "   Rip a vertex in a face away and add a new vertex.\n"
512 "\n"
513 "   :arg loop: The to rip.\n"
514 "   :type loop: :class:`BMFace`\n"
515 "   :return vert: The newly created vertex or None of failure.\n"
516 "   :rtype vert: :class:`BMVert`\n"
517 );
518 static PyObject *bpy_bm_utils_loop_rip(PyObject *UNUSED(self), BPy_BMLoop *value)
519 {
520         BMesh *bm;
521         BMVert *v_new;
522
523         if (!BPy_BMLoop_Check(value)) {
524                 PyErr_Format(PyExc_TypeError,
525                              "loop_rip(loop): BMLoop expected, not '%.200s'",
526                              Py_TYPE(value)->tp_name);
527                 return NULL;
528         }
529
530         BPY_BM_CHECK_OBJ(value);
531
532         bm = value->bm;
533
534         v_new = BM_face_loop_rip(bm, value->l);
535
536         if (v_new != value->l->v) {
537                 return BPy_BMVert_CreatePyObject(bm, v_new);
538         }
539         else {
540                 Py_RETURN_NONE;
541         }
542 }
543
544
545 static struct PyMethodDef BPy_BM_utils_methods[] = {
546     {"vert_collapse_edge",  (PyCFunction)bpy_bm_utils_vert_collapse_edge,  METH_VARARGS, bpy_bm_utils_vert_collapse_edge_doc},
547     {"vert_collapse_faces", (PyCFunction)bpy_bm_utils_vert_collapse_faces, METH_VARARGS, bpy_bm_utils_vert_collapse_faces_doc},
548     {"vert_dissolve",       (PyCFunction)bpy_bm_utils_vert_dissolve,       METH_VARARGS, bpy_bm_utils_vert_dissolve_doc},
549     {"edge_split",          (PyCFunction)bpy_bm_utils_edge_split,          METH_VARARGS, bpy_bm_utils_edge_split_doc},
550     {"edge_rotate",         (PyCFunction)bpy_bm_utils_edge_rotate,         METH_VARARGS, bpy_bm_utils_edge_rotate_doc},
551     {"face_split",          (PyCFunction)bpy_bm_utils_face_split,          METH_VARARGS, bpy_bm_utils_face_split_doc},
552     {"face_join",           (PyCFunction)bpy_bm_utils_face_join,           METH_O,       bpy_bm_utils_face_join_doc},
553     {"face_vert_rip",       (PyCFunction)bpy_bm_utils_face_vert_rip,       METH_VARARGS, bpy_bm_utils_face_vert_rip_doc},
554     {"face_flip",           (PyCFunction)bpy_bm_utils_face_flip,           METH_O,       bpy_bm_utils_face_flip_doc},
555     {"loop_rip",            (PyCFunction)bpy_bm_utils_loop_rip,            METH_O,       bpy_bm_utils_loop_rip_doc},
556     {NULL, NULL, 0, NULL}
557 };
558
559
560 PyDoc_STRVAR(BPy_BM_doc,
561 "This module provides access to blenders bmesh data structures."
562 );
563 static struct PyModuleDef BPy_BM_types_module_def = {
564     PyModuleDef_HEAD_INIT,
565     "bmesh.utils",  /* m_name */
566     BPy_BM_doc,  /* m_doc */
567     0,  /* m_size */
568     BPy_BM_utils_methods,  /* m_methods */
569     NULL,  /* m_reload */
570     NULL,  /* m_traverse */
571     NULL,  /* m_clear */
572     NULL,  /* m_free */
573 };
574
575
576 PyObject *BPyInit_bmesh_utils(void)
577 {
578         PyObject *submodule;
579
580         submodule = PyModule_Create(&BPy_BM_types_module_def);
581
582         return submodule;
583 }