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