PyAPI: correct int range checking
[blender.git] / source / blender / python / bmesh / bmesh_py_types_meshdata.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_types_meshdata.c
27  *  \ingroup pybmesh
28  *
29  * This file defines customdata types which can't be accessed as primitive
30  * python types such as MDeformVert, MLoopUV, MTexPoly
31  */
32
33 #include <Python.h>
34
35 #include "../mathutils/mathutils.h"
36
37 #include "DNA_object_types.h"
38 #include "DNA_meshdata_types.h"
39
40 #include "BLI_utildefines.h"
41 #include "BLI_math_vector.h"
42
43 #include "BKE_deform.h"
44 #include "BKE_library.h"
45
46 #include "bmesh_py_types_meshdata.h"
47
48 #include "../generic/python_utildefines.h"
49
50 /* Mesh Loop UV
51  * ************ */
52
53 #define BPy_BMLoopUV_Check(v)  (Py_TYPE(v) == &BPy_BMLoopUV_Type)
54
55 typedef struct BPy_BMLoopUV {
56         PyObject_VAR_HEAD
57         MLoopUV *data;
58 } BPy_BMLoopUV;
59
60 PyDoc_STRVAR(bpy_bmloopuv_uv_doc,
61 "Loops UV (as a 2D Vector).\n\n:type: :class:`mathutils.Vector`"
62 );
63 static PyObject *bpy_bmloopuv_uv_get(BPy_BMLoopUV *self, void *UNUSED(closure))
64 {
65         return Vector_CreatePyObject_wrap(self->data->uv, 2, NULL);
66 }
67
68 static int bpy_bmloopuv_uv_set(BPy_BMLoopUV *self, PyObject *value, void *UNUSED(closure))
69 {
70         float tvec[2];
71         if (mathutils_array_parse(tvec, 2, 2, value, "BMLoopUV.uv") != -1) {
72                 copy_v2_v2(self->data->uv, tvec);
73                 return 0;
74         }
75         else {
76                 return -1;
77         }
78 }
79
80 PyDoc_STRVAR(bpy_bmloopuv_flag__pin_uv_doc,
81 "UV pin state.\n\n:type: boolean"
82 );
83 PyDoc_STRVAR(bpy_bmloopuv_flag__select_doc,
84 "UV select state.\n\n:type: boolean"
85 );
86 PyDoc_STRVAR(bpy_bmloopuv_flag__select_edge_doc,
87 "UV edge select state.\n\n:type: boolean"
88 );
89
90
91 static PyObject *bpy_bmloopuv_flag_get(BPy_BMLoopUV *self, void *flag_p)
92 {
93         const int flag = GET_INT_FROM_POINTER(flag_p);
94         return PyBool_FromLong(self->data->flag & flag);
95 }
96
97 static int bpy_bmloopuv_flag_set(BPy_BMLoopUV *self, PyObject *value, void *flag_p)
98 {
99         const int flag = GET_INT_FROM_POINTER(flag_p);
100
101         switch (PyLong_AsLong(value)) {
102                 case true:
103                         self->data->flag |= flag;
104                         return 0;
105                 case false:
106                         self->data->flag &= ~flag;
107                         return 0;
108                 default:
109                         PyErr_SetString(PyExc_TypeError,
110                                         "expected a boolean type 0/1");
111                         return -1;
112         }
113 }
114
115 static PyGetSetDef bpy_bmloopuv_getseters[] = {
116         /* attributes match rna_def_mloopuv  */
117         {(char *)"uv",          (getter)bpy_bmloopuv_uv_get,   (setter)bpy_bmloopuv_uv_set,   (char *)bpy_bmloopuv_uv_doc, NULL},
118         {(char *)"pin_uv",      (getter)bpy_bmloopuv_flag_get, (setter)bpy_bmloopuv_flag_set, (char *)bpy_bmloopuv_flag__pin_uv_doc, (void *)MLOOPUV_PINNED},
119         {(char *)"select",      (getter)bpy_bmloopuv_flag_get, (setter)bpy_bmloopuv_flag_set, (char *)bpy_bmloopuv_flag__select_doc, (void *)MLOOPUV_VERTSEL},
120         {(char *)"select_edge", (getter)bpy_bmloopuv_flag_get, (setter)bpy_bmloopuv_flag_set, (char *)bpy_bmloopuv_flag__select_edge_doc, (void *)MLOOPUV_EDGESEL},
121
122         {NULL, NULL, NULL, NULL, NULL} /* Sentinel */
123 };
124
125 PyTypeObject BPy_BMLoopUV_Type; /* bm.loops.layers.uv.active */
126
127 static void bm_init_types_bmloopuv(void)
128 {
129         BPy_BMLoopUV_Type.tp_basicsize = sizeof(BPy_BMLoopUV);
130
131         BPy_BMLoopUV_Type.tp_name = "BMLoopUV";
132
133         BPy_BMLoopUV_Type.tp_doc = NULL; // todo
134
135         BPy_BMLoopUV_Type.tp_getset = bpy_bmloopuv_getseters;
136
137         BPy_BMLoopUV_Type.tp_flags = Py_TPFLAGS_DEFAULT;
138
139         PyType_Ready(&BPy_BMLoopUV_Type);
140 }
141
142 int BPy_BMLoopUV_AssignPyObject(struct MLoopUV *mloopuv, PyObject *value)
143 {
144         if (UNLIKELY(!BPy_BMLoopUV_Check(value))) {
145                 PyErr_Format(PyExc_TypeError, "expected BMLoopUV, not a %.200s", Py_TYPE(value)->tp_name);
146                 return -1;
147         }
148         else {
149                 *((MLoopUV *)mloopuv) = *(((BPy_BMLoopUV *)value)->data);
150                 return 0;
151         }
152 }
153
154 PyObject *BPy_BMLoopUV_CreatePyObject(struct MLoopUV *mloopuv)
155 {
156         BPy_BMLoopUV *self = PyObject_New(BPy_BMLoopUV, &BPy_BMLoopUV_Type);
157         self->data = mloopuv;
158         return (PyObject *)self;
159 }
160
161 /* --- End Mesh Loop UV --- */
162
163 /* Mesh Vert Skin
164  * ************ */
165
166 #define BPy_BMVertSkin_Check(v)  (Py_TYPE(v) == &BPy_BMVertSkin_Type)
167
168 typedef struct BPy_BMVertSkin {
169         PyObject_VAR_HEAD
170         MVertSkin *data;
171 } BPy_BMVertSkin;
172
173 PyDoc_STRVAR(bpy_bmvertskin_radius_doc,
174 "Vert skin radii (as a 2D Vector).\n\n:type: :class:`mathutils.Vector`"
175 );
176 static PyObject *bpy_bmvertskin_radius_get(BPy_BMVertSkin *self, void *UNUSED(closure))
177 {
178         return Vector_CreatePyObject_wrap(self->data->radius, 2, NULL);
179 }
180
181 static int bpy_bmvertskin_radius_set(BPy_BMVertSkin *self, PyObject *value, void *UNUSED(closure))
182 {
183         float tvec[2];
184         if (mathutils_array_parse(tvec, 2, 2, value, "BMVertSkin.radius") != -1) {
185                 copy_v2_v2(self->data->radius, tvec);
186                 return 0;
187         }
188         else {
189                 return -1;
190         }
191 }
192
193 PyDoc_STRVAR(bpy_bmvertskin_flag__use_root_doc,
194 "Use as root vertex.\n\n:type: boolean"
195 );
196 PyDoc_STRVAR(bpy_bmvertskin_flag__use_loose_doc,
197 "Use loose vertex.\n\n:type: boolean"
198 );
199
200 static PyObject *bpy_bmvertskin_flag_get(BPy_BMVertSkin *self, void *flag_p)
201 {
202         const int flag = GET_INT_FROM_POINTER(flag_p);
203         return PyBool_FromLong(self->data->flag & flag);
204 }
205
206 static int bpy_bmvertskin_flag_set(BPy_BMVertSkin *self, PyObject *value, void *flag_p)
207 {
208         const int flag = GET_INT_FROM_POINTER(flag_p);
209
210         switch (PyLong_AsLong(value)) {
211                 case true:
212                         self->data->flag |= flag;
213                         return 0;
214                 case false:
215                         self->data->flag &= ~flag;
216                         return 0;
217                 default:
218                         PyErr_SetString(PyExc_TypeError,
219                                         "expected a boolean type 0/1");
220                         return -1;
221         }
222 }
223
224 /* XXX Todo: Make root settable, currently the code to disable all other verts as roots sits within the modifier */
225 static PyGetSetDef bpy_bmvertskin_getseters[] = {
226         /* attributes match rna_mesh_gen  */
227         {(char *)"radius",    (getter)bpy_bmvertskin_radius_get, (setter)bpy_bmvertskin_radius_set, (char *)bpy_bmvertskin_radius_doc, NULL},
228         {(char *)"use_root",  (getter)bpy_bmvertskin_flag_get,   (setter)NULL,                                     (char *)bpy_bmvertskin_flag__use_root_doc,  (void *)MVERT_SKIN_ROOT},
229         {(char *)"use_loose", (getter)bpy_bmvertskin_flag_get,   (setter)bpy_bmvertskin_flag_set,   (char *)bpy_bmvertskin_flag__use_loose_doc, (void *)MVERT_SKIN_LOOSE},
230
231         {NULL, NULL, NULL, NULL, NULL} /* Sentinel */
232 };
233
234 static PyTypeObject BPy_BMVertSkin_Type; /* bm.loops.layers.uv.active */
235
236 static void bm_init_types_bmvertskin(void)
237 {
238         BPy_BMVertSkin_Type.tp_basicsize = sizeof(BPy_BMVertSkin);
239
240         BPy_BMVertSkin_Type.tp_name = "BMVertSkin";
241
242         BPy_BMVertSkin_Type.tp_doc = NULL; // todo
243
244         BPy_BMVertSkin_Type.tp_getset = bpy_bmvertskin_getseters;
245
246         BPy_BMVertSkin_Type.tp_flags = Py_TPFLAGS_DEFAULT;
247
248         PyType_Ready(&BPy_BMVertSkin_Type);
249 }
250
251 int BPy_BMVertSkin_AssignPyObject(struct MVertSkin *mvertskin, PyObject *value)
252 {
253         if (UNLIKELY(!BPy_BMVertSkin_Check(value))) {
254                 PyErr_Format(PyExc_TypeError, "expected BMVertSkin, not a %.200s", Py_TYPE(value)->tp_name);
255                 return -1;
256         }
257         else {
258                 *((MVertSkin *)mvertskin) = *(((BPy_BMVertSkin *)value)->data);
259                 return 0;
260         }
261 }
262
263 PyObject *BPy_BMVertSkin_CreatePyObject(struct MVertSkin *mvertskin)
264 {
265         BPy_BMVertSkin *self = PyObject_New(BPy_BMVertSkin, &BPy_BMVertSkin_Type);
266         self->data = mvertskin;
267         return (PyObject *)self;
268 }
269
270 /* --- End Mesh Vert Skin --- */
271
272 /* Mesh Loop Color
273  * *************** */
274
275 /* This simply provides a color wrapper for
276  * color which uses mathutils callbacks for mathutils.Color
277  */
278
279 #define MLOOPCOL_FROM_CAPSULE(color_capsule)  \
280         ((MLoopCol *)PyCapsule_GetPointer(color_capsule, NULL))
281
282 static void mloopcol_to_float(const MLoopCol *mloopcol, float r_col[3])
283 {
284         rgb_uchar_to_float(r_col, (const unsigned char *)&mloopcol->r);
285 }
286
287 static void mloopcol_from_float(MLoopCol *mloopcol, const float col[3])
288 {
289         rgb_float_to_uchar((unsigned char *)&mloopcol->r, col);
290 }
291
292 static unsigned char mathutils_bmloopcol_cb_index = -1;
293
294 static int mathutils_bmloopcol_check(BaseMathObject *UNUSED(bmo))
295 {
296         /* always ok */
297         return 0;
298 }
299
300 static int mathutils_bmloopcol_get(BaseMathObject *bmo, int UNUSED(subtype))
301 {
302         MLoopCol *mloopcol = MLOOPCOL_FROM_CAPSULE(bmo->cb_user);
303         mloopcol_to_float(mloopcol, bmo->data);
304         return 0;
305 }
306
307 static int mathutils_bmloopcol_set(BaseMathObject *bmo, int UNUSED(subtype))
308 {
309         MLoopCol *mloopcol = MLOOPCOL_FROM_CAPSULE(bmo->cb_user);
310         mloopcol_from_float(mloopcol, bmo->data);
311         return 0;
312 }
313
314 static int mathutils_bmloopcol_get_index(BaseMathObject *bmo, int subtype, int UNUSED(index))
315 {
316         /* lazy, avoid repeteing the case statement */
317         if (mathutils_bmloopcol_get(bmo, subtype) == -1)
318                 return -1;
319         return 0;
320 }
321
322 static int mathutils_bmloopcol_set_index(BaseMathObject *bmo, int subtype, int index)
323 {
324         const float f = bmo->data[index];
325
326         /* lazy, avoid repeteing the case statement */
327         if (mathutils_bmloopcol_get(bmo, subtype) == -1)
328                 return -1;
329
330         bmo->data[index] = f;
331         return mathutils_bmloopcol_set(bmo, subtype);
332 }
333
334 static Mathutils_Callback mathutils_bmloopcol_cb = {
335         mathutils_bmloopcol_check,
336         mathutils_bmloopcol_get,
337         mathutils_bmloopcol_set,
338         mathutils_bmloopcol_get_index,
339         mathutils_bmloopcol_set_index
340 };
341
342 static void bm_init_types_bmloopcol(void)
343 {
344         /* pass */
345         mathutils_bmloopcol_cb_index = Mathutils_RegisterCallback(&mathutils_bmloopcol_cb);
346 }
347
348 int BPy_BMLoopColor_AssignPyObject(struct MLoopCol *mloopcol, PyObject *value)
349 {
350         float tvec[3];
351         if (mathutils_array_parse(tvec, 3, 3, value, "BMLoopCol") != -1) {
352                 mloopcol_from_float(mloopcol, tvec);
353                 return 0;
354         }
355         else {
356                 return -1;
357         }
358 }
359
360 PyObject *BPy_BMLoopColor_CreatePyObject(struct MLoopCol *data)
361 {
362         PyObject *color_capsule;
363         color_capsule = PyCapsule_New(data, NULL, NULL);
364         return Color_CreatePyObject_cb(color_capsule, mathutils_bmloopcol_cb_index, 0);
365 }
366
367 #undef MLOOPCOL_FROM_CAPSULE
368
369 /* --- End Mesh Loop Color --- */
370
371
372 /* Mesh Deform Vert
373  * **************** */
374
375 /**
376  * This is python type wraps a deform vert as a python dictionary,
377  * hiding the #MDeformWeight on access, since the mapping is very close, eg:
378  *
379  * C:
380  *     weight = defvert_find_weight(dv, group_nr);
381  *     defvert_remove_group(dv, dw)
382  *
383  * Py:
384  *     weight = dv[group_nr]
385  *     del dv[group_nr]
386  *
387  * \note: there is nothing BMesh specific here,
388  * its only that BMesh is the only part of blender that uses a hand written api like this.
389  * This type could eventually be used to access lattice weights.
390  *
391  * \note: Many of blender-api's dict-like-wrappers act like ordered dicts,
392  * This is intentional _not_ ordered, the weights can be in any order and it wont matter,
393  * the order should not be used in the api in any meaningful way (as with a python dict)
394  * only expose as mapping, not a sequence.
395  */
396
397 #define BPy_BMDeformVert_Check(v)  (Py_TYPE(v) == &BPy_BMDeformVert_Type)
398
399 typedef struct BPy_BMDeformVert {
400         PyObject_VAR_HEAD
401         MDeformVert *data;
402 } BPy_BMDeformVert;
403
404
405 /* Mapping Protocols
406  * ================= */
407
408 static int bpy_bmdeformvert_len(BPy_BMDeformVert *self)
409 {
410         return self->data->totweight;
411 }
412
413 static PyObject *bpy_bmdeformvert_subscript(BPy_BMDeformVert *self, PyObject *key)
414 {
415         if (PyIndex_Check(key)) {
416                 int i;
417                 i = PyNumber_AsSsize_t(key, PyExc_IndexError);
418                 if (i == -1 && PyErr_Occurred()) {
419                         return NULL;
420                 }
421                 else {
422                         MDeformWeight *dw = defvert_find_index(self->data, i);
423
424                         if (dw == NULL) {
425                                 PyErr_SetString(PyExc_KeyError, "BMDeformVert[key] = x: "
426                                                 "key not found");
427                                 return NULL;
428                         }
429                         else {
430                                 return PyFloat_FromDouble(dw->weight);
431                         }
432                 }
433         }
434         else {
435                 PyErr_Format(PyExc_TypeError,
436                              "BMDeformVert keys must be integers, not %.200s",
437                              Py_TYPE(key)->tp_name);
438                 return NULL;
439         }
440 }
441
442 static int bpy_bmdeformvert_ass_subscript(BPy_BMDeformVert *self, PyObject *key, PyObject *value)
443 {
444         if (PyIndex_Check(key)) {
445                 int i;
446
447                 i = PyNumber_AsSsize_t(key, PyExc_IndexError);
448                 if (i == -1 && PyErr_Occurred()) {
449                         return -1;
450                 }
451
452                 if (value) {
453                         /* dvert[group_index] = 0.5 */
454                         if (i < 0) {
455                                 PyErr_SetString(PyExc_KeyError, "BMDeformVert[key] = x: "
456                                                 "weight keys can't be negative");
457                                 return -1;
458                         }
459                         else {
460                                 MDeformWeight *dw = defvert_verify_index(self->data, i);
461                                 const float f = PyFloat_AsDouble(value);
462                                 if (f == -1 && PyErr_Occurred()) { // parsed key not a number
463                                         PyErr_SetString(PyExc_TypeError,
464                                                         "BMDeformVert[key] = x: "
465                                                         "assigned value not a number");
466                                         return -1;
467                                 }
468
469                                 dw->weight = CLAMPIS(f, 0.0f, 1.0f);
470                         }
471                 }
472                 else {
473                         /* del dvert[group_index] */
474                         MDeformWeight *dw = defvert_find_index(self->data, i);
475
476                         if (dw == NULL) {
477                                 PyErr_SetString(PyExc_KeyError, "del BMDeformVert[key]: "
478                                                 "key not found");
479                         }
480                         defvert_remove_group(self->data, dw);
481                 }
482
483                 return 0;
484
485         }
486         else {
487                 PyErr_Format(PyExc_TypeError,
488                              "BMDeformVert keys must be integers, not %.200s",
489                              Py_TYPE(key)->tp_name);
490                 return -1;
491         }
492 }
493
494 static int bpy_bmdeformvert_contains(BPy_BMDeformVert *self, PyObject *value)
495 {
496         const int key = PyLong_AsSsize_t(value);
497
498         if (key == -1 && PyErr_Occurred()) {
499                 PyErr_SetString(PyExc_TypeError,
500                                 "BMDeformVert.__contains__: expected an int");
501                 return -1;
502         }
503
504         return (defvert_find_index(self->data, key) != NULL) ? 1 : 0;
505 }
506
507 /* only defined for __contains__ */
508 static PySequenceMethods bpy_bmdeformvert_as_sequence = {
509         (lenfunc)bpy_bmdeformvert_len,               /* sq_length */
510         NULL,                                        /* sq_concat */
511         NULL,                                        /* sq_repeat */
512
513         /* note: if this is set PySequence_Check() returns True,
514          * but in this case we dont want to be treated as a seq */
515         NULL,                                        /* sq_item */
516
517         NULL,                                        /* sq_slice */
518         NULL,                                        /* sq_ass_item */
519         NULL,                                        /* *was* sq_ass_slice */
520         (objobjproc)bpy_bmdeformvert_contains,       /* sq_contains */
521         (binaryfunc) NULL,                           /* sq_inplace_concat */
522         (ssizeargfunc) NULL,                         /* sq_inplace_repeat */
523 };
524
525 static PyMappingMethods bpy_bmdeformvert_as_mapping = {
526         (lenfunc)bpy_bmdeformvert_len,
527         (binaryfunc)bpy_bmdeformvert_subscript,
528         (objobjargproc)bpy_bmdeformvert_ass_subscript
529 };
530
531 /* Methods
532  * ======= */
533
534 PyDoc_STRVAR(bpy_bmdeformvert_keys_doc,
535 ".. method:: keys()\n"
536 "\n"
537 "   Return the group indices used by this vertex\n"
538 "   (matching pythons dict.keys() functionality).\n"
539 "\n"
540 "   :return: the deform group this vertex uses\n"
541 "   :rtype: list of ints\n"
542 );
543 static PyObject *bpy_bmdeformvert_keys(BPy_BMDeformVert *self)
544 {
545         PyObject *ret;
546         int i;
547         MDeformWeight *dw = self->data->dw;
548
549         ret = PyList_New(self->data->totweight);
550         for (i = 0; i < self->data->totweight; i++, dw++) {
551                 PyList_SET_ITEM(ret, i, PyLong_FromLong(dw->def_nr));
552         }
553
554         return ret;
555 }
556
557 PyDoc_STRVAR(bpy_bmdeformvert_values_doc,
558 ".. method:: values()\n"
559 "\n"
560 "   Return the weights of the deform vertex\n"
561 "   (matching pythons dict.values() functionality).\n"
562 "\n"
563 "   :return: The weights that influence this vertex\n"
564 "   :rtype: list of floats\n"
565 );
566 static PyObject *bpy_bmdeformvert_values(BPy_BMDeformVert *self)
567 {
568         PyObject *ret;
569         int i;
570         MDeformWeight *dw = self->data->dw;
571
572         ret = PyList_New(self->data->totweight);
573         for (i = 0; i < self->data->totweight; i++, dw++) {
574                 PyList_SET_ITEM(ret, i, PyFloat_FromDouble(dw->weight));
575         }
576
577         return ret;
578 }
579
580 PyDoc_STRVAR(bpy_bmdeformvert_items_doc,
581 ".. method:: items()\n"
582 "\n"
583 "   Return (group, weight) pairs for this vertex\n"
584 "   (matching pythons dict.items() functionality).\n"
585 "\n"
586 "   :return: (key, value) pairs for each deform weight of this vertex.\n"
587 "   :rtype: list of tuples\n"
588 );
589 static PyObject *bpy_bmdeformvert_items(BPy_BMDeformVert *self)
590 {
591         PyObject *ret;
592         PyObject *item;
593         int i;
594         MDeformWeight *dw = self->data->dw;
595
596         ret = PyList_New(self->data->totweight);
597         for (i = 0; i < self->data->totweight; i++, dw++) {
598                 item = PyTuple_New(2);
599                 PyTuple_SET_ITEMS(item,
600                         PyLong_FromLong(dw->def_nr),
601                         PyFloat_FromDouble(dw->weight));
602                 PyList_SET_ITEM(ret, i, item);
603         }
604
605         return ret;
606 }
607
608 PyDoc_STRVAR(bpy_bmdeformvert_get_doc,
609 ".. method:: get(key, default=None)\n"
610 "\n"
611 "   Returns the deform weight matching the key or default\n"
612 "   when not found (matches pythons dictionary function of the same name).\n"
613 "\n"
614 "   :arg key: The key associated with deform weight.\n"
615 "   :type key: int\n"
616 "   :arg default: Optional argument for the value to return if\n"
617 "      *key* is not found.\n"
618 "   :type default: Undefined\n"
619 );
620 static PyObject *bpy_bmdeformvert_get(BPy_BMDeformVert *self, PyObject *args)
621 {
622         int key;
623         PyObject *def = Py_None;
624
625         if (!PyArg_ParseTuple(args, "i|O:get", &key, &def)) {
626                 return NULL;
627         }
628         else {
629                 MDeformWeight *dw = defvert_find_index(self->data, key);
630
631                 if (dw) {
632                         return PyFloat_FromDouble(dw->weight);
633                 }
634                 else {
635                         return Py_INCREF_RET(def);
636                 }
637         }
638 }
639
640
641 PyDoc_STRVAR(bpy_bmdeformvert_clear_doc,
642 ".. method:: clear()\n"
643 "\n"
644 "   Clears all weights.\n"
645 );
646 static PyObject *bpy_bmdeformvert_clear(BPy_BMDeformVert *self)
647 {
648         defvert_clear(self->data);
649
650         Py_RETURN_NONE;
651 }
652
653 static struct PyMethodDef bpy_bmdeformvert_methods[] = {
654         {"keys",    (PyCFunction)bpy_bmdeformvert_keys,    METH_NOARGS,  bpy_bmdeformvert_keys_doc},
655         {"values",  (PyCFunction)bpy_bmdeformvert_values,  METH_NOARGS,  bpy_bmdeformvert_values_doc},
656         {"items",   (PyCFunction)bpy_bmdeformvert_items,   METH_NOARGS,  bpy_bmdeformvert_items_doc},
657         {"get",     (PyCFunction)bpy_bmdeformvert_get,     METH_VARARGS, bpy_bmdeformvert_get_doc},
658         /* BMESH_TODO pop, popitem, update */
659         {"clear",   (PyCFunction)bpy_bmdeformvert_clear,   METH_NOARGS,  bpy_bmdeformvert_clear_doc},
660         {NULL, NULL, 0, NULL}
661 };
662
663 PyTypeObject BPy_BMDeformVert_Type; /* bm.loops.layers.uv.active */
664
665 static void bm_init_types_bmdvert(void)
666 {
667         BPy_BMDeformVert_Type.tp_basicsize = sizeof(BPy_BMDeformVert);
668
669         BPy_BMDeformVert_Type.tp_name = "BMDeformVert";
670
671         BPy_BMDeformVert_Type.tp_doc = NULL; // todo
672
673         BPy_BMDeformVert_Type.tp_as_sequence = &bpy_bmdeformvert_as_sequence;
674         BPy_BMDeformVert_Type.tp_as_mapping = &bpy_bmdeformvert_as_mapping;
675
676         BPy_BMDeformVert_Type.tp_methods = bpy_bmdeformvert_methods;
677
678         BPy_BMDeformVert_Type.tp_flags = Py_TPFLAGS_DEFAULT;
679
680         PyType_Ready(&BPy_BMDeformVert_Type);
681 }
682
683 int BPy_BMDeformVert_AssignPyObject(struct MDeformVert *dvert, PyObject *value)
684 {
685         if (UNLIKELY(!BPy_BMDeformVert_Check(value))) {
686                 PyErr_Format(PyExc_TypeError, "expected BMDeformVert, not a %.200s", Py_TYPE(value)->tp_name);
687                 return -1;
688         }
689         else {
690                 MDeformVert *dvert_src = ((BPy_BMDeformVert *)value)->data;
691                 if (LIKELY(dvert != dvert_src)) {
692                         defvert_copy(dvert, dvert_src);
693                 }
694                 return 0;
695         }
696 }
697
698 PyObject *BPy_BMDeformVert_CreatePyObject(struct MDeformVert *dvert)
699 {
700         BPy_BMDeformVert *self = PyObject_New(BPy_BMDeformVert, &BPy_BMDeformVert_Type);
701         self->data = dvert;
702         return (PyObject *)self;
703 }
704
705 /* --- End Mesh Deform Vert --- */
706
707
708 /* call to init all types */
709 void BPy_BM_init_types_meshdata(void)
710 {
711         bm_init_types_bmloopuv();
712         bm_init_types_bmloopcol();
713         bm_init_types_bmdvert();
714         bm_init_types_bmvertskin();
715 }
716