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