Blender V4.3
bmesh_py_types_customdata.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
12#include <Python.h>
13
14#include "BLI_math_vector.h"
15#include "BLI_utildefines.h"
16
17#include "bmesh.hh"
18
19#include "bmesh_py_types.hh"
22
26
27#include "BKE_customdata.hh"
28
29#include "DNA_meshdata_types.h"
30
32{
33 switch (htype) {
34 case BM_VERT:
35 return &bm->vdata;
36 case BM_EDGE:
37 return &bm->edata;
38 case BM_FACE:
39 return &bm->pdata;
40 case BM_LOOP:
41 return &bm->ldata;
42 }
43
45 return nullptr;
46}
47
49{
50 CustomData *data = bpy_bm_customdata_get(self->bm, self->htype);
51 const int index_absolute = CustomData_get_layer_index_n(
52 data, eCustomDataType(self->type), self->index);
53 if (index_absolute != -1) {
54 return &data->layers[index_absolute];
55 }
56
57 PyErr_SetString(PyExc_RuntimeError, "layer has become invalid");
58 return nullptr;
59}
60
61/* py-type definitions
62 * ******************* */
63
64/* getseters
65 * ========= */
66
67/* used for many different types. */
68
70 /* Wrap. */
71 bpy_bmlayeraccess_collection__float_doc,
72 "Generic float custom-data layer.\n"
73 "\n"
74 ":type: :class:`BMLayerCollection` of float");
76 /* Wrap. */
77 bpy_bmlayeraccess_collection__int_doc,
78 "Generic int custom-data layer.\n"
79 "\n"
80 ":type: :class:`BMLayerCollection` of int");
82 /* Wrap. */
83 bpy_bmlayeraccess_collection__float_vector_doc,
84 "Generic 3D vector with float precision custom-data layer.\n"
85 "\n"
86 ":type: "
87 ":class:`BMLayerCollection` of :class:`mathutils.Vector`");
89 /* Wrap. */
90 bpy_bmlayeraccess_collection__float_color_doc,
91 "Generic RGBA color with float precision custom-data layer.\n"
92 "\n"
93 ":type: "
94 ":class:`BMLayerCollection` of :class:`mathutils.Vector`");
96 /* Wrap. */
97 bpy_bmlayeraccess_collection__color_doc,
98 "Generic RGBA color with 8-bit precision custom-data layer.\n"
99 "\n"
100 ":type: "
101 ":class:`BMLayerCollection` of :class:`mathutils.Vector`");
103 /* Wrap. */
104 bpy_bmlayeraccess_collection__string_doc,
105 "Generic string custom-data layer (exposed as bytes, 255 max length).\n"
106 "\n"
107 ":type: "
108 ":class:`BMLayerCollection` of bytes");
110 /* Wrap. */
111 bpy_bmlayeraccess_collection__deform_doc,
112 "Vertex deform weight :class:`BMDeformVert` (TODO).\n"
113 "\n"
114 ":type: "
115 ":class:`BMLayerCollection` of :class:`bmesh.types.BMDeformVert`" /* TYPE DOESN'T EXIST YET */
116);
118 /* Wrap. */
119 bpy_bmlayeraccess_collection__shape_doc,
120 "Vertex shapekey absolute location (as a 3D Vector).\n"
121 "\n"
122 ":type: :class:`BMLayerCollection` of :class:`mathutils.Vector`");
124 /* Wrap. */
125 bpy_bmlayeraccess_collection__uv_doc,
126 "Accessor for :class:`BMLoopUV` UV (as a 2D Vector).\n"
127 "\n"
128 ":type: :class:`BMLayerCollection` of :class:`bmesh.types.BMLoopUV`");
130 /* Wrap. */
131 bpy_bmlayeraccess_collection__skin_doc,
132 "Accessor for skin layer.\n"
133 "\n"
134 ":type: :class:`BMLayerCollection` of :class:`bmesh.types.BMVertSkin`");
135#ifdef WITH_FREESTYLE
137 /* Wrap. */
138 bpy_bmlayeraccess_collection__freestyle_edge_doc,
139 "Accessor for Freestyle edge layer.\n"
140 "\n"
141 ":type: :class:`BMLayerCollection`");
143 /* Wrap. */
144 bpy_bmlayeraccess_collection__freestyle_face_doc,
145 "Accessor for Freestyle face layer.\n"
146 "\n"
147 ":type: :class:`BMLayerCollection`");
148#endif
149
151{
152 const int type = int(POINTER_AS_INT(flag));
153
155
156 return BPy_BMLayerCollection_CreatePyObject(self->bm, self->htype, type);
157}
158
160 /* Wrap. */
161 bpy_bmlayercollection_active_doc,
162 "The active layer of this type (read-only).\n"
163 "\n"
164 ":type: :class:`BMLayerItem`");
165static PyObject *bpy_bmlayercollection_active_get(BPy_BMLayerItem *self, void * /*flag*/)
166{
168 int index;
169
171
172 data = bpy_bm_customdata_get(self->bm, self->htype);
173 index = CustomData_get_active_layer(data, eCustomDataType(self->type)); /* type relative */
174
175 if (index != -1) {
176 return BPy_BMLayerItem_CreatePyObject(self->bm, self->htype, self->type, index);
177 }
178
179 Py_RETURN_NONE;
180}
181
182PyDoc_STRVAR(bpy_bmlayercollection_is_singleton_doc,
183 "True if there can exists only one layer of this type (read-only).\n"
184 "\n"
185 ":type: bool");
187{
189
190 return PyBool_FromLong(CustomData_layertype_is_singleton(eCustomDataType(self->type)));
191}
192
194 /* Wrap. */
195 bpy_bmlayercollection_name_doc,
196 "The layers unique name (read-only).\n"
197 "\n"
198 ":type: str");
199static PyObject *bpy_bmlayeritem_name_get(BPy_BMLayerItem *self, void * /*flag*/)
200{
201 CustomDataLayer *layer;
202
204
205 layer = bpy_bmlayeritem_get(self);
206 if (layer) {
207 return PyUnicode_FromString(layer->name);
208 }
209
210 return nullptr;
211}
212
213static PyGetSetDef bpy_bmlayeraccess_vert_getseters[] = {
214 {"deform",
216 (setter) nullptr,
217 bpy_bmlayeraccess_collection__deform_doc,
218 (void *)CD_MDEFORMVERT},
219
220 {"float",
222 (setter) nullptr,
223 bpy_bmlayeraccess_collection__float_doc,
224 (void *)CD_PROP_FLOAT},
225 {"int",
227 (setter) nullptr,
228 bpy_bmlayeraccess_collection__int_doc,
229 (void *)CD_PROP_INT32},
230 {"float_vector",
232 (setter) nullptr,
233 bpy_bmlayeraccess_collection__float_vector_doc,
234 (void *)CD_PROP_FLOAT3},
235 {"float_color",
237 (setter) nullptr,
238 bpy_bmlayeraccess_collection__float_color_doc,
239 (void *)CD_PROP_COLOR},
240 {"color",
242 (setter) nullptr,
243 bpy_bmlayeraccess_collection__color_doc,
244 (void *)CD_PROP_BYTE_COLOR},
245 {"string",
247 (setter) nullptr,
248 bpy_bmlayeraccess_collection__string_doc,
249 (void *)CD_PROP_STRING},
250
251 {"shape",
253 (setter) nullptr,
254 bpy_bmlayeraccess_collection__shape_doc,
255 (void *)CD_SHAPEKEY},
256 {"skin",
258 (setter) nullptr,
259 bpy_bmlayeraccess_collection__skin_doc,
260 (void *)CD_MVERT_SKIN},
261
262 {nullptr, nullptr, nullptr, nullptr, nullptr} /* Sentinel */
263};
264
265static PyGetSetDef bpy_bmlayeraccess_edge_getseters[] = {
266 {"float",
268 (setter) nullptr,
269 bpy_bmlayeraccess_collection__float_doc,
270 (void *)CD_PROP_FLOAT},
271 {"int",
273 (setter) nullptr,
274 bpy_bmlayeraccess_collection__int_doc,
275 (void *)CD_PROP_INT32},
276 {"float_vector",
278 (setter) nullptr,
279 bpy_bmlayeraccess_collection__float_vector_doc,
280 (void *)CD_PROP_FLOAT3},
281 {"float_color",
283 (setter) nullptr,
284 bpy_bmlayeraccess_collection__float_color_doc,
285 (void *)CD_PROP_COLOR},
286 {"color",
288 (setter) nullptr,
289 bpy_bmlayeraccess_collection__color_doc,
290 (void *)CD_PROP_BYTE_COLOR},
291 {"string",
293 (setter) nullptr,
294 bpy_bmlayeraccess_collection__string_doc,
295 (void *)CD_PROP_STRING},
296#ifdef WITH_FREESTYLE
297 {"freestyle",
299 (setter) nullptr,
300 bpy_bmlayeraccess_collection__freestyle_edge_doc,
301 (void *)CD_FREESTYLE_EDGE},
302#endif
303 {nullptr, nullptr, nullptr, nullptr, nullptr} /* Sentinel */
304};
305
306static PyGetSetDef bpy_bmlayeraccess_face_getseters[] = {
307 {"float",
309 (setter) nullptr,
310 bpy_bmlayeraccess_collection__float_doc,
311 (void *)CD_PROP_FLOAT},
312 {"int",
314 (setter) nullptr,
315 bpy_bmlayeraccess_collection__int_doc,
316 (void *)CD_PROP_INT32},
317 {"float_vector",
319 (setter) nullptr,
320 bpy_bmlayeraccess_collection__float_vector_doc,
321 (void *)CD_PROP_FLOAT3},
322 {"float_color",
324 (setter) nullptr,
325 bpy_bmlayeraccess_collection__float_color_doc,
326 (void *)CD_PROP_COLOR},
327 {"color",
329 (setter) nullptr,
330 bpy_bmlayeraccess_collection__color_doc,
331 (void *)CD_PROP_BYTE_COLOR},
332 {"string",
334 (setter) nullptr,
335 bpy_bmlayeraccess_collection__string_doc,
336 (void *)CD_PROP_STRING},
337
338#ifdef WITH_FREESTYLE
339 {"freestyle",
341 (setter) nullptr,
342 bpy_bmlayeraccess_collection__freestyle_face_doc,
343 (void *)CD_FREESTYLE_FACE},
344#endif
345
346 {nullptr, nullptr, nullptr, nullptr, nullptr} /* Sentinel */
347};
348
349static PyGetSetDef bpy_bmlayeraccess_loop_getseters[] = {
350 {"float",
352 (setter) nullptr,
353 bpy_bmlayeraccess_collection__float_doc,
354 (void *)CD_PROP_FLOAT},
355 {"int",
357 (setter) nullptr,
358 bpy_bmlayeraccess_collection__int_doc,
359 (void *)CD_PROP_INT32},
360 {"float_vector",
362 (setter) nullptr,
363 bpy_bmlayeraccess_collection__float_vector_doc,
364 (void *)CD_PROP_FLOAT3},
365 {"float_color",
367 (setter) nullptr,
368 bpy_bmlayeraccess_collection__float_color_doc,
369 (void *)CD_PROP_COLOR},
370 {"string",
372 (setter) nullptr,
373 bpy_bmlayeraccess_collection__string_doc,
374 (void *)CD_PROP_STRING},
375 {"uv",
377 (setter) nullptr,
378 bpy_bmlayeraccess_collection__uv_doc,
379 (void *)CD_PROP_FLOAT2},
380 {"color",
382 (setter) nullptr,
383 bpy_bmlayeraccess_collection__color_doc,
384 (void *)CD_PROP_BYTE_COLOR},
385
386 {nullptr, nullptr, nullptr, nullptr, nullptr} /* Sentinel */
387};
388
389static PyGetSetDef bpy_bmlayercollection_getseters[] = {
390 /* BMESH_TODO, make writeable */
391 {"active",
393 (setter) nullptr,
394 bpy_bmlayercollection_active_doc,
395 nullptr},
396 {"is_singleton",
398 (setter) nullptr,
399 bpy_bmlayercollection_is_singleton_doc,
400 nullptr},
401
402 {nullptr, nullptr, nullptr, nullptr, nullptr} /* Sentinel */
403};
404
405static PyGetSetDef bpy_bmlayeritem_getseters[] = {
406 /* BMESH_TODO, make writeable */
407 {"name",
409 (setter) nullptr,
410 bpy_bmlayercollection_name_doc,
411 nullptr},
412
413 {nullptr, nullptr, nullptr, nullptr, nullptr} /* Sentinel */
414};
415
416/* Methods
417 * ======= */
418
419/* BMLayerCollection
420 * ----------------- */
421
423 /* Wrap. */
424 bpy_bmlayeritem_copy_from_doc,
425 ".. method:: copy_from(other)\n"
426 "\n"
427 " Return a copy of the layer\n"
428 "\n"
429 " :arg other: Another layer to copy from.\n"
430 " :type other: :class:`BMLayerItem`\n");
432{
434
435 if (!BPy_BMLayerItem_Check(value)) {
436 PyErr_Format(PyExc_TypeError,
437 "layer.copy_from(x): expected BMLayerItem, not '%.200s'",
438 Py_TYPE(value)->tp_name);
439 return nullptr;
440 }
441
443 BPY_BM_CHECK_SOURCE_OBJ(self->bm, "layer.copy_from()", value);
444
445 if ((self->htype != value->htype) || (self->type != value->type)) {
446 PyErr_SetString(PyExc_ValueError, "layer.copy_from(other): layer type mismatch");
447 }
448
449 else if (self->index == value->index) {
450 Py_RETURN_NONE;
451 }
452
453 data = bpy_bm_customdata_get(self->bm, self->htype);
454
455 if ((bpy_bmlayeritem_get(self) == nullptr) || (bpy_bmlayeritem_get(value) == nullptr)) {
456 return nullptr;
457 }
458
459 BM_data_layer_copy(self->bm, data, self->type, value->index, self->index);
460
461 Py_RETURN_NONE;
462}
463
464/* similar to new(), but no name arg. */
466 /* Wrap. */
467 bpy_bmlayercollection_verify_doc,
468 ".. method:: verify()\n"
469 "\n"
470 " Create a new layer or return an existing active layer\n"
471 "\n"
472 " :return: The newly verified layer.\n"
473 " :rtype: :class:`BMLayerItem`\n");
475{
476 int index;
478
480
481 data = bpy_bm_customdata_get(self->bm, self->htype);
482
483 index = CustomData_get_active_layer(data, eCustomDataType(self->type)); /* type relative */
484
485 if (index == -1) {
486 BM_data_layer_add(self->bm, data, self->type);
487 index = 0;
488 }
489 if (self->type == CD_PROP_FLOAT2 && self->htype == BM_LOOP) {
490 /* Because adding CustomData layers to a bmesh will invalidate any existing pointers
491 * in Py objects we can't lazily add the associated bool layers. So add them all right
492 * now. */
494 }
495
496 BLI_assert(index >= 0);
497
498 return BPy_BMLayerItem_CreatePyObject(self->bm, self->htype, self->type, index);
499}
500
502 /* Wrap. */
503 bpy_bmlayercollection_new_doc,
504 ".. method:: new(name)\n"
505 "\n"
506 " Create a new layer\n"
507 "\n"
508 " :arg name: Optional name argument (will be made unique).\n"
509 " :type name: str\n"
510 " :return: The newly created layer.\n"
511 " :rtype: :class:`BMLayerItem`\n");
512static PyObject *bpy_bmlayercollection_new(BPy_BMLayerCollection *self, PyObject *args)
513{
514 const char *name = nullptr;
515 int index;
517
519
520 if (!PyArg_ParseTuple(args, "|s:new", &name)) {
521 return nullptr;
522 }
523
524 data = bpy_bm_customdata_get(self->bm, self->htype);
525
528 {
529 PyErr_SetString(PyExc_ValueError, "layers.new(): is a singleton, use verify() instead");
530 return nullptr;
531 }
532
533 if (name) {
534 BM_data_layer_add_named(self->bm, data, self->type, name);
535 }
536 else {
537 BM_data_layer_add(self->bm, data, self->type);
538 }
539
540 if (self->type == CD_PROP_FLOAT2 && self->htype == BM_LOOP) {
541 /* Because adding CustomData layers to a bmesh will invalidate any existing pointers
542 * in Py objects we can't lazily add the associated bool layers. So add them all right
543 * now. */
545 }
546
547 index = CustomData_number_of_layers(data, eCustomDataType(self->type)) - 1;
548 BLI_assert(index >= 0);
549
550 return BPy_BMLayerItem_CreatePyObject(self->bm, self->htype, self->type, index);
551}
552
554 /* Wrap. */
555 bpy_bmlayercollection_remove_doc,
556 ".. method:: remove(layer)\n"
557 "\n"
558 " Remove a layer\n"
559 "\n"
560 " :arg layer: The layer to remove.\n"
561 " :type layer: :class:`BMLayerItem`\n");
563{
565
567
568 if (!BPy_BMLayerItem_Check(value)) {
569 PyErr_Format(PyExc_TypeError,
570 "layers.remove(x): expected BMLayerItem, not '%.200s'",
571 Py_TYPE(value)->tp_name);
572 return nullptr;
573 }
574
575 BPY_BM_CHECK_OBJ(value);
576
577 if ((self->bm != value->bm) || (self->type != value->type) || (self->htype != value->htype)) {
578 PyErr_SetString(PyExc_ValueError, "layers.remove(x): x not in layers");
579 }
580
581 data = bpy_bm_customdata_get(self->bm, self->htype);
582 BM_data_layer_free_n(self->bm, data, self->type, value->index);
583
584 Py_RETURN_NONE;
585}
586
588 /* Wrap. */
589 bpy_bmlayercollection_keys_doc,
590 ".. method:: keys()\n"
591 "\n"
592 " Return the identifiers of collection members\n"
593 " (matching Python's dict.keys() functionality).\n"
594 "\n"
595 " :return: the identifiers for each member of this collection.\n"
596 " :rtype: list[str]\n");
598{
599 PyObject *ret;
600 PyObject *item;
601 int index;
603 int tot, i;
604
606
607 data = bpy_bm_customdata_get(self->bm, self->htype);
608
609 /* Absolute, but no need to make relative. */
610 index = CustomData_get_layer_index(data, eCustomDataType(self->type));
611
612 tot = (index != -1) ? CustomData_number_of_layers(data, eCustomDataType(self->type)) : 0;
613
614 ret = PyList_New(tot);
615
616 for (i = 0; tot-- > 0; index++) {
617 item = PyUnicode_FromString(data->layers[index].name);
618 PyList_SET_ITEM(ret, i++, item);
619 }
620
621 return ret;
622}
623
625 /* Wrap. */
626 bpy_bmlayercollection_items_doc,
627 ".. method:: items()\n"
628 "\n"
629 " Return the identifiers of collection members\n"
630 " (matching Python's dict.items() functionality).\n"
631 "\n"
632 " :return: (key, value) pairs for each member of this collection.\n"
633 " :rtype: list[tuple[str, :class:`BMLayerItem`]]\n");
635{
636 PyObject *ret;
637 PyObject *item;
638 int index;
640 int tot, i;
641
643
644 data = bpy_bm_customdata_get(self->bm, self->htype);
645 index = CustomData_get_layer_index(data, eCustomDataType(self->type));
646 tot = (index != -1) ? CustomData_number_of_layers(data, eCustomDataType(self->type)) : 0;
647
648 ret = PyList_New(tot);
649
650 for (i = 0; tot-- > 0; index++) {
651 item = PyTuple_New(2);
653 PyUnicode_FromString(data->layers[index].name),
654 BPy_BMLayerItem_CreatePyObject(self->bm, self->htype, self->type, i));
655 PyList_SET_ITEM(ret, i++, item);
656 }
657
658 return ret;
659}
660
662 /* Wrap. */
663 bpy_bmlayercollection_values_doc,
664 ".. method:: values()\n"
665 "\n"
666 " Return the values of collection\n"
667 " (matching Python's dict.values() functionality).\n"
668 "\n"
669 " :return: the members of this collection.\n"
670 " :rtype: list[:class:`BMLayerItem`]\n");
672{
673 PyObject *ret;
674 PyObject *item;
675 int index;
677 int tot, i;
678
680
681 data = bpy_bm_customdata_get(self->bm, self->htype);
682 index = CustomData_get_layer_index(data, eCustomDataType(self->type));
683 tot = (index != -1) ? CustomData_number_of_layers(data, eCustomDataType(self->type)) : 0;
684
685 ret = PyList_New(tot);
686
687 for (i = 0; tot-- > 0; index++) {
688 item = BPy_BMLayerItem_CreatePyObject(self->bm, self->htype, self->type, i);
689 PyList_SET_ITEM(ret, i++, item);
690 }
691
692 return ret;
693}
694
696 /* Wrap. */
697 bpy_bmlayercollection_get_doc,
698 ".. method:: get(key, default=None)\n"
699 "\n"
700 " Returns the value of the layer matching the key or default\n"
701 " when not found (matches Python's dictionary function of the same name).\n"
702 "\n"
703 " :arg key: The key associated with the layer.\n"
704 " :type key: str\n"
705 " :arg default: Optional argument for the value to return if\n"
706 " *key* is not found.\n"
707 " :type default: Any\n");
708static PyObject *bpy_bmlayercollection_get(BPy_BMLayerCollection *self, PyObject *args)
709{
710 const char *key;
711 PyObject *def = Py_None;
712
714
715 if (!PyArg_ParseTuple(args, "s|O:get", &key, &def)) {
716 return nullptr;
717 }
718
720 int index;
721
722 data = bpy_bm_customdata_get(self->bm, self->htype);
723 index = CustomData_get_named_layer(data, eCustomDataType(self->type), key); /* type relative */
724
725 if (index != -1) {
726 return BPy_BMLayerItem_CreatePyObject(self->bm, self->htype, self->type, index);
727 }
728
729 return Py_NewRef(def);
730}
731
732static PyMethodDef bpy_bmlayeritem_methods[] = {
733 {"copy_from", (PyCFunction)bpy_bmlayeritem_copy_from, METH_O, bpy_bmlayeritem_copy_from_doc},
734 {nullptr, nullptr, 0, nullptr},
735};
736
737#if (defined(__GNUC__) && !defined(__clang__))
738# pragma GCC diagnostic push
739# pragma GCC diagnostic ignored "-Wcast-function-type"
740#endif
741
742static PyMethodDef bpy_bmelemseq_methods[] = {
743 {"verify",
744 (PyCFunction)bpy_bmlayercollection_verify,
745 METH_NOARGS,
746 bpy_bmlayercollection_verify_doc},
747 {"new", (PyCFunction)bpy_bmlayercollection_new, METH_VARARGS, bpy_bmlayercollection_new_doc},
748 {"remove",
749 (PyCFunction)bpy_bmlayercollection_remove,
750 METH_O,
751 bpy_bmlayercollection_remove_doc},
752
753 {"keys", (PyCFunction)bpy_bmlayercollection_keys, METH_NOARGS, bpy_bmlayercollection_keys_doc},
754 {"values",
755 (PyCFunction)bpy_bmlayercollection_values,
756 METH_NOARGS,
757 bpy_bmlayercollection_values_doc},
758 {"items",
759 (PyCFunction)bpy_bmlayercollection_items,
760 METH_NOARGS,
761 bpy_bmlayercollection_items_doc},
762 {"get", (PyCFunction)bpy_bmlayercollection_get, METH_VARARGS, bpy_bmlayercollection_get_doc},
763 {nullptr, nullptr, 0, nullptr},
764};
765
766#if (defined(__GNUC__) && !defined(__clang__))
767# pragma GCC diagnostic pop
768#endif
769
770/* Sequences
771 * ========= */
772
774{
776
778
779 data = bpy_bm_customdata_get(self->bm, self->htype);
780
782}
783
785 const char *keyname)
786{
788 int index;
789
791
792 data = bpy_bm_customdata_get(self->bm, self->htype);
794 data, eCustomDataType(self->type), keyname); /* type relative */
795
796 if (index != -1) {
797 return BPy_BMLayerItem_CreatePyObject(self->bm, self->htype, self->type, index);
798 }
799
800 PyErr_Format(PyExc_KeyError, "BMLayerCollection[key]: key \"%.200s\" not found", keyname);
801 return nullptr;
802}
803
805 Py_ssize_t keynum)
806{
807 Py_ssize_t len;
809
811
812 if (keynum < 0) {
813 keynum += len;
814 }
815 if (keynum >= 0) {
816 if (keynum < len) {
817 return BPy_BMLayerItem_CreatePyObject(self->bm, self->htype, self->type, keynum);
818 }
819 }
820
821 PyErr_Format(PyExc_IndexError, "BMLayerCollection[index]: index %d out of range", keynum);
822 return nullptr;
823}
824
826 Py_ssize_t start,
827 Py_ssize_t stop)
828{
829 const Py_ssize_t len = bpy_bmlayercollection_length(self);
830 int count = 0;
831
832 PyObject *tuple;
833
835
836 if (start > len) {
837 start = len;
838 }
839 if (stop > len) {
840 stop = len;
841 }
842
843 tuple = PyTuple_New(stop - start);
844
845 for (count = start; count < stop; count++) {
846 PyTuple_SET_ITEM(tuple,
847 count - start,
848 BPy_BMLayerItem_CreatePyObject(self->bm, self->htype, self->type, count));
849 }
850
851 return tuple;
852}
853
855{
856 /* don't need error check here */
857 if (PyUnicode_Check(key)) {
858 return bpy_bmlayercollection_subscript_str(self, PyUnicode_AsUTF8(key));
859 }
860 if (PyIndex_Check(key)) {
861 const Py_ssize_t i = PyNumber_AsSsize_t(key, PyExc_IndexError);
862 if (i == -1 && PyErr_Occurred()) {
863 return nullptr;
864 }
866 }
867 if (PySlice_Check(key)) {
868 PySliceObject *key_slice = (PySliceObject *)key;
869 Py_ssize_t step = 1;
870
871 if (key_slice->step != Py_None && !_PyEval_SliceIndex(key, &step)) {
872 return nullptr;
873 }
874 if (step != 1) {
875 PyErr_SetString(PyExc_TypeError, "BMLayerCollection[slice]: slice steps not supported");
876 return nullptr;
877 }
878 if (key_slice->start == Py_None && key_slice->stop == Py_None) {
879 return bpy_bmlayercollection_subscript_slice(self, 0, PY_SSIZE_T_MAX);
880 }
881
882 Py_ssize_t start = 0, stop = PY_SSIZE_T_MAX;
883
884 /* avoid PySlice_GetIndicesEx because it needs to know the length ahead of time. */
885 if (key_slice->start != Py_None && !_PyEval_SliceIndex(key_slice->start, &start)) {
886 return nullptr;
887 }
888 if (key_slice->stop != Py_None && !_PyEval_SliceIndex(key_slice->stop, &stop)) {
889 return nullptr;
890 }
891
892 if (start < 0 || stop < 0) {
893 /* only get the length for negative values */
894 const Py_ssize_t len = bpy_bmlayercollection_length(self);
895 if (start < 0) {
896 start += len;
897 CLAMP_MIN(start, 0);
898 }
899 if (stop < 0) {
900 stop += len;
901 CLAMP_MIN(stop, 0);
902 }
903 }
904
905 if (stop - start <= 0) {
906 return PyTuple_New(0);
907 }
908
909 return bpy_bmlayercollection_subscript_slice(self, start, stop);
910 }
911
912 PyErr_SetString(PyExc_AttributeError, "BMLayerCollection[key]: invalid key, key must be an int");
913 return nullptr;
914}
915
917{
918 const char *keyname = PyUnicode_AsUTF8(value);
920 int index;
921
923
924 if (keyname == nullptr) {
925 PyErr_SetString(PyExc_TypeError, "BMLayerCollection.__contains__: expected a string");
926 return -1;
927 }
928
929 data = bpy_bm_customdata_get(self->bm, self->htype);
930 index = CustomData_get_named_layer_index(data, eCustomDataType(self->type), keyname);
931
932 return (index != -1) ? 1 : 0;
933}
934
935static PySequenceMethods bpy_bmlayercollection_as_sequence = {
936 /*sq_length*/ (lenfunc)bpy_bmlayercollection_length,
937 /*sq_concat*/ nullptr,
938 /*sq_repeat*/ nullptr,
939 /* Only set this so `PySequence_Check()` returns True. */
940 /*sq_item*/ (ssizeargfunc)bpy_bmlayercollection_subscript_int,
941 /*was_sq_slice*/ nullptr, /* DEPRECATED. */
942 /*sq_ass_item*/ nullptr,
943 /*was_sq_ass_slice*/ nullptr, /* DEPRECATED. */
944 /*sq_contains*/ (objobjproc)bpy_bmlayercollection_contains,
945 /*sq_inplace_concat*/ nullptr,
946 /*sq_inplace_repeat*/ nullptr,
947};
948
949static PyMappingMethods bpy_bmlayercollection_as_mapping = {
950 /*mp_length*/ (lenfunc)bpy_bmlayercollection_length,
951 /*mp_subscript*/ (binaryfunc)bpy_bmlayercollection_subscript,
952 /*mp_ass_subscript*/ (objobjargproc) nullptr,
953};
954
955/* Iterator
956 * -------- */
957
959{
960 /* fake it with a list iterator */
961 PyObject *ret;
962 PyObject *iter = nullptr;
963
965
966 ret = bpy_bmlayercollection_subscript_slice(self, 0, PY_SSIZE_T_MAX);
967
968 if (ret) {
969 iter = PyObject_GetIter(ret);
970 Py_DECREF(ret);
971 }
972
973 return iter;
974}
975
977 /* Wrap. */
978 bpy_bmlayeraccess_type_doc,
979 "Exposes custom-data layer attributes.");
980
982 /* Wrap. */
983 bpy_bmlayercollection_type_doc,
984 "Gives access to a collection of custom-data layers of the same type and behaves "
985 "like Python dictionaries, "
986 "except for the ability to do list like index access.");
987
989 /* Wrap. */
990 bpy_bmlayeritem_type_doc,
991 "Exposes a single custom data layer, "
992 "their main purpose is for use as item accessors to custom-data when used with "
993 "vert/edge/face/loop data.");
994
995PyTypeObject BPy_BMLayerAccessVert_Type; /* bm.verts.layers */
996PyTypeObject BPy_BMLayerAccessEdge_Type; /* bm.edges.layers */
997PyTypeObject BPy_BMLayerAccessFace_Type; /* bm.faces.layers */
998PyTypeObject BPy_BMLayerAccessLoop_Type; /* bm.loops.layers */
999PyTypeObject BPy_BMLayerCollection_Type; /* bm.loops.layers.uv */
1000PyTypeObject BPy_BMLayerItem_Type; /* bm.loops.layers.uv["UVMap"] */
1001
1002PyObject *BPy_BMLayerAccess_CreatePyObject(BMesh *bm, const char htype)
1003{
1005 PyTypeObject *type;
1006
1007 switch (htype) {
1008 case BM_VERT:
1010 break;
1011 case BM_EDGE:
1013 break;
1014 case BM_FACE:
1016 break;
1017 case BM_LOOP:
1019 break;
1020 default: {
1022 type = nullptr;
1023 break;
1024 }
1025 }
1026
1027 self = PyObject_New(BPy_BMLayerAccess, type);
1028 self->bm = bm;
1029 self->htype = htype;
1030 return (PyObject *)self;
1031}
1032
1033PyObject *BPy_BMLayerCollection_CreatePyObject(BMesh *bm, const char htype, int type)
1034{
1036 self->bm = bm;
1037 self->htype = htype;
1038 self->type = type;
1039 return (PyObject *)self;
1040}
1041
1042PyObject *BPy_BMLayerItem_CreatePyObject(BMesh *bm, const char htype, int type, int index)
1043{
1045 self->bm = bm;
1046 self->htype = htype;
1047 self->type = type;
1048 self->index = index;
1049 return (PyObject *)self;
1050}
1051
1053{
1054 BPy_BMLayerAccessVert_Type.tp_basicsize = sizeof(BPy_BMLayerAccess);
1055 BPy_BMLayerAccessEdge_Type.tp_basicsize = sizeof(BPy_BMLayerAccess);
1056 BPy_BMLayerAccessFace_Type.tp_basicsize = sizeof(BPy_BMLayerAccess);
1057 BPy_BMLayerAccessLoop_Type.tp_basicsize = sizeof(BPy_BMLayerAccess);
1059 BPy_BMLayerItem_Type.tp_basicsize = sizeof(BPy_BMLayerItem);
1060
1061 BPy_BMLayerAccessVert_Type.tp_name = "BMLayerAccessVert";
1062 BPy_BMLayerAccessEdge_Type.tp_name = "BMLayerAccessEdge";
1063 BPy_BMLayerAccessFace_Type.tp_name = "BMLayerAccessFace";
1064 BPy_BMLayerAccessLoop_Type.tp_name = "BMLayerAccessLoop";
1065 BPy_BMLayerCollection_Type.tp_name = "BMLayerCollection";
1066 BPy_BMLayerItem_Type.tp_name = "BMLayerItem";
1067
1068 /* todo */
1069 BPy_BMLayerAccessVert_Type.tp_doc = bpy_bmlayeraccess_type_doc;
1070 BPy_BMLayerAccessEdge_Type.tp_doc = bpy_bmlayeraccess_type_doc;
1071 BPy_BMLayerAccessFace_Type.tp_doc = bpy_bmlayeraccess_type_doc;
1072 BPy_BMLayerAccessLoop_Type.tp_doc = bpy_bmlayeraccess_type_doc;
1073 BPy_BMLayerCollection_Type.tp_doc = bpy_bmlayercollection_type_doc;
1074 BPy_BMLayerItem_Type.tp_doc = bpy_bmlayeritem_type_doc;
1075
1076 BPy_BMLayerAccessVert_Type.tp_repr = (reprfunc) nullptr;
1077 BPy_BMLayerAccessEdge_Type.tp_repr = (reprfunc) nullptr;
1078 BPy_BMLayerAccessFace_Type.tp_repr = (reprfunc) nullptr;
1079 BPy_BMLayerAccessLoop_Type.tp_repr = (reprfunc) nullptr;
1080 BPy_BMLayerCollection_Type.tp_repr = (reprfunc) nullptr;
1081 BPy_BMLayerItem_Type.tp_repr = (reprfunc) nullptr;
1082
1089
1090 // BPy_BMLayerAccess_Type.tp_methods = bpy_bmeditselseq_methods;
1093
1095
1097
1099
1100 BPy_BMLayerAccessVert_Type.tp_dealloc = nullptr;
1101 BPy_BMLayerAccessEdge_Type.tp_dealloc = nullptr;
1102 BPy_BMLayerAccessFace_Type.tp_dealloc = nullptr;
1103 BPy_BMLayerAccessLoop_Type.tp_dealloc = nullptr;
1104 BPy_BMLayerCollection_Type.tp_dealloc = nullptr;
1105 BPy_BMLayerItem_Type.tp_dealloc = nullptr;
1106
1107 BPy_BMLayerAccessVert_Type.tp_flags = Py_TPFLAGS_DEFAULT;
1108 BPy_BMLayerAccessEdge_Type.tp_flags = Py_TPFLAGS_DEFAULT;
1109 BPy_BMLayerAccessFace_Type.tp_flags = Py_TPFLAGS_DEFAULT;
1110 BPy_BMLayerAccessLoop_Type.tp_flags = Py_TPFLAGS_DEFAULT;
1111 BPy_BMLayerCollection_Type.tp_flags = Py_TPFLAGS_DEFAULT;
1112 BPy_BMLayerItem_Type.tp_flags = Py_TPFLAGS_DEFAULT;
1113
1114 PyType_Ready(&BPy_BMLayerAccessVert_Type);
1115 PyType_Ready(&BPy_BMLayerAccessEdge_Type);
1116 PyType_Ready(&BPy_BMLayerAccessFace_Type);
1117 PyType_Ready(&BPy_BMLayerAccessLoop_Type);
1118 PyType_Ready(&BPy_BMLayerCollection_Type);
1119 PyType_Ready(&BPy_BMLayerItem_Type);
1120}
1121
1122/* Per Element Get/Set
1123 * ******************* */
1124
1129{
1130 void *value;
1131 BMElem *ele = py_ele->ele;
1133
1134 /* error checking */
1135 if (UNLIKELY(!BPy_BMLayerItem_Check(py_layer))) {
1136 PyErr_SetString(PyExc_AttributeError, "BMElem[key]: invalid key, must be a BMLayerItem");
1137 return nullptr;
1138 }
1139 if (UNLIKELY(py_ele->bm != py_layer->bm)) {
1140 PyErr_SetString(PyExc_ValueError, "BMElem[layer]: layer is from another mesh");
1141 return nullptr;
1142 }
1143 if (UNLIKELY(ele->head.htype != py_layer->htype)) {
1144 char namestr_1[32], namestr_2[32];
1145 PyErr_Format(PyExc_ValueError,
1146 "Layer/Element type mismatch, expected %.200s got layer type %.200s",
1147 BPy_BMElem_StringFromHType_ex(ele->head.htype, namestr_1),
1148 BPy_BMElem_StringFromHType_ex(py_layer->htype, namestr_2));
1149 return nullptr;
1150 }
1151
1152 data = bpy_bm_customdata_get(py_layer->bm, py_layer->htype);
1153
1154 value = CustomData_bmesh_get_n(
1155 data, ele->head.data, eCustomDataType(py_layer->type), py_layer->index);
1156
1157 if (UNLIKELY(value == nullptr)) {
1158 /* this should be fairly unlikely but possible if layers move about after we get them */
1159 PyErr_SetString(PyExc_KeyError, "BMElem[key]: layer not found");
1160 return nullptr;
1161 }
1162
1163 return value;
1164}
1165
1167{
1168 void *value = bpy_bmlayeritem_ptr_get(py_ele, py_layer);
1169 PyObject *ret;
1170
1171 if (UNLIKELY(value == nullptr)) {
1172 return nullptr;
1173 }
1174
1175 switch (py_layer->type) {
1176 case CD_MDEFORMVERT: {
1177 ret = BPy_BMDeformVert_CreatePyObject(static_cast<MDeformVert *>(value));
1178 break;
1179 }
1180 case CD_PROP_FLOAT: {
1181 ret = PyFloat_FromDouble(*(float *)value);
1182 break;
1183 }
1184 case CD_PROP_INT32: {
1185 ret = PyLong_FromLong(*(int *)value);
1186 break;
1187 }
1188 case CD_PROP_FLOAT3: {
1189 ret = Vector_CreatePyObject_wrap((float *)value, 3, nullptr);
1190 break;
1191 }
1192 case CD_PROP_COLOR: {
1193 ret = Vector_CreatePyObject_wrap((float *)value, 4, nullptr);
1194 break;
1195 }
1196 case CD_PROP_STRING: {
1197 MStringProperty *mstring = static_cast<MStringProperty *>(value);
1198 ret = PyBytes_FromStringAndSize(mstring->s, mstring->s_len);
1199 break;
1200 }
1201 case CD_PROP_FLOAT2: {
1202 if (UNLIKELY(py_ele->bm != py_layer->bm)) {
1203 PyErr_SetString(PyExc_ValueError, "BMElem[layer]: layer is from another mesh");
1204 return nullptr;
1205 }
1206 ret = BPy_BMLoopUV_CreatePyObject(py_ele->bm, (BMLoop *)py_ele->ele, py_layer->index);
1207 break;
1208 }
1209 case CD_PROP_BYTE_COLOR: {
1210 ret = BPy_BMLoopColor_CreatePyObject(static_cast<MLoopCol *>(value));
1211 break;
1212 }
1213 case CD_SHAPEKEY: {
1214 ret = Vector_CreatePyObject_wrap((float *)value, 3, nullptr);
1215 break;
1216 }
1217 case CD_MVERT_SKIN: {
1218 ret = BPy_BMVertSkin_CreatePyObject(static_cast<MVertSkin *>(value));
1219 break;
1220 }
1221 default: {
1222 ret = Py_NotImplemented; /* TODO */
1223 Py_INCREF(ret);
1224 break;
1225 }
1226 }
1227
1228 return ret;
1229}
1230
1231int BPy_BMLayerItem_SetItem(BPy_BMElem *py_ele, BPy_BMLayerItem *py_layer, PyObject *py_value)
1232{
1233 int ret = 0;
1234 void *value = bpy_bmlayeritem_ptr_get(py_ele, py_layer);
1235
1236 if (UNLIKELY(value == nullptr)) {
1237 return -1;
1238 }
1239
1240 switch (py_layer->type) {
1241 case CD_MDEFORMVERT: {
1242 ret = BPy_BMDeformVert_AssignPyObject(static_cast<MDeformVert *>(value), py_value);
1243 break;
1244 }
1245 case CD_PROP_FLOAT: {
1246 const float tmp_val = PyFloat_AsDouble(py_value);
1247 if (UNLIKELY(tmp_val == -1 && PyErr_Occurred())) {
1248 PyErr_Format(
1249 PyExc_TypeError, "expected a float, not a %.200s", Py_TYPE(py_value)->tp_name);
1250 ret = -1;
1251 }
1252 else {
1253 *(float *)value = tmp_val;
1254 }
1255 break;
1256 }
1257 case CD_PROP_INT32: {
1258 const int tmp_val = PyC_Long_AsI32(py_value);
1259 if (UNLIKELY(tmp_val == -1 && PyErr_Occurred())) {
1260 /* error is set */
1261 ret = -1;
1262 }
1263 else {
1264 *(int *)value = tmp_val;
1265 }
1266 break;
1267 }
1268 case CD_PROP_FLOAT3: {
1269 if (mathutils_array_parse((float *)value, 3, 3, py_value, "BMElem Float Vector") == -1) {
1270 ret = -1;
1271 }
1272 break;
1273 }
1274 case CD_PROP_COLOR: {
1275 if (mathutils_array_parse((float *)value, 4, 4, py_value, "BMElem Float Color") == -1) {
1276 ret = -1;
1277 }
1278 break;
1279 }
1280 case CD_PROP_STRING: {
1281 MStringProperty *mstring = static_cast<MStringProperty *>(value);
1282 char *tmp_val;
1283 Py_ssize_t tmp_val_len;
1284 if (UNLIKELY(PyBytes_AsStringAndSize(py_value, &tmp_val, &tmp_val_len) == -1)) {
1285 PyErr_Format(PyExc_TypeError, "expected bytes, not a %.200s", Py_TYPE(py_value)->tp_name);
1286 ret = -1;
1287 }
1288 else {
1289 if (tmp_val_len > sizeof(mstring->s)) {
1290 tmp_val_len = sizeof(mstring->s);
1291 }
1292 memcpy(mstring->s, tmp_val, tmp_val_len);
1293 mstring->s_len = tmp_val_len;
1294 }
1295 break;
1296 }
1297 case CD_PROP_FLOAT2: {
1298 if (UNLIKELY(py_ele->bm != py_layer->bm)) {
1299 PyErr_SetString(PyExc_ValueError, "BMElem[layer]: layer is from another mesh");
1300 ret = -1;
1301 }
1302 else {
1303 ret = BPy_BMLoopUV_AssignPyObject(py_ele->bm, (BMLoop *)py_ele->ele, py_value);
1304 }
1305 break;
1306 }
1307 case CD_PROP_BYTE_COLOR: {
1308 ret = BPy_BMLoopColor_AssignPyObject(static_cast<MLoopCol *>(value), py_value);
1309 break;
1310 }
1311 case CD_SHAPEKEY: {
1312 float tmp_val[3];
1313 if (UNLIKELY(mathutils_array_parse(tmp_val, 3, 3, py_value, "BMVert[shape] = value") == -1))
1314 {
1315 ret = -1;
1316 }
1317 else {
1318 copy_v3_v3((float *)value, tmp_val);
1319 }
1320 break;
1321 }
1322 case CD_MVERT_SKIN: {
1323 ret = BPy_BMVertSkin_AssignPyObject(static_cast<MVertSkin *>(value), py_value);
1324 break;
1325 }
1326 default: {
1327 PyErr_SetString(PyExc_AttributeError, "readonly / unsupported type");
1328 ret = -1;
1329 break;
1330 }
1331 }
1332
1333 return ret;
1334}
CustomData interface, see also DNA_customdata_types.h.
int CustomData_get_layer_index_n(const CustomData *data, eCustomDataType type, int n)
int CustomData_get_named_layer(const CustomData *data, eCustomDataType type, blender::StringRef name)
void * CustomData_bmesh_get_n(const CustomData *data, void *block, eCustomDataType type, int n)
int CustomData_get_named_layer_index(const CustomData *data, eCustomDataType type, blender::StringRef name)
int CustomData_get_layer_index(const CustomData *data, eCustomDataType type)
int CustomData_get_active_layer(const CustomData *data, eCustomDataType type)
bool CustomData_has_layer(const CustomData *data, eCustomDataType type)
bool CustomData_layertype_is_singleton(eCustomDataType type)
int CustomData_number_of_layers(const CustomData *data, eCustomDataType type)
#define BLI_assert_unreachable()
Definition BLI_assert.h:97
#define BLI_assert(a)
Definition BLI_assert.h:50
MINLINE void copy_v3_v3(float r[3], const float a[3])
#define POINTER_AS_INT(i)
#define UNLIKELY(x)
#define CLAMP_MIN(a, b)
@ CD_PROP_BYTE_COLOR
@ CD_MVERT_SKIN
@ CD_PROP_FLOAT
@ CD_PROP_FLOAT3
@ CD_MDEFORMVERT
@ CD_PROP_COLOR
@ CD_PROP_INT32
@ CD_PROP_FLOAT2
@ CD_FREESTYLE_EDGE
@ CD_FREESTYLE_FACE
@ CD_PROP_STRING
@ BM_LOOP
void BM_data_layer_free_n(BMesh *bm, CustomData *data, int type, int n)
void BM_data_layer_copy(BMesh *bm, CustomData *data, int type, int src_n, int dst_n)
void BM_data_layer_add(BMesh *bm, CustomData *data, int type)
void BM_data_layer_add_named(BMesh *bm, CustomData *data, int type, const char *name)
void BM_uv_map_ensure_select_and_pin_attrs(BMesh *bm)
ATTR_WARN_UNUSED_RESULT BMesh * bm
#define BM_FACE
#define BM_EDGE
#define BM_VERT
char * BPy_BMElem_StringFromHType_ex(const char htype, char ret[32])
#define BPY_BM_CHECK_OBJ(obj)
#define BPY_BM_CHECK_SOURCE_OBJ(bm, errmsg,...)
#define BPY_BM_CHECK_INT(obj)
PyObject * BPy_BMLayerItem_CreatePyObject(BMesh *bm, const char htype, int type, int index)
static PyGetSetDef bpy_bmlayeritem_getseters[]
PyTypeObject BPy_BMLayerCollection_Type
PyObject * BPy_BMLayerAccess_CreatePyObject(BMesh *bm, const char htype)
static PyObject * bpy_bmlayercollection_iter(BPy_BMLayerCollection *self)
static PyObject * bpy_bmlayercollection_subscript_slice(BPy_BMLayerCollection *self, Py_ssize_t start, Py_ssize_t stop)
PyTypeObject BPy_BMLayerItem_Type
static PyGetSetDef bpy_bmlayercollection_getseters[]
static PyObject * bpy_bmlayercollection_keys(BPy_BMLayerCollection *self)
static PySequenceMethods bpy_bmlayercollection_as_sequence
static PyObject * bpy_bmlayercollection_subscript(BPy_BMLayerCollection *self, PyObject *key)
PyTypeObject BPy_BMLayerAccessLoop_Type
PyTypeObject BPy_BMLayerAccessVert_Type
static PyObject * bpy_bmlayercollection_verify(BPy_BMLayerCollection *self)
static PyGetSetDef bpy_bmlayeraccess_loop_getseters[]
static void * bpy_bmlayeritem_ptr_get(BPy_BMElem *py_ele, BPy_BMLayerItem *py_layer)
static int bpy_bmlayercollection_contains(BPy_BMLayerCollection *self, PyObject *value)
static PyGetSetDef bpy_bmlayeraccess_edge_getseters[]
static PyObject * bpy_bmlayercollection_subscript_int(BPy_BMLayerCollection *self, Py_ssize_t keynum)
static PyMethodDef bpy_bmelemseq_methods[]
static Py_ssize_t bpy_bmlayercollection_length(BPy_BMLayerCollection *self)
int BPy_BMLayerItem_SetItem(BPy_BMElem *py_ele, BPy_BMLayerItem *py_layer, PyObject *py_value)
static PyObject * bpy_bmlayeritem_copy_from(BPy_BMLayerItem *self, BPy_BMLayerItem *value)
PyTypeObject BPy_BMLayerAccessFace_Type
static PyObject * bpy_bmlayercollection_new(BPy_BMLayerCollection *self, PyObject *args)
static PyObject * bpy_bmlayercollection_is_singleton_get(BPy_BMLayerItem *self, void *)
static PyGetSetDef bpy_bmlayeraccess_face_getseters[]
static PyObject * bpy_bmlayercollection_items(BPy_BMLayerCollection *self)
static PyMappingMethods bpy_bmlayercollection_as_mapping
static PyObject * bpy_bmlayercollection_subscript_str(BPy_BMLayerCollection *self, const char *keyname)
PyTypeObject BPy_BMLayerAccessEdge_Type
static PyObject * bpy_bmlayeraccess_collection_get(BPy_BMLayerAccess *self, void *flag)
static PyObject * bpy_bmlayercollection_values(BPy_BMLayerCollection *self)
static CustomDataLayer * bpy_bmlayeritem_get(BPy_BMLayerItem *self)
static PyObject * bpy_bmlayercollection_get(BPy_BMLayerCollection *self, PyObject *args)
static PyObject * bpy_bmlayeritem_name_get(BPy_BMLayerItem *self, void *)
void BPy_BM_init_types_customdata()
static PyObject * bpy_bmlayercollection_remove(BPy_BMLayerCollection *self, BPy_BMLayerItem *value)
PyObject * BPy_BMLayerCollection_CreatePyObject(BMesh *bm, const char htype, int type)
static PyObject * bpy_bmlayercollection_active_get(BPy_BMLayerItem *self, void *)
PyDoc_STRVAR(bpy_bmlayeraccess_collection__float_doc, "Generic float custom-data layer.\n" "\n" ":type: :class:`BMLayerCollection` of float")
static PyMethodDef bpy_bmlayeritem_methods[]
PyObject * BPy_BMLayerItem_GetItem(BPy_BMElem *py_ele, BPy_BMLayerItem *py_layer)
BMElem.__getitem__() / setitem()
static PyGetSetDef bpy_bmlayeraccess_vert_getseters[]
static CustomData * bpy_bm_customdata_get(BMesh *bm, char htype)
#define BPy_BMLayerItem_Check(v)
int BPy_BMVertSkin_AssignPyObject(MVertSkin *mvertskin, PyObject *value)
PyObject * BPy_BMDeformVert_CreatePyObject(MDeformVert *dvert)
int BPy_BMDeformVert_AssignPyObject(MDeformVert *dvert, PyObject *value)
PyObject * BPy_BMLoopColor_CreatePyObject(MLoopCol *mloopcol)
PyObject * BPy_BMLoopUV_CreatePyObject(BMesh *bm, BMLoop *loop, int layer)
int BPy_BMLoopColor_AssignPyObject(MLoopCol *mloopcol, PyObject *value)
int BPy_BMLoopUV_AssignPyObject(BMesh *bm, BMLoop *loop, PyObject *value)
PyObject * BPy_BMVertSkin_CreatePyObject(MVertSkin *mvertskin)
PyObject * self
int len
draw_view push_constant(Type::INT, "radiance_src") .push_constant(Type capture_info_buf storage_buf(1, Qualifier::READ, "ObjectBounds", "bounds_buf[]") .push_constant(Type draw_view int
int count
int mathutils_array_parse(float *array, int array_num_min, int array_num_max, PyObject *value, const char *error_prefix)
Definition mathutils.cc:97
PyObject * Vector_CreatePyObject_wrap(float *vec, const int vec_num, PyTypeObject *base_type)
header-only utilities
#define PyTuple_SET_ITEMS(op_arg,...)
return ret
BMHeader head
void * data
CustomData vdata
CustomData edata
CustomData pdata
CustomData ldata
PyObject_VAR_HEAD BMesh * bm
PyObject_VAR_HEAD BMesh * bm
uint8_t flag
Definition wm_window.cc:138