py/bmesh api - support for converting from/to BMO_OP_SLOT_MAPPING type.
This commit is contained in:
@@ -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
|
||||
|
||||
@@ -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));
|
||||
|
||||
@@ -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);
|
||||
|
||||
|
||||
@@ -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;
|
||||
|
||||
for (hash_iter = BLI_ghashIterator_new(slot_hash);
|
||||
!BLI_ghashIterator_isDone(hash_iter);
|
||||
BLI_ghashIterator_step(hash_iter) )
|
||||
switch (slot->slot_subtype) {
|
||||
case BMO_OP_SLOT_SUBTYPE_MAP_ELEM:
|
||||
{
|
||||
BMHeader *ele_key = BLI_ghashIterator_getKey(hash_iter);
|
||||
BMHeader **ele_val = BLI_ghashIterator_getValue(hash_iter);
|
||||
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 = 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);
|
||||
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);
|
||||
}
|
||||
BLI_ghashIterator_free(hash_iter);
|
||||
}
|
||||
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);
|
||||
|
||||
PyObject *py_key = BPy_BMElem_CreatePyObject(bm, ele_key);
|
||||
|
||||
PySet_Add(item, py_key);
|
||||
|
||||
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;
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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 {
|
||||
|
||||
Reference in New Issue
Block a user