Blender V4.3
bmesh_py_types_meshdata.cc
Go to the documentation of this file.
1/* SPDX-FileCopyrightText: 2012 Blender Authors
2 *
3 * SPDX-License-Identifier: GPL-2.0-or-later */
4
20#include <Python.h>
21
23
24#include "DNA_meshdata_types.h"
25
26#include "BKE_customdata.hh"
27
28#include "BLI_math_base.h"
29#include "BLI_math_color.h"
30#include "BLI_math_vector.h"
31#include "BLI_utildefines.h"
32
33#include "BKE_deform.hh"
34
35#include "bmesh.hh"
37
40
41/* Mesh Loop UV
42 * ************ */
43
44#define BPy_BMLoopUV_Check(v) (Py_TYPE(v) == &BPy_BMLoopUV_Type)
45
47 PyObject_VAR_HEAD
48 float *uv;
49 /* vert_select, edge_select and pin could be nullptr, signifying those layers don't exist.
50 * Currently those layers are always created on a BMesh because adding layers to an existing
51 * BMesh is slow and invalidates existing python objects having pointers into the original
52 * datablocks (adding a layer re-generates all blocks). But eventually the plan is to lazily
53 * allocate the bool layers 'on demand'. Therefore the code tries to handle all cases where
54 * the layers don't exist. */
57 bool *pin;
59};
60
62 /* Wrap. */
63 bpy_bmloopuv_uv_doc,
64 "Loops UV (as a 2D Vector).\n"
65 "\n"
66 ":type: :class:`mathutils.Vector`");
67static PyObject *bpy_bmloopuv_uv_get(BPy_BMLoopUV *self, void * /*closure*/)
68{
69 return Vector_CreatePyObject_wrap(self->uv, 2, nullptr);
70}
71
72static int bpy_bmloopuv_uv_set(BPy_BMLoopUV *self, PyObject *value, void * /*closure*/)
73{
74 float tvec[2];
75 if (mathutils_array_parse(tvec, 2, 2, value, "BMLoopUV.uv") != -1) {
76 copy_v2_v2(self->uv, tvec);
77 return 0;
78 }
79
80 return -1;
81}
82
84 /* Wrap. */
85 bpy_bmloopuv_pin_uv_doc,
86 "UV pin state.\n"
87 "\n"
88 ":type: bool");
90 /* Wrap. */
91 bpy_bmloopuv_select_doc,
92 "UV select state.\n"
93 "\n"
94 ":type: bool");
96 /* Wrap. */
97 bpy_bmloopuv_select_edge_doc,
98 "UV edge select state.\n"
99 "\n"
100 ":type: bool");
101
102static PyObject *bpy_bmloopuv_pin_uv_get(BPy_BMLoopUV *self, void * /*closure*/)
103{
104 /* A non existing pin layer means nothing is currently pinned */
105 return self->pin ? PyBool_FromLong(*self->pin) : nullptr;
106}
107
108static int bpy_bmloopuv_pin_uv_set(BPy_BMLoopUV *self, PyObject *value, void * /*closure*/)
109{
110 /* TODO: if we add lazy allocation of the associated uv map bool layers to BMesh we need
111 * to add a pin layer and update self->pin in the case of self->pin being nullptr.
112 * This isn't easy to do currently as adding CustomData layers to a BMesh invalidates
113 * existing python objects. So for now lazy allocation isn't done and self->pin should
114 * never be nullptr. */
115 BLI_assert(self->pin);
116 if (self->pin) {
117 *self->pin = PyC_Long_AsBool(value);
118 }
119 else {
120 PyErr_SetString(PyExc_RuntimeError,
121 "active uv layer has no associated pin layer. This is a bug!");
122 return -1;
123 }
124 return 0;
125}
126
127static PyObject *bpy_bmloopuv_select_get(BPy_BMLoopUV *self, void * /*closure*/)
128{
129 /* A non existing vert_select layer means nothing is currently selected */
130 return self->vert_select ? PyBool_FromLong(*self->vert_select) : nullptr;
131}
132static int bpy_bmloopuv_select_set(BPy_BMLoopUV *self, PyObject *value, void * /*closure*/)
133{
134 /* TODO: see comment above on bpy_bmloopuv_pin_uv_set(), the same applies here. */
135 BLI_assert(self->vert_select);
136 if (self->vert_select) {
137 *self->vert_select = PyC_Long_AsBool(value);
138 }
139 else {
140 PyErr_SetString(PyExc_RuntimeError,
141 "active uv layer has no associated vertex selection layer. This is a bug!");
142 return -1;
143 }
144 return 0;
145}
146
147static PyObject *bpy_bmloopuv_select_edge_get(BPy_BMLoopUV *self, void * /*closure*/)
148{
149 /* A non existing edge_select layer means nothing is currently selected */
150 return self->edge_select ? PyBool_FromLong(*self->edge_select) : nullptr;
151}
152static int bpy_bmloopuv_select_edge_set(BPy_BMLoopUV *self, PyObject *value, void * /*closure*/)
153{
154 /* TODO: see comment above on bpy_bmloopuv_pin_uv_set(), the same applies here. */
155 BLI_assert(self->edge_select);
156 if (self->edge_select) {
157 *self->edge_select = PyC_Long_AsBool(value);
158 }
159 else {
160 PyErr_SetString(PyExc_RuntimeError,
161 "active uv layer has no associated edge selection layer. This is a bug!");
162 return -1;
163 }
164 return 0;
165}
166
167static PyGetSetDef bpy_bmloopuv_getseters[] = {
168 /* attributes match rna_def_mloopuv. */
169 {"uv", (getter)bpy_bmloopuv_uv_get, (setter)bpy_bmloopuv_uv_set, bpy_bmloopuv_uv_doc, nullptr},
170 {"pin_uv",
173 bpy_bmloopuv_pin_uv_doc,
174 nullptr},
175 {"select",
178 bpy_bmloopuv_select_doc,
179 nullptr},
180 {"select_edge",
183 bpy_bmloopuv_select_edge_doc,
184 nullptr},
185
186 {nullptr, nullptr, nullptr, nullptr, nullptr} /* Sentinel */
187};
188
189PyTypeObject BPy_BMLoopUV_Type; /* bm.loops.layers.uv.active */
190
192{
193 BPy_BMLoopUV_Type.tp_basicsize = sizeof(BPy_BMLoopUV);
194
195 BPy_BMLoopUV_Type.tp_name = "BMLoopUV";
196
197 BPy_BMLoopUV_Type.tp_doc = nullptr; /* todo */
198
200
201 BPy_BMLoopUV_Type.tp_flags = Py_TPFLAGS_DEFAULT;
202
203 PyType_Ready(&BPy_BMLoopUV_Type);
204}
205
206int BPy_BMLoopUV_AssignPyObject(BMesh *bm, BMLoop *loop, PyObject *value)
207{
208 if (UNLIKELY(!BPy_BMLoopUV_Check(value))) {
209 PyErr_Format(PyExc_TypeError, "expected BMLoopUV, not a %.200s", Py_TYPE(value)->tp_name);
210 return -1;
211 }
212
213 BPy_BMLoopUV *src = (BPy_BMLoopUV *)value;
214 const BMUVOffsets offsets = BM_uv_map_get_offsets(bm);
215
216 float *luv = BM_ELEM_CD_GET_FLOAT_P(loop, offsets.uv);
217 copy_v2_v2(luv, src->uv);
218
219 if (src->vert_select) {
220 BM_ELEM_CD_SET_BOOL(loop, offsets.select_vert, *src->vert_select);
221 }
222
223 if (src->edge_select) {
224 BM_ELEM_CD_SET_BOOL(loop, offsets.select_edge, *src->edge_select);
225 }
226 if (src->pin) {
227 BM_ELEM_CD_SET_BOOL(loop, offsets.pin, *src->pin);
228 }
229 return 0;
230}
231
232PyObject *BPy_BMLoopUV_CreatePyObject(BMesh *bm, BMLoop *loop, int layer)
233{
235
236 const BMUVOffsets offsets = BM_uv_map_get_offsets_from_layer(bm, layer);
237
238 self->uv = BM_ELEM_CD_GET_FLOAT_P(loop, offsets.uv);
239 self->vert_select = offsets.select_vert >= 0 ? BM_ELEM_CD_GET_BOOL_P(loop, offsets.select_vert) :
240 nullptr;
241 self->edge_select = offsets.select_edge >= 0 ? BM_ELEM_CD_GET_BOOL_P(loop, offsets.select_edge) :
242 nullptr;
243 self->pin = offsets.pin >= 0 ? BM_ELEM_CD_GET_BOOL_P(loop, offsets.pin) : nullptr;
244
245 return (PyObject *)self;
246}
247
248/* --- End Mesh Loop UV --- */
249
250/* Mesh Vert Skin
251 * ************ */
252
253#define BPy_BMVertSkin_Check(v) (Py_TYPE(v) == &BPy_BMVertSkin_Type)
254
256 PyObject_VAR_HEAD
258};
259
261 /* Wrap. */
262 bpy_bmvertskin_radius_doc,
263 "Vert skin radii (as a 2D Vector).\n"
264 "\n"
265 ":type: :class:`mathutils.Vector`");
266static PyObject *bpy_bmvertskin_radius_get(BPy_BMVertSkin *self, void * /*closure*/)
267{
268 return Vector_CreatePyObject_wrap(self->data->radius, 2, nullptr);
269}
270
271static int bpy_bmvertskin_radius_set(BPy_BMVertSkin *self, PyObject *value, void * /*closure*/)
272{
273 float tvec[2];
274 if (mathutils_array_parse(tvec, 2, 2, value, "BMVertSkin.radius") != -1) {
275 copy_v2_v2(self->data->radius, tvec);
276 return 0;
277 }
278
279 return -1;
280}
281
283 /* Wrap. */
284 bpy_bmvertskin_flag__use_root_doc,
285 "Use as root vertex. Setting this flag does not clear other roots in the same mesh island.\n"
286 "\n"
287 ":type: bool");
289 /* Wrap. */
290 bpy_bmvertskin_flag__use_loose_doc,
291 "Use loose vertex.\n"
292 "\n"
293 ":type: bool");
294
295static PyObject *bpy_bmvertskin_flag_get(BPy_BMVertSkin *self, void *flag_p)
296{
297 const int flag = POINTER_AS_INT(flag_p);
298 return PyBool_FromLong(self->data->flag & flag);
299}
300
301static int bpy_bmvertskin_flag_set(BPy_BMVertSkin *self, PyObject *value, void *flag_p)
302{
303 const int flag = POINTER_AS_INT(flag_p);
304
305 switch (PyC_Long_AsBool(value)) {
306 case true:
307 self->data->flag |= flag;
308 return 0;
309 case false:
310 self->data->flag &= ~flag;
311 return 0;
312 default:
313 /* error is set */
314 return -1;
315 }
316}
317
318static PyGetSetDef bpy_bmvertskin_getseters[] = {
319 /* attributes match rna_mesh_gen. */
320 {"radius",
323 bpy_bmvertskin_radius_doc,
324 nullptr},
325 {"use_root",
328 bpy_bmvertskin_flag__use_root_doc,
329 (void *)MVERT_SKIN_ROOT},
330 {"use_loose",
333 bpy_bmvertskin_flag__use_loose_doc,
334 (void *)MVERT_SKIN_LOOSE},
335
336 {nullptr, nullptr, nullptr, nullptr, nullptr} /* Sentinel */
337};
338
339static PyTypeObject BPy_BMVertSkin_Type; /* bm.loops.layers.skin.active */
340
342{
343 BPy_BMVertSkin_Type.tp_basicsize = sizeof(BPy_BMVertSkin);
344
345 BPy_BMVertSkin_Type.tp_name = "BMVertSkin";
346
347 BPy_BMVertSkin_Type.tp_doc = nullptr; /* todo */
348
350
351 BPy_BMVertSkin_Type.tp_flags = Py_TPFLAGS_DEFAULT;
352
353 PyType_Ready(&BPy_BMVertSkin_Type);
354}
355
356int BPy_BMVertSkin_AssignPyObject(MVertSkin *mvertskin, PyObject *value)
357{
358 if (UNLIKELY(!BPy_BMVertSkin_Check(value))) {
359 PyErr_Format(PyExc_TypeError, "expected BMVertSkin, not a %.200s", Py_TYPE(value)->tp_name);
360 return -1;
361 }
362
363 *((MVertSkin *)mvertskin) = *(((BPy_BMVertSkin *)value)->data);
364 return 0;
365}
366
368{
370 self->data = mvertskin;
371 return (PyObject *)self;
372}
373
374/* --- End Mesh Vert Skin --- */
375
376/* Mesh Loop Color
377 * *************** */
378
379/* This simply provides a color wrapper for
380 * color which uses mathutils callbacks for mathutils.Color
381 */
382
383#define MLOOPCOL_FROM_CAPSULE(color_capsule) \
384 ((MLoopCol *)PyCapsule_GetPointer(color_capsule, nullptr))
385
386static void mloopcol_to_float(const MLoopCol *mloopcol, float r_col[4])
387{
388 rgba_uchar_to_float(r_col, (const uchar *)&mloopcol->r);
389}
390
391static void mloopcol_from_float(MLoopCol *mloopcol, const float col[4])
392{
393 rgba_float_to_uchar((uchar *)&mloopcol->r, col);
394}
395
397
399{
400 /* always ok */
401 return 0;
402}
403
404static int mathutils_bmloopcol_get(BaseMathObject *bmo, int /*subtype*/)
405{
406 MLoopCol *mloopcol = MLOOPCOL_FROM_CAPSULE(bmo->cb_user);
407 mloopcol_to_float(mloopcol, bmo->data);
408 return 0;
409}
410
411static int mathutils_bmloopcol_set(BaseMathObject *bmo, int /*subtype*/)
412{
413 MLoopCol *mloopcol = MLOOPCOL_FROM_CAPSULE(bmo->cb_user);
414 mloopcol_from_float(mloopcol, bmo->data);
415 return 0;
416}
417
418static int mathutils_bmloopcol_get_index(BaseMathObject *bmo, int subtype, int /*index*/)
419{
420 /* Lazy, avoid repeating the case statement. */
421 if (mathutils_bmloopcol_get(bmo, subtype) == -1) {
422 return -1;
423 }
424 return 0;
425}
426
427static int mathutils_bmloopcol_set_index(BaseMathObject *bmo, int subtype, int index)
428{
429 const float f = bmo->data[index];
430
431 /* Lazy, avoid repeating the case statement. */
432 if (mathutils_bmloopcol_get(bmo, subtype) == -1) {
433 return -1;
434 }
435
436 bmo->data[index] = f;
437 return mathutils_bmloopcol_set(bmo, subtype);
438}
439
447
453
454int BPy_BMLoopColor_AssignPyObject(MLoopCol *mloopcol, PyObject *value)
455{
456 float tvec[4];
457 if (mathutils_array_parse(tvec, 4, 4, value, "BMLoopCol") != -1) {
458 mloopcol_from_float(mloopcol, tvec);
459 return 0;
460 }
461
462 return -1;
463}
464
466{
467 PyObject *color_capsule;
468 color_capsule = PyCapsule_New(mloopcol, nullptr, nullptr);
469 return Vector_CreatePyObject_cb(color_capsule, 4, mathutils_bmloopcol_cb_index, 0);
470}
471
472#undef MLOOPCOL_FROM_CAPSULE
473
474/* --- End Mesh Loop Color --- */
475
476/* Mesh Deform Vert
477 * **************** */
478
503#define BPy_BMDeformVert_Check(v) (Py_TYPE(v) == &BPy_BMDeformVert_Type)
504
506 PyObject_VAR_HEAD
508};
509
510/* Mapping Protocols
511 * ================= */
512
514{
515 return self->data->totweight;
516}
517
518static PyObject *bpy_bmdeformvert_subscript(BPy_BMDeformVert *self, PyObject *key)
519{
520 if (PyIndex_Check(key)) {
521 int i;
522 i = PyNumber_AsSsize_t(key, PyExc_IndexError);
523 if (i == -1 && PyErr_Occurred()) {
524 return nullptr;
525 }
526
528
529 if (dw == nullptr) {
530 PyErr_SetString(PyExc_KeyError,
531 "BMDeformVert[key] = x: "
532 "key not found");
533 return nullptr;
534 }
535
536 return PyFloat_FromDouble(dw->weight);
537 }
538
539 PyErr_Format(
540 PyExc_TypeError, "BMDeformVert keys must be integers, not %.200s", Py_TYPE(key)->tp_name);
541 return nullptr;
542}
543
544static int bpy_bmdeformvert_ass_subscript(BPy_BMDeformVert *self, PyObject *key, PyObject *value)
545{
546 if (PyIndex_Check(key)) {
547 int i;
548
549 i = PyNumber_AsSsize_t(key, PyExc_IndexError);
550 if (i == -1 && PyErr_Occurred()) {
551 return -1;
552 }
553
554 if (value) {
555 /* Handle `dvert[group_index] = 0.5`. */
556 if (i < 0) {
557 PyErr_SetString(PyExc_KeyError,
558 "BMDeformVert[key] = x: "
559 "weight keys can't be negative");
560 return -1;
561 }
562
564 const float f = PyFloat_AsDouble(value);
565 if (f == -1 && PyErr_Occurred()) { /* Parsed key not a number. */
566 PyErr_SetString(PyExc_TypeError,
567 "BMDeformVert[key] = x: "
568 "assigned value not a number");
569 return -1;
570 }
571
572 dw->weight = clamp_f(f, 0.0f, 1.0f);
573 }
574 else {
575 /* Handle `del dvert[group_index]`. */
577
578 if (dw == nullptr) {
579 PyErr_SetString(PyExc_KeyError,
580 "del BMDeformVert[key]: "
581 "key not found");
582 }
584 }
585
586 return 0;
587 }
588
589 PyErr_Format(
590 PyExc_TypeError, "BMDeformVert keys must be integers, not %.200s", Py_TYPE(key)->tp_name);
591 return -1;
592}
593
595{
596 const int key = PyLong_AsSsize_t(value);
597
598 if (key == -1 && PyErr_Occurred()) {
599 PyErr_SetString(PyExc_TypeError, "BMDeformVert.__contains__: expected an int");
600 return -1;
601 }
602
603 return (BKE_defvert_find_index(self->data, key) != nullptr) ? 1 : 0;
604}
605
606/* only defined for __contains__ */
607static PySequenceMethods bpy_bmdeformvert_as_sequence = {
608 /*sq_length*/ (lenfunc)bpy_bmdeformvert_len,
609 /*sq_concat*/ nullptr,
610 /*sq_repeat*/ nullptr,
611 /* NOTE: if this is set #PySequence_Check() returns True,
612 * but in this case we don't want to be treated as a seq. */
613 /*sq_item*/ nullptr,
614 /*was_sq_slice*/ nullptr, /* DEPRECATED. */
615 /*sq_ass_item*/ nullptr,
616 /*was_sq_ass_slice*/ nullptr, /* DEPRECATED. */
617 /*sq_contains*/ (objobjproc)bpy_bmdeformvert_contains,
618 /*sq_inplace_concat*/ nullptr,
619 /*sq_inplace_repeat*/ nullptr,
620};
621
622static PyMappingMethods bpy_bmdeformvert_as_mapping = {
623 /*mp_length*/ (lenfunc)bpy_bmdeformvert_len,
624 /*mp_subscript*/ (binaryfunc)bpy_bmdeformvert_subscript,
625 /*mp_ass_subscript*/ (objobjargproc)bpy_bmdeformvert_ass_subscript,
626};
627
628/* Methods
629 * ======= */
630
632 /* Wrap. */
633 bpy_bmdeformvert_keys_doc,
634 ".. method:: keys()\n"
635 "\n"
636 " Return the group indices used by this vertex\n"
637 " (matching Python's dict.keys() functionality).\n"
638 "\n"
639 " :return: the deform group this vertex uses\n"
640 " :rtype: list[int]\n");
642{
643 PyObject *ret;
644 int i;
645 MDeformWeight *dw = self->data->dw;
646
647 ret = PyList_New(self->data->totweight);
648 for (i = 0; i < self->data->totweight; i++, dw++) {
649 PyList_SET_ITEM(ret, i, PyLong_FromLong(dw->def_nr));
650 }
651
652 return ret;
653}
654
656 /* Wrap. */
657 bpy_bmdeformvert_values_doc,
658 ".. method:: values()\n"
659 "\n"
660 " Return the weights of the deform vertex\n"
661 " (matching Python's dict.values() functionality).\n"
662 "\n"
663 " :return: The weights that influence this vertex\n"
664 " :rtype: list[float]\n");
666{
667 PyObject *ret;
668 int i;
669 MDeformWeight *dw = self->data->dw;
670
671 ret = PyList_New(self->data->totweight);
672 for (i = 0; i < self->data->totweight; i++, dw++) {
673 PyList_SET_ITEM(ret, i, PyFloat_FromDouble(dw->weight));
674 }
675
676 return ret;
677}
678
680 /* Wrap. */
681 bpy_bmdeformvert_items_doc,
682 ".. method:: items()\n"
683 "\n"
684 " Return (group, weight) pairs for this vertex\n"
685 " (matching Python's dict.items() functionality).\n"
686 "\n"
687 " :return: (key, value) pairs for each deform weight of this vertex.\n"
688 " :rtype: list[tuple[int, float]]\n");
690{
691 PyObject *ret;
692 PyObject *item;
693 int i;
694 MDeformWeight *dw = self->data->dw;
695
696 ret = PyList_New(self->data->totweight);
697 for (i = 0; i < self->data->totweight; i++, dw++) {
698 item = PyTuple_New(2);
699 PyTuple_SET_ITEMS(item, PyLong_FromLong(dw->def_nr), PyFloat_FromDouble(dw->weight));
700 PyList_SET_ITEM(ret, i, item);
701 }
702
703 return ret;
704}
705
707 /* Wrap. */
708 bpy_bmdeformvert_get_doc,
709 ".. method:: get(key, default=None)\n"
710 "\n"
711 " Returns the deform weight matching the key or default\n"
712 " when not found (matches Python's dictionary function of the same name).\n"
713 "\n"
714 " :arg key: The key associated with deform weight.\n"
715 " :type key: int\n"
716 " :arg default: Optional argument for the value to return if\n"
717 " *key* is not found.\n"
718 " :type default: Any\n");
719static PyObject *bpy_bmdeformvert_get(BPy_BMDeformVert *self, PyObject *args)
720{
721 int key;
722 PyObject *def = Py_None;
723
724 if (!PyArg_ParseTuple(args, "i|O:get", &key, &def)) {
725 return nullptr;
726 }
727
728 MDeformWeight *dw = BKE_defvert_find_index(self->data, key);
729
730 if (dw) {
731 return PyFloat_FromDouble(dw->weight);
732 }
733
734 return Py_NewRef(def);
735}
736
738 /* Wrap. */
739 bpy_bmdeformvert_clear_doc,
740 ".. method:: clear()\n"
741 "\n"
742 " Clears all weights.\n");
744{
745 BKE_defvert_clear(self->data);
746
747 Py_RETURN_NONE;
748}
749
750#if (defined(__GNUC__) && !defined(__clang__))
751# pragma GCC diagnostic push
752# pragma GCC diagnostic ignored "-Wcast-function-type"
753#endif
754
755static PyMethodDef bpy_bmdeformvert_methods[] = {
756 {"keys", (PyCFunction)bpy_bmdeformvert_keys, METH_NOARGS, bpy_bmdeformvert_keys_doc},
757 {"values", (PyCFunction)bpy_bmdeformvert_values, METH_NOARGS, bpy_bmdeformvert_values_doc},
758 {"items", (PyCFunction)bpy_bmdeformvert_items, METH_NOARGS, bpy_bmdeformvert_items_doc},
759 {"get", (PyCFunction)bpy_bmdeformvert_get, METH_VARARGS, bpy_bmdeformvert_get_doc},
760 /* BMESH_TODO `pop`, `popitem`, `update`. */
761 {"clear", (PyCFunction)bpy_bmdeformvert_clear, METH_NOARGS, bpy_bmdeformvert_clear_doc},
762 {nullptr, nullptr, 0, nullptr},
763};
764
765#if (defined(__GNUC__) && !defined(__clang__))
766# pragma GCC diagnostic pop
767#endif
768
769PyTypeObject BPy_BMDeformVert_Type; /* bm.loops.layers.uv.active */
770
772{
773 BPy_BMDeformVert_Type.tp_basicsize = sizeof(BPy_BMDeformVert);
774
775 BPy_BMDeformVert_Type.tp_name = "BMDeformVert";
776
777 BPy_BMDeformVert_Type.tp_doc = nullptr; /* todo */
778
781
783
784 BPy_BMDeformVert_Type.tp_flags = Py_TPFLAGS_DEFAULT;
785
786 PyType_Ready(&BPy_BMDeformVert_Type);
787}
788
790{
791 if (UNLIKELY(!BPy_BMDeformVert_Check(value))) {
792 PyErr_Format(PyExc_TypeError, "expected BMDeformVert, not a %.200s", Py_TYPE(value)->tp_name);
793 return -1;
794 }
795
796 MDeformVert *dvert_src = ((BPy_BMDeformVert *)value)->data;
797 if (LIKELY(dvert != dvert_src)) {
798 BKE_defvert_copy(dvert, dvert_src);
799 }
800 return 0;
801}
802
804{
806 self->data = dvert;
807 return (PyObject *)self;
808}
809
810/* --- End Mesh Deform Vert --- */
811
CustomData interface, see also DNA_customdata_types.h.
support for deformation groups and hooks.
MDeformWeight * BKE_defvert_ensure_index(MDeformVert *dv, int defgroup)
Definition deform.cc:814
MDeformWeight * BKE_defvert_find_index(const MDeformVert *dv, int defgroup)
Definition deform.cc:795
void BKE_defvert_clear(MDeformVert *dvert)
Definition deform.cc:904
void BKE_defvert_copy(MDeformVert *dvert_dst, const MDeformVert *dvert_src)
Definition deform.cc:130
void BKE_defvert_remove_group(MDeformVert *dvert, MDeformWeight *dw)
Definition deform.cc:871
#define BLI_assert(a)
Definition BLI_assert.h:50
MINLINE float clamp_f(float value, float min, float max)
void rgba_uchar_to_float(float r_col[4], const unsigned char col_ub[4])
void rgba_float_to_uchar(unsigned char r_col[4], const float col_f[4])
MINLINE void copy_v2_v2(float r[2], const float a[2])
unsigned char uchar
#define POINTER_AS_INT(i)
#define UNLIKELY(x)
#define LIKELY(x)
@ MVERT_SKIN_LOOSE
@ MVERT_SKIN_ROOT
#define BM_ELEM_CD_GET_FLOAT_P(ele, offset)
#define BM_ELEM_CD_SET_BOOL(ele, offset, f)
#define BM_ELEM_CD_GET_BOOL_P(ele, offset)
ATTR_WARN_UNUSED_RESULT BMesh * bm
static PyObject * bpy_bmdeformvert_items(BPy_BMDeformVert *self)
static int bpy_bmloopuv_uv_set(BPy_BMLoopUV *self, PyObject *value, void *)
static PySequenceMethods bpy_bmdeformvert_as_sequence
static int mathutils_bmloopcol_set(BaseMathObject *bmo, int)
int BPy_BMVertSkin_AssignPyObject(MVertSkin *mvertskin, PyObject *value)
static PyObject * bpy_bmdeformvert_clear(BPy_BMDeformVert *self)
static void bm_init_types_bmloopuv()
static PyObject * bpy_bmloopuv_pin_uv_get(BPy_BMLoopUV *self, void *)
static int bpy_bmvertskin_flag_set(BPy_BMVertSkin *self, PyObject *value, void *flag_p)
static PyObject * bpy_bmdeformvert_subscript(BPy_BMDeformVert *self, PyObject *key)
static void mloopcol_to_float(const MLoopCol *mloopcol, float r_col[4])
static PyObject * bpy_bmvertskin_flag_get(BPy_BMVertSkin *self, void *flag_p)
static PyObject * bpy_bmloopuv_select_edge_get(BPy_BMLoopUV *self, void *)
static PyMethodDef bpy_bmdeformvert_methods[]
static PyObject * bpy_bmloopuv_select_get(BPy_BMLoopUV *self, void *)
PyObject * BPy_BMDeformVert_CreatePyObject(MDeformVert *dvert)
static int bpy_bmloopuv_pin_uv_set(BPy_BMLoopUV *self, PyObject *value, void *)
static PyObject * bpy_bmdeformvert_keys(BPy_BMDeformVert *self)
#define MLOOPCOL_FROM_CAPSULE(color_capsule)
static PyObject * bpy_bmdeformvert_get(BPy_BMDeformVert *self, PyObject *args)
int BPy_BMDeformVert_AssignPyObject(MDeformVert *dvert, PyObject *value)
static void bm_init_types_bmdvert()
void BPy_BM_init_types_meshdata()
PyObject * BPy_BMLoopColor_CreatePyObject(MLoopCol *mloopcol)
static int mathutils_bmloopcol_get_index(BaseMathObject *bmo, int subtype, int)
static int mathutils_bmloopcol_set_index(BaseMathObject *bmo, int subtype, int index)
static Mathutils_Callback mathutils_bmloopcol_cb
static int bpy_bmloopuv_select_set(BPy_BMLoopUV *self, PyObject *value, void *)
static PyObject * bpy_bmvertskin_radius_get(BPy_BMVertSkin *self, void *)
static PyGetSetDef bpy_bmloopuv_getseters[]
static void bm_init_types_bmvertskin()
static int mathutils_bmloopcol_get(BaseMathObject *bmo, int)
PyObject * BPy_BMLoopUV_CreatePyObject(BMesh *bm, BMLoop *loop, int layer)
static PyObject * bpy_bmloopuv_uv_get(BPy_BMLoopUV *self, void *)
static int bpy_bmdeformvert_contains(BPy_BMDeformVert *self, PyObject *value)
static int bpy_bmdeformvert_ass_subscript(BPy_BMDeformVert *self, PyObject *key, PyObject *value)
PyTypeObject BPy_BMDeformVert_Type
PyDoc_STRVAR(bpy_bmloopuv_uv_doc, "Loops UV (as a 2D Vector).\n" "\n" ":type: :class:`mathutils.Vector`")
static PyGetSetDef bpy_bmvertskin_getseters[]
static PyObject * bpy_bmdeformvert_values(BPy_BMDeformVert *self)
#define BPy_BMVertSkin_Check(v)
static int bpy_bmvertskin_radius_set(BPy_BMVertSkin *self, PyObject *value, void *)
static void mloopcol_from_float(MLoopCol *mloopcol, const float col[4])
#define BPy_BMDeformVert_Check(v)
int BPy_BMLoopColor_AssignPyObject(MLoopCol *mloopcol, PyObject *value)
static uchar mathutils_bmloopcol_cb_index
static void bm_init_types_bmloopcol()
int BPy_BMLoopUV_AssignPyObject(BMesh *bm, BMLoop *loop, PyObject *value)
static int bpy_bmloopuv_select_edge_set(BPy_BMLoopUV *self, PyObject *value, void *)
static Py_ssize_t bpy_bmdeformvert_len(BPy_BMDeformVert *self)
PyTypeObject BPy_BMLoopUV_Type
static int mathutils_bmloopcol_check(BaseMathObject *)
PyObject * BPy_BMVertSkin_CreatePyObject(MVertSkin *mvertskin)
#define BPy_BMLoopUV_Check(v)
static PyMappingMethods bpy_bmdeformvert_as_mapping
static PyTypeObject BPy_BMVertSkin_Type
BMUVOffsets BM_uv_map_get_offsets_from_layer(const BMesh *bm, const int layer)
BMUVOffsets BM_uv_map_get_offsets(const BMesh *bm)
PyObject * self
uint col
int mathutils_array_parse(float *array, int array_num_min, int array_num_max, PyObject *value, const char *error_prefix)
Definition mathutils.cc:97
uchar Mathutils_RegisterCallback(Mathutils_Callback *cb)
Definition mathutils.cc:522
PyObject * Vector_CreatePyObject_cb(PyObject *cb_user, int vec_num, uchar cb_type, uchar cb_subtype)
PyObject * Vector_CreatePyObject_wrap(float *vec, const int vec_num, PyTypeObject *base_type)
int PyC_Long_AsBool(PyObject *value)
header-only utilities
#define PyTuple_SET_ITEMS(op_arg,...)
return ret
PyObject_VAR_HEAD MDeformVert * data
PyObject_VAR_HEAD float * uv
PyObject_VAR_HEAD MVertSkin * data
unsigned int def_nr
unsigned char r
uint8_t flag
Definition wm_window.cc:138