22 #include "../generic/py_capi_utils.h"
23 #include "../generic/python_utildefines.h"
24 #include "../mathutils/mathutils.h"
51 if (index_absolute != -1) {
52 return &
data->layers[index_absolute];
55 PyErr_SetString(PyExc_RuntimeError,
"layer has become invalid");
68 "Generic float custom-data layer.\n\ntype: :class:`BMLayerCollection`");
70 "Generic int custom-data layer.\n\ntype: :class:`BMLayerCollection`");
72 "Generic 3D vector with float precision custom-data layer.\n\ntype: "
73 ":class:`BMLayerCollection`");
75 "Generic RGBA color with float precision custom-data layer.\n\ntype: "
76 ":class:`BMLayerCollection`");
78 "Generic RGBA color with 8-bit precision custom-data layer.\n\ntype: "
79 ":class:`BMLayerCollection`");
81 "Generic string custom-data layer (exposed as bytes, 255 max length).\n\ntype: "
82 ":class:`BMLayerCollection`");
84 "Vertex deform weight :class:`BMDeformVert` (TODO).\n\ntype: "
85 ":class:`BMLayerCollection`"
88 bpy_bmlayeraccess_collection__shape_doc,
89 "Vertex shapekey absolute location (as a 3D Vector).\n\n:type: :class:`BMLayerCollection`");
91 "Bevel weight float in [0 - 1].\n\n:type: :class:`BMLayerCollection`");
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`");
99 "Accessor for skin layer.\n\ntype: :class:`BMLayerCollection`");
101 "Accessor for paint mask layer.\n\ntype: :class:`BMLayerCollection`");
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`");
121 "The active layer of this type (read-only).\n\n:type: :class:`BMLayerItem`");
140 bpy_bmlayercollection_is_singleton_doc,
141 "True if there can exists only one layer of this type (read-only).\n\n:type: boolean");
150 "The layers unique name (read-only).\n\n:type: string");
159 return PyUnicode_FromString(layer->
name);
169 bpy_bmlayeraccess_collection__deform_doc,
175 bpy_bmlayeraccess_collection__float_doc,
180 bpy_bmlayeraccess_collection__int_doc,
185 bpy_bmlayeraccess_collection__float_vector_doc,
190 bpy_bmlayeraccess_collection__float_color_doc,
195 bpy_bmlayeraccess_collection__color_doc,
200 bpy_bmlayeraccess_collection__string_doc,
206 bpy_bmlayeraccess_collection__shape_doc,
211 bpy_bmlayeraccess_collection__bevel_weight_doc,
216 bpy_bmlayeraccess_collection__crease_doc,
221 bpy_bmlayeraccess_collection__skin_doc,
226 bpy_bmlayeraccess_collection__paint_mask_doc,
236 bpy_bmlayeraccess_collection__float_doc,
241 bpy_bmlayeraccess_collection__int_doc,
246 bpy_bmlayeraccess_collection__float_vector_doc,
251 bpy_bmlayeraccess_collection__float_color_doc,
256 bpy_bmlayeraccess_collection__color_doc,
261 bpy_bmlayeraccess_collection__string_doc,
267 bpy_bmlayeraccess_collection__bevel_weight_doc,
272 bpy_bmlayeraccess_collection__crease_doc,
274 #ifdef WITH_FREESTYLE
278 bpy_bmlayeraccess_collection__freestyle_edge_doc,
289 bpy_bmlayeraccess_collection__float_doc,
294 bpy_bmlayeraccess_collection__int_doc,
299 bpy_bmlayeraccess_collection__float_vector_doc,
304 bpy_bmlayeraccess_collection__float_color_doc,
309 bpy_bmlayeraccess_collection__color_doc,
314 bpy_bmlayeraccess_collection__string_doc,
319 bpy_bmlayeraccess_collection__face_map_doc,
322 #ifdef WITH_FREESTYLE
326 bpy_bmlayeraccess_collection__freestyle_face_doc,
337 bpy_bmlayeraccess_collection__float_doc,
342 bpy_bmlayeraccess_collection__int_doc,
347 bpy_bmlayeraccess_collection__float_vector_doc,
352 bpy_bmlayeraccess_collection__float_color_doc,
357 bpy_bmlayeraccess_collection__string_doc,
362 bpy_bmlayeraccess_collection__uv_doc,
367 bpy_bmlayeraccess_collection__color_doc,
378 bpy_bmlayercollection_active_doc,
383 bpy_bmlayercollection_is_singleton_doc,
403 ".. method:: copy_from(other)\n"
405 " Return a copy of the layer\n"
407 " :arg other: Another layer to copy from.\n"
408 " :arg other: :class:`BMLayerItem`\n");
414 PyErr_Format(PyExc_TypeError,
415 "layer.copy_from(x): expected BMLayerItem, not '%.200s'",
416 Py_TYPE(value)->tp_name);
424 PyErr_SetString(PyExc_ValueError,
"layer.copy_from(other): layer type mismatch");
444 ".. method:: verify()\n"
446 " Create a new layer or return an existing active layer\n"
448 " :return: The newly verified layer.\n"
449 " :rtype: :class:`BMLayerItem`\n");
472 ".. method:: new(name)\n"
474 " Create a new layer\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");
482 const char *name =
NULL;
488 if (!PyArg_ParseTuple(args,
"|s:new", &name)) {
495 PyErr_SetString(PyExc_ValueError,
"layers.new(): is a singleton, use verify() instead");
513 ".. method:: remove(layer)\n"
517 " :arg layer: The layer to remove.\n"
518 " :type layer: :class:`BMLayerItem`\n");
526 PyErr_Format(PyExc_TypeError,
527 "layers.remove(x): expected BMLayerItem, not '%.200s'",
528 Py_TYPE(value)->tp_name);
535 PyErr_SetString(PyExc_ValueError,
"layers.remove(x): x not in layers");
545 ".. method:: keys()\n"
547 " Return the identifiers of collection members\n"
548 " (matching pythons dict.keys() functionality).\n"
550 " :return: the identifiers for each member of this collection.\n"
551 " :rtype: list of strings\n");
569 ret = PyList_New(tot);
571 for (i = 0; tot-- > 0; index++) {
572 item = PyUnicode_FromString(
data->layers[index].name);
573 PyList_SET_ITEM(
ret, i++, item);
580 ".. method:: items()\n"
582 " Return the identifiers of collection members\n"
583 " (matching pythons dict.items() functionality).\n"
585 " :return: (key, value) pairs for each member of this collection.\n"
586 " :rtype: list of tuples\n");
601 ret = PyList_New(tot);
603 for (i = 0; tot-- > 0; index++) {
604 item = PyTuple_New(2);
606 PyUnicode_FromString(
data->layers[index].name),
608 PyList_SET_ITEM(
ret, i++, item);
615 ".. method:: values()\n"
617 " Return the values of collection\n"
618 " (matching pythons dict.values() functionality).\n"
620 " :return: the members of this collection.\n"
636 ret = PyList_New(tot);
638 for (i = 0; tot-- > 0; index++) {
640 PyList_SET_ITEM(
ret, i++, item);
647 ".. method:: get(key, default=None)\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"
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");
660 PyObject *def = Py_None;
664 if (!PyArg_ParseTuple(args,
"s|O:get", &key, &def)) {
678 return Py_INCREF_RET(def);
690 bpy_bmlayercollection_verify_doc},
695 bpy_bmlayercollection_remove_doc},
701 bpy_bmlayercollection_values_doc},
705 bpy_bmlayercollection_items_doc},
739 PyErr_Format(PyExc_KeyError,
"BMLayerCollection[key]: key \"%.200s\" not found", keyname);
759 PyErr_Format(PyExc_IndexError,
"BMLayerCollection[index]: index %d out of range", keynum);
781 tuple = PyTuple_New(stop - start);
784 PyTuple_SET_ITEM(tuple,
795 if (PyUnicode_Check(key)) {
798 if (PyIndex_Check(key)) {
799 const Py_ssize_t i = PyNumber_AsSsize_t(key, PyExc_IndexError);
800 if (i == -1 && PyErr_Occurred()) {
805 if (PySlice_Check(key)) {
806 PySliceObject *key_slice = (PySliceObject *)key;
809 if (key_slice->step != Py_None && !_PyEval_SliceIndex(key, &step)) {
813 PyErr_SetString(PyExc_TypeError,
"BMLayerCollection[slice]: slice steps not supported");
816 if (key_slice->start == Py_None && key_slice->stop == Py_None) {
820 Py_ssize_t start = 0, stop = PY_SSIZE_T_MAX;
823 if (key_slice->start != Py_None && !_PyEval_SliceIndex(key_slice->start, &start)) {
826 if (key_slice->stop != Py_None && !_PyEval_SliceIndex(key_slice->stop, &stop)) {
830 if (start < 0 || stop < 0) {
843 if (stop - start <= 0) {
844 return PyTuple_New(0);
850 PyErr_SetString(PyExc_AttributeError,
"BMLayerCollection[key]: invalid key, key must be an int");
856 const char *keyname = PyUnicode_AsUTF8(value);
862 if (keyname ==
NULL) {
863 PyErr_SetString(PyExc_TypeError,
"BMLayerCollection.__contains__: expected a string");
870 return (index != -1) ? 1 : 0;
880 (ssizeobjargproc)
NULL,
900 PyObject *iter =
NULL;
907 iter = PyObject_GetIter(
ret);
914 PyDoc_STRVAR(bpy_bmlayeraccess_type_doc,
"Exposes custom-data layer attributes.");
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.");
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.");
961 return (PyObject *)
self;
970 return (PyObject *)
self;
980 return (PyObject *)
self;
1067 PyErr_SetString(PyExc_AttributeError,
"BMElem[key]: invalid key, must be a BMLayerItem");
1071 PyErr_SetString(PyExc_ValueError,
"BMElem[layer]: layer is from another mesh");
1075 char namestr_1[32], namestr_2[32];
1076 PyErr_Format(PyExc_ValueError,
1077 "Layer/Element type mismatch, expected %.200s got layer type %.200s",
1089 PyErr_SetString(PyExc_KeyError,
"BMElem[key]: layer not found");
1105 switch (py_layer->
type) {
1112 ret = PyFloat_FromDouble(*(
float *)value);
1117 ret = PyLong_FromLong(*(
int *)value);
1130 ret = PyBytes_FromStringAndSize(mstring->
s, mstring->
s_len);
1146 ret = PyFloat_FromDouble(*(
float *)value);
1150 ret = PyFloat_FromDouble(*(
float *)value);
1158 ret = Py_NotImplemented;
1176 switch (py_layer->
type) {
1183 const float tmp_val = PyFloat_AsDouble(py_value);
1184 if (
UNLIKELY(tmp_val == -1 && PyErr_Occurred())) {
1186 PyExc_TypeError,
"expected a float, not a %.200s", Py_TYPE(py_value)->tp_name);
1190 *(
float *)value = tmp_val;
1196 const int tmp_val = PyC_Long_AsI32(py_value);
1197 if (
UNLIKELY(tmp_val == -1 && PyErr_Occurred())) {
1202 *(
int *)value = 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);
1227 if (tmp_val_len >
sizeof(mstring->
s)) {
1228 tmp_val_len =
sizeof(mstring->
s);
1230 memcpy(mstring->
s, tmp_val, tmp_val_len);
1231 mstring->
s_len = tmp_val_len;
1255 const float tmp_val = PyFloat_AsDouble(py_value);
1256 if (
UNLIKELY(tmp_val == -1 && PyErr_Occurred())) {
1258 PyExc_TypeError,
"expected a float, not a %.200s", Py_TYPE(py_value)->tp_name);
1262 *(
float *)value =
clamp_f(tmp_val, 0.0f, 1.0f);
1267 const float tmp_val = PyFloat_AsDouble(py_value);
1268 if (
UNLIKELY(tmp_val == -1 && PyErr_Occurred())) {
1270 PyExc_TypeError,
"expected a float, not a %.200s", Py_TYPE(py_value)->tp_name);
1274 *(
float *)value =
clamp_f(tmp_val, 0.0f, 1.0f);
1283 PyErr_SetString(PyExc_AttributeError,
"readonly / unsupported type");
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)
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()
MINLINE float clamp_f(float value, float min, float max)
MINLINE void copy_v3_v3(float r[3], const float a[3])
#define POINTER_AS_INT(i)
_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
void BM_data_layer_free_n(BMesh *bm, CustomData *data, int type, int n)
void BM_data_layer_copy(BMesh *bm, CustomData *data, int type, int src_n, int dst_n)
void BM_data_layer_add(BMesh *bm, CustomData *data, int type)
void BM_data_layer_add_named(BMesh *bm, CustomData *data, int type, const char *name)
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)
int mathutils_array_parse(float *array, int array_num_min, int array_num_max, PyObject *value, const char *error_prefix)
PyObject * Vector_CreatePyObject_wrap(float *vec, const int vec_num, PyTypeObject *base_type)
#define PyTuple_SET_ITEMS(op_arg,...)
PyObject_VAR_HEAD struct BMesh * bm
PyObject_VAR_HEAD struct BMesh * bm