Cleanup: minor changes to the BMesh Python API

- Add typed array access functions, avoiding the need for casting.
- Share error prefix for exceptions.
- Use "num" suffix instead of "len".
This commit is contained in:
Campbell Barton
2025-09-23 13:35:33 +10:00
parent 16118be339
commit 4b82edd53c
5 changed files with 230 additions and 174 deletions

View File

@@ -768,20 +768,22 @@ static PyObject *bpy_bmfaceseq_active_get(BPy_BMElemSeq *self, void * /*closure*
static int bpy_bmfaceseq_active_set(BPy_BMElem *self, PyObject *value, void * /*closure*/)
{
const char *error_prefix = "faces.active = f";
BMesh *bm = self->bm;
if (value == Py_None) {
bm->act_face = nullptr;
return 0;
}
if (BPy_BMFace_Check(value)) {
BPY_BM_CHECK_SOURCE_INT(bm, "faces.active = f", value);
BPY_BM_CHECK_SOURCE_INT(bm, error_prefix, value);
bm->act_face = ((BPy_BMFace *)value)->f;
return 0;
}
PyErr_Format(PyExc_TypeError,
"faces.active = f: expected BMFace or None, not %.200s",
"%s: expected BMFace or None, not %.200s",
error_prefix,
Py_TYPE(value)->tp_name);
return -1;
}
@@ -1143,14 +1145,10 @@ PyDoc_STRVAR(
" :rtype: :class:`BMesh`\n");
static PyObject *bpy_bmesh_copy(BPy_BMesh *self)
{
BMesh *bm;
BMesh *bm_copy;
BPY_BM_CHECK_OBJ(self);
bm = self->bm;
bm_copy = BM_mesh_copy(bm);
BMesh *bm = self->bm;
BMesh *bm_copy = BM_mesh_copy(bm);
if (bm_copy) {
return BPy_BMesh_CreatePyObject(bm_copy, BPY_BMFLAG_NOP);
@@ -1168,11 +1166,9 @@ PyDoc_STRVAR(
" Clear all mesh data.\n");
static PyObject *bpy_bmesh_clear(BPy_BMesh *self)
{
BMesh *bm;
BPY_BM_CHECK_OBJ(self);
bm = self->bm;
BMesh *bm = self->bm;
BM_mesh_clear(bm);
@@ -1225,7 +1221,6 @@ static PyObject *bpy_bmesh_to_mesh(BPy_BMesh *self, PyObject *args)
{
PyObject *py_mesh;
Mesh *mesh;
BMesh *bm;
BPY_BM_CHECK_OBJ(self);
@@ -1241,7 +1236,7 @@ static PyObject *bpy_bmesh_to_mesh(BPy_BMesh *self, PyObject *args)
return nullptr;
}
bm = self->bm;
BMesh *bm = self->bm;
Main *bmain = nullptr;
BMeshToMeshParams params{};
@@ -1293,7 +1288,6 @@ static PyObject *bpy_bmesh_from_object(BPy_BMesh *self, PyObject *args, PyObject
Depsgraph *depsgraph;
Scene *scene_eval;
const Mesh *mesh_eval;
BMesh *bm;
bool use_cage = false;
bool use_fnorm = true;
bool use_vert_normal = true;
@@ -1358,7 +1352,7 @@ static PyObject *bpy_bmesh_from_object(BPy_BMesh *self, PyObject *args, PyObject
return nullptr;
}
bm = self->bm;
BMesh *bm = self->bm;
BMeshFromMeshParams params{};
params.calc_face_normal = use_fnorm;
@@ -1400,7 +1394,6 @@ static PyObject *bpy_bmesh_from_mesh(BPy_BMesh *self, PyObject *args, PyObject *
{
static const char *kwlist[] = {
"mesh", "face_normals", "vertex_normals", "use_shape_key", "shape_key_index", nullptr};
BMesh *bm;
PyObject *py_mesh;
Mesh *mesh;
bool use_fnorm = true;
@@ -1427,7 +1420,7 @@ static PyObject *bpy_bmesh_from_mesh(BPy_BMesh *self, PyObject *args, PyObject *
return nullptr;
}
bm = self->bm;
BMesh *bm = self->bm;
BMeshFromMeshParams params{};
params.calc_face_normal = use_fnorm;
@@ -1598,23 +1591,20 @@ PyDoc_STRVAR(
" :rtype: list[tuple[:class:`BMLoop`, :class:`BMLoop`, :class:`BMLoop`]]\n");
static PyObject *bpy_bmesh_calc_loop_triangles(BPy_BMElem *self)
{
BMesh *bm;
int corner_tris_tot;
PyObject *ret;
int i;
BPY_BM_CHECK_OBJ(self);
bm = self->bm;
BMesh *bm = self->bm;
corner_tris_tot = poly_to_tri_count(bm->totface, bm->totloop);
blender::Array<std::array<BMLoop *, 3>> corner_tris(corner_tris_tot);
BM_mesh_calc_tessellation(bm, corner_tris);
ret = PyList_New(corner_tris_tot);
for (i = 0; i < corner_tris_tot; i++) {
for (int i = 0; i < corner_tris_tot; i++) {
PyList_SET_ITEM(ret, i, BPy_BMLoop_Array_As_Tuple(bm, corner_tris[i].data(), 3));
}
@@ -1760,6 +1750,7 @@ PyDoc_STRVAR(
" :type fac: float\n");
static PyObject *bpy_bmvert_copy_from_vert_interp(BPy_BMVert *self, PyObject *args)
{
const char *error_prefix = "BMVert.copy_from_vert_interp(...)";
PyObject *vert_seq;
float fac;
@@ -1770,19 +1761,10 @@ static PyObject *bpy_bmvert_copy_from_vert_interp(BPy_BMVert *self, PyObject *ar
}
BMesh *bm = self->bm;
BMVert **vert_array = nullptr;
Py_ssize_t vert_seq_len; /* always 2 */
vert_array = static_cast<BMVert **>(
BPy_BMElem_PySeq_As_Array(&bm,
vert_seq,
2,
2,
&vert_seq_len,
BM_VERT,
true,
true,
"BMVert.copy_from_vert_interp(...)"));
Py_ssize_t vert_seq_num; /* Always 2. */
BMVert **vert_array = BPy_BMVert_PySeq_As_Array(
&bm, vert_seq, 2, 2, &vert_seq_num, true, true, error_prefix);
if (vert_array == nullptr) {
return nullptr;
@@ -1806,6 +1788,7 @@ PyDoc_STRVAR(
" :type face: :class:`BMFace`\n");
static PyObject *bpy_bmvert_copy_from_face_interp(BPy_BMVert *self, PyObject *args)
{
const char *error_prefix = "copy_from_face_interp(...)";
BPy_BMFace *py_face = nullptr;
BPY_BM_CHECK_OBJ(self);
@@ -1816,7 +1799,7 @@ static PyObject *bpy_bmvert_copy_from_face_interp(BPy_BMVert *self, PyObject *ar
BMesh *bm = self->bm;
BPY_BM_CHECK_SOURCE_OBJ(bm, "copy_from_face_interp()", py_face);
BPY_BM_CHECK_SOURCE_OBJ(bm, error_prefix, py_face);
BM_vert_interp_from_face(bm, self->v, py_face->f);
@@ -2039,17 +2022,19 @@ PyDoc_STRVAR(
" :rtype: :class:`BMVert` | None\n");
static PyObject *bpy_bmedge_other_vert(BPy_BMEdge *self, BPy_BMVert *value)
{
const char *error_prefix = "BMEdge.other_vert(...)";
BMVert *other;
BPY_BM_CHECK_OBJ(self);
if (!BPy_BMVert_Check(value)) {
PyErr_Format(PyExc_TypeError,
"BMEdge.other_vert(vert): BMVert expected, not '%.200s'",
"%s: BMVert expected, not '%.200s'",
error_prefix,
Py_TYPE(value)->tp_name);
return nullptr;
}
BPY_BM_CHECK_SOURCE_OBJ(self->bm, "BMEdge.other_vert(vert)", value);
BPY_BM_CHECK_SOURCE_OBJ(self->bm, error_prefix, value);
other = BM_edge_other_vert(self->e, value->v);
@@ -2096,6 +2081,7 @@ PyDoc_STRVAR(
" :type vert: bool\n");
static PyObject *bpy_bmface_copy_from_face_interp(BPy_BMFace *self, PyObject *args)
{
const char *error_prefix = "BMFace.copy_from_face_interp(...)";
BPy_BMFace *py_face = nullptr;
bool do_vertex = true;
@@ -2113,7 +2099,7 @@ static PyObject *bpy_bmface_copy_from_face_interp(BPy_BMFace *self, PyObject *ar
BMesh *bm = self->bm;
BPY_BM_CHECK_SOURCE_OBJ(bm, "BMFace.copy_from_face_interp(face)", py_face);
BPY_BM_CHECK_SOURCE_OBJ(bm, error_prefix, py_face);
BM_face_interp_from_face(bm, self->f, py_face->f, do_vertex);
@@ -2376,6 +2362,7 @@ PyDoc_STRVAR(
" :type multires: bool\n");
static PyObject *bpy_bmloop_copy_from_face_interp(BPy_BMLoop *self, PyObject *args)
{
const char *error_prefix = "BMLoop.copy_from_face_interp(face)";
BPy_BMFace *py_face = nullptr;
bool do_vertex = true;
bool do_multires = true;
@@ -2396,7 +2383,7 @@ static PyObject *bpy_bmloop_copy_from_face_interp(BPy_BMLoop *self, PyObject *ar
BMesh *bm = self->bm;
BPY_BM_CHECK_SOURCE_OBJ(bm, "BMLoop.copy_from_face_interp(face)", py_face);
BPY_BM_CHECK_SOURCE_OBJ(bm, error_prefix, py_face);
BM_loop_interp_from_face(bm, self->l, py_face->f, do_vertex, do_multires);
@@ -2532,6 +2519,7 @@ PyDoc_STRVAR(
" :rtype: :class:`BMEdge`\n");
static PyObject *bpy_bmedgeseq_new(BPy_BMElemSeq *self, PyObject *args)
{
const char *error_prefix = "edges.new(...)";
PyObject *vert_seq;
BPy_BMEdge *py_edge_example = nullptr; /* optional */
@@ -2543,17 +2531,15 @@ static PyObject *bpy_bmedgeseq_new(BPy_BMElemSeq *self, PyObject *args)
BMesh *bm = self->bm;
BMEdge *e;
BMVert **vert_array = nullptr;
Py_ssize_t vert_seq_len; /* always 2 */
PyObject *ret = nullptr;
if (py_edge_example) {
BPY_BM_CHECK_OBJ(py_edge_example);
}
vert_array = static_cast<BMVert **>(BPy_BMElem_PySeq_As_Array(
&bm, vert_seq, 2, 2, &vert_seq_len, BM_VERT, true, true, "edges.new(...)"));
Py_ssize_t vert_seq_num; /* Always 2. */
BMVert **vert_array = BPy_BMVert_PySeq_As_Array(
&bm, vert_seq, 2, 2, &vert_seq_num, true, true, error_prefix);
if (vert_array == nullptr) {
return nullptr;
}
@@ -2608,6 +2594,7 @@ PyDoc_STRVAR(
" :rtype: :class:`BMFace`\n");
static PyObject *bpy_bmfaceseq_new(BPy_BMElemSeq *self, PyObject *args)
{
const char *error_prefix = "faces.new(...)";
PyObject *vert_seq;
BPy_BMFace *py_face_example = nullptr; /* optional */
@@ -2618,9 +2605,6 @@ static PyObject *bpy_bmfaceseq_new(BPy_BMElemSeq *self, PyObject *args)
}
BMesh *bm = self->bm;
Py_ssize_t vert_seq_len;
BMVert **vert_array = nullptr;
PyObject *ret = nullptr;
@@ -2630,16 +2614,16 @@ static PyObject *bpy_bmfaceseq_new(BPy_BMElemSeq *self, PyObject *args)
BPY_BM_CHECK_OBJ(py_face_example);
}
vert_array = static_cast<BMVert **>(BPy_BMElem_PySeq_As_Array(
&bm, vert_seq, 3, PY_SSIZE_T_MAX, &vert_seq_len, BM_VERT, true, true, "faces.new(...)"));
Py_ssize_t vert_seq_num;
BMVert **vert_array = BPy_BMVert_PySeq_As_Array(
&bm, vert_seq, 3, PY_SSIZE_T_MAX, &vert_seq_num, true, true, error_prefix);
if (vert_array == nullptr) {
return nullptr;
}
/* check if the face exists */
if (BM_face_exists(vert_array, vert_seq_len) != nullptr) {
PyErr_SetString(PyExc_ValueError, "faces.new(verts): face already exists");
if (BM_face_exists(vert_array, vert_seq_num) != nullptr) {
PyErr_Format(PyExc_ValueError, "%s: face already exists", error_prefix);
goto cleanup;
}
@@ -2648,14 +2632,14 @@ static PyObject *bpy_bmfaceseq_new(BPy_BMElemSeq *self, PyObject *args)
f_new = BM_face_create_verts(bm,
vert_array,
vert_seq_len,
vert_seq_num,
py_face_example ? py_face_example->f : nullptr,
BM_CREATE_NOP,
true);
if (UNLIKELY(f_new == nullptr)) {
PyErr_SetString(PyExc_ValueError,
"faces.new(verts): couldn't create the new face, internal error");
PyErr_Format(
PyExc_ValueError, "%s: couldn't create the new face, internal error", error_prefix);
goto cleanup;
}
@@ -2682,6 +2666,7 @@ PyDoc_STRVAR(
" :type vert: :class:`BMVert`\n");
static PyObject *bpy_bmvertseq_remove(BPy_BMElemSeq *self, BPy_BMVert *value)
{
const char *error_prefix = "verts.remove(vert)";
BPY_BM_CHECK_OBJ(self);
if (!BPy_BMVert_Check(value)) {
@@ -2690,7 +2675,7 @@ static PyObject *bpy_bmvertseq_remove(BPy_BMElemSeq *self, BPy_BMVert *value)
BMesh *bm = self->bm;
BPY_BM_CHECK_SOURCE_OBJ(bm, "verts.remove(vert)", value);
BPY_BM_CHECK_SOURCE_OBJ(bm, error_prefix, value);
BM_vert_kill(bm, value->v);
bpy_bm_generic_invalidate((BPy_BMGeneric *)value);
@@ -2708,6 +2693,7 @@ PyDoc_STRVAR(
" :type edge: :class:`BMEdge`\n");
static PyObject *bpy_bmedgeseq_remove(BPy_BMElemSeq *self, BPy_BMEdge *value)
{
const char *error_prefix = "edges.remove(...)";
BPY_BM_CHECK_OBJ(self);
if (!BPy_BMEdge_Check(value)) {
@@ -2716,7 +2702,7 @@ static PyObject *bpy_bmedgeseq_remove(BPy_BMElemSeq *self, BPy_BMEdge *value)
BMesh *bm = self->bm;
BPY_BM_CHECK_SOURCE_OBJ(bm, "edges.remove(edges)", value);
BPY_BM_CHECK_SOURCE_OBJ(bm, error_prefix, value);
BM_edge_kill(bm, value->e);
bpy_bm_generic_invalidate((BPy_BMGeneric *)value);
@@ -2734,6 +2720,7 @@ PyDoc_STRVAR(
" :type face: :class:`BMFace`\n");
static PyObject *bpy_bmfaceseq_remove(BPy_BMElemSeq *self, BPy_BMFace *value)
{
const char *error_prefix = "faces.remove(...)";
BPY_BM_CHECK_OBJ(self);
if (!BPy_BMFace_Check(value)) {
@@ -2742,7 +2729,7 @@ static PyObject *bpy_bmfaceseq_remove(BPy_BMElemSeq *self, BPy_BMFace *value)
BMesh *bm = self->bm;
BPY_BM_CHECK_SOURCE_OBJ(bm, "faces.remove(face)", value);
BPY_BM_CHECK_SOURCE_OBJ(bm, error_prefix, value);
BM_face_kill(bm, value->f);
bpy_bm_generic_invalidate((BPy_BMGeneric *)value);
@@ -2764,6 +2751,7 @@ PyDoc_STRVAR(
" :rtype: :class:`BMEdge`\n");
static PyObject *bpy_bmedgeseq_get__method(BPy_BMElemSeq *self, PyObject *args)
{
const char *error_prefix = "edges.get(...)";
PyObject *vert_seq;
PyObject *fallback = Py_None; /* optional */
@@ -2775,12 +2763,11 @@ static PyObject *bpy_bmedgeseq_get__method(BPy_BMElemSeq *self, PyObject *args)
BMesh *bm = self->bm;
BMEdge *e;
BMVert **vert_array = nullptr;
Py_ssize_t vert_seq_len; /* always 2 */
PyObject *ret = nullptr;
vert_array = static_cast<BMVert **>(BPy_BMElem_PySeq_As_Array(
&bm, vert_seq, 2, 2, &vert_seq_len, BM_VERT, true, true, "edges.get(...)"));
Py_ssize_t vert_seq_num; /* Always 2. */
BMVert **vert_array = BPy_BMVert_PySeq_As_Array(
&bm, vert_seq, 2, 2, &vert_seq_num, true, true, error_prefix);
if (vert_array == nullptr) {
return nullptr;
@@ -2812,6 +2799,7 @@ PyDoc_STRVAR(
" :rtype: :class:`BMFace`\n");
static PyObject *bpy_bmfaceseq_get__method(BPy_BMElemSeq *self, PyObject *args)
{
const char *error_prefix = "faces.get(...)";
PyObject *vert_seq;
PyObject *fallback = Py_None; /* optional */
@@ -2823,18 +2811,17 @@ static PyObject *bpy_bmfaceseq_get__method(BPy_BMElemSeq *self, PyObject *args)
BMesh *bm = self->bm;
BMFace *f = nullptr;
BMVert **vert_array = nullptr;
Py_ssize_t vert_seq_len;
PyObject *ret = nullptr;
vert_array = static_cast<BMVert **>(BPy_BMElem_PySeq_As_Array(
&bm, vert_seq, 1, PY_SSIZE_T_MAX, &vert_seq_len, BM_VERT, true, true, "faces.get(...)"));
Py_ssize_t vert_seq_num;
BMVert **vert_array = BPy_BMVert_PySeq_As_Array(
&bm, vert_seq, 1, PY_SSIZE_T_MAX, &vert_seq_num, true, true, error_prefix);
if (vert_array == nullptr) {
return nullptr;
}
f = BM_face_exists(vert_array, vert_seq_len);
f = BM_face_exists(vert_array, vert_seq_num);
if (f != nullptr) {
ret = BPy_BMFace_CreatePyObject(bm, f);
}
@@ -4457,7 +4444,7 @@ void *BPy_BMElem_PySeq_As_Array_FAST(BMesh **r_bm,
PyObject *seq_fast,
Py_ssize_t min,
Py_ssize_t max,
Py_ssize_t *r_size,
Py_ssize_t *r_seq_num,
const char htype,
const bool do_unique_check,
const bool do_bm_check,
@@ -4465,28 +4452,28 @@ void *BPy_BMElem_PySeq_As_Array_FAST(BMesh **r_bm,
{
BMesh *bm = (r_bm && *r_bm) ? *r_bm : nullptr;
PyObject **seq_fast_items = PySequence_Fast_ITEMS(seq_fast);
const Py_ssize_t seq_len = PySequence_Fast_GET_SIZE(seq_fast);
const Py_ssize_t seq_num = PySequence_Fast_GET_SIZE(seq_fast);
Py_ssize_t i, i_last_dirty = PY_SSIZE_T_MAX;
BPy_BMElem *item;
BMElem **alloc;
*r_size = 0;
*r_seq_num = 0;
if (seq_len < min || seq_len > max) {
if (seq_num < min || seq_num > max) {
PyErr_Format(PyExc_TypeError,
"%s: sequence incorrect size, expected [%d - %d], given %d",
error_prefix,
min,
max,
seq_len);
seq_num);
return nullptr;
}
/* from now on, use goto */
alloc = static_cast<BMElem **>(PyMem_MALLOC(seq_len * sizeof(BPy_BMElem **)));
alloc = static_cast<BMElem **>(PyMem_MALLOC(seq_num * sizeof(BPy_BMElem **)));
for (i = 0; i < seq_len; i++) {
for (i = 0; i < seq_num; i++) {
item = (BPy_BMElem *)seq_fast_items[i];
if (!BPy_BMElem_CheckHType(Py_TYPE(item), htype)) {
@@ -4528,7 +4515,7 @@ void *BPy_BMElem_PySeq_As_Array_FAST(BMesh **r_bm,
if (do_unique_check) {
/* check for double verts! */
bool ok = true;
for (i = 0; i < seq_len; i++) {
for (i = 0; i < seq_num; i++) {
if (UNLIKELY(BM_elem_flag_test(alloc[i], BM_ELEM_INTERNAL_TAG) == false)) {
ok = false;
}
@@ -4548,7 +4535,7 @@ void *BPy_BMElem_PySeq_As_Array_FAST(BMesh **r_bm,
}
}
*r_size = seq_len;
*r_seq_num = seq_num;
if (r_bm) {
*r_bm = bm;
}
@@ -4568,7 +4555,7 @@ void *BPy_BMElem_PySeq_As_Array(BMesh **r_bm,
PyObject *seq,
Py_ssize_t min,
Py_ssize_t max,
Py_ssize_t *r_size,
Py_ssize_t *r_seq_num,
const char htype,
const bool do_unique_check,
const bool do_bm_check,
@@ -4582,55 +4569,104 @@ void *BPy_BMElem_PySeq_As_Array(BMesh **r_bm,
}
ret = static_cast<PyObject *>(BPy_BMElem_PySeq_As_Array_FAST(
r_bm, seq_fast, min, max, r_size, htype, do_unique_check, do_bm_check, error_prefix));
r_bm, seq_fast, min, max, r_seq_num, htype, do_unique_check, do_bm_check, error_prefix));
Py_DECREF(seq_fast);
return ret;
}
PyObject *BPy_BMElem_Array_As_Tuple(BMesh *bm, BMHeader **elem, Py_ssize_t elem_len)
BMVert **BPy_BMVert_PySeq_As_Array(BMesh **r_bm,
PyObject *seq,
Py_ssize_t min,
Py_ssize_t max,
Py_ssize_t *r_seq_num,
bool do_unique_check,
bool do_bm_check,
const char *error_prefix)
{
return static_cast<BMVert **>(BPy_BMElem_PySeq_As_Array(
r_bm, seq, min, max, r_seq_num, BM_VERT, do_unique_check, do_bm_check, error_prefix));
}
BMEdge **BPy_BMEdge_PySeq_As_Array(BMesh **r_bm,
PyObject *seq,
Py_ssize_t min,
Py_ssize_t max,
Py_ssize_t *r_seq_num,
bool do_unique_check,
bool do_bm_check,
const char *error_prefix)
{
return static_cast<BMEdge **>(BPy_BMElem_PySeq_As_Array(
r_bm, seq, min, max, r_seq_num, BM_EDGE, do_unique_check, do_bm_check, error_prefix));
}
BMFace **BPy_BMFace_PySeq_As_Array(BMesh **r_bm,
PyObject *seq,
Py_ssize_t min,
Py_ssize_t max,
Py_ssize_t *r_seq_num,
bool do_unique_check,
bool do_bm_check,
const char *error_prefix)
{
return static_cast<BMFace **>(BPy_BMElem_PySeq_As_Array(
r_bm, seq, min, max, r_seq_num, BM_FACE, do_unique_check, do_bm_check, error_prefix));
}
BMLoop **BPy_BMLoop_PySeq_As_Array(BMesh **r_bm,
PyObject *seq,
Py_ssize_t min,
Py_ssize_t max,
Py_ssize_t *r_seq_num,
bool do_unique_check,
bool do_bm_check,
const char *error_prefix)
{
return static_cast<BMLoop **>(BPy_BMElem_PySeq_As_Array(
r_bm, seq, min, max, r_seq_num, BM_LOOP, do_unique_check, do_bm_check, error_prefix));
}
PyObject *BPy_BMElem_Array_As_Tuple(BMesh *bm, BMHeader **elem, Py_ssize_t elem_num)
{
Py_ssize_t i;
PyObject *ret = PyTuple_New(elem_len);
for (i = 0; i < elem_len; i++) {
PyObject *ret = PyTuple_New(elem_num);
for (i = 0; i < elem_num; i++) {
PyTuple_SET_ITEM(ret, i, BPy_BMElem_CreatePyObject(bm, elem[i]));
}
return ret;
}
PyObject *BPy_BMVert_Array_As_Tuple(BMesh *bm, BMVert **elem, Py_ssize_t elem_len)
PyObject *BPy_BMVert_Array_As_Tuple(BMesh *bm, BMVert **elem, Py_ssize_t elem_num)
{
Py_ssize_t i;
PyObject *ret = PyTuple_New(elem_len);
for (i = 0; i < elem_len; i++) {
PyObject *ret = PyTuple_New(elem_num);
for (i = 0; i < elem_num; i++) {
PyTuple_SET_ITEM(ret, i, BPy_BMVert_CreatePyObject(bm, elem[i]));
}
return ret;
}
PyObject *BPy_BMEdge_Array_As_Tuple(BMesh *bm, BMEdge **elem, Py_ssize_t elem_len)
PyObject *BPy_BMEdge_Array_As_Tuple(BMesh *bm, BMEdge **elem, Py_ssize_t elem_num)
{
Py_ssize_t i;
PyObject *ret = PyTuple_New(elem_len);
for (i = 0; i < elem_len; i++) {
PyObject *ret = PyTuple_New(elem_num);
for (i = 0; i < elem_num; i++) {
PyTuple_SET_ITEM(ret, i, BPy_BMEdge_CreatePyObject(bm, elem[i]));
}
return ret;
}
PyObject *BPy_BMFace_Array_As_Tuple(BMesh *bm, BMFace **elem, Py_ssize_t elem_len)
PyObject *BPy_BMFace_Array_As_Tuple(BMesh *bm, BMFace **elem, Py_ssize_t elem_num)
{
Py_ssize_t i;
PyObject *ret = PyTuple_New(elem_len);
for (i = 0; i < elem_len; i++) {
PyObject *ret = PyTuple_New(elem_num);
for (i = 0; i < elem_num; i++) {
PyTuple_SET_ITEM(ret, i, BPy_BMFace_CreatePyObject(bm, elem[i]));
}
return ret;
}
PyObject *BPy_BMLoop_Array_As_Tuple(BMesh *bm, BMLoop *const *elem, Py_ssize_t elem_len)
PyObject *BPy_BMLoop_Array_As_Tuple(BMesh *bm, BMLoop *const *elem, Py_ssize_t elem_num)
{
Py_ssize_t i;
PyObject *ret = PyTuple_New(elem_len);
for (i = 0; i < elem_len; i++) {
PyObject *ret = PyTuple_New(elem_num);
for (i = 0; i < elem_num; i++) {
PyTuple_SET_ITEM(ret, i, BPy_BMLoop_CreatePyObject(bm, elem[i]));
}

View File

@@ -157,7 +157,7 @@ enum {
PyObject *seq_fast,
Py_ssize_t min,
Py_ssize_t max,
Py_ssize_t *r_size,
Py_ssize_t *r_seq_num,
char htype,
bool do_unique_check,
bool do_bm_check,
@@ -166,19 +166,52 @@ enum {
PyObject *seq,
Py_ssize_t min,
Py_ssize_t max,
Py_ssize_t *r_size,
Py_ssize_t *r_seq_num,
char htype,
bool do_unique_check,
bool do_bm_check,
const char *error_prefix);
[[nodiscard]] PyObject *BPy_BMElem_Array_As_Tuple(BMesh *bm, BMHeader **elem, Py_ssize_t elem_len);
[[nodiscard]] PyObject *BPy_BMVert_Array_As_Tuple(BMesh *bm, BMVert **elem, Py_ssize_t elem_len);
[[nodiscard]] PyObject *BPy_BMEdge_Array_As_Tuple(BMesh *bm, BMEdge **elem, Py_ssize_t elem_len);
[[nodiscard]] PyObject *BPy_BMFace_Array_As_Tuple(BMesh *bm, BMFace **elem, Py_ssize_t elem_len);
[[nodiscard]] BMVert **BPy_BMVert_PySeq_As_Array(BMesh **r_bm,
PyObject *seq,
Py_ssize_t min,
Py_ssize_t max,
Py_ssize_t *r_seq_num,
bool do_unique_check,
bool do_bm_check,
const char *error_prefix);
[[nodiscard]] BMEdge **BPy_BMEdge_PySeq_As_Array(BMesh **r_bm,
PyObject *seq,
Py_ssize_t min,
Py_ssize_t max,
Py_ssize_t *r_seq_num,
bool do_unique_check,
bool do_bm_check,
const char *error_prefix);
[[nodiscard]] BMFace **BPy_BMFace_PySeq_As_Array(BMesh **r_bm,
PyObject *seq,
Py_ssize_t min,
Py_ssize_t max,
Py_ssize_t *r_seq_num,
bool do_unique_check,
bool do_bm_check,
const char *error_prefix);
[[nodiscard]] BMLoop **BPy_BMLoop_PySeq_As_Array(BMesh **r_bm,
PyObject *seq,
Py_ssize_t min,
Py_ssize_t max,
Py_ssize_t *r_seq_num,
bool do_unique_check,
bool do_bm_check,
const char *error_prefix);
[[nodiscard]] PyObject *BPy_BMElem_Array_As_Tuple(BMesh *bm, BMHeader **elem, Py_ssize_t elem_num);
[[nodiscard]] PyObject *BPy_BMVert_Array_As_Tuple(BMesh *bm, BMVert **elem, Py_ssize_t elem_num);
[[nodiscard]] PyObject *BPy_BMEdge_Array_As_Tuple(BMesh *bm, BMEdge **elem, Py_ssize_t elem_num);
[[nodiscard]] PyObject *BPy_BMFace_Array_As_Tuple(BMesh *bm, BMFace **elem, Py_ssize_t elem_num);
[[nodiscard]] PyObject *BPy_BMLoop_Array_As_Tuple(BMesh *bm,
BMLoop *const *elem,
Py_ssize_t elem_len);
Py_ssize_t elem_num);
[[nodiscard]] int BPy_BMElem_CheckHType(PyTypeObject *type, char htype);
/**

View File

@@ -431,20 +431,22 @@ PyDoc_STRVAR(
" :type other: :class:`BMLayerItem`\n");
static PyObject *bpy_bmlayeritem_copy_from(BPy_BMLayerItem *self, BPy_BMLayerItem *value)
{
const char *error_prefix = "layer.copy_from(...)";
CustomData *data;
if (!BPy_BMLayerItem_Check(value)) {
PyErr_Format(PyExc_TypeError,
"layer.copy_from(x): expected BMLayerItem, not '%.200s'",
"%s: expected BMLayerItem, not '%.200s'",
error_prefix,
Py_TYPE(value)->tp_name);
return nullptr;
}
BPY_BM_CHECK_OBJ(self);
BPY_BM_CHECK_SOURCE_OBJ(self->bm, "layer.copy_from()", value);
BPY_BM_CHECK_SOURCE_OBJ(self->bm, error_prefix, value);
if ((self->htype != value->htype) || (self->type != value->type)) {
PyErr_SetString(PyExc_ValueError, "layer.copy_from(other): layer type mismatch");
PyErr_Format(PyExc_ValueError, "%s: layer type mismatch", error_prefix);
}
else if (self->index == value->index) {

View File

@@ -86,15 +86,18 @@ PyDoc_STRVAR(
" 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)
{
const char *error_prefix = "select_history.add(...)";
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);
PyErr_Format(PyExc_TypeError,
"%s: expected a BMVert/BMedge/BMFace not a %.200s",
error_prefix,
Py_TYPE(value)->tp_name);
return nullptr;
}
BPY_BM_CHECK_SOURCE_OBJ(self->bm, "select_history.add()", value);
BPY_BM_CHECK_SOURCE_OBJ(self->bm, error_prefix, value);
BM_select_history_store(self->bm, value->ele);
@@ -109,18 +112,21 @@ PyDoc_STRVAR(
" Remove an element from the selection history.\n");
static PyObject *bpy_bmeditselseq_remove(BPy_BMEditSelSeq *self, BPy_BMElem *value)
{
const char *error_prefix = "select_history.remove(...)";
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);
PyErr_Format(PyExc_TypeError,
"%s: expected a BMVert/BMedge/BMFace not a %.200s",
error_prefix,
Py_TYPE(value)->tp_name);
return nullptr;
}
BPY_BM_CHECK_SOURCE_OBJ(self->bm, "select_history.remove()", value);
BPY_BM_CHECK_SOURCE_OBJ(self->bm, error_prefix, value);
if (BM_select_history_remove(self->bm, value->ele) == false) {
PyErr_SetString(PyExc_ValueError, "Element not found in selection history");
PyErr_Format(PyExc_ValueError, "%s: element not found in selection history", error_prefix);
return nullptr;
}
@@ -137,15 +143,18 @@ PyDoc_STRVAR(
" Like remove but doesn't raise an error when the elements not in the selection list.\n");
static PyObject *bpy_bmeditselseq_discard(BPy_BMEditSelSeq *self, BPy_BMElem *value)
{
const char *error_prefix = "select_history.discard()";
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);
PyErr_Format(PyExc_TypeError,
"%s: expected a BMVert/BMedge/BMFace not a %.200s",
error_prefix,
Py_TYPE(value)->tp_name);
return nullptr;
}
BPY_BM_CHECK_SOURCE_OBJ(self->bm, "select_history.discard()", value);
BPY_BM_CHECK_SOURCE_OBJ(self->bm, error_prefix, value);
BM_select_history_remove(self->bm, value->ele);
@@ -427,24 +436,22 @@ void BPy_BM_init_types_select()
int BPy_BMEditSel_Assign(BPy_BMesh *self, PyObject *value)
{
BMesh *bm;
Py_ssize_t value_len;
Py_ssize_t i;
BMElem **value_array = nullptr;
const char *error_prefix = "BMesh.select_history = value";
BPY_BM_CHECK_INT(self);
bm = self->bm;
BMesh *bm = self->bm;
value_array = static_cast<BMElem **>(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"));
Py_ssize_t value_num;
BMElem **value_array = static_cast<BMElem **>(
BPy_BMElem_PySeq_As_Array(&bm,
value,
0,
PY_SSIZE_T_MAX,
&value_num,
BM_VERT | BM_EDGE | BM_FACE,
true,
true,
error_prefix));
if (value_array == nullptr) {
return -1;
@@ -452,7 +459,7 @@ int BPy_BMEditSel_Assign(BPy_BMesh *self, PyObject *value)
BM_select_history_clear(bm);
for (i = 0; i < value_len; i++) {
for (Py_ssize_t i = 0; i < value_num; i++) {
BM_select_history_store_notest(bm, value_array[i]);
}

View File

@@ -196,6 +196,7 @@ PyDoc_STRVAR(
" .. note:: The verts mustn't share an edge or face.\n");
static PyObject *bpy_bm_utils_vert_splice(PyObject * /*self*/, PyObject *args)
{
const char *error_prefix = "vert_splice(...)";
BPy_BMVert *py_vert;
BPy_BMVert *py_vert_target;
@@ -213,20 +214,20 @@ static PyObject *bpy_bm_utils_vert_splice(PyObject * /*self*/, PyObject *args)
BPY_BM_CHECK_OBJ(py_vert_target);
bm = py_vert->bm;
BPY_BM_CHECK_SOURCE_OBJ(bm, "vert_splice", py_vert_target);
BPY_BM_CHECK_SOURCE_OBJ(bm, error_prefix, py_vert_target);
if (py_vert->v == py_vert_target->v) {
PyErr_SetString(PyExc_ValueError, "vert_splice(...): vert arguments match");
PyErr_Format(PyExc_ValueError, "%s: vert arguments match", error_prefix);
return nullptr;
}
if (BM_edge_exists(py_vert->v, py_vert_target->v)) {
PyErr_SetString(PyExc_ValueError, "vert_splice(...): verts cannot share an edge");
PyErr_Format(PyExc_ValueError, "%s: verts cannot share an edge", error_prefix);
return nullptr;
}
if (BM_vert_pair_share_face_check(py_vert->v, py_vert_target->v)) {
PyErr_SetString(PyExc_ValueError, "vert_splice(...): verts cannot share a face");
PyErr_Format(PyExc_ValueError, "%s: verts cannot share a face", error_prefix);
return nullptr;
}
@@ -253,6 +254,7 @@ PyDoc_STRVAR(
" :rtype: tuple[:class:`bmesh.types.BMVert`, ...]\n");
static PyObject *bpy_bm_utils_vert_separate(PyObject * /*self*/, PyObject *args)
{
const char *error_prefix = "vert_separate(...)";
BPy_BMVert *py_vert;
PyObject *edge_seq;
@@ -260,10 +262,6 @@ static PyObject *bpy_bm_utils_vert_separate(PyObject * /*self*/, PyObject *args)
BMVert **elem;
int elem_len;
/* edges to split */
BMEdge **edge_array;
Py_ssize_t edge_array_len;
PyObject *ret;
if (!PyArg_ParseTuple(args, "O!O:vert_separate", &BPy_BMVert_Type, &py_vert, &edge_seq)) {
@@ -274,21 +272,16 @@ static PyObject *bpy_bm_utils_vert_separate(PyObject * /*self*/, PyObject *args)
bm = py_vert->bm;
edge_array = static_cast<BMEdge **>(BPy_BMElem_PySeq_As_Array(&bm,
edge_seq,
0,
PY_SSIZE_T_MAX,
&edge_array_len,
BM_EDGE,
true,
true,
"vert_separate(...)"));
/* Edges to split. */
Py_ssize_t edge_array_num;
BMEdge **edge_array = BPy_BMEdge_PySeq_As_Array(
&bm, edge_seq, 0, PY_SSIZE_T_MAX, &edge_array_num, true, true, error_prefix);
if (edge_array == nullptr) {
return nullptr;
}
BM_vert_separate(bm, py_vert->v, edge_array, edge_array_len, false, &elem, &elem_len);
BM_vert_separate(bm, py_vert->v, edge_array, edge_array_num, false, &elem, &elem_len);
/* return collected verts */
ret = BPy_BMVert_Array_As_Tuple(bm, elem, elem_len);
MEM_freeN(elem);
@@ -554,14 +547,12 @@ PyDoc_STRVAR(
"ignored as loose edges.\n");
static PyObject *bpy_bm_utils_face_split_edgenet(PyObject * /*self*/, PyObject *args, PyObject *kw)
{
const char *error_prefix = "face_split_edgenet(...)";
static const char *kwlist[] = {"face", "edgenet", nullptr};
BPy_BMFace *py_face;
PyObject *edge_seq;
BMEdge **edge_array;
Py_ssize_t edge_array_len;
BMesh *bm;
bool ok;
@@ -581,15 +572,9 @@ static PyObject *bpy_bm_utils_face_split_edgenet(PyObject * /*self*/, PyObject *
bm = py_face->bm;
edge_array = static_cast<BMEdge **>(BPy_BMElem_PySeq_As_Array(&bm,
edge_seq,
1,
PY_SSIZE_T_MAX,
&edge_array_len,
BM_EDGE,
true,
true,
"face_split_edgenet(...)"));
Py_ssize_t edge_array_num;
BMEdge **edge_array = BPy_BMEdge_PySeq_As_Array(
&bm, edge_seq, 1, PY_SSIZE_T_MAX, &edge_array_num, true, true, error_prefix);
if (edge_array == nullptr) {
return nullptr;
@@ -597,7 +582,7 @@ static PyObject *bpy_bm_utils_face_split_edgenet(PyObject * /*self*/, PyObject *
/* --- main function body --- */
blender::Vector<BMFace *> face_arr;
ok = BM_face_split_edgenet(bm, py_face->f, edge_array, edge_array_len, &face_arr);
ok = BM_face_split_edgenet(bm, py_face->f, edge_array, edge_array_num, &face_arr);
PyMem_FREE(edge_array);
@@ -626,10 +611,9 @@ PyDoc_STRVAR(
" :rtype: :class:`bmesh.types.BMFace`\n");
static PyObject *bpy_bm_utils_face_join(PyObject * /*self*/, PyObject *args)
{
const char *error_prefix = "face_join(...)";
BMesh *bm = nullptr;
PyObject *py_face_array;
BMFace **face_array;
Py_ssize_t face_seq_len = 0;
BMFace *f_new;
bool do_remove = true;
@@ -637,16 +621,9 @@ static PyObject *bpy_bm_utils_face_join(PyObject * /*self*/, PyObject *args)
return nullptr;
}
face_array = static_cast<BMFace **>(BPy_BMElem_PySeq_As_Array(&bm,
py_face_array,
2,
PY_SSIZE_T_MAX,
&face_seq_len,
BM_FACE,
true,
true,
"face_join(...)"));
Py_ssize_t face_seq_len = 0;
BMFace **face_array = BPy_BMFace_PySeq_As_Array(
&bm, py_face_array, 2, PY_SSIZE_T_MAX, &face_seq_len, true, true, error_prefix);
if (face_array == nullptr) {
return nullptr; /* error will be set */
}
@@ -687,6 +664,7 @@ PyDoc_STRVAR(
" This is the same as loop_separate, and has only been added for convenience.\n");
static PyObject *bpy_bm_utils_face_vert_separate(PyObject * /*self*/, PyObject *args)
{
const char *error_prefix = "face_vert_separate()";
BPy_BMFace *py_face;
BPy_BMVert *py_vert;
@@ -703,12 +681,12 @@ static PyObject *bpy_bm_utils_face_vert_separate(PyObject * /*self*/, PyObject *
bm = py_face->bm;
BPY_BM_CHECK_OBJ(py_face);
BPY_BM_CHECK_SOURCE_OBJ(bm, "face_vert_separate()", py_vert);
BPY_BM_CHECK_SOURCE_OBJ(bm, error_prefix, py_vert);
l = BM_face_vert_share_loop(py_face->f, py_vert->v);
if (l == nullptr) {
PyErr_SetString(PyExc_ValueError, "vertex not found in face");
PyErr_Format(PyExc_ValueError, "%s: vertex not found in face", error_prefix);
return nullptr;
}