diff options
author | Campbell Barton <ideasman42@gmail.com> | 2012-03-14 08:46:12 +0400 |
---|---|---|
committer | Campbell Barton <ideasman42@gmail.com> | 2012-03-14 08:46:12 +0400 |
commit | f15c15e992a9836a7295166af275522690ada315 (patch) | |
tree | ceab2edb87f3b2d1a8b05a661134f4a2696496a6 | |
parent | 99f72dfbfcb004418ae3c701f3badfd36996e6e5 (diff) |
bmesh py api: finished todo - editable select_history
eg:
bm.select_history = vert, face, edge
bm.select_history.add(edge)
-rw-r--r-- | doc/python_api/rst/include__bmesh.rst | 1 | ||||
-rw-r--r-- | doc/python_api/sphinx_doc_gen.py | 5 | ||||
-rw-r--r-- | source/blender/bmesh/intern/bmesh_marking.c | 14 | ||||
-rw-r--r-- | source/blender/bmesh/intern/bmesh_marking.h | 1 | ||||
-rw-r--r-- | source/blender/python/bmesh/bmesh_py_select.c | 71 | ||||
-rw-r--r-- | source/blender/python/bmesh/bmesh_py_select.h | 3 | ||||
-rw-r--r-- | source/blender/python/bmesh/bmesh_py_types.c | 58 | ||||
-rw-r--r-- | source/blender/python/bmesh/bmesh_py_types.h | 4 | ||||
-rw-r--r-- | source/blender/python/bmesh/bmesh_py_utils.c | 4 |
9 files changed, 134 insertions, 27 deletions
diff --git a/doc/python_api/rst/include__bmesh.rst b/doc/python_api/rst/include__bmesh.rst index 1c702275f62..2481c4a739c 100644 --- a/doc/python_api/rst/include__bmesh.rst +++ b/doc/python_api/rst/include__bmesh.rst @@ -33,7 +33,6 @@ For an overview of BMesh data types and how they reference each other see: .. todo:: * add access to BMesh **walkers** - * add access selection history (readonly access done) * add a way to re-tessellate an editmode bmesh. diff --git a/doc/python_api/sphinx_doc_gen.py b/doc/python_api/sphinx_doc_gen.py index 49193ad8f22..b15fcd9303b 100644 --- a/doc/python_api/sphinx_doc_gen.py +++ b/doc/python_api/sphinx_doc_gen.py @@ -94,12 +94,13 @@ def handle_args(): usage=SCRIPT_HELP_MSG ) - # optional arguments + # optional arguments parser.add_argument("-o", "--output", dest="output_dir", type=str, default=SCRIPT_DIR, - help="Path of the API docs (default=<script dir>)", + # XXX, THIS ISNT WORKING, EXAMPLE SCRIPTS WILL NOT BE FOUND + help="Path of the API docs (default=<script dir>).", required=False) parser.add_argument("-B", "--sphinx-build", diff --git a/source/blender/bmesh/intern/bmesh_marking.c b/source/blender/bmesh/intern/bmesh_marking.c index 4108d00fe7a..89bce16f2ca 100644 --- a/source/blender/bmesh/intern/bmesh_marking.c +++ b/source/blender/bmesh/intern/bmesh_marking.c @@ -720,14 +720,18 @@ void BM_select_history_clear(BMesh *bm) bm->selected.first = bm->selected.last = NULL; } +void BM_select_history_store_notest(BMesh *bm, BMElem *ele) +{ + BMEditSelection *ese = (BMEditSelection *) MEM_callocN(sizeof(BMEditSelection), "BMEdit Selection"); + ese->htype = ((BMHeader *)ele)->htype; + ese->ele = ele; + BLI_addtail(&(bm->selected), ese); +} + void BM_select_history_store(BMesh *bm, BMElem *ele) { - BMEditSelection *ese; if (!BM_select_history_check(bm, ele)) { - ese = (BMEditSelection *) MEM_callocN(sizeof(BMEditSelection), "BMEdit Selection"); - ese->htype = ((BMHeader *)ele)->htype; - ese->ele = ele; - BLI_addtail(&(bm->selected), ese); + BM_select_history_store_notest(bm, ele); } } diff --git a/source/blender/bmesh/intern/bmesh_marking.h b/source/blender/bmesh/intern/bmesh_marking.h index 8e4a4ab7d66..f0e81b1dd9f 100644 --- a/source/blender/bmesh/intern/bmesh_marking.h +++ b/source/blender/bmesh/intern/bmesh_marking.h @@ -71,6 +71,7 @@ void BM_editselection_plane(BMesh *bm, float r_plane[3], BMEditSelection *ese); int BM_select_history_check(BMesh *bm, const BMElem *ele); int BM_select_history_remove(BMesh *bm, BMElem *ele); +void BM_select_history_store_notest(BMesh *bm, BMElem *ele); void BM_select_history_store(BMesh *bm, BMElem *ele); void BM_select_history_validate(BMesh *bm); void BM_select_history_clear(BMesh *em); diff --git a/source/blender/python/bmesh/bmesh_py_select.c b/source/blender/python/bmesh/bmesh_py_select.c index cd6145709e0..a9fb5b2b018 100644 --- a/source/blender/python/bmesh/bmesh_py_select.c +++ b/source/blender/python/bmesh/bmesh_py_select.c @@ -28,6 +28,9 @@ * * This file defines the types for 'BMesh.select_history' * sequence and iterator. + * + * select_history is very loosely based on pytons set() type, + * since items can only exist once. however they do have an order. */ #include <Python.h> @@ -93,6 +96,37 @@ static PyObject *bpy_bmeditselseq_clear(BPy_BMEditSelSeq *self) Py_RETURN_NONE; } +PyDoc_STRVAR(bpy_bmeditselseq_add_doc, +".. method:: add(element)\n" +"\n" +" Add an element to the selection history (no action taken if its already added).\n" +); +static PyObject *bpy_bmeditselseq_add(BPy_BMEditSelSeq *self, BPy_BMElem *value) +{ + BPY_BM_CHECK_OBJ(self); + + if ((BPy_BMVert_Check(value) || + BPy_BMEdge_Check(value) || + BPy_BMFace_Check(value)) == FALSE) + { + PyErr_Format(PyExc_TypeError, + "Expected a BMVert/BMedge/BMFace not a %.200s", Py_TYPE(value)->tp_name); + return NULL; + } + + BPY_BM_CHECK_OBJ(value); + + if (self->bm != value->bm) { + PyErr_SetString(PyExc_ValueError, + "Element is not from this mesh"); + return NULL; + } + + BM_select_history_store(self->bm, value->ele) + + Py_RETURN_NONE; +} + PyDoc_STRVAR(bpy_bmeditselseq_remove_doc, ".. method:: remove(element)\n" "\n" @@ -127,6 +161,8 @@ static PyObject *bpy_bmeditselseq_remove(BPy_BMEditSelSeq *self, BPy_BMElem *val static struct PyMethodDef bpy_bmeditselseq_methods[] = { {"validate", (PyCFunction)bpy_bmeditselseq_validate, METH_NOARGS, bpy_bmeditselseq_validate_doc}, {"clear", (PyCFunction)bpy_bmeditselseq_clear, METH_NOARGS, bpy_bmeditselseq_clear_doc}, + + {"add", (PyCFunction)bpy_bmeditselseq_add, METH_O, bpy_bmeditselseq_add_doc}, {"remove", (PyCFunction)bpy_bmeditselseq_remove, METH_O, bpy_bmeditselseq_remove_doc}, {NULL, NULL, 0, NULL} }; @@ -381,3 +417,38 @@ void BPy_BM_init_select_types(void) PyType_Ready(&BPy_BMEditSelSeq_Type); PyType_Ready(&BPy_BMEditSelIter_Type); } + + +/* utility function */ + +/** + * \note doesnt actually check selection. + */ +int BPy_BMEditSel_Assign(BPy_BMesh *self, PyObject *value) +{ + BMesh *bm; + Py_ssize_t value_len; + Py_ssize_t i; + BMElem **value_array = NULL; + + BPY_BM_CHECK_INT(self); + + bm = self->bm; + + value_array = BPy_BMElem_PySeq_As_Array(&bm, value, 0, PY_SSIZE_T_MAX, + &value_len, BM_VERT | BM_EDGE | BM_FACE, + TRUE, TRUE, "BMesh.select_history = value"); + + if (value_array == NULL) { + return -1; + } + + BM_select_history_clear(bm); + + for (i = 0; i < value_len; i++) { + BM_select_history_store_notest(bm, value_array[i]); + } + + PyMem_FREE(value_array); + return 0; +} diff --git a/source/blender/python/bmesh/bmesh_py_select.h b/source/blender/python/bmesh/bmesh_py_select.h index d1bfcdcb6b3..3992dbe1ffe 100644 --- a/source/blender/python/bmesh/bmesh_py_select.h +++ b/source/blender/python/bmesh/bmesh_py_select.h @@ -30,6 +30,8 @@ #ifndef __BMESH_PY_SELECT_H__ #define __BMESH_PY_SELECT_H__ +struct BPy_BMesh; + extern PyTypeObject BPy_BMEditSelSeq_Type; extern PyTypeObject BPy_BMEditSelIter_Type; @@ -51,5 +53,6 @@ void BPy_BM_init_select_types(void); PyObject *BPy_BMEditSel_CreatePyObject(BMesh *bm); PyObject *BPy_BMEditSelIter_CreatePyObject(BMesh *bm); +int BPy_BMEditSel_Assign(struct BPy_BMesh *self, PyObject *value); #endif /* __BMESH_PY_SELECT_H__ */ diff --git a/source/blender/python/bmesh/bmesh_py_types.c b/source/blender/python/bmesh/bmesh_py_types.c index 6d4d1b20e7b..313761db5e2 100644 --- a/source/blender/python/bmesh/bmesh_py_types.c +++ b/source/blender/python/bmesh/bmesh_py_types.c @@ -302,12 +302,11 @@ static PyObject *bpy_bmesh_select_history_get(BPy_BMesh *self) return BPy_BMEditSel_CreatePyObject(self->bm); } -static int bpy_bmesh_select_history_set(BPy_BMesh *self, PyObject *UNUSED(value)) +static int bpy_bmesh_select_history_set(BPy_BMesh *self, PyObject *value) { BPY_BM_CHECK_INT(self); - PyErr_SetString(PyExc_NotImplementedError, "not yet functional"); - return -1; + return BPy_BMEditSel_Assign(self, value); } /* Vert @@ -1045,7 +1044,7 @@ static PyObject *bpy_bmvert_copy_from_vert_interp(BPy_BMVert *self, PyObject *ar Py_ssize_t vert_seq_len; /* always 2 */ vert_array = BPy_BMElem_PySeq_As_Array(&bm, vert_seq, 2, 2, - &vert_seq_len, &BPy_BMVert_Type, + &vert_seq_len, BM_VERT, TRUE, TRUE, "BMVert.copy_from_vert_interp(...)"); if (vert_array == NULL) { @@ -1532,7 +1531,7 @@ static PyObject *bpy_bmedgeseq_new(BPy_BMElemSeq *self, PyObject *args) } vert_array = BPy_BMElem_PySeq_As_Array(&bm, vert_seq, 2, 2, - &vert_seq_len, &BPy_BMVert_Type, + &vert_seq_len, BM_VERT, TRUE, TRUE, "edges.new(...)"); if (vert_array == NULL) { @@ -1599,7 +1598,7 @@ static PyObject *bpy_bmfaceseq_new(BPy_BMElemSeq *self, PyObject *args) } vert_array = BPy_BMElem_PySeq_As_Array(&bm, vert_seq, 3, PY_SSIZE_T_MAX, - &vert_seq_len, &BPy_BMVert_Type, + &vert_seq_len, BM_VERT, TRUE, TRUE, "faces.new(...)"); if (vert_array == NULL) { @@ -1821,7 +1820,7 @@ static PyObject *bpy_bmedgeseq_get(BPy_BMElemSeq *self, PyObject *args) PyObject *ret = NULL; vert_array = BPy_BMElem_PySeq_As_Array(&bm, vert_seq, 2, 2, - &vert_seq_len, &BPy_BMVert_Type, + &vert_seq_len, BM_VERT, TRUE, TRUE, "edges.get(...)"); if (vert_array == NULL) { @@ -1863,7 +1862,7 @@ static PyObject *bpy_bmfaceseq_get(BPy_BMElemSeq *self, PyObject *args) PyObject *ret = NULL; vert_array = BPy_BMElem_PySeq_As_Array(&bm, vert_seq, 1, PY_SSIZE_T_MAX, - &vert_seq_len, &BPy_BMVert_Type, + &vert_seq_len, BM_VERT, TRUE, TRUE, "faces.get(...)"); if (vert_array == NULL) { @@ -2849,7 +2848,7 @@ void bpy_bm_generic_invalidate(BPy_BMGeneric *self) * The 'bm_r' value is assigned when empty, and used when set. */ void *BPy_BMElem_PySeq_As_Array(BMesh **r_bm, PyObject *seq, Py_ssize_t min, Py_ssize_t max, Py_ssize_t *r_size, - PyTypeObject *type, + const char htype, const char do_unique_check, const char do_bm_check, const char *error_prefix) { @@ -2883,16 +2882,16 @@ void *BPy_BMElem_PySeq_As_Array(BMesh **r_bm, PyObject *seq, Py_ssize_t min, Py_ for (i = 0; i < seq_len; i++) { item = (BPy_BMElem *)PySequence_Fast_GET_ITEM(seq_fast, i); - if (Py_TYPE(item) != type) { + if (!BPy_BMElem_CheckHType(Py_TYPE(item), htype)) { PyErr_Format(PyExc_TypeError, - "%s: expected '%.200s', not '%.200s'", - error_prefix, type->tp_name, Py_TYPE(item)->tp_name); + "%s: expected %.200s, not '%.200s'", + error_prefix, BPy_BMElem_StringFromHType(htype), Py_TYPE(item)->tp_name); goto err_cleanup; } else if (!BPY_BM_IS_VALID(item)) { PyErr_Format(PyExc_TypeError, "%s: %d %s has been removed", - error_prefix, i, type->tp_name); + error_prefix, i, Py_TYPE(item)->tp_name); goto err_cleanup; } /* trick so we can ensure all items have the same mesh, @@ -2900,7 +2899,7 @@ void *BPy_BMElem_PySeq_As_Array(BMesh **r_bm, PyObject *seq, Py_ssize_t min, Py_ else if (do_bm_check && (bm && bm != item->bm)) { PyErr_Format(PyExc_ValueError, "%s: %d %s is from another mesh", - error_prefix, i, type->tp_name); + error_prefix, i, BPy_BMElem_StringFromHType(htype)); goto err_cleanup; } @@ -2929,8 +2928,8 @@ void *BPy_BMElem_PySeq_As_Array(BMesh **r_bm, PyObject *seq, Py_ssize_t min, Py_ if (ok == FALSE) { PyErr_Format(PyExc_ValueError, - "%s: found the same %s used multiple times", - error_prefix, type->tp_name); + "%s: found the same %.200s used multiple times", + error_prefix, BPy_BMElem_StringFromHType(htype)); goto err_cleanup; } } @@ -2958,3 +2957,30 @@ PyObject *BPy_BMElem_Array_As_Tuple(BMesh *bm, BMHeader **elem, Py_ssize_t elem_ return ret; } + +int BPy_BMElem_CheckHType(PyTypeObject *type, const char htype) +{ + return (((htype & BM_VERT) && (type == &BPy_BMVert_Type)) || + ((htype & BM_EDGE) && (type == &BPy_BMEdge_Type)) || + ((htype & BM_FACE) && (type == &BPy_BMFace_Type)) || + ((htype & BM_LOOP) && (type == &BPy_BMLoop_Type))); +} + +/** + * Use for error strings only, not thread safe, + * + * \return a sting like '(BMVert/BMEdge/BMFace/BMLoop)' + */ +char *BPy_BMElem_StringFromHType(const char htype) +{ + /* 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); + if (htype & BM_FACE) ret_ptr += sprintf(ret_ptr, "/%s", BPy_BMFace_Type.tp_name); + if (htype & BM_LOOP) ret_ptr += sprintf(ret_ptr, "/%s", BPy_BMLoop_Type.tp_name); + ret[0] = '('; + *ret_ptr = ')'; + return ret; +} diff --git a/source/blender/python/bmesh/bmesh_py_types.h b/source/blender/python/bmesh/bmesh_py_types.h index b5b96002ccc..452c8b2103f 100644 --- a/source/blender/python/bmesh/bmesh_py_types.h +++ b/source/blender/python/bmesh/bmesh_py_types.h @@ -139,11 +139,13 @@ int bpy_bm_generic_valid_check(BPy_BMGeneric *self); void bpy_bm_generic_invalidate(BPy_BMGeneric *self); void *BPy_BMElem_PySeq_As_Array(BMesh **r_bm, PyObject *seq, Py_ssize_t min, Py_ssize_t max, Py_ssize_t *r_size, - PyTypeObject *type, + const char htype, const char do_unique_check, const char do_bm_check, const char *error_prefix); 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(const char htype); #define BPY_BM_CHECK_OBJ(obj) if (UNLIKELY(bpy_bm_generic_valid_check((BPy_BMGeneric *)obj) == -1)) { return NULL; } (void)0 diff --git a/source/blender/python/bmesh/bmesh_py_utils.c b/source/blender/python/bmesh/bmesh_py_utils.c index a41d5e7f766..736802c7f60 100644 --- a/source/blender/python/bmesh/bmesh_py_utils.c +++ b/source/blender/python/bmesh/bmesh_py_utils.c @@ -238,7 +238,7 @@ static PyObject *bpy_bm_utils_vert_separate(PyObject *UNUSED(self), PyObject *ar bm = py_vert->bm; edge_array = BPy_BMElem_PySeq_As_Array(&bm, edge_seq, 0, PY_SSIZE_T_MAX, - &edge_array_len, &BPy_BMEdge_Type, + &edge_array_len, BM_EDGE, TRUE, TRUE, "vert_separate(...)"); if (edge_array == NULL) { @@ -460,7 +460,7 @@ static PyObject *bpy_bm_utils_face_join(PyObject *UNUSED(self), PyObject *value) BMFace *f_new; face_array = BPy_BMElem_PySeq_As_Array(&bm, value, 2, PY_SSIZE_T_MAX, - &face_seq_len, &BPy_BMFace_Type, + &face_seq_len, BM_FACE, TRUE, TRUE, "face_join(...)"); if (face_array == NULL) { |