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