Blender V4.5
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:`BMLayerCollection` of float");
78 /* Wrap. */
79 bpy_bmlayeraccess_collection__int_doc,
80 "Generic int custom-data layer.\n"
81 "\n"
82 ":type: :class:`BMLayerCollection` of int");
84 /* Wrap. */
85 bpy_bmlayeraccess_collection__bool_doc,
86 "Generic boolean custom-data layer.\n"
87 "\n"
88 ":type: :class:`BMLayerCollection` of boolean");
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:`BMLayerCollection` of :class:`mathutils.Vector`");
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:`BMLayerCollection` of :class:`mathutils.Vector`");
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:`BMLayerCollection` of :class:`mathutils.Vector`");
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:`BMLayerCollection` of bytes");
118 /* Wrap. */
119 bpy_bmlayeraccess_collection__deform_doc,
120 "Vertex deform weight :class:`BMDeformVert` (TODO).\n"
121 "\n"
122 ":type: "
123 ":class:`BMLayerCollection` of :class:`bmesh.types.BMDeformVert`" /* TYPE DOESN'T EXIST YET */
124);
126 /* Wrap. */
127 bpy_bmlayeraccess_collection__shape_doc,
128 "Vertex shapekey absolute location (as a 3D Vector).\n"
129 "\n"
130 ":type: :class:`BMLayerCollection` of :class:`mathutils.Vector`");
132 /* Wrap. */
133 bpy_bmlayeraccess_collection__uv_doc,
134 "Accessor for :class:`BMLoopUV` UV (as a 2D Vector).\n"
135 "\n"
136 ":type: :class:`BMLayerCollection` of :class:`bmesh.types.BMLoopUV`");
138 /* Wrap. */
139 bpy_bmlayeraccess_collection__skin_doc,
140 "Accessor for skin layer.\n"
141 "\n"
142 ":type: :class:`BMLayerCollection` of :class:`bmesh.types.BMVertSkin`");
143#ifdef WITH_FREESTYLE
145 /* Wrap. */
146 bpy_bmlayeraccess_collection__freestyle_edge_doc,
147 "Accessor for Freestyle edge layer.\n"
148 "\n"
149 ":type: :class:`BMLayerCollection`");
151 /* Wrap. */
152 bpy_bmlayeraccess_collection__freestyle_face_doc,
153 "Accessor for Freestyle face layer.\n"
154 "\n"
155 ":type: :class:`BMLayerCollection`");
156#endif
157
159{
160 const int type = int(POINTER_AS_INT(flag));
161
163
164 return BPy_BMLayerCollection_CreatePyObject(self->bm, self->htype, type);
165}
166
168 /* Wrap. */
169 bpy_bmlayercollection_active_doc,
170 "The active layer of this type (read-only).\n"
171 "\n"
172 ":type: :class:`BMLayerItem`");
173static PyObject *bpy_bmlayercollection_active_get(BPy_BMLayerItem *self, void * /*flag*/)
174{
176 int index;
177
179
180 data = bpy_bm_customdata_get(self->bm, self->htype);
181 index = CustomData_get_active_layer(data, eCustomDataType(self->type)); /* type relative */
182
183 if (index != -1) {
184 return BPy_BMLayerItem_CreatePyObject(self->bm, self->htype, self->type, index);
185 }
186
187 Py_RETURN_NONE;
188}
189
190PyDoc_STRVAR(bpy_bmlayercollection_is_singleton_doc,
191 "True if there can exists only one layer of this type (read-only).\n"
192 "\n"
193 ":type: bool");
195{
197
198 return PyBool_FromLong(CustomData_layertype_is_singleton(eCustomDataType(self->type)));
199}
200
202 /* Wrap. */
203 bpy_bmlayercollection_name_doc,
204 "The layers unique name (read-only).\n"
205 "\n"
206 ":type: str");
207static PyObject *bpy_bmlayeritem_name_get(BPy_BMLayerItem *self, void * /*flag*/)
208{
209 CustomDataLayer *layer;
210
212
213 layer = bpy_bmlayeritem_get(self);
214 if (layer) {
215 return PyUnicode_FromString(layer->name);
216 }
217
218 return nullptr;
219}
220
221static PyGetSetDef bpy_bmlayeraccess_vert_getseters[] = {
222 {"deform",
224 (setter) nullptr,
225 bpy_bmlayeraccess_collection__deform_doc,
226 (void *)CD_MDEFORMVERT},
227
228 {"float",
230 (setter) nullptr,
231 bpy_bmlayeraccess_collection__float_doc,
232 (void *)CD_PROP_FLOAT},
233 {"bool",
235 (setter) nullptr,
236 bpy_bmlayeraccess_collection__bool_doc,
237 (void *)CD_PROP_BOOL},
238 {"int",
240 (setter) nullptr,
241 bpy_bmlayeraccess_collection__int_doc,
242 (void *)CD_PROP_INT32},
243 {"float_vector",
245 (setter) nullptr,
246 bpy_bmlayeraccess_collection__float_vector_doc,
247 (void *)CD_PROP_FLOAT3},
248 {"float_color",
250 (setter) nullptr,
251 bpy_bmlayeraccess_collection__float_color_doc,
252 (void *)CD_PROP_COLOR},
253 {"color",
255 (setter) nullptr,
256 bpy_bmlayeraccess_collection__color_doc,
257 (void *)CD_PROP_BYTE_COLOR},
258 {"string",
260 (setter) nullptr,
261 bpy_bmlayeraccess_collection__string_doc,
262 (void *)CD_PROP_STRING},
263
264 {"shape",
266 (setter) nullptr,
267 bpy_bmlayeraccess_collection__shape_doc,
268 (void *)CD_SHAPEKEY},
269 {"skin",
271 (setter) nullptr,
272 bpy_bmlayeraccess_collection__skin_doc,
273 (void *)CD_MVERT_SKIN},
274
275 {nullptr, nullptr, nullptr, nullptr, nullptr} /* Sentinel */
276};
277
278static PyGetSetDef bpy_bmlayeraccess_edge_getseters[] = {
279 {"float",
281 (setter) nullptr,
282 bpy_bmlayeraccess_collection__float_doc,
283 (void *)CD_PROP_FLOAT},
284 {"int",
286 (setter) nullptr,
287 bpy_bmlayeraccess_collection__int_doc,
288 (void *)CD_PROP_INT32},
289 {"bool",
291 (setter) nullptr,
292 bpy_bmlayeraccess_collection__bool_doc,
293 (void *)CD_PROP_BOOL},
294 {"float_vector",
296 (setter) nullptr,
297 bpy_bmlayeraccess_collection__float_vector_doc,
298 (void *)CD_PROP_FLOAT3},
299 {"float_color",
301 (setter) nullptr,
302 bpy_bmlayeraccess_collection__float_color_doc,
303 (void *)CD_PROP_COLOR},
304 {"color",
306 (setter) nullptr,
307 bpy_bmlayeraccess_collection__color_doc,
308 (void *)CD_PROP_BYTE_COLOR},
309 {"string",
311 (setter) nullptr,
312 bpy_bmlayeraccess_collection__string_doc,
313 (void *)CD_PROP_STRING},
314#ifdef WITH_FREESTYLE
315 {"freestyle",
317 (setter) nullptr,
318 bpy_bmlayeraccess_collection__freestyle_edge_doc,
319 (void *)CD_FREESTYLE_EDGE},
320#endif
321 {nullptr, nullptr, nullptr, nullptr, nullptr} /* Sentinel */
322};
323
324static PyGetSetDef bpy_bmlayeraccess_face_getseters[] = {
325 {"float",
327 (setter) nullptr,
328 bpy_bmlayeraccess_collection__float_doc,
329 (void *)CD_PROP_FLOAT},
330 {"int",
332 (setter) nullptr,
333 bpy_bmlayeraccess_collection__int_doc,
334 (void *)CD_PROP_INT32},
335 {"bool",
337 (setter) nullptr,
338 bpy_bmlayeraccess_collection__bool_doc,
339 (void *)CD_PROP_BOOL},
340 {"float_vector",
342 (setter) nullptr,
343 bpy_bmlayeraccess_collection__float_vector_doc,
344 (void *)CD_PROP_FLOAT3},
345 {"float_color",
347 (setter) nullptr,
348 bpy_bmlayeraccess_collection__float_color_doc,
349 (void *)CD_PROP_COLOR},
350 {"color",
352 (setter) nullptr,
353 bpy_bmlayeraccess_collection__color_doc,
354 (void *)CD_PROP_BYTE_COLOR},
355 {"string",
357 (setter) nullptr,
358 bpy_bmlayeraccess_collection__string_doc,
359 (void *)CD_PROP_STRING},
360
361#ifdef WITH_FREESTYLE
362 {"freestyle",
364 (setter) nullptr,
365 bpy_bmlayeraccess_collection__freestyle_face_doc,
366 (void *)CD_FREESTYLE_FACE},
367#endif
368
369 {nullptr, nullptr, nullptr, nullptr, nullptr} /* Sentinel */
370};
371
372static PyGetSetDef bpy_bmlayeraccess_loop_getseters[] = {
373 {"float",
375 (setter) nullptr,
376 bpy_bmlayeraccess_collection__float_doc,
377 (void *)CD_PROP_FLOAT},
378 {"int",
380 (setter) nullptr,
381 bpy_bmlayeraccess_collection__int_doc,
382 (void *)CD_PROP_INT32},
383 {"bool",
385 (setter) nullptr,
386 bpy_bmlayeraccess_collection__bool_doc,
387 (void *)CD_PROP_BOOL},
388 {"float_vector",
390 (setter) nullptr,
391 bpy_bmlayeraccess_collection__float_vector_doc,
392 (void *)CD_PROP_FLOAT3},
393 {"float_color",
395 (setter) nullptr,
396 bpy_bmlayeraccess_collection__float_color_doc,
397 (void *)CD_PROP_COLOR},
398 {"string",
400 (setter) nullptr,
401 bpy_bmlayeraccess_collection__string_doc,
402 (void *)CD_PROP_STRING},
403 {"uv",
405 (setter) nullptr,
406 bpy_bmlayeraccess_collection__uv_doc,
407 (void *)CD_PROP_FLOAT2},
408 {"color",
410 (setter) nullptr,
411 bpy_bmlayeraccess_collection__color_doc,
412 (void *)CD_PROP_BYTE_COLOR},
413
414 {nullptr, nullptr, nullptr, nullptr, nullptr} /* Sentinel */
415};
416
417static PyGetSetDef bpy_bmlayercollection_getseters[] = {
418 /* BMESH_TODO, make writeable */
419 {"active",
421 (setter) nullptr,
422 bpy_bmlayercollection_active_doc,
423 nullptr},
424 {"is_singleton",
426 (setter) nullptr,
427 bpy_bmlayercollection_is_singleton_doc,
428 nullptr},
429
430 {nullptr, nullptr, nullptr, nullptr, nullptr} /* Sentinel */
431};
432
433static PyGetSetDef bpy_bmlayeritem_getseters[] = {
434 /* BMESH_TODO, make writeable */
435 {"name",
437 (setter) nullptr,
438 bpy_bmlayercollection_name_doc,
439 nullptr},
440
441 {nullptr, nullptr, nullptr, nullptr, nullptr} /* Sentinel */
442};
443
444/* Methods
445 * ======= */
446
447/* BMLayerCollection
448 * ----------------- */
449
451 /* Wrap. */
452 bpy_bmlayeritem_copy_from_doc,
453 ".. method:: copy_from(other)\n"
454 "\n"
455 " Return a copy of the layer\n"
456 "\n"
457 " :arg other: Another layer to copy from.\n"
458 " :type other: :class:`BMLayerItem`\n");
460{
462
463 if (!BPy_BMLayerItem_Check(value)) {
464 PyErr_Format(PyExc_TypeError,
465 "layer.copy_from(x): expected BMLayerItem, not '%.200s'",
466 Py_TYPE(value)->tp_name);
467 return nullptr;
468 }
469
471 BPY_BM_CHECK_SOURCE_OBJ(self->bm, "layer.copy_from()", value);
472
473 if ((self->htype != value->htype) || (self->type != value->type)) {
474 PyErr_SetString(PyExc_ValueError, "layer.copy_from(other): layer type mismatch");
475 }
476
477 else if (self->index == value->index) {
478 Py_RETURN_NONE;
479 }
480
481 data = bpy_bm_customdata_get(self->bm, self->htype);
482
483 if ((bpy_bmlayeritem_get(self) == nullptr) || (bpy_bmlayeritem_get(value) == nullptr)) {
484 return nullptr;
485 }
486
487 BM_data_layer_copy(self->bm, data, self->type, value->index, self->index);
488
489 Py_RETURN_NONE;
490}
491
492/* similar to new(), but no name arg. */
494 /* Wrap. */
495 bpy_bmlayercollection_verify_doc,
496 ".. method:: verify()\n"
497 "\n"
498 " Create a new layer or return an existing active layer\n"
499 "\n"
500 " :return: The newly verified layer.\n"
501 " :rtype: :class:`BMLayerItem`\n");
503{
504 int index;
506
508
509 data = bpy_bm_customdata_get(self->bm, self->htype);
510
511 index = CustomData_get_active_layer(data, eCustomDataType(self->type)); /* type relative */
512
513 if (index == -1) {
514 BM_data_layer_add(self->bm, data, self->type);
515 index = 0;
516 }
517 if (self->type == CD_PROP_FLOAT2 && self->htype == BM_LOOP) {
518 /* Because adding CustomData layers to a bmesh will invalidate any existing pointers
519 * in Py objects we can't lazily add the associated bool layers. So add them all right
520 * now. */
522 }
523
524 BLI_assert(index >= 0);
525
526 return BPy_BMLayerItem_CreatePyObject(self->bm, self->htype, self->type, index);
527}
528
530 /* Wrap. */
531 bpy_bmlayercollection_new_doc,
532 ".. method:: new(name)\n"
533 "\n"
534 " Create a new layer\n"
535 "\n"
536 " :arg name: Optional name argument (will be made unique).\n"
537 " :type name: str\n"
538 " :return: The newly created layer.\n"
539 " :rtype: :class:`BMLayerItem`\n");
540static PyObject *bpy_bmlayercollection_new(BPy_BMLayerCollection *self, PyObject *args)
541{
542 const char *name = nullptr;
543 int index;
545
547
548 if (!PyArg_ParseTuple(args, "|s:new", &name)) {
549 return nullptr;
550 }
551
552 data = bpy_bm_customdata_get(self->bm, self->htype);
553
556 {
557 PyErr_SetString(PyExc_ValueError, "layers.new(): is a singleton, use verify() instead");
558 return nullptr;
559 }
560
561 if (name) {
562 BM_data_layer_add_named(self->bm, data, self->type, name);
563 }
564 else {
565 BM_data_layer_add(self->bm, data, self->type);
566 }
567
568 if (self->type == CD_PROP_FLOAT2 && self->htype == BM_LOOP) {
569 /* Because adding CustomData layers to a bmesh will invalidate any existing pointers
570 * in Py objects we can't lazily add the associated bool layers. So add them all right
571 * now. */
573 }
574
576 BLI_assert(index >= 0);
577
578 return BPy_BMLayerItem_CreatePyObject(self->bm, self->htype, self->type, index);
579}
580
582 /* Wrap. */
583 bpy_bmlayercollection_remove_doc,
584 ".. method:: remove(layer)\n"
585 "\n"
586 " Remove a layer\n"
587 "\n"
588 " :arg layer: The layer to remove.\n"
589 " :type layer: :class:`BMLayerItem`\n");
591{
593
595
596 if (!BPy_BMLayerItem_Check(value)) {
597 PyErr_Format(PyExc_TypeError,
598 "layers.remove(x): expected BMLayerItem, not '%.200s'",
599 Py_TYPE(value)->tp_name);
600 return nullptr;
601 }
602
603 BPY_BM_CHECK_OBJ(value);
604
605 if ((self->bm != value->bm) || (self->type != value->type) || (self->htype != value->htype)) {
606 PyErr_SetString(PyExc_ValueError, "layers.remove(x): x not in layers");
607 }
608
609 data = bpy_bm_customdata_get(self->bm, self->htype);
610 BM_data_layer_free_n(self->bm, data, self->type, value->index);
611
612 Py_RETURN_NONE;
613}
614
616 /* Wrap. */
617 bpy_bmlayercollection_keys_doc,
618 ".. method:: keys()\n"
619 "\n"
620 " Return the identifiers of collection members\n"
621 " (matching Python's dict.keys() functionality).\n"
622 "\n"
623 " :return: the identifiers for each member of this collection.\n"
624 " :rtype: list[str]\n");
626{
627 PyObject *ret;
628 PyObject *item;
629 int index;
631 int tot, i;
632
634
635 data = bpy_bm_customdata_get(self->bm, self->htype);
636
637 /* Absolute, but no need to make relative. */
639
640 tot = (index != -1) ? CustomData_number_of_layers(data, eCustomDataType(self->type)) : 0;
641
642 ret = PyList_New(tot);
643
644 for (i = 0; tot-- > 0; index++) {
645 item = PyUnicode_FromString(data->layers[index].name);
646 PyList_SET_ITEM(ret, i++, item);
647 }
648
649 return ret;
650}
651
653 /* Wrap. */
654 bpy_bmlayercollection_items_doc,
655 ".. method:: items()\n"
656 "\n"
657 " Return the identifiers of collection members\n"
658 " (matching Python's dict.items() functionality).\n"
659 "\n"
660 " :return: (key, value) pairs for each member of this collection.\n"
661 " :rtype: list[tuple[str, :class:`BMLayerItem`]]\n");
663{
664 PyObject *ret;
665 PyObject *item;
666 int index;
668 int tot, i;
669
671
672 data = bpy_bm_customdata_get(self->bm, self->htype);
674 tot = (index != -1) ? CustomData_number_of_layers(data, eCustomDataType(self->type)) : 0;
675
676 ret = PyList_New(tot);
677
678 for (i = 0; tot-- > 0; index++) {
679 item = PyTuple_New(2);
681 PyUnicode_FromString(data->layers[index].name),
682 BPy_BMLayerItem_CreatePyObject(self->bm, self->htype, self->type, i));
683 PyList_SET_ITEM(ret, i++, item);
684 }
685
686 return ret;
687}
688
690 /* Wrap. */
691 bpy_bmlayercollection_values_doc,
692 ".. method:: values()\n"
693 "\n"
694 " Return the values of collection\n"
695 " (matching Python's dict.values() functionality).\n"
696 "\n"
697 " :return: the members of this collection.\n"
698 " :rtype: list[:class:`BMLayerItem`]\n");
700{
701 PyObject *ret;
702 PyObject *item;
703 int index;
705 int tot, i;
706
708
709 data = bpy_bm_customdata_get(self->bm, self->htype);
711 tot = (index != -1) ? CustomData_number_of_layers(data, eCustomDataType(self->type)) : 0;
712
713 ret = PyList_New(tot);
714
715 for (i = 0; tot-- > 0; index++) {
716 item = BPy_BMLayerItem_CreatePyObject(self->bm, self->htype, self->type, i);
717 PyList_SET_ITEM(ret, i++, item);
718 }
719
720 return ret;
721}
722
724 /* Wrap. */
725 bpy_bmlayercollection_get_doc,
726 ".. method:: get(key, default=None)\n"
727 "\n"
728 " Returns the value of the layer matching the key or default\n"
729 " when not found (matches Python's dictionary function of the same name).\n"
730 "\n"
731 " :arg key: The key associated with the layer.\n"
732 " :type key: str\n"
733 " :arg default: Optional argument for the value to return if\n"
734 " *key* is not found.\n"
735 " :type default: Any\n");
736static PyObject *bpy_bmlayercollection_get(BPy_BMLayerCollection *self, PyObject *args)
737{
738 const char *key;
739 PyObject *def = Py_None;
740
742
743 if (!PyArg_ParseTuple(args, "s|O:get", &key, &def)) {
744 return nullptr;
745 }
746
748 int index;
749
750 data = bpy_bm_customdata_get(self->bm, self->htype);
751 index = CustomData_get_named_layer(data, eCustomDataType(self->type), key); /* type relative */
752
753 if (index != -1) {
754 return BPy_BMLayerItem_CreatePyObject(self->bm, self->htype, self->type, index);
755 }
756
757 return Py_NewRef(def);
758}
759
760static PyMethodDef bpy_bmlayeritem_methods[] = {
761 {"copy_from", (PyCFunction)bpy_bmlayeritem_copy_from, METH_O, bpy_bmlayeritem_copy_from_doc},
762 {nullptr, nullptr, 0, nullptr},
763};
764
765#ifdef __GNUC__
766# ifdef __clang__
767# pragma clang diagnostic push
768# pragma clang diagnostic ignored "-Wcast-function-type"
769# else
770# pragma GCC diagnostic push
771# pragma GCC diagnostic ignored "-Wcast-function-type"
772# endif
773#endif
774
775static PyMethodDef bpy_bmelemseq_methods[] = {
776 {"verify",
777 (PyCFunction)bpy_bmlayercollection_verify,
778 METH_NOARGS,
779 bpy_bmlayercollection_verify_doc},
780 {"new", (PyCFunction)bpy_bmlayercollection_new, METH_VARARGS, bpy_bmlayercollection_new_doc},
781 {"remove",
782 (PyCFunction)bpy_bmlayercollection_remove,
783 METH_O,
784 bpy_bmlayercollection_remove_doc},
785
786 {"keys", (PyCFunction)bpy_bmlayercollection_keys, METH_NOARGS, bpy_bmlayercollection_keys_doc},
787 {"values",
788 (PyCFunction)bpy_bmlayercollection_values,
789 METH_NOARGS,
790 bpy_bmlayercollection_values_doc},
791 {"items",
792 (PyCFunction)bpy_bmlayercollection_items,
793 METH_NOARGS,
794 bpy_bmlayercollection_items_doc},
795 {"get", (PyCFunction)bpy_bmlayercollection_get, METH_VARARGS, bpy_bmlayercollection_get_doc},
796 {nullptr, nullptr, 0, nullptr},
797};
798
799#ifdef __GNUC__
800# ifdef __clang__
801# pragma clang diagnostic pop
802# else
803# pragma GCC diagnostic pop
804# endif
805#endif
806
807/* Sequences
808 * ========= */
809
820
822 const char *keyname)
823{
825 int index;
826
828
829 data = bpy_bm_customdata_get(self->bm, self->htype);
831 data, eCustomDataType(self->type), keyname); /* type relative */
832
833 if (index != -1) {
834 return BPy_BMLayerItem_CreatePyObject(self->bm, self->htype, self->type, index);
835 }
836
837 PyErr_Format(PyExc_KeyError, "BMLayerCollection[key]: key \"%.200s\" not found", keyname);
838 return nullptr;
839}
840
842 Py_ssize_t keynum)
843{
844 Py_ssize_t len;
846
848
849 if (keynum < 0) {
850 keynum += len;
851 }
852 if (keynum >= 0) {
853 if (keynum < len) {
854 return BPy_BMLayerItem_CreatePyObject(self->bm, self->htype, self->type, keynum);
855 }
856 }
857
858 PyErr_Format(PyExc_IndexError, "BMLayerCollection[index]: index %d out of range", keynum);
859 return nullptr;
860}
861
863 Py_ssize_t start,
864 Py_ssize_t stop)
865{
866 const Py_ssize_t len = bpy_bmlayercollection_length(self);
867 int count = 0;
868
869 PyObject *tuple;
870
872
873 start = std::min(start, len);
874 stop = std::min(stop, len);
875
876 tuple = PyTuple_New(stop - start);
877
878 for (count = start; count < stop; count++) {
879 PyTuple_SET_ITEM(tuple,
880 count - start,
881 BPy_BMLayerItem_CreatePyObject(self->bm, self->htype, self->type, count));
882 }
883
884 return tuple;
885}
886
888{
889 /* don't need error check here */
890 if (PyUnicode_Check(key)) {
891 return bpy_bmlayercollection_subscript_str(self, PyUnicode_AsUTF8(key));
892 }
893 if (PyIndex_Check(key)) {
894 const Py_ssize_t i = PyNumber_AsSsize_t(key, PyExc_IndexError);
895 if (i == -1 && PyErr_Occurred()) {
896 return nullptr;
897 }
899 }
900 if (PySlice_Check(key)) {
901 PySliceObject *key_slice = (PySliceObject *)key;
902 Py_ssize_t step = 1;
903
904 if (key_slice->step != Py_None && !_PyEval_SliceIndex(key, &step)) {
905 return nullptr;
906 }
907 if (step != 1) {
908 PyErr_SetString(PyExc_TypeError, "BMLayerCollection[slice]: slice steps not supported");
909 return nullptr;
910 }
911 if (key_slice->start == Py_None && key_slice->stop == Py_None) {
912 return bpy_bmlayercollection_subscript_slice(self, 0, PY_SSIZE_T_MAX);
913 }
914
915 Py_ssize_t start = 0, stop = PY_SSIZE_T_MAX;
916
917 /* avoid PySlice_GetIndicesEx because it needs to know the length ahead of time. */
918 if (key_slice->start != Py_None && !_PyEval_SliceIndex(key_slice->start, &start)) {
919 return nullptr;
920 }
921 if (key_slice->stop != Py_None && !_PyEval_SliceIndex(key_slice->stop, &stop)) {
922 return nullptr;
923 }
924
925 if (start < 0 || stop < 0) {
926 /* only get the length for negative values */
927 const Py_ssize_t len = bpy_bmlayercollection_length(self);
928 if (start < 0) {
929 start += len;
930 CLAMP_MIN(start, 0);
931 }
932 if (stop < 0) {
933 stop += len;
934 CLAMP_MIN(stop, 0);
935 }
936 }
937
938 if (stop - start <= 0) {
939 return PyTuple_New(0);
940 }
941
943 }
944
945 PyErr_SetString(PyExc_AttributeError, "BMLayerCollection[key]: invalid key, key must be an int");
946 return nullptr;
947}
948
950{
951 const char *keyname = PyUnicode_AsUTF8(value);
953 int index;
954
956
957 if (keyname == nullptr) {
958 PyErr_SetString(PyExc_TypeError, "BMLayerCollection.__contains__: expected a string");
959 return -1;
960 }
961
962 data = bpy_bm_customdata_get(self->bm, self->htype);
964
965 return (index != -1) ? 1 : 0;
966}
967
968static PySequenceMethods bpy_bmlayercollection_as_sequence = {
969 /*sq_length*/ (lenfunc)bpy_bmlayercollection_length,
970 /*sq_concat*/ nullptr,
971 /*sq_repeat*/ nullptr,
972 /* Only set this so `PySequence_Check()` returns True. */
973 /*sq_item*/ (ssizeargfunc)bpy_bmlayercollection_subscript_int,
974 /*was_sq_slice*/ nullptr, /* DEPRECATED. */
975 /*sq_ass_item*/ nullptr,
976 /*was_sq_ass_slice*/ nullptr, /* DEPRECATED. */
977 /*sq_contains*/ (objobjproc)bpy_bmlayercollection_contains,
978 /*sq_inplace_concat*/ nullptr,
979 /*sq_inplace_repeat*/ nullptr,
980};
981
982static PyMappingMethods bpy_bmlayercollection_as_mapping = {
983 /*mp_length*/ (lenfunc)bpy_bmlayercollection_length,
984 /*mp_subscript*/ (binaryfunc)bpy_bmlayercollection_subscript,
985 /*mp_ass_subscript*/ (objobjargproc) nullptr,
986};
987
988/* Iterator
989 * -------- */
990
992{
993 /* fake it with a list iterator */
994 PyObject *ret;
995 PyObject *iter = nullptr;
996
998
999 ret = bpy_bmlayercollection_subscript_slice(self, 0, PY_SSIZE_T_MAX);
1000
1001 if (ret) {
1002 iter = PyObject_GetIter(ret);
1003 Py_DECREF(ret);
1004 }
1005
1006 return iter;
1007}
1008
1010 /* Wrap. */
1011 bpy_bmlayeraccess_type_doc,
1012 "Exposes custom-data layer attributes.");
1013
1015 /* Wrap. */
1016 bpy_bmlayercollection_type_doc,
1017 "Gives access to a collection of custom-data layers of the same type and behaves "
1018 "like Python dictionaries, "
1019 "except for the ability to do list like index access.");
1020
1022 /* Wrap. */
1023 bpy_bmlayeritem_type_doc,
1024 "Exposes a single custom data layer, "
1025 "their main purpose is for use as item accessors to custom-data when used with "
1026 "vert/edge/face/loop data.");
1027
1028PyTypeObject BPy_BMLayerAccessVert_Type; /* bm.verts.layers */
1029PyTypeObject BPy_BMLayerAccessEdge_Type; /* bm.edges.layers */
1030PyTypeObject BPy_BMLayerAccessFace_Type; /* bm.faces.layers */
1031PyTypeObject BPy_BMLayerAccessLoop_Type; /* bm.loops.layers */
1032PyTypeObject BPy_BMLayerCollection_Type; /* bm.loops.layers.uv */
1033PyTypeObject BPy_BMLayerItem_Type; /* bm.loops.layers.uv["UVMap"] */
1034
1035PyObject *BPy_BMLayerAccess_CreatePyObject(BMesh *bm, const char htype)
1036{
1038 PyTypeObject *type;
1039
1040 switch (htype) {
1041 case BM_VERT:
1043 break;
1044 case BM_EDGE:
1046 break;
1047 case BM_FACE:
1049 break;
1050 case BM_LOOP:
1052 break;
1053 default: {
1055 type = nullptr;
1056 break;
1057 }
1058 }
1059
1060 self = PyObject_New(BPy_BMLayerAccess, type);
1061 self->bm = bm;
1062 self->htype = htype;
1063 return (PyObject *)self;
1064}
1065
1066PyObject *BPy_BMLayerCollection_CreatePyObject(BMesh *bm, const char htype, int type)
1067{
1069 self->bm = bm;
1070 self->htype = htype;
1071 self->type = type;
1072 return (PyObject *)self;
1073}
1074
1075PyObject *BPy_BMLayerItem_CreatePyObject(BMesh *bm, const char htype, int type, int index)
1076{
1078 self->bm = bm;
1079 self->htype = htype;
1080 self->type = type;
1081 self->index = index;
1082 return (PyObject *)self;
1083}
1084
1086{
1087 BPy_BMLayerAccessVert_Type.tp_basicsize = sizeof(BPy_BMLayerAccess);
1088 BPy_BMLayerAccessEdge_Type.tp_basicsize = sizeof(BPy_BMLayerAccess);
1089 BPy_BMLayerAccessFace_Type.tp_basicsize = sizeof(BPy_BMLayerAccess);
1090 BPy_BMLayerAccessLoop_Type.tp_basicsize = sizeof(BPy_BMLayerAccess);
1092 BPy_BMLayerItem_Type.tp_basicsize = sizeof(BPy_BMLayerItem);
1093
1094 BPy_BMLayerAccessVert_Type.tp_name = "BMLayerAccessVert";
1095 BPy_BMLayerAccessEdge_Type.tp_name = "BMLayerAccessEdge";
1096 BPy_BMLayerAccessFace_Type.tp_name = "BMLayerAccessFace";
1097 BPy_BMLayerAccessLoop_Type.tp_name = "BMLayerAccessLoop";
1098 BPy_BMLayerCollection_Type.tp_name = "BMLayerCollection";
1099 BPy_BMLayerItem_Type.tp_name = "BMLayerItem";
1100
1101 /* todo */
1102 BPy_BMLayerAccessVert_Type.tp_doc = bpy_bmlayeraccess_type_doc;
1103 BPy_BMLayerAccessEdge_Type.tp_doc = bpy_bmlayeraccess_type_doc;
1104 BPy_BMLayerAccessFace_Type.tp_doc = bpy_bmlayeraccess_type_doc;
1105 BPy_BMLayerAccessLoop_Type.tp_doc = bpy_bmlayeraccess_type_doc;
1106 BPy_BMLayerCollection_Type.tp_doc = bpy_bmlayercollection_type_doc;
1107 BPy_BMLayerItem_Type.tp_doc = bpy_bmlayeritem_type_doc;
1108
1109 BPy_BMLayerAccessVert_Type.tp_repr = (reprfunc) nullptr;
1110 BPy_BMLayerAccessEdge_Type.tp_repr = (reprfunc) nullptr;
1111 BPy_BMLayerAccessFace_Type.tp_repr = (reprfunc) nullptr;
1112 BPy_BMLayerAccessLoop_Type.tp_repr = (reprfunc) nullptr;
1113 BPy_BMLayerCollection_Type.tp_repr = (reprfunc) nullptr;
1114 BPy_BMLayerItem_Type.tp_repr = (reprfunc) nullptr;
1115
1122
1123 // BPy_BMLayerAccess_Type.tp_methods = bpy_bmeditselseq_methods;
1126
1128
1130
1132
1133 BPy_BMLayerAccessVert_Type.tp_dealloc = nullptr;
1134 BPy_BMLayerAccessEdge_Type.tp_dealloc = nullptr;
1135 BPy_BMLayerAccessFace_Type.tp_dealloc = nullptr;
1136 BPy_BMLayerAccessLoop_Type.tp_dealloc = nullptr;
1137 BPy_BMLayerCollection_Type.tp_dealloc = nullptr;
1138 BPy_BMLayerItem_Type.tp_dealloc = nullptr;
1139
1140 BPy_BMLayerAccessVert_Type.tp_flags = Py_TPFLAGS_DEFAULT;
1141 BPy_BMLayerAccessEdge_Type.tp_flags = Py_TPFLAGS_DEFAULT;
1142 BPy_BMLayerAccessFace_Type.tp_flags = Py_TPFLAGS_DEFAULT;
1143 BPy_BMLayerAccessLoop_Type.tp_flags = Py_TPFLAGS_DEFAULT;
1144 BPy_BMLayerCollection_Type.tp_flags = Py_TPFLAGS_DEFAULT;
1145 BPy_BMLayerItem_Type.tp_flags = Py_TPFLAGS_DEFAULT;
1146
1147 PyType_Ready(&BPy_BMLayerAccessVert_Type);
1148 PyType_Ready(&BPy_BMLayerAccessEdge_Type);
1149 PyType_Ready(&BPy_BMLayerAccessFace_Type);
1150 PyType_Ready(&BPy_BMLayerAccessLoop_Type);
1151 PyType_Ready(&BPy_BMLayerCollection_Type);
1152 PyType_Ready(&BPy_BMLayerItem_Type);
1153}
1154
1155/* Per Element Get/Set
1156 * ******************* */
1157
1162{
1163 void *value;
1164 BMElem *ele = py_ele->ele;
1166
1167 /* error checking */
1168 if (UNLIKELY(!BPy_BMLayerItem_Check(py_layer))) {
1169 PyErr_SetString(PyExc_AttributeError, "BMElem[key]: invalid key, must be a BMLayerItem");
1170 return nullptr;
1171 }
1172 if (UNLIKELY(py_ele->bm != py_layer->bm)) {
1173 PyErr_SetString(PyExc_ValueError, "BMElem[layer]: layer is from another mesh");
1174 return nullptr;
1175 }
1176 if (UNLIKELY(ele->head.htype != py_layer->htype)) {
1177 char namestr_1[32], namestr_2[32];
1178 PyErr_Format(PyExc_ValueError,
1179 "Layer/Element type mismatch, expected %.200s got layer type %.200s",
1180 BPy_BMElem_StringFromHType_ex(ele->head.htype, namestr_1),
1181 BPy_BMElem_StringFromHType_ex(py_layer->htype, namestr_2));
1182 return nullptr;
1183 }
1184
1185 data = bpy_bm_customdata_get(py_layer->bm, py_layer->htype);
1186
1187 value = CustomData_bmesh_get_n(
1188 data, ele->head.data, eCustomDataType(py_layer->type), py_layer->index);
1189
1190 if (UNLIKELY(value == nullptr)) {
1191 /* this should be fairly unlikely but possible if layers move about after we get them */
1192 PyErr_SetString(PyExc_KeyError, "BMElem[key]: layer not found");
1193 return nullptr;
1194 }
1195
1196 return value;
1197}
1198
1200{
1201 void *value = bpy_bmlayeritem_ptr_get(py_ele, py_layer);
1202 PyObject *ret;
1203
1204 if (UNLIKELY(value == nullptr)) {
1205 return nullptr;
1206 }
1207
1208 switch (py_layer->type) {
1209 case CD_MDEFORMVERT: {
1210 ret = BPy_BMDeformVert_CreatePyObject(static_cast<MDeformVert *>(value));
1211 break;
1212 }
1213 case CD_PROP_FLOAT: {
1214 ret = PyFloat_FromDouble(*(float *)value);
1215 break;
1216 }
1217 case CD_PROP_INT32: {
1218 ret = PyLong_FromLong(*(int *)value);
1219 break;
1220 }
1221 case CD_PROP_BOOL: {
1222 ret = PyBool_FromLong(*(bool *)value);
1223 break;
1224 }
1225 case CD_PROP_FLOAT3: {
1226 ret = Vector_CreatePyObject_wrap((float *)value, 3, nullptr);
1227 break;
1228 }
1229 case CD_PROP_COLOR: {
1230 ret = Vector_CreatePyObject_wrap((float *)value, 4, nullptr);
1231 break;
1232 }
1233 case CD_PROP_STRING: {
1234 MStringProperty *mstring = static_cast<MStringProperty *>(value);
1235 ret = PyBytes_FromStringAndSize(mstring->s, mstring->s_len);
1236 break;
1237 }
1238 case CD_PROP_FLOAT2: {
1239 if (UNLIKELY(py_ele->bm != py_layer->bm)) {
1240 PyErr_SetString(PyExc_ValueError, "BMElem[layer]: layer is from another mesh");
1241 return nullptr;
1242 }
1243 ret = BPy_BMLoopUV_CreatePyObject(py_ele->bm, (BMLoop *)py_ele->ele, py_layer->index);
1244 break;
1245 }
1246 case CD_PROP_BYTE_COLOR: {
1247 ret = BPy_BMLoopColor_CreatePyObject(static_cast<MLoopCol *>(value));
1248 break;
1249 }
1250 case CD_SHAPEKEY: {
1251 ret = Vector_CreatePyObject_wrap((float *)value, 3, nullptr);
1252 break;
1253 }
1254 case CD_MVERT_SKIN: {
1255 ret = BPy_BMVertSkin_CreatePyObject(static_cast<MVertSkin *>(value));
1256 break;
1257 }
1258 default: {
1259 ret = Py_NotImplemented; /* TODO */
1260 Py_INCREF(ret);
1261 break;
1262 }
1263 }
1264
1265 return ret;
1266}
1267
1268int BPy_BMLayerItem_SetItem(BPy_BMElem *py_ele, BPy_BMLayerItem *py_layer, PyObject *py_value)
1269{
1270 int ret = 0;
1271 void *value = bpy_bmlayeritem_ptr_get(py_ele, py_layer);
1272
1273 if (UNLIKELY(value == nullptr)) {
1274 return -1;
1275 }
1276
1277 switch (py_layer->type) {
1278 case CD_MDEFORMVERT: {
1279 ret = BPy_BMDeformVert_AssignPyObject(static_cast<MDeformVert *>(value), py_value);
1280 break;
1281 }
1282 case CD_PROP_FLOAT: {
1283 const float tmp_val = PyFloat_AsDouble(py_value);
1284 if (UNLIKELY(tmp_val == -1 && PyErr_Occurred())) {
1285 PyErr_Format(
1286 PyExc_TypeError, "expected a float, not a %.200s", Py_TYPE(py_value)->tp_name);
1287 ret = -1;
1288 }
1289 else {
1290 *(float *)value = tmp_val;
1291 }
1292 break;
1293 }
1294 case CD_PROP_INT32: {
1295 const int tmp_val = PyC_Long_AsI32(py_value);
1296 if (UNLIKELY(tmp_val == -1 && PyErr_Occurred())) {
1297 /* error is set */
1298 ret = -1;
1299 }
1300 else {
1301 *(int *)value = tmp_val;
1302 }
1303 break;
1304 }
1305 case CD_PROP_BOOL: {
1306 const int tmp_val = PyC_Long_AsBool(py_value);
1307 if (UNLIKELY(tmp_val == -1)) {
1308 /* The error has been set. */
1309 ret = -1;
1310 }
1311 else {
1312 *(bool *)value = tmp_val;
1313 }
1314 break;
1315 }
1316 case CD_PROP_FLOAT3: {
1317 if (mathutils_array_parse((float *)value, 3, 3, py_value, "BMElem Float Vector") == -1) {
1318 ret = -1;
1319 }
1320 break;
1321 }
1322 case CD_PROP_COLOR: {
1323 if (mathutils_array_parse((float *)value, 4, 4, py_value, "BMElem Float Color") == -1) {
1324 ret = -1;
1325 }
1326 break;
1327 }
1328 case CD_PROP_STRING: {
1329 MStringProperty *mstring = static_cast<MStringProperty *>(value);
1330 char *tmp_val;
1331 Py_ssize_t tmp_val_len;
1332 if (UNLIKELY(PyBytes_AsStringAndSize(py_value, &tmp_val, &tmp_val_len) == -1)) {
1333 PyErr_Format(PyExc_TypeError, "expected bytes, not a %.200s", Py_TYPE(py_value)->tp_name);
1334 ret = -1;
1335 }
1336 else {
1337 tmp_val_len = std::min<ulong>(tmp_val_len, sizeof(mstring->s));
1338 memcpy(mstring->s, tmp_val, tmp_val_len);
1339 mstring->s_len = tmp_val_len;
1340 }
1341 break;
1342 }
1343 case CD_PROP_FLOAT2: {
1344 if (UNLIKELY(py_ele->bm != py_layer->bm)) {
1345 PyErr_SetString(PyExc_ValueError, "BMElem[layer]: layer is from another mesh");
1346 ret = -1;
1347 }
1348 else {
1349 ret = BPy_BMLoopUV_AssignPyObject(py_ele->bm, (BMLoop *)py_ele->ele, py_value);
1350 }
1351 break;
1352 }
1353 case CD_PROP_BYTE_COLOR: {
1354 ret = BPy_BMLoopColor_AssignPyObject(static_cast<MLoopCol *>(value), py_value);
1355 break;
1356 }
1357 case CD_SHAPEKEY: {
1358 float tmp_val[3];
1359 if (UNLIKELY(mathutils_array_parse(tmp_val, 3, 3, py_value, "BMVert[shape] = value") == -1))
1360 {
1361 ret = -1;
1362 }
1363 else {
1364 copy_v3_v3((float *)value, tmp_val);
1365 }
1366 break;
1367 }
1368 case CD_MVERT_SKIN: {
1369 ret = BPy_BMVertSkin_AssignPyObject(static_cast<MVertSkin *>(value), py_value);
1370 break;
1371 }
1372 default: {
1373 PyErr_SetString(PyExc_AttributeError, "readonly / unsupported type");
1374 ret = -1;
1375 break;
1376 }
1377 }
1378
1379 return ret;
1380}
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_FREESTYLE_EDGE
@ CD_FREESTYLE_FACE
@ CD_PROP_STRING
bool stop
Definition WM_types.hh:1016
@ BM_LOOP
void BM_data_layer_free_n(BMesh *bm, CustomData *data, int type, int n)
void BM_uv_map_attr_select_and_pin_ensure(BMesh *bm)
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)
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)
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 *)
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
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)
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:139