Welcome to mirror list, hosted at ThFree Co, Russian Federation.

git.blender.org/blender.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
path: root/source
diff options
context:
space:
mode:
authorCampbell Barton <ideasman42@gmail.com>2012-03-16 12:26:22 +0400
committerCampbell Barton <ideasman42@gmail.com>2012-03-16 12:26:22 +0400
commitf91407150a9415b55765abc7ac870c2be2703334 (patch)
treead689025f6accf3d6d8da367353bde161781700e /source
parent1823bb4abb68b24b6c8db4cd388a855457dc45f4 (diff)
bmesh py api:
initial support for editing bmesh customdata per vert/edge/face/loop shapes, crease, bevel weights working, missing UVs and Vertex Colors still.
Diffstat (limited to 'source')
-rw-r--r--source/blender/bmesh/bmesh_error.h2
-rw-r--r--source/blender/python/bmesh/bmesh_py_types.c40
-rw-r--r--source/blender/python/bmesh/bmesh_py_types.h1
-rw-r--r--source/blender/python/bmesh/bmesh_py_types_customdata.c258
-rw-r--r--source/blender/python/bmesh/bmesh_py_types_customdata.h5
5 files changed, 302 insertions, 4 deletions
diff --git a/source/blender/bmesh/bmesh_error.h b/source/blender/bmesh/bmesh_error.h
index b88b1ff890f..84065fe88f6 100644
--- a/source/blender/bmesh/bmesh_error.h
+++ b/source/blender/bmesh/bmesh_error.h
@@ -49,7 +49,7 @@ void BMO_error_clear(BMesh *bm);
* errorcode is either the errorcode, or BMERR_ALL for any
* error.*/
-/* not yet implimented.
+/* not yet implemented.
* int BMO_error_catch_op(BMesh *bm, BMOperator *catchop, int errorcode, char **msg);
*/
diff --git a/source/blender/python/bmesh/bmesh_py_types.c b/source/blender/python/bmesh/bmesh_py_types.c
index d9344c3b690..8b3a32ea923 100644
--- a/source/blender/python/bmesh/bmesh_py_types.c
+++ b/source/blender/python/bmesh/bmesh_py_types.c
@@ -2097,6 +2097,9 @@ static struct PyMethodDef bpy_bmelemseq_methods[] = {
/* Sequences
* ========= */
+/* BMElemSeq / Iter
+ * ---------------- */
+
static PyTypeObject *bpy_bm_itype_as_pytype(const char itype)
{
/* should cover all types */
@@ -2305,6 +2308,23 @@ static int bpy_bmelemseq_contains(BPy_BMElemSeq *self, PyObject *value)
return 0;
}
+/* BMElem (customdata)
+ * ------------------- */
+
+static PyObject *bpy_bmelem_subscript(BPy_BMElem *self, BPy_BMLayerItem *key)
+{
+ BPY_BM_CHECK_OBJ(self);
+
+ return BPy_BMLayerItem_GetItem(self, key);
+}
+
+static int bpy_bmelem_ass_subscript(BPy_BMElem *self, BPy_BMLayerItem *key, PyObject *value)
+{
+ BPY_BM_CHECK_INT(self);
+
+ return BPy_BMLayerItem_SetItem(self, key, value);
+}
+
static PySequenceMethods bpy_bmelemseq_as_sequence = {
(lenfunc)bpy_bmelemseq_length, /* sq_length */
NULL, /* sq_concat */
@@ -2324,6 +2344,13 @@ static PyMappingMethods bpy_bmelemseq_as_mapping = {
(objobjargproc)NULL, /* mp_ass_subscript */
};
+/* for customdata access */
+static PyMappingMethods bpy_bm_elem_as_mapping = {
+ (lenfunc)NULL, /* mp_length */ /* keep this empty, messes up 'if elem: ...' test */
+ (binaryfunc)bpy_bmelem_subscript, /* mp_subscript */
+ (objobjargproc)bpy_bmelem_ass_subscript, /* mp_ass_subscript */
+};
+
/* Iterator
* -------- */
@@ -2613,6 +2640,10 @@ void BPy_BM_init_types(void)
BPy_BMElemSeq_Type.tp_as_sequence = &bpy_bmelemseq_as_sequence;
+ BPy_BMVert_Type.tp_as_mapping = &bpy_bm_elem_as_mapping;
+ BPy_BMEdge_Type.tp_as_mapping = &bpy_bm_elem_as_mapping;
+ BPy_BMFace_Type.tp_as_mapping = &bpy_bm_elem_as_mapping;
+ BPy_BMLoop_Type.tp_as_mapping = &bpy_bm_elem_as_mapping;
BPy_BMElemSeq_Type.tp_as_mapping = &bpy_bmelemseq_as_mapping;
BPy_BMElemSeq_Type.tp_iter = (getiterfunc)bpy_bmelemseq_iter;
@@ -3015,10 +3046,9 @@ int BPy_BMElem_CheckHType(PyTypeObject *type, const char htype)
*
* \return a sting like '(BMVert/BMEdge/BMFace/BMLoop)'
*/
-char *BPy_BMElem_StringFromHType(const char htype)
+char *BPy_BMElem_StringFromHType_ex(const char htype, char ret[32])
{
/* zero to ensure string is always NULL terminated */
- static char ret[32];
char *ret_ptr = ret;
if (htype & BM_VERT) ret_ptr += sprintf(ret_ptr, "/%s", BPy_BMVert_Type.tp_name);
if (htype & BM_EDGE) ret_ptr += sprintf(ret_ptr, "/%s", BPy_BMEdge_Type.tp_name);
@@ -3028,3 +3058,9 @@ char *BPy_BMElem_StringFromHType(const char htype)
*ret_ptr = ')';
return ret;
}
+char *BPy_BMElem_StringFromHType(const char htype)
+{
+ /* zero to ensure string is always NULL terminated */
+ static char ret[32];
+ return BPy_BMElem_StringFromHType_ex(htype, ret);
+}
diff --git a/source/blender/python/bmesh/bmesh_py_types.h b/source/blender/python/bmesh/bmesh_py_types.h
index 452c8b2103f..cb4646330a7 100644
--- a/source/blender/python/bmesh/bmesh_py_types.h
+++ b/source/blender/python/bmesh/bmesh_py_types.h
@@ -145,6 +145,7 @@ void *BPy_BMElem_PySeq_As_Array(BMesh **r_bm, PyObject *seq, Py_ssize_t min, Py_
PyObject *BPy_BMElem_Array_As_Tuple(BMesh *bm, BMHeader **elem, Py_ssize_t elem_len);
int BPy_BMElem_CheckHType(PyTypeObject *type, const char htype);
+char *BPy_BMElem_StringFromHType_ex(const char htype, char ret[32]);
char *BPy_BMElem_StringFromHType(const char htype);
diff --git a/source/blender/python/bmesh/bmesh_py_types_customdata.c b/source/blender/python/bmesh/bmesh_py_types_customdata.c
index 4b53b6e11d0..a44cc78088d 100644
--- a/source/blender/python/bmesh/bmesh_py_types_customdata.c
+++ b/source/blender/python/bmesh/bmesh_py_types_customdata.c
@@ -32,13 +32,20 @@
#include <Python.h>
+#include "BLI_string.h"
+#include "BLI_math_vector.h"
+
#include "bmesh.h"
#include "bmesh_py_types.h"
#include "bmesh_py_types_customdata.h"
+#include "../mathutils/mathutils.h"
+
#include "BKE_customdata.h"
+#include "DNA_meshdata_types.h"
+
static CustomData *bpy_bm_customdata_get(BMesh *bm, char htype)
{
switch (htype) {
@@ -95,7 +102,7 @@ static PyGetSetDef bpy_bmlayeraccess_getseters[] = {
{(char *)"color", (getter)bpy_bmlayeraccess_collection_get, (setter)NULL, (char *)NULL, (void *)CD_MLOOPCOL},
{(char *)"shape", (getter)bpy_bmlayeraccess_collection_get, (setter)NULL, (char *)NULL, (void *)CD_SHAPEKEY},
- {(char *)"bevel_weight", (getter)bpy_bmlayeraccess_collection_get, (setter)NULL, (char *)NULL, (void *)CD_SHAPEKEY},
+ {(char *)"bevel_weight", (getter)bpy_bmlayeraccess_collection_get, (setter)NULL, (char *)NULL, (void *)CD_BWEIGHT},
{(char *)"crease", (getter)bpy_bmlayeraccess_collection_get, (setter)NULL, (char *)NULL, (void *)CD_CREASE},
{NULL, NULL, NULL, NULL, NULL} /* Sentinel */
@@ -545,3 +552,252 @@ void BPy_BM_init_types_customdata(void)
PyType_Ready(&BPy_BMLayerCollection_Type);
PyType_Ready(&BPy_BMLayerItem_Type);
}
+
+
+/* Per Element Get/Set
+ * ******************* */
+
+/**
+ * helper function for get/set, NULL return means the error is set
+*/
+static void *bpy_bmlayeritem_ptr_get(BPy_BMElem *py_ele, BPy_BMLayerItem *py_layer)
+{
+ void *value;
+ BMElem *ele = py_ele->ele;
+ CustomData *data;
+
+ /* error checking */
+ if (UNLIKELY(!BPy_BMLayerItem_Check(py_layer))) {
+ PyErr_SetString(PyExc_AttributeError,
+ "BMElem[key]: invalid key, must be a BMLayerItem");
+ return NULL;
+ }
+ else if (UNLIKELY(py_ele->bm != py_layer->bm)) {
+ PyErr_SetString(PyExc_ValueError,
+ "BMElem[layer]: layer is from another mesh");
+ return NULL;
+ }
+ else if (UNLIKELY(ele->head.htype != py_layer->htype)) {
+ char namestr_1[32], namestr_2[32];
+ PyErr_Format(PyExc_ValueError,
+ "Layer/Element type mismatch, expected %.200s got layer type %.200s",
+ BPy_BMElem_StringFromHType_ex(ele->head.htype, namestr_1),
+ BPy_BMElem_StringFromHType_ex(py_layer->htype, namestr_2));
+ return NULL;
+ }
+
+ data = bpy_bm_customdata_get(py_layer->bm, py_layer->htype);
+
+ value = CustomData_bmesh_get_n(data, ele->head.data, py_layer->type, py_layer->index);
+
+ if (UNLIKELY(value == NULL)) {
+ /* this should be fairly unlikely but possible if layers move about after we get them */
+ PyErr_SetString(PyExc_KeyError,
+ "BMElem[key]: layer not found");
+ return NULL;
+ }
+ else {
+ return value;
+ }
+}
+
+
+/**
+ *\brief BMElem.__getitem__()
+ *
+ * assume all error checks are done, eg:
+ *
+ * uv = vert[uv_layer]
+ */
+PyObject *BPy_BMLayerItem_GetItem(BPy_BMElem *py_ele, BPy_BMLayerItem *py_layer)
+{
+ void *value = bpy_bmlayeritem_ptr_get(py_ele, py_layer);
+ PyObject *ret;
+
+ if (UNLIKELY(value == NULL)) {
+ return NULL;
+ }
+
+ switch (py_layer->type) {
+ case CD_MDEFORMVERT:
+ {
+ ret = Py_NotImplemented; /* TODO */
+ Py_INCREF(ret);
+ break;
+ }
+ case CD_PROP_FLT:
+ {
+ ret = PyFloat_FromDouble(*(float *)value);
+ break;
+ }
+ case CD_PROP_INT:
+ {
+ ret = PyLong_FromSsize_t((Py_ssize_t)(*(int *)value));
+ break;
+ }
+ case CD_PROP_STR:
+ {
+ MStringProperty *mstring = value;
+ ret = PyBytes_FromStringAndSize(mstring->s, BLI_strnlen(mstring->s, sizeof(mstring->s)));
+ break;
+ }
+ case CD_MTEXPOLY:
+ {
+ ret = Py_NotImplemented; /* TODO */
+ Py_INCREF(ret);
+ break;
+ }
+ case CD_MLOOPUV:
+ {
+ ret = Py_NotImplemented; /* TODO */
+ Py_INCREF(ret);
+ break;
+ }
+ case CD_MLOOPCOL:
+ {
+ ret = Py_NotImplemented; /* TODO */
+ Py_INCREF(ret);
+ break;
+ }
+ case CD_SHAPEKEY:
+ {
+ ret = Vector_CreatePyObject((float *)value, 3, Py_WRAP, NULL);
+ break;
+ }
+ case CD_BWEIGHT:
+ {
+ ret = PyFloat_FromDouble(*(float *)value);
+ break;
+ }
+ case CD_CREASE:
+ {
+ ret = PyFloat_FromDouble(*(float *)value);
+ break;
+ }
+ default:
+ {
+ ret = Py_NotImplemented; /* TODO */
+ Py_INCREF(ret);
+ break;
+ }
+ }
+
+ return ret;
+}
+
+int BPy_BMLayerItem_SetItem(BPy_BMElem *py_ele, BPy_BMLayerItem *py_layer, PyObject *py_value)
+{
+ int ret = 0;
+ void *value = bpy_bmlayeritem_ptr_get(py_ele, py_layer);
+
+ if (UNLIKELY(value == NULL)) {
+ return -1;
+ }
+
+ switch (py_layer->type) {
+ case CD_MDEFORMVERT:
+ {
+ PyErr_SetString(PyExc_AttributeError, "readonly"); /* could make this writeable later */
+ ret = -1;
+ break;
+ }
+ case CD_PROP_FLT:
+ {
+ float tmp_val = PyFloat_AsDouble(py_value);
+ if (UNLIKELY(tmp_val == -1 && PyErr_Occurred())) {
+ PyErr_Format(PyExc_TypeError, "expected a float, not a %.200s", Py_TYPE(py_value)->tp_name);
+ ret = -1;
+ }
+ else {
+ *(float *)value = tmp_val;
+ }
+ break;
+ }
+ case CD_PROP_INT:
+ {
+ int tmp_val = PyLong_AsSsize_t(py_value);
+ if (UNLIKELY(tmp_val == -1 && PyErr_Occurred())) {
+ PyErr_Format(PyExc_TypeError, "expected an int, not a %.200s", Py_TYPE(py_value)->tp_name);
+ ret = -1;
+ }
+ else {
+ *(int *)value = tmp_val;
+ }
+ break;
+ }
+ case CD_PROP_STR:
+ {
+ MStringProperty *mstring = value;
+ const char *tmp_val = PyBytes_AsString(py_value);
+ if (UNLIKELY(tmp_val == NULL)) {
+ PyErr_Format(PyExc_TypeError, "expected bytes, not a %.200s", Py_TYPE(py_value)->tp_name);
+ ret = -1;
+ }
+ else {
+ BLI_strncpy(mstring->s, tmp_val, sizeof(mstring->s));
+ }
+ break;
+ }
+ case CD_MTEXPOLY:
+ {
+ PyErr_SetString(PyExc_AttributeError, "readonly"); /* could make this writeable later */
+ ret = -1;
+ break;
+ }
+ case CD_MLOOPUV:
+ {
+ PyErr_SetString(PyExc_AttributeError, "readonly"); /* could make this writeable later */
+ ret = -1;
+ break;
+ }
+ case CD_MLOOPCOL:
+ {
+ PyErr_SetString(PyExc_AttributeError, "readonly");
+ ret = -1;
+ break;
+ }
+ case CD_SHAPEKEY:
+ {
+ float tmp_val[3];
+ if (UNLIKELY(mathutils_array_parse(tmp_val, 3, 3, py_value, "BMVert[shape] = value") == -1)) {
+ ret = -1;
+ }
+ else {
+ copy_v3_v3((float *)value,tmp_val);
+ }
+ break;
+ }
+ case CD_BWEIGHT:
+ {
+ float tmp_val = PyFloat_AsDouble(py_value);
+ if (UNLIKELY(tmp_val == -1 && PyErr_Occurred())) {
+ PyErr_Format(PyExc_TypeError, "expected a float, not a %.200s", Py_TYPE(py_value)->tp_name);
+ ret = -1;
+ }
+ else {
+ *(float *)value = CLAMPIS(tmp_val, 0.0f, 1.0f);
+ }
+ break;
+ }
+ case CD_CREASE:
+ {
+ float tmp_val = PyFloat_AsDouble(py_value);
+ if (UNLIKELY(tmp_val == -1 && PyErr_Occurred())) {
+ PyErr_Format(PyExc_TypeError, "expected a float, not a %.200s", Py_TYPE(py_value)->tp_name);
+ ret = -1;
+ }
+ else {
+ *(float *)value = CLAMPIS(tmp_val, 0.0f, 1.0f);
+ }
+ break;
+ }
+ default:
+ {
+ PyErr_SetString(PyExc_AttributeError, "readonly / unsupported type");
+ ret = -1;
+ break;
+ }
+ }
+
+ return ret;
+}
diff --git a/source/blender/python/bmesh/bmesh_py_types_customdata.h b/source/blender/python/bmesh/bmesh_py_types_customdata.h
index 0de79d7bd21..6ec947f98fa 100644
--- a/source/blender/python/bmesh/bmesh_py_types_customdata.h
+++ b/source/blender/python/bmesh/bmesh_py_types_customdata.h
@@ -68,4 +68,9 @@ PyObject *BPy_BMLayerItem_CreatePyObject(BMesh *bm, const char htype, int type,
void BPy_BM_init_types_customdata(void);
+/* __getitem__ / __setitem__ */
+PyObject *BPy_BMLayerItem_GetItem(BPy_BMElem *py_ele, BPy_BMLayerItem *py_layer);
+int BPy_BMLayerItem_SetItem(BPy_BMElem *py_ele, BPy_BMLayerItem *py_layer, PyObject *value);
+
+
#endif /* __BMESH_PY_TYPES_CUSTOMDATA_H__ */