diff options
author | Campbell Barton <ideasman42@gmail.com> | 2012-11-26 12:44:37 +0400 |
---|---|---|
committer | Campbell Barton <ideasman42@gmail.com> | 2012-11-26 12:44:37 +0400 |
commit | 42c54bcd9362922bed70d596568c7495fa6334bb (patch) | |
tree | fc82676c84a4675d1464fad757ae7addddc8e028 /source | |
parent | 9784f3d466e80f442c8d922b971b6b2937c8cbd6 (diff) |
py/bmesh api - support for converting from/to BMO_OP_SLOT_MAPPING type.
Diffstat (limited to 'source')
-rw-r--r-- | source/blender/bmesh/intern/bmesh_operator_api.h | 5 | ||||
-rw-r--r-- | source/blender/bmesh/intern/bmesh_operator_api_inline.h | 6 | ||||
-rw-r--r-- | source/blender/bmesh/intern/bmesh_operators.c | 8 | ||||
-rw-r--r-- | source/blender/python/bmesh/bmesh_py_ops.c | 280 | ||||
-rw-r--r-- | source/blender/python/bmesh/bmesh_py_types.c | 3 | ||||
-rw-r--r-- | source/blender/python/bmesh/bmesh_py_types.h | 2 |
6 files changed, 281 insertions, 23 deletions
diff --git a/source/blender/bmesh/intern/bmesh_operator_api.h b/source/blender/bmesh/intern/bmesh_operator_api.h index efc2f6a492e..e84883540d6 100644 --- a/source/blender/bmesh/intern/bmesh_operator_api.h +++ b/source/blender/bmesh/intern/bmesh_operator_api.h @@ -414,7 +414,7 @@ int BMO_slot_buffer_count(BMOpSlot slot_args[BMO_OP_MAX_SLOTS], const char *slot int BMO_slot_map_count(BMOpSlot slot_args[BMO_OP_MAX_SLOTS], const char *slot_name); void BMO_slot_map_insert(BMOperator *op, BMOpSlot *slot, - const void *element, void *data, int len); + const void *element, const void *data, const int len); /* Counts the number of edges with tool flag toolflag around */ @@ -502,6 +502,9 @@ typedef struct BMOElemMapping { int len; } BMOElemMapping; +/* pointer after BMOElemMapping */ +#define BMO_OP_SLOT_MAPPING_DATA(var) (void *)(((BMOElemMapping *)var) + 1) + extern const int BMO_OPSLOT_TYPEINFO[BMO_OP_SLOT_TOTAL_TYPES]; #ifdef __cplusplus diff --git a/source/blender/bmesh/intern/bmesh_operator_api_inline.h b/source/blender/bmesh/intern/bmesh_operator_api_inline.h index acbc765f0df..4143c4d0883 100644 --- a/source/blender/bmesh/intern/bmesh_operator_api_inline.h +++ b/source/blender/bmesh/intern/bmesh_operator_api_inline.h @@ -70,14 +70,14 @@ BLI_INLINE void _bmo_elem_flag_toggle(BMesh *bm, BMFlagLayer *oflags, const shor } BLI_INLINE void BMO_slot_map_int_insert(BMOperator *op, BMOpSlot *slot, - void *element, int val) + void *element, const int val) { BLI_assert(slot->slot_subtype == BMO_OP_SLOT_SUBTYPE_MAP_INT); BMO_slot_map_insert(op, slot, element, &val, sizeof(int)); } BLI_INLINE void BMO_slot_map_bool_insert(BMOperator *op, BMOpSlot *slot, - void *element, int val) + void *element, const int val) { BLI_assert(slot->slot_subtype == BMO_OP_SLOT_SUBTYPE_MAP_BOOL); BLI_assert(val == FALSE || val == TRUE); @@ -85,7 +85,7 @@ BLI_INLINE void BMO_slot_map_bool_insert(BMOperator *op, BMOpSlot *slot, } BLI_INLINE void BMO_slot_map_float_insert(BMOperator *op, BMOpSlot *slot, - void *element, float val) + void *element, const float val) { BLI_assert(slot->slot_subtype == BMO_OP_SLOT_SUBTYPE_MAP_FLOAT); BMO_slot_map_insert(op, slot, element, &val, sizeof(float)); diff --git a/source/blender/bmesh/intern/bmesh_operators.c b/source/blender/bmesh/intern/bmesh_operators.c index fd26ac16224..83fd338ef1f 100644 --- a/source/blender/bmesh/intern/bmesh_operators.c +++ b/source/blender/bmesh/intern/bmesh_operators.c @@ -314,7 +314,7 @@ void _bmo_slot_copy(BMOpSlot slot_args_src[BMO_OP_MAX_SLOTS], const char *slot_n dstmap->element = srcmap->element; dstmap->len = srcmap->len; - memcpy(dstmap + 1, srcmap + 1, srcmap->len); + memcpy(BMO_OP_SLOT_MAPPING_DATA(dstmap), BMO_OP_SLOT_MAPPING_DATA(srcmap), srcmap->len); BLI_ghash_insert(slot_dst->data.ghash, dstmap->element, dstmap); } @@ -596,7 +596,7 @@ int BMO_slot_map_count(BMOpSlot slot_args[BMO_OP_MAX_SLOTS], const char *slot_na * value, it doesn't store a reference to it. */ void BMO_slot_map_insert(BMOperator *op, BMOpSlot *slot, - const void *element, void *data, int len) + const void *element, const void *data, const int len) { BMOElemMapping *mapping; BLI_assert(slot->slot_type == BMO_OP_SLOT_MAPPING); @@ -606,7 +606,7 @@ void BMO_slot_map_insert(BMOperator *op, BMOpSlot *slot, mapping->element = (BMHeader *) element; mapping->len = len; - memcpy(mapping + 1, data, len); + memcpy(BMO_OP_SLOT_MAPPING_DATA(mapping), data, len); if (!slot->data.ghash) { slot->data.ghash = BLI_ghash_ptr_new("bmesh slot map hash"); @@ -1279,7 +1279,7 @@ void *BMO_iter_step(BMOIter *iter) void *ret = BLI_ghashIterator_getKey(&iter->giter); map = BLI_ghashIterator_getValue(&iter->giter); - iter->val = map + 1; + iter->val = BMO_OP_SLOT_MAPPING_DATA(map); BLI_ghashIterator_step(&iter->giter); diff --git a/source/blender/python/bmesh/bmesh_py_ops.c b/source/blender/python/bmesh/bmesh_py_ops.c index 5ab8b7c0e26..84b06504d2e 100644 --- a/source/blender/python/bmesh/bmesh_py_ops.c +++ b/source/blender/python/bmesh/bmesh_py_ops.c @@ -305,6 +305,179 @@ static PyObject *pyrna_op_call(BPy_BMeshOpFunc *self, PyObject *args, PyObject * break; } + case BMO_OP_SLOT_MAPPING: + { + /* first check types */ + if (slot->slot_subtype != BMO_OP_SLOT_SUBTYPE_MAP_EMPTY) { + if (!PyDict_Check(value)) { + PyErr_Format(PyExc_TypeError, + "%.200s: keyword \"%.200s\" expected " + "a dict, not %.200s", + self->opname, slot_name, Py_TYPE(value)->tp_name); + return NULL; + } + } + else { + if (!PySet_Check(value)) { + PyErr_Format(PyExc_TypeError, + "%.200s: keyword \"%.200s\" expected " + "a set, not %.200s", + self->opname, slot_name, Py_TYPE(value)->tp_name); + return NULL; + } + } + + switch (slot->slot_subtype) { + + /* this could be a static function */ +#define BPY_BM_MAPPING_KEY_CHECK(arg_key) \ + if (!BPy_BMElem_Check(arg_key)) { \ + PyErr_Format(PyExc_TypeError, \ + "%.200s: keyword \"%.200s\" expected " \ + "a dict with bmesh element keys, not %.200s", \ + self->opname, slot_name, Py_TYPE(arg_key)->tp_name); \ + return NULL; \ + } \ + else if (((BPy_BMGeneric *)arg_key)->bm == NULL) { \ + PyErr_Format(PyExc_TypeError, \ + "%.200s: keyword \"%.200s\" invalidated element key in dict", \ + self->opname, slot_name); \ + return NULL; \ + } (void)0 + + + case BMO_OP_SLOT_SUBTYPE_MAP_ELEM: + { + if (PyDict_Size(value) > 0) { + PyObject *arg_key, *arg_value; + Py_ssize_t arg_pos = 0; + while (PyDict_Next(value, &arg_pos, &arg_key, &arg_value)) { + /* TODO, check the elements come from the right mesh? */ + BPY_BM_MAPPING_KEY_CHECK(arg_key); + + if (!BPy_BMElem_Check(arg_value)) { + PyErr_Format(PyExc_TypeError, + "%.200s: keyword \"%.200s\" expected " + "a dict with bmesh element values, not %.200s", + self->opname, slot_name, Py_TYPE(arg_value)->tp_name); + return NULL; + } + else if (((BPy_BMGeneric *)arg_value)->bm == NULL) { + PyErr_Format(PyExc_TypeError, + "%.200s: keyword \"%.200s\" invalidated element value in dict", + self->opname, slot_name); + return NULL; + } + + BMO_slot_map_elem_insert(&bmop, slot, + ((BPy_BMElem *)arg_key)->ele, ((BPy_BMElem *)arg_value)->ele); + } + } + break; + } + case BMO_OP_SLOT_SUBTYPE_MAP_FLOAT: + { + if (PyDict_Size(value) > 0) { + PyObject *arg_key, *arg_value; + Py_ssize_t arg_pos = 0; + while (PyDict_Next(value, &arg_pos, &arg_key, &arg_value)) { + float value_f; + /* TODO, check the elements come from the right mesh? */ + BPY_BM_MAPPING_KEY_CHECK(arg_key); + value_f = PyFloat_AsDouble(arg_value); + + if (value_f == -1.0f && PyErr_Occurred()) { + PyErr_Format(PyExc_TypeError, + "%.200s: keyword \"%.200s\" expected " + "a dict with float values, not %.200s", + self->opname, slot_name, Py_TYPE(arg_value)->tp_name); + return NULL; + } + + BMO_slot_map_float_insert(&bmop, slot, + ((BPy_BMElem *)arg_key)->ele, value_f); + } + } + break; + } + case BMO_OP_SLOT_SUBTYPE_MAP_INT: + { + if (PyDict_Size(value) > 0) { + PyObject *arg_key, *arg_value; + Py_ssize_t arg_pos = 0; + while (PyDict_Next(value, &arg_pos, &arg_key, &arg_value)) { + int value_i; + /* TODO, check the elements come from the right mesh? */ + BPY_BM_MAPPING_KEY_CHECK(arg_key); + value_i = PyLong_AsLong(arg_value); + + if (value_i == -1 && PyErr_Occurred()) { + PyErr_Format(PyExc_TypeError, + "%.200s: keyword \"%.200s\" expected " + "a dict with int values, not %.200s", + self->opname, slot_name, Py_TYPE(arg_value)->tp_name); + return NULL; + } + + BMO_slot_map_int_insert(&bmop, slot, + ((BPy_BMElem *)arg_key)->ele, value_i); + } + } + break; + } + case BMO_OP_SLOT_SUBTYPE_MAP_BOOL: + { + if (PyDict_Size(value) > 0) { + PyObject *arg_key, *arg_value; + Py_ssize_t arg_pos = 0; + while (PyDict_Next(value, &arg_pos, &arg_key, &arg_value)) { + int value_i; + /* TODO, check the elements come from the right mesh? */ + BPY_BM_MAPPING_KEY_CHECK(arg_key); + value_i = PyLong_AsLong(arg_value); + + if (value_i == -1 && PyErr_Occurred()) { + PyErr_Format(PyExc_TypeError, + "%.200s: keyword \"%.200s\" expected " + "a dict with bool values, not %.200s", + self->opname, slot_name, Py_TYPE(arg_value)->tp_name); + return NULL; + } + + BMO_slot_map_bool_insert(&bmop, slot, + ((BPy_BMElem *)arg_key)->ele, value_i != 0); + } + } + break; + } + case BMO_OP_SLOT_SUBTYPE_MAP_EMPTY: + { + if (PySet_Size(value) > 0) { + PyObject *arg_key; + Py_ssize_t arg_pos = 0; + Py_ssize_t arg_hash = 0; + while (_PySet_NextEntry(value, &arg_pos, &arg_key, &arg_hash)) { + /* TODO, check the elements come from the right mesh? */ + BPY_BM_MAPPING_KEY_CHECK(arg_key); + + BMO_slot_map_empty_insert(&bmop, slot, + ((BPy_BMElem *)arg_key)->ele); + } + } + break; + } + case BMO_OP_SLOT_SUBTYPE_MAP_INTERNAL: + default: + { + /* can't convert from these */ + PyErr_Format(PyExc_NotImplementedError, + "This arguments mapping subtype %d is not supported", slot->slot_subtype); + break; + } +#undef BPY_BM_MAPPING_KEY_CHECK + + } + } default: /* TODO --- many others */ PyErr_Format(PyExc_NotImplementedError, @@ -373,24 +546,103 @@ static PyObject *pyrna_op_call(BPy_BMeshOpFunc *self, PyObject *args, PyObject * case BMO_OP_SLOT_MAPPING: { GHash *slot_hash = BMO_SLOT_AS_GHASH(slot); - GHashIterator *hash_iter; - item = PyDict_New(); + GHashIterator hash_iter; + + switch (slot->slot_subtype) { + case BMO_OP_SLOT_SUBTYPE_MAP_ELEM: + { + item = PyDict_New(); + if (slot_hash) { + GHASH_ITER (hash_iter, slot_hash) { + BMHeader *ele_key = BLI_ghashIterator_getKey(&hash_iter); + BMOElemMapping *ele_val = BLI_ghashIterator_getValue(&hash_iter); + + PyObject *py_key = BPy_BMElem_CreatePyObject(bm, ele_key); + PyObject *py_val = BPy_BMElem_CreatePyObject(bm, *(void **)BMO_OP_SLOT_MAPPING_DATA(ele_val)); + + PyDict_SetItem(ret, py_key, py_val); + Py_DECREF(py_key); + Py_DECREF(py_val); + } + } + break; + } + case BMO_OP_SLOT_SUBTYPE_MAP_FLOAT: + { + item = PyDict_New(); + if (slot_hash) { + GHASH_ITER (hash_iter, slot_hash) { + BMHeader *ele_key = BLI_ghashIterator_getKey(&hash_iter); + BMOElemMapping *ele_val = BLI_ghashIterator_getValue(&hash_iter); + + PyObject *py_key = BPy_BMElem_CreatePyObject(bm, ele_key); + PyObject *py_val = PyFloat_FromDouble(*(float *)BMO_OP_SLOT_MAPPING_DATA(ele_val)); + + PyDict_SetItem(ret, py_key, py_val); + Py_DECREF(py_key); + Py_DECREF(py_val); + } + } + break; + } + case BMO_OP_SLOT_SUBTYPE_MAP_INT: + { + item = PyDict_New(); + if (slot_hash) { + GHASH_ITER (hash_iter, slot_hash) { + BMHeader *ele_key = BLI_ghashIterator_getKey(&hash_iter); + BMOElemMapping *ele_val = BLI_ghashIterator_getValue(&hash_iter); + + PyObject *py_key = BPy_BMElem_CreatePyObject(bm, ele_key); + PyObject *py_val = PyLong_FromLong(*(int *)BMO_OP_SLOT_MAPPING_DATA(ele_val)); + + PyDict_SetItem(ret, py_key, py_val); + Py_DECREF(py_key); + Py_DECREF(py_val); + } + } + break; + } + case BMO_OP_SLOT_SUBTYPE_MAP_BOOL: + { + item = PyDict_New(); + if (slot_hash) { + GHASH_ITER (hash_iter, slot_hash) { + BMHeader *ele_key = BLI_ghashIterator_getKey(&hash_iter); + BMOElemMapping *ele_val = BLI_ghashIterator_getValue(&hash_iter); + + PyObject *py_key = BPy_BMElem_CreatePyObject(bm, ele_key); + PyObject *py_val = PyBool_FromLong(*(int *)BMO_OP_SLOT_MAPPING_DATA(ele_val)); + + PyDict_SetItem(ret, py_key, py_val); + Py_DECREF(py_key); + Py_DECREF(py_val); + } + } + break; + } + case BMO_OP_SLOT_SUBTYPE_MAP_EMPTY: + { + item = PySet_New(NULL); + if (slot_hash) { + GHASH_ITER (hash_iter, slot_hash) { + BMHeader *ele_key = BLI_ghashIterator_getKey(&hash_iter); - for (hash_iter = BLI_ghashIterator_new(slot_hash); - !BLI_ghashIterator_isDone(hash_iter); - BLI_ghashIterator_step(hash_iter) ) - { - BMHeader *ele_key = BLI_ghashIterator_getKey(hash_iter); - BMHeader **ele_val = BLI_ghashIterator_getValue(hash_iter); + PyObject *py_key = BPy_BMElem_CreatePyObject(bm, ele_key); - PyObject *py_key = ele_key ? BPy_BMElem_CreatePyObject(bm, ele_key) : (Py_INCREF(Py_None), Py_None); - PyObject *py_val = *ele_val ? BPy_BMElem_CreatePyObject(bm, *ele_val) : (Py_INCREF(Py_None), Py_None); + PySet_Add(item, py_key); - PyDict_SetItem(ret, py_key, py_val); - Py_DECREF(py_key); - Py_DECREF(py_val); + Py_DECREF(py_key); + } + } + break; + } + case BMO_OP_SLOT_SUBTYPE_MAP_INTERNAL: + default: + /* can't convert from these */ + item = (Py_INCREF(Py_None), Py_None); + break; } - BLI_ghashIterator_free(hash_iter); break; } } diff --git a/source/blender/python/bmesh/bmesh_py_types.c b/source/blender/python/bmesh/bmesh_py_types.c index ee4528df50d..51c2a2be1fd 100644 --- a/source/blender/python/bmesh/bmesh_py_types.c +++ b/source/blender/python/bmesh/bmesh_py_types.c @@ -3032,7 +3032,8 @@ void BPy_BM_init_types(void) BPy_BMLoopSeq_Type.tp_methods = bpy_bmloopseq_methods; BPy_BMIter_Type.tp_methods = NULL; - + /*BPy_BMElem_Check() uses bpy_bm_elem_hash() to check types. + * if this changes update the macro */ BPy_BMesh_Type.tp_hash = bpy_bm_hash; BPy_BMVert_Type.tp_hash = bpy_bm_elem_hash; BPy_BMEdge_Type.tp_hash = bpy_bm_elem_hash; diff --git a/source/blender/python/bmesh/bmesh_py_types.h b/source/blender/python/bmesh/bmesh_py_types.h index df5231a4b1b..8de69c2d8a2 100644 --- a/source/blender/python/bmesh/bmesh_py_types.h +++ b/source/blender/python/bmesh/bmesh_py_types.h @@ -55,6 +55,8 @@ extern PyTypeObject BPy_BMIter_Type; #define BPy_BMFaceSeq_Check(v) (Py_TYPE(v) == &BPy_BMFaceSeq_Type) #define BPy_BMLoopSeq_Check(v) (Py_TYPE(v) == &BPy_BMLoopSeq_Type) #define BPy_BMIter_Check(v) (Py_TYPE(v) == &BPy_BMIter_Type) +/* trick since we know they share a hash function */ +#define BPy_BMElem_Check(v) (Py_TYPE(v)->tp_hash == BPy_BMVert_Type.tp_hash) /* cast from _any_ bmesh type - they all have BMesh first */ typedef struct BPy_BMGeneric { |