bmesh python api additions:
- BMesh.is_wrapped - BMesh.copy() - BMesh.clear() - BMesh.free() - BMesh.from_object(obj, apply_modifiers=True) - BMEdge.calc_length() - BMLoop.calc_normal() - BMLoop.calc_tangent()
This commit is contained in:
@@ -154,13 +154,6 @@ void BM_mesh_data_free(BMesh *bm)
|
|||||||
|
|
||||||
BLI_freelistN(&bm->selected);
|
BLI_freelistN(&bm->selected);
|
||||||
|
|
||||||
if (bm->py_handle) {
|
|
||||||
extern void bpy_bm_generic_invalidate(void *self);
|
|
||||||
|
|
||||||
bpy_bm_generic_invalidate(bm->py_handle);
|
|
||||||
bm->py_handle = NULL;
|
|
||||||
}
|
|
||||||
|
|
||||||
BMO_error_clear(bm);
|
BMO_error_clear(bm);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -195,6 +188,16 @@ void BM_mesh_clear(BMesh *bm)
|
|||||||
void BM_mesh_free(BMesh *bm)
|
void BM_mesh_free(BMesh *bm)
|
||||||
{
|
{
|
||||||
BM_mesh_data_free(bm);
|
BM_mesh_data_free(bm);
|
||||||
|
|
||||||
|
if (bm->py_handle) {
|
||||||
|
/* keep this out of 'BM_mesh_data_free' because we wan't python
|
||||||
|
* to be able to clear the mesh and maintain access. */
|
||||||
|
extern void bpy_bm_generic_invalidate(void *self);
|
||||||
|
|
||||||
|
bpy_bm_generic_invalidate(bm->py_handle);
|
||||||
|
bm->py_handle = NULL;
|
||||||
|
}
|
||||||
|
|
||||||
MEM_freeN(bm);
|
MEM_freeN(bm);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -616,6 +616,65 @@ float BM_loop_face_angle(BMesh *UNUSED(bm), BMLoop *l)
|
|||||||
l->next->v->co);
|
l->next->v->co);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* \brief BM_loop_face_normal
|
||||||
|
*
|
||||||
|
* Calculate the normal at this loop corner or fallback to the face normal on straignt lines.
|
||||||
|
*
|
||||||
|
* \param bm The BMesh
|
||||||
|
* \param l The loop to calculate the normal at
|
||||||
|
* \param r_normal Resulting normal
|
||||||
|
*/
|
||||||
|
void BM_loop_face_normal(BMesh *UNUSED(bm), BMLoop *l, float r_normal[3])
|
||||||
|
{
|
||||||
|
if (normal_tri_v3(r_normal,
|
||||||
|
l->prev->v->co,
|
||||||
|
l->v->co,
|
||||||
|
l->next->v->co) != 0.0f)
|
||||||
|
{
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
copy_v3_v3(r_normal, l->f->no);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* \brief BM_loop_face_tangent
|
||||||
|
*
|
||||||
|
* Calculate the tangent at this loop corner or fallback to the face normal on straignt lines.
|
||||||
|
* This vector always points inward into the face.
|
||||||
|
*
|
||||||
|
* \param bm The BMesh
|
||||||
|
* \param l The loop to calculate the tangent at
|
||||||
|
* \param r_tangent Resulting tangent
|
||||||
|
*/
|
||||||
|
void BM_loop_face_tangent(BMesh *UNUSED(bm), BMLoop *l, float r_tangent[3])
|
||||||
|
{
|
||||||
|
float v_prev[3];
|
||||||
|
float v_next[3];
|
||||||
|
|
||||||
|
sub_v3_v3v3(v_prev, l->prev->v->co, l->v->co);
|
||||||
|
sub_v3_v3v3(v_next, l->v->co, l->next->v->co);
|
||||||
|
|
||||||
|
normalize_v3(v_prev);
|
||||||
|
normalize_v3(v_next);
|
||||||
|
|
||||||
|
if (compare_v3v3(v_prev, v_next, FLT_EPSILON) == FALSE) {
|
||||||
|
float dir[3];
|
||||||
|
float nor[3]; /* for this purpose doesnt need to be normalized */
|
||||||
|
add_v3_v3v3(dir, v_prev, v_next);
|
||||||
|
cross_v3_v3v3(nor, v_prev, v_next);
|
||||||
|
cross_v3_v3v3(r_tangent, dir, nor);
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
/* prev/next are the same - compare with face normal since we dont have one */
|
||||||
|
cross_v3_v3v3(r_tangent, v_next, l->f->no);
|
||||||
|
}
|
||||||
|
|
||||||
|
normalize_v3(r_tangent);
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* \brief BMESH EDGE/FACE ANGLE
|
* \brief BMESH EDGE/FACE ANGLE
|
||||||
*
|
*
|
||||||
|
|||||||
@@ -54,6 +54,8 @@ int BM_edge_is_manifold(BMesh *bm, BMEdge *e);
|
|||||||
int BM_edge_is_boundary(BMEdge *e);
|
int BM_edge_is_boundary(BMEdge *e);
|
||||||
|
|
||||||
float BM_loop_face_angle(BMesh *bm, BMLoop *l);
|
float BM_loop_face_angle(BMesh *bm, BMLoop *l);
|
||||||
|
void BM_loop_face_normal(BMesh *bm, BMLoop *l, float r_normal[3]);
|
||||||
|
void BM_loop_face_tangent(BMesh *bm, BMLoop *l, float r_tangent[3]);
|
||||||
|
|
||||||
float BM_edge_face_angle(BMesh *bm, BMEdge *e);
|
float BM_edge_face_angle(BMesh *bm, BMEdge *e);
|
||||||
float BM_vert_edge_angle(BMesh *bm, BMVert *v);
|
float BM_vert_edge_angle(BMesh *bm, BMVert *v);
|
||||||
|
|||||||
@@ -57,14 +57,11 @@ PyDoc_STRVAR(bpy_bm_new_doc,
|
|||||||
|
|
||||||
static PyObject *bpy_bm_new(PyObject *UNUSED(self))
|
static PyObject *bpy_bm_new(PyObject *UNUSED(self))
|
||||||
{
|
{
|
||||||
BPy_BMesh *py_bmesh;
|
|
||||||
BMesh *bm;
|
BMesh *bm;
|
||||||
|
|
||||||
bm = BM_mesh_create(NULL, &bm_mesh_allocsize_default);
|
bm = BM_mesh_create(NULL, &bm_mesh_allocsize_default);
|
||||||
|
|
||||||
py_bmesh = (BPy_BMesh *)BPy_BMesh_CreatePyObject(bm);
|
return BPy_BMesh_CreatePyObject(bm, BPY_BMFLAG_NOP);
|
||||||
py_bmesh->py_owns = TRUE;
|
|
||||||
return (PyObject *)py_bmesh;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
PyDoc_STRVAR(bpy_bm_from_edit_mesh_doc,
|
PyDoc_STRVAR(bpy_bm_from_edit_mesh_doc,
|
||||||
@@ -77,7 +74,6 @@ PyDoc_STRVAR(bpy_bm_from_edit_mesh_doc,
|
|||||||
);
|
);
|
||||||
static PyObject *bpy_bm_from_edit_mesh(PyObject *UNUSED(self), PyObject *value)
|
static PyObject *bpy_bm_from_edit_mesh(PyObject *UNUSED(self), PyObject *value)
|
||||||
{
|
{
|
||||||
BPy_BMesh *py_bmesh;
|
|
||||||
BMesh *bm;
|
BMesh *bm;
|
||||||
Mesh *me = PyC_RNA_AsPointer(value, "Mesh");
|
Mesh *me = PyC_RNA_AsPointer(value, "Mesh");
|
||||||
|
|
||||||
@@ -93,9 +89,7 @@ static PyObject *bpy_bm_from_edit_mesh(PyObject *UNUSED(self), PyObject *value)
|
|||||||
|
|
||||||
bm = me->edit_btmesh->bm;
|
bm = me->edit_btmesh->bm;
|
||||||
|
|
||||||
py_bmesh = (BPy_BMesh *)BPy_BMesh_CreatePyObject(bm);
|
return BPy_BMesh_CreatePyObject(bm, BPY_BMFLAG_IS_WRAPPED);
|
||||||
py_bmesh->py_owns = FALSE;
|
|
||||||
return (PyObject *)py_bmesh;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static struct PyMethodDef BPy_BM_methods[] = {
|
static struct PyMethodDef BPy_BM_methods[] = {
|
||||||
|
|||||||
@@ -36,6 +36,7 @@
|
|||||||
|
|
||||||
#include "BKE_depsgraph.h"
|
#include "BKE_depsgraph.h"
|
||||||
#include "BKE_customdata.h"
|
#include "BKE_customdata.h"
|
||||||
|
#include "BKE_DerivedMesh.h"
|
||||||
|
|
||||||
#include "bmesh.h"
|
#include "bmesh.h"
|
||||||
|
|
||||||
@@ -252,6 +253,15 @@ static PyObject *bpy_bm_is_valid_get(BPy_BMGeneric *self)
|
|||||||
return PyBool_FromLong(BPY_BM_IS_VALID(self));
|
return PyBool_FromLong(BPY_BM_IS_VALID(self));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
PyDoc_STRVAR(bpy_bmesh_is_wrapped_doc,
|
||||||
|
"True when this mesh is owned by blender (typically the editmode BMesh).\n\n:type: boolean"
|
||||||
|
);
|
||||||
|
static PyObject *bpy_bmesh_is_wrapped_get(BPy_BMesh *self)
|
||||||
|
{
|
||||||
|
BPY_BM_CHECK_OBJ(self);
|
||||||
|
|
||||||
|
return PyBool_FromLong(self->flag & BPY_BMFLAG_IS_WRAPPED);
|
||||||
|
}
|
||||||
|
|
||||||
PyDoc_STRVAR(bpy_bmesh_select_mode_doc,
|
PyDoc_STRVAR(bpy_bmesh_select_mode_doc,
|
||||||
"The selection mode, values can be {'VERT', 'EDGE', 'FACE'}, can't be assigned an empty set.\n\n:type: set"
|
"The selection mode, values can be {'VERT', 'EDGE', 'FACE'}, can't be assigned an empty set.\n\n:type: set"
|
||||||
@@ -484,6 +494,7 @@ static PyGetSetDef bpy_bmesh_getseters[] = {
|
|||||||
{(char *)"select_history", (getter)bpy_bmesh_select_history_get, (setter)bpy_bmesh_select_history_set, (char *)bpy_bmesh_select_history_doc, NULL},
|
{(char *)"select_history", (getter)bpy_bmesh_select_history_get, (setter)bpy_bmesh_select_history_set, (char *)bpy_bmesh_select_history_doc, NULL},
|
||||||
|
|
||||||
/* readonly checks */
|
/* readonly checks */
|
||||||
|
{(char *)"is_wrapped", (getter)bpy_bmesh_is_wrapped_get, (setter)NULL, (char *)bpy_bmesh_is_wrapped_doc, NULL}, /* as with mathutils */
|
||||||
{(char *)"is_valid", (getter)bpy_bm_is_valid_get, (setter)NULL, (char *)bpy_bm_is_valid_doc, NULL},
|
{(char *)"is_valid", (getter)bpy_bm_is_valid_get, (setter)NULL, (char *)bpy_bm_is_valid_doc, NULL},
|
||||||
|
|
||||||
{NULL, NULL, NULL, NULL, NULL} /* Sentinel */
|
{NULL, NULL, NULL, NULL, NULL} /* Sentinel */
|
||||||
@@ -590,6 +601,76 @@ static PyGetSetDef bpy_bmloop_getseters[] = {
|
|||||||
/* Mesh
|
/* Mesh
|
||||||
* ---- */
|
* ---- */
|
||||||
|
|
||||||
|
PyDoc_STRVAR(bpy_bmesh_copy_doc,
|
||||||
|
".. method:: copy()\n"
|
||||||
|
"\n"
|
||||||
|
" :return: A copy of this BMesh.\n"
|
||||||
|
" :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);
|
||||||
|
|
||||||
|
if (bm_copy) {
|
||||||
|
return BPy_BMesh_CreatePyObject(bm_copy, BPY_BMFLAG_NOP);
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
PyErr_SetString(PyExc_SystemError, "Unable to copy BMesh, internal error");
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
PyDoc_STRVAR(bpy_bmesh_clear_doc,
|
||||||
|
".. method:: clear()\n"
|
||||||
|
"\n"
|
||||||
|
" Clear all mesh data.\n"
|
||||||
|
);
|
||||||
|
static PyObject *bpy_bmesh_clear(BPy_BMesh *self)
|
||||||
|
{
|
||||||
|
BMesh *bm;
|
||||||
|
|
||||||
|
BPY_BM_CHECK_OBJ(self);
|
||||||
|
|
||||||
|
bm = self->bm;
|
||||||
|
|
||||||
|
BM_mesh_clear(bm);
|
||||||
|
|
||||||
|
Py_RETURN_NONE;
|
||||||
|
}
|
||||||
|
|
||||||
|
PyDoc_STRVAR(bpy_bmesh_free_doc,
|
||||||
|
".. method:: free()\n"
|
||||||
|
"\n"
|
||||||
|
" Explicitly free the BMesh data from memory, causing exceptions on further access.\n"
|
||||||
|
"\n"
|
||||||
|
" .. note::\n"
|
||||||
|
"\n"
|
||||||
|
" The BMesh is freed automatically, typically when the script finishes executing.\n"
|
||||||
|
" However in some cases its hard to predict when this will be and its useful to\n"
|
||||||
|
" explicitly free the data.\n"
|
||||||
|
);
|
||||||
|
static PyObject *bpy_bmesh_free(BPy_BMesh *self)
|
||||||
|
{
|
||||||
|
if (self->bm) {
|
||||||
|
BMesh *bm = self->bm;
|
||||||
|
|
||||||
|
if ((self->flag & BPY_BMFLAG_IS_WRAPPED) == 0) {
|
||||||
|
BM_mesh_free(bm);
|
||||||
|
}
|
||||||
|
|
||||||
|
bpy_bm_generic_invalidate((BPy_BMGeneric *)self);
|
||||||
|
}
|
||||||
|
|
||||||
|
Py_RETURN_NONE;
|
||||||
|
}
|
||||||
|
|
||||||
PyDoc_STRVAR(bpy_bmesh_to_mesh_doc,
|
PyDoc_STRVAR(bpy_bmesh_to_mesh_doc,
|
||||||
".. method:: to_mesh(mesh)\n"
|
".. method:: to_mesh(mesh)\n"
|
||||||
"\n"
|
"\n"
|
||||||
@@ -630,6 +711,49 @@ static PyObject *bpy_bmesh_to_mesh(BPy_BMesh *self, PyObject *args)
|
|||||||
Py_RETURN_NONE;
|
Py_RETURN_NONE;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* note: rna_Object_to_mesh() also has apply_modifiers arg that works the same way */
|
||||||
|
PyDoc_STRVAR(bpy_bmesh_from_object_doc,
|
||||||
|
".. method:: from_object(mesh, apply_modifiers=True)\n"
|
||||||
|
"\n"
|
||||||
|
" Initialize this bmesh from existing object datablock.\n"
|
||||||
|
"\n"
|
||||||
|
" :arg object: The object data to load.\n"
|
||||||
|
" :type object: :class:`Object`\n"
|
||||||
|
" :arg apply_modifiers: Use the final display mesh rather then the deformed cage.\n"
|
||||||
|
" :type apply_modifiers: boolean\n"
|
||||||
|
);
|
||||||
|
static PyObject *bpy_bmesh_from_object(BPy_BMesh *self, PyObject *args)
|
||||||
|
{
|
||||||
|
PyObject *py_object;
|
||||||
|
Object *ob;
|
||||||
|
BMesh *bm;
|
||||||
|
int apply_modifiers = TRUE;
|
||||||
|
DerivedMesh *dm;
|
||||||
|
|
||||||
|
BPY_BM_CHECK_OBJ(self);
|
||||||
|
|
||||||
|
if (!PyArg_ParseTuple(args, "O|i:from_object", &py_object, &apply_modifiers) ||
|
||||||
|
!(ob = PyC_RNA_AsPointer(py_object, "Object")))
|
||||||
|
{
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
dm = apply_modifiers ? ob->derivedFinal : ob->derivedDeform;
|
||||||
|
|
||||||
|
if (dm == NULL) {
|
||||||
|
PyErr_Format(PyExc_ValueError,
|
||||||
|
"from_object(...): Object '%s' has no usable mesh data", ob->id.name + 2);
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
bm = self->bm;
|
||||||
|
|
||||||
|
DM_to_bmesh_ex(dm, bm);
|
||||||
|
|
||||||
|
Py_RETURN_NONE;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
PyDoc_STRVAR(bpy_bmesh_from_mesh_doc,
|
PyDoc_STRVAR(bpy_bmesh_from_mesh_doc,
|
||||||
".. method:: from_mesh(mesh, use_shape_key=False, shape_key_index=0)\n"
|
".. method:: from_mesh(mesh, use_shape_key=False, shape_key_index=0)\n"
|
||||||
"\n"
|
"\n"
|
||||||
@@ -651,7 +775,7 @@ static PyObject *bpy_bmesh_from_mesh(BPy_BMesh *self, PyObject *args, PyObject *
|
|||||||
int use_shape_key = FALSE;
|
int use_shape_key = FALSE;
|
||||||
int shape_key_index = 0;
|
int shape_key_index = 0;
|
||||||
|
|
||||||
if (!PyArg_ParseTupleAndKeywords(args, kw, "O|ii:to_mesh", (char **)kwlist,
|
if (!PyArg_ParseTupleAndKeywords(args, kw, "O|ii:from_mesh", (char **)kwlist,
|
||||||
&py_mesh, &use_shape_key, &shape_key_index) ||
|
&py_mesh, &use_shape_key, &shape_key_index) ||
|
||||||
!(me = PyC_RNA_AsPointer(py_mesh, "Mesh")))
|
!(me = PyC_RNA_AsPointer(py_mesh, "Mesh")))
|
||||||
{
|
{
|
||||||
@@ -1001,12 +1125,22 @@ static PyObject *bpy_bmvert_normal_update(BPy_BMVert *self)
|
|||||||
/* Edge
|
/* Edge
|
||||||
* ---- */
|
* ---- */
|
||||||
|
|
||||||
|
PyDoc_STRVAR(bpy_bmedge_calc_length_doc,
|
||||||
|
".. method:: calc_length()\n"
|
||||||
|
"\n"
|
||||||
|
" :return: The length between both verts.\n"
|
||||||
|
" :rtype: float\n"
|
||||||
|
);
|
||||||
|
static PyObject *bpy_bmedge_calc_length(BPy_BMEdge *self)
|
||||||
|
{
|
||||||
|
BPY_BM_CHECK_OBJ(self);
|
||||||
|
return PyFloat_FromDouble(len_v3v3(self->e->v1->co, self->e->v2->co));
|
||||||
|
}
|
||||||
|
|
||||||
PyDoc_STRVAR(bpy_bmedge_calc_face_angle_doc,
|
PyDoc_STRVAR(bpy_bmedge_calc_face_angle_doc,
|
||||||
".. method:: calc_face_angle()\n"
|
".. method:: calc_face_angle()\n"
|
||||||
"\n"
|
"\n"
|
||||||
" Return the angle between 2 connected faces.\n"
|
" :return: The angle between 2 connected faces in radians.\n"
|
||||||
"\n"
|
|
||||||
" :return: The angle between both faces in radians.\n"
|
|
||||||
" :rtype: float\n"
|
" :rtype: float\n"
|
||||||
);
|
);
|
||||||
static PyObject *bpy_bmedge_calc_face_angle(BPy_BMEdge *self)
|
static PyObject *bpy_bmedge_calc_face_angle(BPy_BMEdge *self)
|
||||||
@@ -1270,21 +1404,54 @@ static PyObject *bpy_bmloop_copy_from_face_interp(BPy_BMLoop *self, PyObject *ar
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
PyDoc_STRVAR(bpy_bmloop_calc_face_angle_doc,
|
PyDoc_STRVAR(bpy_bmloop_calc_angle_doc,
|
||||||
".. method:: calc_face_angle()\n"
|
".. method:: calc_angle()\n"
|
||||||
"\n"
|
"\n"
|
||||||
" Return angle at this loops corner of the face.\n"
|
" Return the angle at this loops corner of the face.\n"
|
||||||
" This is calculated so sharper corners give lower angles.\n"
|
" This is calculated so sharper corners give lower angles.\n"
|
||||||
"\n"
|
"\n"
|
||||||
" :return: The angle in radians.\n"
|
" :return: The angle in radians.\n"
|
||||||
" :rtype: float\n"
|
" :rtype: float\n"
|
||||||
);
|
);
|
||||||
static PyObject *bpy_bmloop_calc_face_angle(BPy_BMLoop *self)
|
static PyObject *bpy_bmloop_calc_angle(BPy_BMLoop *self)
|
||||||
{
|
{
|
||||||
BPY_BM_CHECK_OBJ(self);
|
BPY_BM_CHECK_OBJ(self);
|
||||||
return PyFloat_FromDouble(BM_loop_face_angle(self->bm, self->l));
|
return PyFloat_FromDouble(BM_loop_face_angle(self->bm, self->l));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
PyDoc_STRVAR(bpy_bmloop_calc_normal_doc,
|
||||||
|
".. method:: calc_normal()\n"
|
||||||
|
"\n"
|
||||||
|
" Return normal at this loops corner of the face.\n"
|
||||||
|
" Falls back to the face normal for straignt lines.\n"
|
||||||
|
"\n"
|
||||||
|
" :return: a normalized vector.\n"
|
||||||
|
" :rtype: :class:`mathutils.Vector`\n"
|
||||||
|
);
|
||||||
|
static PyObject *bpy_bmloop_calc_normal(BPy_BMLoop *self)
|
||||||
|
{
|
||||||
|
float vec[3];
|
||||||
|
BPY_BM_CHECK_OBJ(self);
|
||||||
|
BM_loop_face_normal(self->bm, self->l, vec);
|
||||||
|
return Vector_CreatePyObject(vec, 3, Py_NEW, NULL);
|
||||||
|
}
|
||||||
|
|
||||||
|
PyDoc_STRVAR(bpy_bmloop_calc_tangent_doc,
|
||||||
|
".. method:: calc_tangent()\n"
|
||||||
|
"\n"
|
||||||
|
" Return the tangent at this loops corner of the face (pointing inward into the face).\n"
|
||||||
|
" Falls back to the face normal for straignt lines.\n"
|
||||||
|
"\n"
|
||||||
|
" :return: a normalized vector.\n"
|
||||||
|
" :rtype: :class:`mathutils.Vector`\n"
|
||||||
|
);
|
||||||
|
static PyObject *bpy_bmloop_calc_tangent(BPy_BMLoop *self)
|
||||||
|
{
|
||||||
|
float vec[3];
|
||||||
|
BPY_BM_CHECK_OBJ(self);
|
||||||
|
BM_loop_face_tangent(self->bm, self->l, vec);
|
||||||
|
return Vector_CreatePyObject(vec, 3, Py_NEW, NULL);
|
||||||
|
}
|
||||||
|
|
||||||
/* Vert Seq
|
/* Vert Seq
|
||||||
* -------- */
|
* -------- */
|
||||||
@@ -1796,9 +1963,17 @@ static PyObject *bpy_bmelemseq_index_update(BPy_BMElemSeq *self)
|
|||||||
|
|
||||||
|
|
||||||
static struct PyMethodDef bpy_bmesh_methods[] = {
|
static struct PyMethodDef bpy_bmesh_methods[] = {
|
||||||
|
/* utility */
|
||||||
|
{"copy", (PyCFunction)bpy_bmesh_copy, METH_NOARGS, bpy_bmesh_copy_doc},
|
||||||
|
{"clear", (PyCFunction)bpy_bmesh_clear, METH_NOARGS, bpy_bmesh_clear_doc},
|
||||||
|
{"free", (PyCFunction)bpy_bmesh_free, METH_NOARGS, bpy_bmesh_free_doc},
|
||||||
|
|
||||||
|
/* conversion */
|
||||||
|
{"from_object", (PyCFunction)bpy_bmesh_from_object, METH_VARARGS | METH_KEYWORDS, bpy_bmesh_from_object_doc},
|
||||||
{"from_mesh", (PyCFunction)bpy_bmesh_from_mesh, METH_VARARGS | METH_KEYWORDS, bpy_bmesh_from_mesh_doc},
|
{"from_mesh", (PyCFunction)bpy_bmesh_from_mesh, METH_VARARGS | METH_KEYWORDS, bpy_bmesh_from_mesh_doc},
|
||||||
{"to_mesh", (PyCFunction)bpy_bmesh_to_mesh, METH_VARARGS, bpy_bmesh_to_mesh_doc},
|
{"to_mesh", (PyCFunction)bpy_bmesh_to_mesh, METH_VARARGS, bpy_bmesh_to_mesh_doc},
|
||||||
|
|
||||||
|
/* meshdata */
|
||||||
{"select_flush_mode", (PyCFunction)bpy_bmesh_select_flush_mode, METH_NOARGS, bpy_bmesh_select_flush_mode_doc},
|
{"select_flush_mode", (PyCFunction)bpy_bmesh_select_flush_mode, METH_NOARGS, bpy_bmesh_select_flush_mode_doc},
|
||||||
{"select_flush", (PyCFunction)bpy_bmesh_select_flush, METH_O, bpy_bmesh_select_flush_doc},
|
{"select_flush", (PyCFunction)bpy_bmesh_select_flush, METH_O, bpy_bmesh_select_flush_doc},
|
||||||
{"normal_update", (PyCFunction)bpy_bmesh_normal_update, METH_VARARGS, bpy_bmesh_normal_update_doc},
|
{"normal_update", (PyCFunction)bpy_bmesh_normal_update, METH_VARARGS, bpy_bmesh_normal_update_doc},
|
||||||
@@ -1827,6 +2002,7 @@ static struct PyMethodDef bpy_bmedge_methods[] = {
|
|||||||
|
|
||||||
{"other_vert", (PyCFunction)bpy_bmedge_other_vert, METH_O, bpy_bmedge_other_vert_doc},
|
{"other_vert", (PyCFunction)bpy_bmedge_other_vert, METH_O, bpy_bmedge_other_vert_doc},
|
||||||
|
|
||||||
|
{"calc_length", (PyCFunction)bpy_bmedge_calc_length, METH_NOARGS, bpy_bmedge_calc_length_doc},
|
||||||
{"calc_face_angle", (PyCFunction)bpy_bmedge_calc_face_angle, METH_NOARGS, bpy_bmedge_calc_face_angle_doc},
|
{"calc_face_angle", (PyCFunction)bpy_bmedge_calc_face_angle, METH_NOARGS, bpy_bmedge_calc_face_angle_doc},
|
||||||
|
|
||||||
{"normal_update", (PyCFunction)bpy_bmedge_normal_update, METH_NOARGS, bpy_bmedge_normal_update_doc},
|
{"normal_update", (PyCFunction)bpy_bmedge_normal_update, METH_NOARGS, bpy_bmedge_normal_update_doc},
|
||||||
@@ -1856,7 +2032,9 @@ static struct PyMethodDef bpy_bmloop_methods[] = {
|
|||||||
{"copy_from", (PyCFunction)bpy_bm_elem_copy_from, METH_O, bpy_bm_elem_copy_from_doc},
|
{"copy_from", (PyCFunction)bpy_bm_elem_copy_from, METH_O, bpy_bm_elem_copy_from_doc},
|
||||||
{"copy_from_face_interp", (PyCFunction)bpy_bmloop_copy_from_face_interp, METH_O, bpy_bmloop_copy_from_face_interp_doc},
|
{"copy_from_face_interp", (PyCFunction)bpy_bmloop_copy_from_face_interp, METH_O, bpy_bmloop_copy_from_face_interp_doc},
|
||||||
|
|
||||||
{"calc_angle", (PyCFunction)bpy_bmloop_calc_face_angle, METH_NOARGS, bpy_bmloop_calc_face_angle_doc},
|
{"calc_angle", (PyCFunction)bpy_bmloop_calc_angle, METH_NOARGS, bpy_bmloop_calc_angle_doc},
|
||||||
|
{"calc_normal", (PyCFunction)bpy_bmloop_calc_normal, METH_NOARGS, bpy_bmloop_calc_normal_doc},
|
||||||
|
{"calc_tangent", (PyCFunction)bpy_bmloop_calc_tangent, METH_NOARGS, bpy_bmloop_calc_tangent_doc},
|
||||||
{NULL, NULL, 0, NULL}
|
{NULL, NULL, 0, NULL}
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -2143,11 +2321,11 @@ static void bpy_bmesh_dealloc(BPy_BMesh *self)
|
|||||||
BM_data_layer_free(bm, &bm->ldata, CD_BM_ELEM_PYPTR);
|
BM_data_layer_free(bm, &bm->ldata, CD_BM_ELEM_PYPTR);
|
||||||
|
|
||||||
bm->py_handle = NULL;
|
bm->py_handle = NULL;
|
||||||
}
|
|
||||||
|
|
||||||
if (self->py_owns) {
|
if ((self->flag & BPY_BMFLAG_IS_WRAPPED) == 0) {
|
||||||
BM_mesh_free(bm);
|
BM_mesh_free(bm);
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
PyObject_DEL(self);
|
PyObject_DEL(self);
|
||||||
}
|
}
|
||||||
@@ -2476,7 +2654,7 @@ PyObject *BPyInit_bmesh_types(void)
|
|||||||
/* Utility Functions
|
/* Utility Functions
|
||||||
* ***************** */
|
* ***************** */
|
||||||
|
|
||||||
PyObject *BPy_BMesh_CreatePyObject(BMesh *bm)
|
PyObject *BPy_BMesh_CreatePyObject(BMesh *bm, int flag)
|
||||||
{
|
{
|
||||||
BPy_BMesh *self;
|
BPy_BMesh *self;
|
||||||
|
|
||||||
@@ -2487,6 +2665,8 @@ PyObject *BPy_BMesh_CreatePyObject(BMesh *bm)
|
|||||||
else {
|
else {
|
||||||
self = PyObject_New(BPy_BMesh, &BPy_BMesh_Type);
|
self = PyObject_New(BPy_BMesh, &BPy_BMesh_Type);
|
||||||
self->bm = bm;
|
self->bm = bm;
|
||||||
|
self->flag = flag;
|
||||||
|
|
||||||
bm->py_handle = self; /* point back */
|
bm->py_handle = self; /* point back */
|
||||||
|
|
||||||
BM_data_layer_add(bm, &bm->vdata, CD_BM_ELEM_PYPTR);
|
BM_data_layer_add(bm, &bm->vdata, CD_BM_ELEM_PYPTR);
|
||||||
|
|||||||
@@ -62,7 +62,7 @@ typedef struct BPy_BMElem {
|
|||||||
typedef struct BPy_BMesh {
|
typedef struct BPy_BMesh {
|
||||||
PyObject_VAR_HEAD
|
PyObject_VAR_HEAD
|
||||||
struct BMesh *bm; /* keep first */
|
struct BMesh *bm; /* keep first */
|
||||||
char py_owns; /* when set, free along with the PyObject */
|
int flag;
|
||||||
} BPy_BMesh;
|
} BPy_BMesh;
|
||||||
|
|
||||||
/* element types */
|
/* element types */
|
||||||
@@ -120,7 +120,12 @@ void BPy_BM_init_types(void);
|
|||||||
|
|
||||||
PyObject *BPyInit_bmesh_types(void);
|
PyObject *BPyInit_bmesh_types(void);
|
||||||
|
|
||||||
PyObject *BPy_BMesh_CreatePyObject(BMesh *bm);
|
enum {
|
||||||
|
BPY_BMFLAG_NOP = 0, /* do nothing */
|
||||||
|
BPY_BMFLAG_IS_WRAPPED = 1 /* the mesh is owned by editmode */
|
||||||
|
};
|
||||||
|
|
||||||
|
PyObject *BPy_BMesh_CreatePyObject(BMesh *bm, int flag);
|
||||||
PyObject *BPy_BMVert_CreatePyObject(BMesh *bm, BMVert *v);
|
PyObject *BPy_BMVert_CreatePyObject(BMesh *bm, BMVert *v);
|
||||||
PyObject *BPy_BMEdge_CreatePyObject(BMesh *bm, BMEdge *e);
|
PyObject *BPy_BMEdge_CreatePyObject(BMesh *bm, BMEdge *e);
|
||||||
PyObject *BPy_BMFace_CreatePyObject(BMesh *bm, BMFace *f);
|
PyObject *BPy_BMFace_CreatePyObject(BMesh *bm, BMFace *f);
|
||||||
|
|||||||
Reference in New Issue
Block a user