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