diff options
Diffstat (limited to 'source/blender/freestyle/intern/python/Interface0D')
12 files changed, 1791 insertions, 0 deletions
diff --git a/source/blender/freestyle/intern/python/Interface0D/BPy_CurvePoint.cpp b/source/blender/freestyle/intern/python/Interface0D/BPy_CurvePoint.cpp new file mode 100644 index 00000000000..3e2cc495785 --- /dev/null +++ b/source/blender/freestyle/intern/python/Interface0D/BPy_CurvePoint.cpp @@ -0,0 +1,246 @@ +#include "BPy_CurvePoint.h" + +#include "../BPy_Convert.h" +#include "../Interface0D/BPy_SVertex.h" + +#ifdef __cplusplus +extern "C" { +#endif + +/////////////////////////////////////////////////////////////////////////////////////////// + +/*----------------------CurvePoint methods----------------------------*/ + +PyDoc_STRVAR(CurvePoint_doc, +"Class hierarchy: :class:`Interface0D` > :class:`CurvePoint`\n" +"\n" +"Class to represent a point of a curve. A CurvePoint can be any point\n" +"of a 1D curve (it doesn't have to be a vertex of the curve). Any\n" +":class:`Interface1D` is built upon ViewEdges, themselves built upon\n" +"FEdges. Therefore, a curve is basically a polyline made of a list of\n" +":class:`SVertex` objects. Thus, a CurvePoint is built by linearly\n" +"interpolating two :class:`SVertex` instances. CurvePoint can be used\n" +"as virtual points while querying 0D information along a curve at a\n" +"given resolution.\n" +"\n" +".. method:: __init__()\n" +"\n" +" Defult constructor.\n" +"\n" +".. method:: __init__(iBrother)\n" +"\n" +" Copy constructor.\n" +"\n" +" :arg iBrother: A CurvePoint object.\n" +" :type iBrother: :class:`CurvePoint`\n" +"\n" +".. method:: __init__(iA, iB, t2d)\n" +"\n" +" Builds a CurvePoint from two SVertex and an interpolation parameter.\n" +"\n" +" :arg iA: The first SVertex.\n" +" :type iA: :class:`SVertex`\n" +" :arg iB: The second SVertex.\n" +" :type iB: :class:`SVertex`\n" +" :arg t2d: A 2D interpolation parameter used to linearly interpolate\n" +" iA and iB.\n" +" :type t2d: float\n" +"\n" +".. method:: __init__(iA, iB, t2d)\n" +"\n" +" Builds a CurvePoint from two CurvePoint and an interpolation\n" +" parameter.\n" +"\n" +" :arg iA: The first CurvePoint.\n" +" :type iA: :class:`CurvePoint`\n" +" :arg iB: The second CurvePoint.\n" +" :type iB: :class:`CurvePoint`\n" +" :arg t2d: The 2D interpolation parameter used to linearly\n" +" interpolate iA and iB.\n" +" :type t2d: float"); + +static int CurvePoint_init(BPy_CurvePoint *self, PyObject *args, PyObject *kwds) +{ + + PyObject *obj1 = 0, *obj2 = 0 , *obj3 = 0; + + if (! PyArg_ParseTuple(args, "|OOO!", &obj1, &obj2, &PyFloat_Type, &obj3) ) + return -1; + + if( !obj1 ){ + self->cp = new CurvePoint(); + + } else if( !obj2 && BPy_CurvePoint_Check(obj1) ) { + self->cp = new CurvePoint( *(((BPy_CurvePoint *) obj1)->cp) ); + + } else if( obj3 && BPy_SVertex_Check(obj1) && BPy_SVertex_Check(obj2) ) { + self->cp = new CurvePoint( ((BPy_SVertex *) obj1)->sv, + ((BPy_SVertex *) obj2)->sv, + PyFloat_AsDouble( obj3 ) ); + + } else if( obj3 && BPy_CurvePoint_Check(obj1) && BPy_CurvePoint_Check(obj2) ) { + CurvePoint *cp1 = ((BPy_CurvePoint *) obj1)->cp; + CurvePoint *cp2 = ((BPy_CurvePoint *) obj2)->cp; + if( !cp1 || cp1->A() == 0 || cp1->B() == 0 ) { + PyErr_SetString(PyExc_TypeError, "argument 1 is an invalid CurvePoint object"); + return -1; + } + if( !cp2 || cp2->A() == 0 || cp2->B() == 0 ) { + PyErr_SetString(PyExc_TypeError, "argument 2 is an invalid CurvePoint object"); + return -1; + } + self->cp = new CurvePoint( cp1, cp2, PyFloat_AsDouble( obj3 ) ); + + } else { + PyErr_SetString(PyExc_TypeError, "invalid argument(s)"); + return -1; + } + + self->py_if0D.if0D = self->cp; + self->py_if0D.borrowed = 0; + + return 0; +} + +///bool operator== (const CurvePoint &b) + +static PyMethodDef BPy_CurvePoint_methods[] = { + {NULL, NULL, 0, NULL} +}; + +/*----------------------CurvePoint get/setters ----------------------------*/ + +PyDoc_STRVAR(CurvePoint_first_svertex_doc, +"The first SVertex upon which the CurvePoint is built.\n" +"\n" +":type: int"); + +static PyObject *CurvePoint_first_svertex_get(BPy_CurvePoint *self, void *UNUSED(closure)) +{ + SVertex *A = self->cp->A(); + if (A) + return BPy_SVertex_from_SVertex(*A); + Py_RETURN_NONE; +} + +static int CurvePoint_first_svertex_set(BPy_CurvePoint *self, PyObject *value, void *UNUSED(closure)) +{ + if (!BPy_SVertex_Check(value)) { + PyErr_SetString(PyExc_TypeError, "value must be an SVertex"); + return -1; + } + self->cp->setA(((BPy_SVertex *)value)->sv); + return 0; +} + +PyDoc_STRVAR(CurvePoint_second_svertex_doc, +"The second SVertex upon which the CurvePoint is built.\n" +"\n" +":type: int"); + +static PyObject *CurvePoint_second_svertex_get(BPy_CurvePoint *self, void *UNUSED(closure)) +{ + SVertex *B = self->cp->B(); + if (B) + return BPy_SVertex_from_SVertex(*B); + Py_RETURN_NONE; +} + +static int CurvePoint_second_svertex_set(BPy_CurvePoint *self, PyObject *value, void *UNUSED(closure)) +{ + if (!BPy_SVertex_Check(value)) { + PyErr_SetString(PyExc_TypeError, "value must be an SVertex"); + return -1; + } + self->cp->setB(((BPy_SVertex *)value)->sv); + return 0; +} + +PyDoc_STRVAR(CurvePoint_t2d_doc, +"The 2D interpolation parameter.\n" +"\n" +":type: float"); + +static PyObject *CurvePoint_t2d_get(BPy_CurvePoint *self, void *UNUSED(closure)) +{ + return PyFloat_FromDouble(self->cp->t2d()); +} + +static int CurvePoint_t2d_set(BPy_CurvePoint *self, PyObject *value, void *UNUSED(closure)) +{ + float scalar; + if ((scalar = PyFloat_AsDouble(value)) == -1.0f && PyErr_Occurred()) { + PyErr_SetString(PyExc_TypeError, "value must be a number"); + return -1; + } + self->cp->setT2d(scalar); + return 0; +} + +PyDoc_STRVAR(CurvePoint_curvature_fredo_doc, +"The angle (Fredo's curvature) in radians.\n" +"\n" +":type: float"); + +static PyObject *CurvePoint_curvature_fredo_get(BPy_CurvePoint *self, void *UNUSED(closure)) +{ + return PyFloat_FromDouble(self->cp->curvatureFredo()); +} + +// todo - CurvePoint.directionFredo() + +static PyGetSetDef BPy_CurvePoint_getseters[] = { + {(char *)"first_svertex", (getter)CurvePoint_first_svertex_get, (setter)CurvePoint_first_svertex_set, (char *)CurvePoint_first_svertex_doc, NULL}, + {(char *)"second_svertex", (getter)CurvePoint_second_svertex_get, (setter)CurvePoint_second_svertex_set, (char *)CurvePoint_second_svertex_doc, NULL}, + {(char *)"t2d", (getter)CurvePoint_t2d_get, (setter)CurvePoint_t2d_set, (char *)CurvePoint_t2d_doc, NULL}, + {(char *)"curvature_fredo", (getter)CurvePoint_curvature_fredo_get, (setter)NULL, (char *)CurvePoint_curvature_fredo_doc, NULL}, + {NULL, NULL, NULL, NULL, NULL} /* Sentinel */ +}; + +/*-----------------------BPy_CurvePoint type definition ------------------------------*/ +PyTypeObject CurvePoint_Type = { + PyVarObject_HEAD_INIT(NULL, 0) + "CurvePoint", /* tp_name */ + sizeof(BPy_CurvePoint), /* tp_basicsize */ + 0, /* tp_itemsize */ + 0, /* tp_dealloc */ + 0, /* tp_print */ + 0, /* tp_getattr */ + 0, /* tp_setattr */ + 0, /* tp_reserved */ + 0, /* tp_repr */ + 0, /* tp_as_number */ + 0, /* tp_as_sequence */ + 0, /* tp_as_mapping */ + 0, /* tp_hash */ + 0, /* tp_call */ + 0, /* tp_str */ + 0, /* tp_getattro */ + 0, /* tp_setattro */ + 0, /* tp_as_buffer */ + Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE, /* tp_flags */ + CurvePoint_doc, /* tp_doc */ + 0, /* tp_traverse */ + 0, /* tp_clear */ + 0, /* tp_richcompare */ + 0, /* tp_weaklistoffset */ + 0, /* tp_iter */ + 0, /* tp_iternext */ + BPy_CurvePoint_methods, /* tp_methods */ + 0, /* tp_members */ + BPy_CurvePoint_getseters, /* tp_getset */ + &Interface0D_Type, /* tp_base */ + 0, /* tp_dict */ + 0, /* tp_descr_get */ + 0, /* tp_descr_set */ + 0, /* tp_dictoffset */ + (initproc)CurvePoint_init, /* tp_init */ + 0, /* tp_alloc */ + 0, /* tp_new */ +}; + +/////////////////////////////////////////////////////////////////////////////////////////// + +#ifdef __cplusplus +} +#endif diff --git a/source/blender/freestyle/intern/python/Interface0D/BPy_CurvePoint.h b/source/blender/freestyle/intern/python/Interface0D/BPy_CurvePoint.h new file mode 100644 index 00000000000..b4c22645503 --- /dev/null +++ b/source/blender/freestyle/intern/python/Interface0D/BPy_CurvePoint.h @@ -0,0 +1,31 @@ +#ifndef FREESTYLE_PYTHON_CURVEPOINT_H +#define FREESTYLE_PYTHON_CURVEPOINT_H + +#include "../BPy_Interface0D.h" +#include "../../stroke/Curve.h" + +#ifdef __cplusplus +extern "C" { +#endif + +/////////////////////////////////////////////////////////////////////////////////////////// + +#include <Python.h> + +extern PyTypeObject CurvePoint_Type; + +#define BPy_CurvePoint_Check(v) ( PyObject_IsInstance( (PyObject *) v, (PyObject *) &CurvePoint_Type) ) + +/*---------------------------Python BPy_CurvePoint structure definition----------*/ +typedef struct { + BPy_Interface0D py_if0D; + CurvePoint *cp; +} BPy_CurvePoint; + +/////////////////////////////////////////////////////////////////////////////////////////// + +#ifdef __cplusplus +} +#endif + +#endif /* FREESTYLE_PYTHON_CURVEPOINT_H */ diff --git a/source/blender/freestyle/intern/python/Interface0D/BPy_SVertex.cpp b/source/blender/freestyle/intern/python/Interface0D/BPy_SVertex.cpp new file mode 100644 index 00000000000..0d0a772b4e5 --- /dev/null +++ b/source/blender/freestyle/intern/python/Interface0D/BPy_SVertex.cpp @@ -0,0 +1,448 @@ +#include "BPy_SVertex.h" + +#include "../BPy_Convert.h" +#include "../BPy_Id.h" +#include "../Interface1D/BPy_FEdge.h" + +#ifdef __cplusplus +extern "C" { +#endif + +/////////////////////////////////////////////////////////////////////////////////////////// + +/*----------------------SVertex methods ----------------------------*/ + +PyDoc_STRVAR(SVertex_doc, +"Class hierarchy: :class:`Interface0D` > :class:`SVertex`\n" +"\n" +"Class to define a vertex of the embedding.\n" +"\n" +".. method:: __init__()\n" +"\n" +" Default constructor.\n" +"\n" +".. method:: __init__(iBrother)\n" +"\n" +" Copy constructor.\n" +"\n" +" :arg iBrother: A SVertex object.\n" +" :type iBrother: :class:`SVertex`\n" +"\n" +".. method:: __init__(iPoint3D, id)\n" +"\n" +" Builds a SVertex from 3D coordinates and an Id.\n" +"\n" +" :arg iPoint3D: A three-dimensional vector.\n" +" :type iPoint3D: :class:`mathutils.Vector`\n" +" :arg id: An Id object.\n" +" :type id: :class:`Id`"); + +static int SVertex_init(BPy_SVertex *self, PyObject *args, PyObject *kwds) +{ + PyObject *py_point = 0; + BPy_Id *py_id = 0; + + if (!PyArg_ParseTuple(args, "|OO!", &py_point, &Id_Type, &py_id)) + return -1; + + if (!py_point) { + self->sv = new SVertex(); + + } else if (!py_id && BPy_SVertex_Check(py_point)) { + self->sv = new SVertex( *(((BPy_SVertex *)py_point)->sv) ); + + } else if (py_point && py_id) { + Vec3r *v = Vec3r_ptr_from_PyObject(py_point); + if (!v) { + PyErr_SetString(PyExc_TypeError, "argument 1 must be a 3D vector (either a list of 3 elements or Vector)"); + return -1; + } + self->sv = new SVertex(*v, *(py_id->id)); + delete v; + + } else { + PyErr_SetString(PyExc_TypeError, "invalid argument(s)"); + return -1; + } + + self->py_if0D.if0D = self->sv; + self->py_if0D.borrowed = 0; + + return 0; +} + +PyDoc_STRVAR(SVertex_add_normal_doc, +".. method:: add_normal(n)\n" +"\n" +" Adds a normal to the SVertex's set of normals. If the same normal\n" +" is already in the set, nothing changes.\n" +"\n" +" :arg n: A three-dimensional vector.\n" +" :type n: :class:`mathutils.Vector`, list or tuple of 3 real numbers"); + +static PyObject *SVertex_add_normal( BPy_SVertex *self , PyObject *args) { + PyObject *py_normal; + + if (!PyArg_ParseTuple(args, "O", &py_normal)) + return NULL; + Vec3r *n = Vec3r_ptr_from_PyObject(py_normal); + if (!n) { + PyErr_SetString(PyExc_TypeError, "argument 1 must be a 3D vector (either a list of 3 elements or Vector)"); + return NULL; + } + self->sv->AddNormal(*n); + delete n; + + Py_RETURN_NONE; +} + +PyDoc_STRVAR(SVertex_add_fedge_doc, +".. method:: add_fedge(fe)\n" +"\n" +" Add an FEdge to the list of edges emanating from this SVertex.\n" +"\n" +" :arg fe: An FEdge.\n" +" :type fe: :class:`FEdge`"); + +static PyObject *SVertex_add_fedge( BPy_SVertex *self , PyObject *args) { + PyObject *py_fe; + + if (!PyArg_ParseTuple(args, "O!", &FEdge_Type, &py_fe)) + return NULL; + + self->sv->AddFEdge(((BPy_FEdge *)py_fe)->fe); + + Py_RETURN_NONE; +} + +// virtual bool operator== (const SVertex &iBrother) + +static PyMethodDef BPy_SVertex_methods[] = { + {"add_normal", (PyCFunction)SVertex_add_normal, METH_VARARGS, SVertex_add_normal_doc}, + {"add_fedge", (PyCFunction)SVertex_add_fedge, METH_VARARGS, SVertex_add_fedge_doc}, + {NULL, NULL, 0, NULL} +}; + +/*----------------------mathutils callbacks ----------------------------*/ + +/* subtype */ +#define MATHUTILS_SUBTYPE_POINT3D 1 +#define MATHUTILS_SUBTYPE_POINT2D 2 + +static int SVertex_mathutils_check(BaseMathObject *bmo) +{ + if (!BPy_SVertex_Check(bmo->cb_user)) + return -1; + return 0; +} + +static int SVertex_mathutils_get(BaseMathObject *bmo, int subtype) +{ + BPy_SVertex *self = (BPy_SVertex *)bmo->cb_user; + switch (subtype) { + case MATHUTILS_SUBTYPE_POINT3D: + bmo->data[0] = self->sv->getX(); + bmo->data[1] = self->sv->getY(); + bmo->data[2] = self->sv->getZ(); + break; + case MATHUTILS_SUBTYPE_POINT2D: + bmo->data[0] = self->sv->getProjectedX(); + bmo->data[1] = self->sv->getProjectedY(); + bmo->data[2] = self->sv->getProjectedZ(); + break; + default: + return -1; + } + return 0; +} + +static int SVertex_mathutils_set(BaseMathObject *bmo, int subtype) +{ + BPy_SVertex *self = (BPy_SVertex *)bmo->cb_user; + switch (subtype) { + case MATHUTILS_SUBTYPE_POINT3D: + { + Vec3r p(bmo->data[0], bmo->data[1], bmo->data[2]); + self->sv->setPoint3D(p); + } + break; + case MATHUTILS_SUBTYPE_POINT2D: + { + Vec3r p(bmo->data[0], bmo->data[1], bmo->data[2]); + self->sv->setPoint2D(p); + } + break; + default: + return -1; + } + return 0; +} + +static int SVertex_mathutils_get_index(BaseMathObject *bmo, int subtype, int index) +{ + BPy_SVertex *self = (BPy_SVertex *)bmo->cb_user; + switch (subtype) { + case MATHUTILS_SUBTYPE_POINT3D: + switch (index) { + case 0: bmo->data[0] = self->sv->getX(); break; + case 1: bmo->data[1] = self->sv->getY(); break; + case 2: bmo->data[2] = self->sv->getZ(); break; + default: + return -1; + } + break; + case MATHUTILS_SUBTYPE_POINT2D: + switch (index) { + case 0: bmo->data[0] = self->sv->getProjectedX(); break; + case 1: bmo->data[1] = self->sv->getProjectedY(); break; + case 2: bmo->data[2] = self->sv->getProjectedZ(); break; + default: + return -1; + } + break; + default: + return -1; + } + return 0; +} + +static int SVertex_mathutils_set_index(BaseMathObject *bmo, int subtype, int index) +{ + BPy_SVertex *self = (BPy_SVertex *)bmo->cb_user; + switch (subtype) { + case MATHUTILS_SUBTYPE_POINT3D: + { + Vec3r p(self->sv->point3D()); + p[index] = bmo->data[index]; + self->sv->setPoint3D(p); + } + break; + case MATHUTILS_SUBTYPE_POINT2D: + { + Vec3r p(self->sv->point2D()); + p[index] = bmo->data[index]; + self->sv->setPoint2D(p); + } + break; + default: + return -1; + } + return 0; +} + +static Mathutils_Callback SVertex_mathutils_cb = { + SVertex_mathutils_check, + SVertex_mathutils_get, + SVertex_mathutils_set, + SVertex_mathutils_get_index, + SVertex_mathutils_set_index +}; + +static unsigned char SVertex_mathutils_cb_index = -1; + +void SVertex_mathutils_register_callback() +{ + SVertex_mathutils_cb_index = Mathutils_RegisterCallback(&SVertex_mathutils_cb); +} + +/*----------------------SVertex get/setters ----------------------------*/ + +PyDoc_STRVAR(SVertex_point_3d_doc, +"The 3D coordinates of the SVertex.\n" +"\n" +":type: mathutils.Vector"); + +static PyObject *SVertex_point_3d_get(BPy_SVertex *self, void *UNUSED(closure)) +{ + return Vector_CreatePyObject_cb((PyObject *)self, 3, SVertex_mathutils_cb_index, MATHUTILS_SUBTYPE_POINT3D); +} + +static int SVertex_point_3d_set(BPy_SVertex *self, PyObject *value, void *UNUSED(closure)) +{ + float v[3]; + if (!float_array_from_PyObject(value, v, 3)) { + PyErr_SetString(PyExc_ValueError, "value must be a 3-dimensional vector"); + return -1; + } + Vec3r p(v[0], v[1], v[2]); + self->sv->setPoint3D(p); + return 0; +} + +PyDoc_STRVAR(SVertex_point_2d_doc, +"The projected 3D coordinates of the SVertex.\n" +"\n" +":type: mathutils.Vector"); + +static PyObject *SVertex_point_2d_get(BPy_SVertex *self, void *UNUSED(closure)) +{ + return Vector_CreatePyObject_cb((PyObject *)self, 3, SVertex_mathutils_cb_index, MATHUTILS_SUBTYPE_POINT2D); +} + +static int SVertex_point_2d_set(BPy_SVertex *self, PyObject *value, void *UNUSED(closure)) +{ + float v[3]; + if (!float_array_from_PyObject(value, v, 3)) { + PyErr_SetString(PyExc_ValueError, "value must be a 3-dimensional vector"); + return -1; + } + Vec3r p(v[0], v[1], v[2]); + self->sv->setPoint2D(p); + return 0; +} + +PyDoc_STRVAR(SVertex_id_doc, +"The Id of this SVertex.\n" +"\n" +":type: :class:`Id`"); + +static PyObject *SVertex_id_get(BPy_SVertex *self, void *UNUSED(closure)) +{ + Id id(self->sv->getId()); + return BPy_Id_from_Id(id); // return a copy +} + +static int SVertex_id_set(BPy_SVertex *self, PyObject *value, void *UNUSED(closure)) +{ + if (!BPy_Id_Check(value)) { + PyErr_SetString(PyExc_TypeError, "value must be an Id"); + return -1; + } + self->sv->setId(*(((BPy_Id *)value)->id)); + return 0; +} + +PyDoc_STRVAR(SVertex_normals_doc, +"The normals for this Vertex as a list. In a sharp surface, an SVertex\n" +"has exactly one normal. In a smooth surface, an SVertex can have any\n" +"number of normals.\n" +"\n" +":type: list of :class:`mathutils.Vector` objects"); + +static PyObject *SVertex_normals_get(BPy_SVertex *self, void *UNUSED(closure)) +{ + PyObject *py_normals; + set< Vec3r > normals; + + py_normals = PyList_New(0); + normals = self->sv->normals(); + for (set< Vec3r >::iterator set_iterator = normals.begin(); set_iterator != normals.end(); set_iterator++) { + Vec3r v(*set_iterator); + PyList_Append(py_normals, Vector_from_Vec3r(v)); + } + return py_normals; +} + +PyDoc_STRVAR(SVertex_normals_size_doc, +"The number of different normals for this SVertex.\n" +"\n" +":type: int"); + +static PyObject *SVertex_normals_size_get(BPy_SVertex *self, void *UNUSED(closure)) +{ + return PyLong_FromLong(self->sv->normalsSize()); +} + +PyDoc_STRVAR(SVertex_viewvertex_doc, +"If this SVertex is also a ViewVertex, this property refers to the\n" +"ViewVertex, and None otherwise.\n" +":type: :class:`ViewVertex`"); + +static PyObject *SVertex_viewvertex_get(BPy_SVertex *self, void *UNUSED(closure)) +{ + ViewVertex *vv = self->sv->viewvertex(); + if (vv) + return Any_BPy_ViewVertex_from_ViewVertex(*vv); + Py_RETURN_NONE; +} + +PyDoc_STRVAR(SVertex_curvatures_doc, +"Curvature information expressed in the form of a seven-element tuple\n" +"(K1, e1, K2, e2, Kr, er, dKr), where K1 and K2 are scalar values\n" +"representing the first (maximum) and second (minimum) principal\n" +"curvatures at this SVertex, respectively; e1 and e2 are\n" +"three-dimensional vectors representing the first and second principal\n" +"directions, i.e. the directions of the normal plane where the\n" +"curvature takes its maximum and minimum values, respectively; and Kr,\n" +"er and dKr are the radial curvature, radial direction, and the\n" +"derivative of the radial curvature at this SVertex, repectively.\n" +"\n" +":type: tuple"); + +static PyObject *SVertex_curvatures_get(BPy_SVertex *self, void *UNUSED(closure)) +{ + const CurvatureInfo *info = self->sv->getCurvatureInfo(); + if (!info) + Py_RETURN_NONE; + Vec3r e1(info->e1.x(), info->e1.y(), info->e1.z()); + Vec3r e2(info->e2.x(), info->e2.y(), info->e2.z()); + Vec3r er(info->er.x(), info->er.y(), info->er.z()); + PyObject *retval = PyTuple_New(7); + PyTuple_SET_ITEM(retval, 0, PyFloat_FromDouble(info->K1)); + PyTuple_SET_ITEM(retval, 2, Vector_from_Vec3r(e1)); + PyTuple_SET_ITEM(retval, 1, PyFloat_FromDouble(info->K2)); + PyTuple_SET_ITEM(retval, 3, Vector_from_Vec3r(e2)); + PyTuple_SET_ITEM(retval, 4, PyFloat_FromDouble(info->Kr)); + PyTuple_SET_ITEM(retval, 5, Vector_from_Vec3r(er)); + PyTuple_SET_ITEM(retval, 6, PyFloat_FromDouble(info->dKr)); + return retval; +} + +static PyGetSetDef BPy_SVertex_getseters[] = { + {(char *)"point_3d", (getter)SVertex_point_3d_get, (setter)SVertex_point_3d_set, (char *)SVertex_point_3d_doc, NULL}, + {(char *)"point_2d", (getter)SVertex_point_2d_get, (setter)SVertex_point_2d_set, (char *)SVertex_point_2d_doc, NULL}, + {(char *)"id", (getter)SVertex_id_get, (setter)SVertex_id_set, (char *)SVertex_id_doc, NULL}, + {(char *)"normals", (getter)SVertex_normals_get, (setter)NULL, (char *)SVertex_normals_doc, NULL}, + {(char *)"normals_size", (getter)SVertex_normals_size_get, (setter)NULL, (char *)SVertex_normals_size_doc, NULL}, + {(char *)"viewvertex", (getter)SVertex_viewvertex_get, (setter)NULL, (char *)SVertex_viewvertex_doc, NULL}, + {(char *)"curvatures", (getter)SVertex_curvatures_get, (setter)NULL, (char *)SVertex_curvatures_doc, NULL}, + {NULL, NULL, NULL, NULL, NULL} /* Sentinel */ +}; + +/*-----------------------BPy_SVertex type definition ------------------------------*/ +PyTypeObject SVertex_Type = { + PyVarObject_HEAD_INIT(NULL, 0) + "SVertex", /* tp_name */ + sizeof(BPy_SVertex), /* tp_basicsize */ + 0, /* tp_itemsize */ + 0, /* tp_dealloc */ + 0, /* tp_print */ + 0, /* tp_getattr */ + 0, /* tp_setattr */ + 0, /* tp_reserved */ + 0, /* tp_repr */ + 0, /* tp_as_number */ + 0, /* tp_as_sequence */ + 0, /* tp_as_mapping */ + 0, /* tp_hash */ + 0, /* tp_call */ + 0, /* tp_str */ + 0, /* tp_getattro */ + 0, /* tp_setattro */ + 0, /* tp_as_buffer */ + Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE, /* tp_flags */ + SVertex_doc, /* tp_doc */ + 0, /* tp_traverse */ + 0, /* tp_clear */ + 0, /* tp_richcompare */ + 0, /* tp_weaklistoffset */ + 0, /* tp_iter */ + 0, /* tp_iternext */ + BPy_SVertex_methods, /* tp_methods */ + 0, /* tp_members */ + BPy_SVertex_getseters, /* tp_getset */ + &Interface0D_Type, /* tp_base */ + 0, /* tp_dict */ + 0, /* tp_descr_get */ + 0, /* tp_descr_set */ + 0, /* tp_dictoffset */ + (initproc)SVertex_init, /* tp_init */ + 0, /* tp_alloc */ + 0, /* tp_new */ +}; + +/////////////////////////////////////////////////////////////////////////////////////////// + +#ifdef __cplusplus +} +#endif diff --git a/source/blender/freestyle/intern/python/Interface0D/BPy_SVertex.h b/source/blender/freestyle/intern/python/Interface0D/BPy_SVertex.h new file mode 100644 index 00000000000..61c65659a5e --- /dev/null +++ b/source/blender/freestyle/intern/python/Interface0D/BPy_SVertex.h @@ -0,0 +1,36 @@ +#ifndef FREESTYLE_PYTHON_SVERTEX_H +#define FREESTYLE_PYTHON_SVERTEX_H + +#include "../../view_map/Silhouette.h" +#include "../BPy_Interface0D.h" + + +#ifdef __cplusplus +extern "C" { +#endif + +/////////////////////////////////////////////////////////////////////////////////////////// + +#include <Python.h> + +extern PyTypeObject SVertex_Type; + +#define BPy_SVertex_Check(v) ( PyObject_IsInstance( (PyObject *) v, (PyObject *) &SVertex_Type) ) + +/*---------------------------Python BPy_SVertex structure definition----------*/ +typedef struct { + BPy_Interface0D py_if0D; + SVertex *sv; +} BPy_SVertex; + +/*---------------------------Python BPy_SVertex visible prototypes-----------*/ + +void SVertex_mathutils_register_callback(); + +/////////////////////////////////////////////////////////////////////////////////////////// + +#ifdef __cplusplus +} +#endif + +#endif /* FREESTYLE_PYTHON_SVERTEX_H */ diff --git a/source/blender/freestyle/intern/python/Interface0D/BPy_ViewVertex.cpp b/source/blender/freestyle/intern/python/Interface0D/BPy_ViewVertex.cpp new file mode 100644 index 00000000000..4fabfc508db --- /dev/null +++ b/source/blender/freestyle/intern/python/Interface0D/BPy_ViewVertex.cpp @@ -0,0 +1,199 @@ +#include "BPy_ViewVertex.h" + +#include "../BPy_Convert.h" +#include "../Interface1D/BPy_ViewEdge.h" +#include "../BPy_Nature.h" + +#ifdef __cplusplus +extern "C" { +#endif + +/////////////////////////////////////////////////////////////////////////////////////////// + +/*----------------------ViewVertex methods----------------------------*/ + +PyDoc_STRVAR(ViewVertex_doc, +"Class hierarchy: :class:`Interface0D` > :class:`ViewVertex`\n" +"\n" +"Class to define a view vertex. A view vertex is a feature vertex\n" +"corresponding to a point of the image graph, where the characteristics\n" +"of an edge (e.g., nature and visibility) might change. A\n" +":class:`ViewVertex` can be of two kinds: A :class:`TVertex` when it\n" +"corresponds to the intersection between two ViewEdges or a\n" +":class:`NonTVertex` when it corresponds to a vertex of the initial\n" +"input mesh (it is the case for vertices such as corners for example).\n" +"Thus, this class can be specialized into two classes, the\n" +":class:`TVertex` class and the :class:`NonTVertex` class.\n" +"\n" +".. method:: __init__()\n" +"\n" +" Default constructor.\n" +"\n" +".. method:: __init__(iBrother)\n" +"\n" +" Copy constructor.\n" +"\n" +" :arg iBrother: A ViewVertex object.\n" +" :type iBrother: :class:`ViewVertex`"); + +static int ViewVertex_init(BPy_ViewVertex *self, PyObject *args, PyObject *kwds) +{ + if (!PyArg_ParseTuple(args, "")) + return -1; + self->vv = 0; // ViewVertex is abstract + self->py_if0D.if0D = self->vv; + self->py_if0D.borrowed = 0; + return 0; +} + +PyDoc_STRVAR(ViewVertex_edges_begin_doc, +".. method:: edges_begin()\n" +"\n" +" Returns an iterator over the ViewEdges that goes to or comes from\n" +" this ViewVertex pointing to the first ViewEdge of the list. The\n" +" orientedViewEdgeIterator allows to iterate in CCW order over these\n" +" ViewEdges and to get the orientation for each ViewEdge\n" +" (incoming/outgoing).\n" +"\n" +" :return: An orientedViewEdgeIterator pointing to the first ViewEdge.\n" +" :rtype: :class:`orientedViewEdgeIterator`"); + +static PyObject * ViewVertex_edges_begin(BPy_ViewVertex *self) +{ + if (!self->vv) + Py_RETURN_NONE; + ViewVertexInternal::orientedViewEdgeIterator ove_it(self->vv->edgesBegin()); + return BPy_orientedViewEdgeIterator_from_orientedViewEdgeIterator(ove_it, 0); +} + +PyDoc_STRVAR(ViewVertex_edges_end_doc, +".. method:: edges_end()\n" +"\n" +" Returns an orientedViewEdgeIterator over the ViewEdges around this\n" +" ViewVertex, pointing after the last ViewEdge.\n" +"\n" +" :return: An orientedViewEdgeIterator pointing after the last ViewEdge.\n" +" :rtype: :class:`orientedViewEdgeIterator`"); + +static PyObject * ViewVertex_edges_end(BPy_ViewVertex *self) +{ +#if 0 + if (!self->vv) + Py_RETURN_NONE; + ViewVertexInternal::orientedViewEdgeIterator ove_it(self->vv->edgesEnd()); + return BPy_orientedViewEdgeIterator_from_orientedViewEdgeIterator(ove_it, 1); +#else + PyErr_SetString(PyExc_NotImplementedError, "edges_end method currently disabled"); + return NULL; +#endif +} + +PyDoc_STRVAR(ViewVertex_edges_iterator_doc, +".. method:: edges_iterator(iEdge)\n" +"\n" +" Returns an orientedViewEdgeIterator pointing to the ViewEdge given\n" +" as argument.\n" +"\n" +" :arg iEdge: A ViewEdge object.\n" +" :type iEdge: :class:`ViewEdge`\n" +" :return: An orientedViewEdgeIterator pointing to the given ViewEdge.\n" +" :rtype: :class:`orientedViewEdgeIterator`"); + +static PyObject * ViewVertex_edges_iterator(BPy_ViewVertex *self, PyObject *args) +{ + PyObject *py_ve; + + if (!self->vv) + Py_RETURN_NONE; + if (!PyArg_ParseTuple(args, "O!", &ViewEdge_Type, &py_ve)) + return NULL; + ViewEdge *ve = ((BPy_ViewEdge *)py_ve)->ve; + ViewVertexInternal::orientedViewEdgeIterator ove_it(self->vv->edgesIterator(ve)); + return BPy_orientedViewEdgeIterator_from_orientedViewEdgeIterator(ove_it, 0); +} + +static PyMethodDef BPy_ViewVertex_methods[] = { + {"edges_begin", (PyCFunction)ViewVertex_edges_begin, METH_NOARGS, ViewVertex_edges_begin_doc}, + {"edges_end", (PyCFunction)ViewVertex_edges_end, METH_NOARGS, ViewVertex_edges_end_doc}, + {"edges_iterator", (PyCFunction)ViewVertex_edges_iterator, METH_VARARGS, ViewVertex_edges_iterator_doc}, + {NULL, NULL, 0, NULL} +}; + +/*----------------------ViewVertex get/setters ----------------------------*/ + +PyDoc_STRVAR(ViewVertex_nature_doc, +"The nature of this ViewVertex.\n" +"\n" +":type: :class:`Nature`"); + +static PyObject *ViewVertex_nature_get(BPy_ViewVertex *self, void *UNUSED(closure)) +{ + Nature::VertexNature nature = self->vv->getNature(); + if (PyErr_Occurred()) + return NULL; + return BPy_Nature_from_Nature(nature); // return a copy +} + +static int ViewVertex_nature_set(BPy_ViewVertex *self, PyObject *value, void *UNUSED(closure)) +{ + if (!BPy_Nature_Check(value)) { + PyErr_SetString(PyExc_TypeError, "value must be a Nature"); + return -1; + } + self->vv->setNature(PyLong_AsLong((PyObject *)&((BPy_Nature *)value)->i)); + return 0; +} + +static PyGetSetDef BPy_ViewVertex_getseters[] = { + {(char *)"nature", (getter)ViewVertex_nature_get, (setter)ViewVertex_nature_set, (char *)ViewVertex_nature_doc, NULL}, + {NULL, NULL, NULL, NULL, NULL} /* Sentinel */ +}; + +/*-----------------------BPy_ViewVertex type definition ------------------------------*/ +PyTypeObject ViewVertex_Type = { + PyVarObject_HEAD_INIT(NULL, 0) + "ViewVertex", /* tp_name */ + sizeof(BPy_ViewVertex), /* tp_basicsize */ + 0, /* tp_itemsize */ + 0, /* tp_dealloc */ + 0, /* tp_print */ + 0, /* tp_getattr */ + 0, /* tp_setattr */ + 0, /* tp_reserved */ + 0, /* tp_repr */ + 0, /* tp_as_number */ + 0, /* tp_as_sequence */ + 0, /* tp_as_mapping */ + 0, /* tp_hash */ + 0, /* tp_call */ + 0, /* tp_str */ + 0, /* tp_getattro */ + 0, /* tp_setattro */ + 0, /* tp_as_buffer */ + Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE, /* tp_flags */ + ViewVertex_doc, /* tp_doc */ + 0, /* tp_traverse */ + 0, /* tp_clear */ + 0, /* tp_richcompare */ + 0, /* tp_weaklistoffset */ + 0, /* tp_iter */ + 0, /* tp_iternext */ + BPy_ViewVertex_methods, /* tp_methods */ + 0, /* tp_members */ + BPy_ViewVertex_getseters, /* tp_getset */ + &Interface0D_Type, /* tp_base */ + 0, /* tp_dict */ + 0, /* tp_descr_get */ + 0, /* tp_descr_set */ + 0, /* tp_dictoffset */ + (initproc)ViewVertex_init, /* tp_init */ + 0, /* tp_alloc */ + 0, /* tp_new */ +}; + +/////////////////////////////////////////////////////////////////////////////////////////// + +#ifdef __cplusplus +} +#endif + diff --git a/source/blender/freestyle/intern/python/Interface0D/BPy_ViewVertex.h b/source/blender/freestyle/intern/python/Interface0D/BPy_ViewVertex.h new file mode 100644 index 00000000000..26c06b50d71 --- /dev/null +++ b/source/blender/freestyle/intern/python/Interface0D/BPy_ViewVertex.h @@ -0,0 +1,31 @@ +#ifndef FREESTYLE_PYTHON_VIEWVERTEX_H +#define FREESTYLE_PYTHON_VIEWVERTEX_H + +#include "../../view_map/ViewMap.h" +#include "../BPy_Interface0D.h" + +#ifdef __cplusplus +extern "C" { +#endif + +/////////////////////////////////////////////////////////////////////////////////////////// + +#include <Python.h> + +extern PyTypeObject ViewVertex_Type; + +#define BPy_ViewVertex_Check(v) ( PyObject_IsInstance( (PyObject *) v, (PyObject *) &ViewVertex_Type) ) + +/*---------------------------Python BPy_ViewVertex structure definition----------*/ +typedef struct { + BPy_Interface0D py_if0D; + ViewVertex *vv; +} BPy_ViewVertex; + +/////////////////////////////////////////////////////////////////////////////////////////// + +#ifdef __cplusplus +} +#endif + +#endif /* FREESTYLE_PYTHON_VIEWVERTEX_H */ diff --git a/source/blender/freestyle/intern/python/Interface0D/CurvePoint/BPy_StrokeVertex.cpp b/source/blender/freestyle/intern/python/Interface0D/CurvePoint/BPy_StrokeVertex.cpp new file mode 100644 index 00000000000..ad83a6933c3 --- /dev/null +++ b/source/blender/freestyle/intern/python/Interface0D/CurvePoint/BPy_StrokeVertex.cpp @@ -0,0 +1,338 @@ +#include "BPy_StrokeVertex.h" + +#include "../../BPy_Freestyle.h" +#include "../../BPy_Convert.h" +#include "../../BPy_StrokeAttribute.h" +#include "../../Interface0D/BPy_SVertex.h" + +#ifdef __cplusplus +extern "C" { +#endif + +#include "../../../python/mathutils/mathutils.h" /* for Vector callbacks */ + +/////////////////////////////////////////////////////////////////////////////////////////// + +//------------------------INSTANCE METHODS ---------------------------------- + +PyDoc_STRVAR(StrokeVertex_doc, +"Class hierarchy: :class:`Interface0D` > :class:`CurvePoint` > :class:`StrokeVertex`\n" +"\n" +"Class to define a stroke vertex.\n" +"\n" +".. method:: __init__()\n" +"\n" +" Default constructor.\n" +"\n" +".. method:: __init__(iBrother)\n" +"\n" +" Copy constructor.\n" +"\n" +" :arg iBrother: A StrokeVertex object.\n" +" :type iBrother: :class:`StrokeVertex`\n" +"\n" +".. method:: __init__(iA, iB, t3)\n" +"\n" +" Builds a stroke vertex from 2 stroke vertices and an interpolation\n" +" parameter.\n" +"\n" +" :arg iA: The first StrokeVertex.\n" +" :type iA: :class:`StrokeVertex`\n" +" :arg iB: The second StrokeVertex.\n" +" :type iB: :class:`StrokeVertex`\n" +" :arg t3: An interpolation parameter.\n" +" :type t3: float\n" +"\n" +".. method:: __init__(iPoint)\n" +"\n" +" Builds a stroke vertex from a CurvePoint\n" +"\n" +" :arg iPoint: A CurvePoint object.\n" +" :type iPoint: :class:`CurvePoint`\n" +"\n" +".. method:: __init__(iSVertex)\n" +"\n" +" Builds a stroke vertex from a SVertex\n" +"\n" +" :arg iSVertex: An SVertex object.\n" +" :type iSVertex: :class:`SVertex`\n" +"\n" +".. method:: __init__(iSVertex, iAttribute)\n" +"\n" +" Builds a stroke vertex from an SVertex and a StrokeAttribute object.\n" +"\n" +" :arg iSVertex: An SVertex object.\n" +" :type iSVertex: :class:`SVertex`\n" +" :arg iAttribute: A StrokeAttribute object.\n" +" :type iAttribute: :class:`StrokeAttribute`"); + +static int StrokeVertex_init(BPy_StrokeVertex *self, PyObject *args, PyObject *kwds) +{ + + PyObject *obj1 = 0, *obj2 = 0 , *obj3 = 0; + + if (!PyArg_ParseTuple(args, "|OOO!", &obj1, &obj2, &PyFloat_Type, &obj3)) + return -1; + + if (!obj1){ + self->sv = new StrokeVertex(); + + } else if (!obj2 && BPy_StrokeVertex_Check(obj1) && ((BPy_StrokeVertex *) obj1)->sv) { + self->sv = new StrokeVertex( *(((BPy_StrokeVertex *) obj1)->sv) ); + + } else if (!obj2 && BPy_CurvePoint_Check(obj1) && ((BPy_CurvePoint *) obj1)->cp) { + self->sv = new StrokeVertex( ((BPy_CurvePoint *) obj1)->cp ); + + } else if (!obj2 && BPy_SVertex_Check(obj1) && ((BPy_SVertex *) obj1)->sv) { + self->sv = new StrokeVertex( ((BPy_SVertex *) obj1)->sv ); + + } else if (obj3 && BPy_StrokeVertex_Check(obj1) && BPy_StrokeVertex_Check(obj2)) { + StrokeVertex *sv1 = ((BPy_StrokeVertex *) obj1)->sv; + StrokeVertex *sv2 = ((BPy_StrokeVertex *) obj2)->sv; + if (!sv1 || (sv1->A() == 0 && sv1->B() == 0)) { + PyErr_SetString(PyExc_TypeError, "argument 1 is an invalid StrokeVertex object"); + return -1; + } + if (!sv2 || (sv2->A() == 0 && sv2->B() == 0)) { + PyErr_SetString(PyExc_TypeError, "argument 2 is an invalid StrokeVertex object"); + return -1; + } + self->sv = new StrokeVertex(sv1, sv2, PyFloat_AsDouble(obj3)); + + } else { + PyErr_SetString(PyExc_TypeError, "invalid argument(s)"); + return -1; + } + + self->py_cp.cp = self->sv; + self->py_cp.py_if0D.if0D = self->sv; + self->py_cp.py_if0D.borrowed = 0; + + return 0; +} + +// real operator[] (const int i) const +// real & operator[] (const int i) + +/*----------------------StrokeVertex instance definitions ----------------------------*/ +static PyMethodDef BPy_StrokeVertex_methods[] = { + {NULL, NULL, 0, NULL} +}; + +/*----------------------mathutils callbacks ----------------------------*/ + +static int StrokeVertex_mathutils_check(BaseMathObject *bmo) +{ + if (!BPy_StrokeVertex_Check(bmo->cb_user)) + return -1; + return 0; +} + +static int StrokeVertex_mathutils_get(BaseMathObject *bmo, int subtype) +{ + BPy_StrokeVertex *self = (BPy_StrokeVertex *)bmo->cb_user; + bmo->data[0] = (float)self->sv->x(); + bmo->data[1] = (float)self->sv->y(); + return 0; +} + +static int StrokeVertex_mathutils_set(BaseMathObject *bmo, int subtype) +{ + BPy_StrokeVertex *self = (BPy_StrokeVertex *)bmo->cb_user; + self->sv->setX((real)bmo->data[0]); + self->sv->setY((real)bmo->data[1]); + return 0; +} + +static int StrokeVertex_mathutils_get_index(BaseMathObject *bmo, int subtype, int index) +{ + BPy_StrokeVertex *self = (BPy_StrokeVertex *)bmo->cb_user; + switch (index) { + case 0: bmo->data[0] = (float)self->sv->x(); break; + case 1: bmo->data[1] = (float)self->sv->y(); break; + default: + return -1; + } + return 0; +} + +static int StrokeVertex_mathutils_set_index(BaseMathObject *bmo, int subtype, int index) +{ + BPy_StrokeVertex *self = (BPy_StrokeVertex *)bmo->cb_user; + switch (index) { + case 0: self->sv->setX((real)bmo->data[0]); break; + case 1: self->sv->setY((real)bmo->data[1]); break; + default: + return -1; + } + return 0; +} + +static Mathutils_Callback StrokeVertex_mathutils_cb = { + StrokeVertex_mathutils_check, + StrokeVertex_mathutils_get, + StrokeVertex_mathutils_set, + StrokeVertex_mathutils_get_index, + StrokeVertex_mathutils_set_index +}; + +static unsigned char StrokeVertex_mathutils_cb_index = -1; + +void StrokeVertex_mathutils_register_callback() +{ + StrokeVertex_mathutils_cb_index = Mathutils_RegisterCallback(&StrokeVertex_mathutils_cb); +} + +/*----------------------StrokeVertex get/setters ----------------------------*/ + +PyDoc_STRVAR(StrokeVertex_attribute_doc, +"StrokeAttribute for this StrokeVertex.\n" +"\n" +":type: StrokeAttribute"); + +static PyObject *StrokeVertex_attribute_get(BPy_StrokeVertex *self, void *UNUSED(closure)) +{ + return BPy_StrokeAttribute_from_StrokeAttribute(self->sv->attribute()); +} + +static int StrokeVertex_attribute_set(BPy_StrokeVertex *self, PyObject *value, void *UNUSED(closure)) +{ + if (!BPy_StrokeAttribute_Check(value)) { + PyErr_SetString(PyExc_TypeError, "value must be a StrokeAttribute object"); + return -1; + } + self->sv->setAttribute(*(((BPy_StrokeAttribute *)value)->sa)); + return 0; +} + +PyDoc_STRVAR(StrokeVertex_curvilinear_abscissa_doc, +"Curvilinear abscissa of this StrokeVertex in the Stroke.\n" +"\n" +":type: float"); + +static PyObject *StrokeVertex_curvilinear_abscissa_get(BPy_StrokeVertex *self, void *UNUSED(closure)) +{ + return PyFloat_FromDouble(self->sv->curvilinearAbscissa()); +} + +static int StrokeVertex_curvilinear_abscissa_set(BPy_StrokeVertex *self, PyObject *value, void *UNUSED(closure)) +{ + float scalar; + if ((scalar = PyFloat_AsDouble(value)) == -1.0f && PyErr_Occurred()) { /* parsed item not a number */ + PyErr_SetString(PyExc_TypeError, "value must be a number"); + return -1; + } + self->sv->setCurvilinearAbscissa(scalar); + return 0; +} + +PyDoc_STRVAR(StrokeVertex_point_doc, +"2D point coordinates.\n" +"\n" +":type: mathutils.Vector"); + +static PyObject *StrokeVertex_point_get(BPy_StrokeVertex *self, void *UNUSED(closure)) +{ + return Vector_CreatePyObject_cb((PyObject *)self, 2, StrokeVertex_mathutils_cb_index, 0); +} + +static int StrokeVertex_point_set(BPy_StrokeVertex *self, PyObject *value, void *UNUSED(closure)) +{ + float v[2]; + if (!float_array_from_PyObject(value, v, 2)) { + PyErr_SetString(PyExc_ValueError, "value must be a 2-dimensional vector"); + return -1; + } + self->sv->setX(v[0]); + self->sv->setY(v[1]); + return 0; +} + +PyDoc_STRVAR(StrokeVertex_stroke_length_doc, +"Stroke length (it is only a value retained by the StrokeVertex,\n" +"and it won't change the real stroke length).\n" +"\n" +":type: float"); + +static PyObject *StrokeVertex_stroke_length_get(BPy_StrokeVertex *self, void *UNUSED(closure)) +{ + return PyFloat_FromDouble(self->sv->strokeLength()); +} + +static int StrokeVertex_stroke_length_set(BPy_StrokeVertex *self, PyObject *value, void *UNUSED(closure)) +{ + float scalar; + if ((scalar = PyFloat_AsDouble(value)) == -1.0f && PyErr_Occurred()) { /* parsed item not a number */ + PyErr_SetString(PyExc_TypeError, "value must be a number"); + return -1; + } + self->sv->setStrokeLength(scalar); + return 0; +} + +PyDoc_STRVAR(StrokeVertex_u_doc, +"Curvilinear abscissa of this StrokeVertex in the Stroke.\n" +"\n" +":type: float"); + +static PyObject *StrokeVertex_u_get(BPy_StrokeVertex *self, void *UNUSED(closure)) +{ + return PyFloat_FromDouble(self->sv->u()); +} + +static PyGetSetDef BPy_StrokeVertex_getseters[] = { + {(char *)"attribute", (getter)StrokeVertex_attribute_get, (setter)StrokeVertex_attribute_set, (char *)StrokeVertex_attribute_doc, NULL}, + {(char *)"curvilinear_abscissa", (getter)StrokeVertex_curvilinear_abscissa_get, (setter)StrokeVertex_curvilinear_abscissa_set, (char *)StrokeVertex_curvilinear_abscissa_doc, NULL}, + {(char *)"point", (getter)StrokeVertex_point_get, (setter)StrokeVertex_point_set, (char *)StrokeVertex_point_doc, NULL}, + {(char *)"stroke_length", (getter)StrokeVertex_stroke_length_get, (setter)StrokeVertex_stroke_length_set, (char *)StrokeVertex_stroke_length_doc, NULL}, + {(char *)"u", (getter)StrokeVertex_u_get, (setter)NULL, (char *)StrokeVertex_u_doc, NULL}, + {NULL, NULL, NULL, NULL, NULL} /* Sentinel */ +}; + +/*-----------------------BPy_StrokeVertex type definition ------------------------------*/ +PyTypeObject StrokeVertex_Type = { + PyVarObject_HEAD_INIT(NULL, 0) + "StrokeVertex", /* tp_name */ + sizeof(BPy_StrokeVertex), /* tp_basicsize */ + 0, /* tp_itemsize */ + 0, /* tp_dealloc */ + 0, /* tp_print */ + 0, /* tp_getattr */ + 0, /* tp_setattr */ + 0, /* tp_reserved */ + 0, /* tp_repr */ + 0, /* tp_as_number */ + 0, /* tp_as_sequence */ + 0, /* tp_as_mapping */ + 0, /* tp_hash */ + 0, /* tp_call */ + 0, /* tp_str */ + 0, /* tp_getattro */ + 0, /* tp_setattro */ + 0, /* tp_as_buffer */ + Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE, /* tp_flags */ + StrokeVertex_doc, /* tp_doc */ + 0, /* tp_traverse */ + 0, /* tp_clear */ + 0, /* tp_richcompare */ + 0, /* tp_weaklistoffset */ + 0, /* tp_iter */ + 0, /* tp_iternext */ + BPy_StrokeVertex_methods, /* tp_methods */ + 0, /* tp_members */ + BPy_StrokeVertex_getseters, /* tp_getset */ + &CurvePoint_Type, /* tp_base */ + 0, /* tp_dict */ + 0, /* tp_descr_get */ + 0, /* tp_descr_set */ + 0, /* tp_dictoffset */ + (initproc)StrokeVertex_init, /* tp_init */ + 0, /* tp_alloc */ + 0, /* tp_new */ +}; + +/////////////////////////////////////////////////////////////////////////////////////////// + +#ifdef __cplusplus +} +#endif diff --git a/source/blender/freestyle/intern/python/Interface0D/CurvePoint/BPy_StrokeVertex.h b/source/blender/freestyle/intern/python/Interface0D/CurvePoint/BPy_StrokeVertex.h new file mode 100644 index 00000000000..a1cf3e80662 --- /dev/null +++ b/source/blender/freestyle/intern/python/Interface0D/CurvePoint/BPy_StrokeVertex.h @@ -0,0 +1,35 @@ +#ifndef FREESTYLE_PYTHON_STROKEVERTEX_H +#define FREESTYLE_PYTHON_STROKEVERTEX_H + +#include "../BPy_CurvePoint.h" +#include "../../../stroke/Stroke.h" + +#ifdef __cplusplus +extern "C" { +#endif + +/////////////////////////////////////////////////////////////////////////////////////////// + +#include <Python.h> + +extern PyTypeObject StrokeVertex_Type; + +#define BPy_StrokeVertex_Check(v) ( PyObject_IsInstance( (PyObject *) v, (PyObject *) &StrokeVertex_Type) ) + +/*---------------------------Python BPy_StrokeVertex structure definition----------*/ +typedef struct { + BPy_CurvePoint py_cp; + StrokeVertex *sv; +} BPy_StrokeVertex; + +/*---------------------------Python BPy_StrokeVertex visible prototypes-----------*/ + +void StrokeVertex_mathutils_register_callback(); + +/////////////////////////////////////////////////////////////////////////////////////////// + +#ifdef __cplusplus +} +#endif + +#endif /* FREESTYLE_PYTHON_STROKEVERTEX_H */ diff --git a/source/blender/freestyle/intern/python/Interface0D/ViewVertex/BPy_NonTVertex.cpp b/source/blender/freestyle/intern/python/Interface0D/ViewVertex/BPy_NonTVertex.cpp new file mode 100644 index 00000000000..a0e0717ef37 --- /dev/null +++ b/source/blender/freestyle/intern/python/Interface0D/ViewVertex/BPy_NonTVertex.cpp @@ -0,0 +1,143 @@ +#include "BPy_NonTVertex.h" + +#include "../../BPy_Convert.h" +#include "../BPy_SVertex.h" + +#ifdef __cplusplus +extern "C" { +#endif + +/////////////////////////////////////////////////////////////////////////////////////////// + +/*----------------------NonTVertex methods ----------------------------*/ + +PyDoc_STRVAR(NonTVertex_doc, +"Class hierarchy: :class:`Interface0D` > :class:`ViewVertex` > :class:`NonTVertex`\n" +"\n" +"View vertex for corners, cusps, etc. associated to a single SVertex.\n" +"Can be associated to 2 or more view edges.\n" +"\n" +".. method:: __init__()\n" +"\n" +" Default constructor.\n" +"\n" +".. method:: __init__(iBrother)\n" +"\n" +" Copy constructor.\n" +"\n" +" :arg iBrother: A NonTVertex object.\n" +" :type iBrother: :class:`NonTVertex`\n" +"\n" +".. method:: __init__(iSVertex)\n" +"\n" +" Builds a NonTVertex from a SVertex.\n" +"\n" +" :arg iSVertex: An SVertex object.\n" +" :type iSVertex: :class:`SVertex`"); + +static int NonTVertex_init(BPy_NonTVertex *self, PyObject *args, PyObject *kwds) +{ + PyObject *obj = 0; + + if (!PyArg_ParseTuple(args, "|O!", &SVertex_Type, &obj)) + return -1; + + if (!obj) { + self->ntv = new NonTVertex(); + + } else if(((BPy_SVertex *)obj)->sv) { + self->ntv = new NonTVertex(((BPy_SVertex *)obj)->sv); + + } else { + PyErr_SetString(PyExc_TypeError, "invalid argument"); + return -1; + } + + self->py_vv.vv = self->ntv; + self->py_vv.py_if0D.if0D = self->ntv; + self->py_vv.py_if0D.borrowed = 0; + + return 0; +} + +static PyMethodDef BPy_NonTVertex_methods[] = { + {NULL, NULL, 0, NULL} +}; + +/*----------------------NonTVertex get/setters ----------------------------*/ + +PyDoc_STRVAR(NonTVertex_svertex_doc, +"The SVertex on top of which this NonTVertex is built.\n" +"\n" +":type: :class:`SVertex`"); + +static PyObject *NonTVertex_svertex_get(BPy_NonTVertex *self, void *UNUSED(closure)) +{ + SVertex *v = self->ntv->svertex(); + if (v) + return BPy_SVertex_from_SVertex(*v); + Py_RETURN_NONE; +} + +static int NonTVertex_svertex_set(BPy_NonTVertex *self, PyObject *value, void *UNUSED(closure)) +{ + if (!BPy_SVertex_Check(value)) { + PyErr_SetString(PyExc_TypeError, "value must be an SVertex"); + return -1; + } + self->ntv->setSVertex(((BPy_SVertex *)value)->sv); + return 0; +} + +static PyGetSetDef BPy_NonTVertex_getseters[] = { + {(char *)"svertex", (getter)NonTVertex_svertex_get, (setter)NonTVertex_svertex_set, (char *)NonTVertex_svertex_doc, NULL}, + {NULL, NULL, NULL, NULL, NULL} /* Sentinel */ +}; + +/*-----------------------BPy_NonTVertex type definition ------------------------------*/ +PyTypeObject NonTVertex_Type = { + PyVarObject_HEAD_INIT(NULL, 0) + "NonTVertex", /* tp_name */ + sizeof(BPy_NonTVertex), /* tp_basicsize */ + 0, /* tp_itemsize */ + 0, /* tp_dealloc */ + 0, /* tp_print */ + 0, /* tp_getattr */ + 0, /* tp_setattr */ + 0, /* tp_reserved */ + 0, /* tp_repr */ + 0, /* tp_as_number */ + 0, /* tp_as_sequence */ + 0, /* tp_as_mapping */ + 0, /* tp_hash */ + 0, /* tp_call */ + 0, /* tp_str */ + 0, /* tp_getattro */ + 0, /* tp_setattro */ + 0, /* tp_as_buffer */ + Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE, /* tp_flags */ + NonTVertex_doc, /* tp_doc */ + 0, /* tp_traverse */ + 0, /* tp_clear */ + 0, /* tp_richcompare */ + 0, /* tp_weaklistoffset */ + 0, /* tp_iter */ + 0, /* tp_iternext */ + BPy_NonTVertex_methods, /* tp_methods */ + 0, /* tp_members */ + BPy_NonTVertex_getseters, /* tp_getset */ + &ViewVertex_Type, /* tp_base */ + 0, /* tp_dict */ + 0, /* tp_descr_get */ + 0, /* tp_descr_set */ + 0, /* tp_dictoffset */ + (initproc)NonTVertex_init, /* tp_init */ + 0, /* tp_alloc */ + 0, /* tp_new */ +}; + +/////////////////////////////////////////////////////////////////////////////////////////// + +#ifdef __cplusplus +} +#endif diff --git a/source/blender/freestyle/intern/python/Interface0D/ViewVertex/BPy_NonTVertex.h b/source/blender/freestyle/intern/python/Interface0D/ViewVertex/BPy_NonTVertex.h new file mode 100644 index 00000000000..071194d2d42 --- /dev/null +++ b/source/blender/freestyle/intern/python/Interface0D/ViewVertex/BPy_NonTVertex.h @@ -0,0 +1,31 @@ +#ifndef FREESTYLE_PYTHON_NONTVERTEX_H +#define FREESTYLE_PYTHON_NONTVERTEX_H + +#include "../BPy_ViewVertex.h" +#include "../../../view_map/ViewMap.h" + +#ifdef __cplusplus +extern "C" { +#endif + +/////////////////////////////////////////////////////////////////////////////////////////// + +#include <Python.h> + +extern PyTypeObject NonTVertex_Type; + +#define BPy_NonTVertex_Check(v) ( PyObject_IsInstance( (PyObject *) v, (PyObject *) &NonTVertex_Type) ) + +/*---------------------------Python BPy_NonTVertex structure definition----------*/ +typedef struct { + BPy_ViewVertex py_vv; + NonTVertex *ntv; +} BPy_NonTVertex; + +/////////////////////////////////////////////////////////////////////////////////////////// + +#ifdef __cplusplus +} +#endif + +#endif /* FREESTYLE_PYTHON_NONTVERTEX_H */ diff --git a/source/blender/freestyle/intern/python/Interface0D/ViewVertex/BPy_TVertex.cpp b/source/blender/freestyle/intern/python/Interface0D/ViewVertex/BPy_TVertex.cpp new file mode 100644 index 00000000000..55c8b64d13c --- /dev/null +++ b/source/blender/freestyle/intern/python/Interface0D/ViewVertex/BPy_TVertex.cpp @@ -0,0 +1,222 @@ +#include "BPy_TVertex.h" + +#include "../../BPy_Convert.h" +#include "../BPy_SVertex.h" +#include "../../BPy_Id.h" +#include "../../Interface1D/BPy_FEdge.h" +#include "../../Interface1D/BPy_ViewEdge.h" + +#ifdef __cplusplus +extern "C" { +#endif + +/////////////////////////////////////////////////////////////////////////////////////////// + +/*----------------------TVertex methods ----------------------------*/ + +PyDoc_STRVAR(TVertex_doc, +"Class hierarchy: :class:`Interface0D` > :class:`ViewVertex` > :class:`TVertex`\n" +"\n" +"Class to define a T vertex, i.e. an intersection between two edges.\n" +"It points towards two SVertex and four ViewEdges. Among the\n" +"ViewEdges, two are front and the other two are back. Basically a\n" +"front edge hides part of a back edge. So, among the back edges, one\n" +"is of invisibility N and the other of invisibility N+1.\n" +"\n" +".. method:: __init__()\n" +"\n" +" Default constructor.\n" +"\n" +".. method:: __init__(iBrother)\n" +"\n" +" Copy constructor.\n" +"\n" +" :arg iBrother: A TVertex object.\n" +" :type iBrother: :class:`TVertex`"); + +static int TVertex_init(BPy_TVertex *self, PyObject *args, PyObject *kwds) +{ + if (!PyArg_ParseTuple(args, "")) + return -1; + self->tv = new TVertex(); + self->py_vv.vv = self->tv; + self->py_vv.py_if0D.if0D = self->tv; + self->py_vv.py_if0D.borrowed = 0; + return 0; +} + +PyDoc_STRVAR(TVertex_get_svertex_doc, +".. method:: get_svertex(iFEdge)\n" +"\n" +" Returns the SVertex (among the 2) belonging to the given FEdge.\n" +"\n" +" :arg iFEdge: An FEdge object.\n" +" :type iFEdge: :class:`FEdge`\n" +" :return: The SVertex belonging to the given FEdge.\n" +" :rtype: :class:`SVertex`"); + +static PyObject * TVertex_get_svertex( BPy_TVertex *self, PyObject *args) +{ + PyObject *py_fe; + + if (!PyArg_ParseTuple(args, "O!", &FEdge_Type, &py_fe)) + return NULL; + SVertex *sv = self->tv->getSVertex(((BPy_FEdge *)py_fe)->fe); + if (sv) + return BPy_SVertex_from_SVertex(*sv); + Py_RETURN_NONE; +} + +PyDoc_STRVAR(TVertex_get_mate_doc, +".. method:: get_mate(iEdgeA)\n" +"\n" +" Returns the mate edge of the ViewEdge given as argument. If the\n" +" ViewEdge is frontEdgeA, frontEdgeB is returned. If the ViewEdge is\n" +" frontEdgeB, frontEdgeA is returned. Same for back edges.\n" +"\n" +" :arg iEdgeA: A ViewEdge object.\n" +" :type iEdgeA: :class:`ViewEdge`\n" +" :return: The mate edge of the given ViewEdge.\n" +" :rtype: :class:`ViewEdge`"); + +static PyObject * TVertex_get_mate( BPy_TVertex *self, PyObject *args) +{ + PyObject *py_ve; + + if (!PyArg_ParseTuple(args, "O!", &ViewEdge_Type, &py_ve)) + return NULL; + ViewEdge *ve = self->tv->mate(((BPy_ViewEdge *)py_ve)->ve); + if (ve) + return BPy_ViewEdge_from_ViewEdge(*ve); + Py_RETURN_NONE; +} + +static PyMethodDef BPy_TVertex_methods[] = { + {"get_svertex", (PyCFunction)TVertex_get_svertex, METH_VARARGS, TVertex_get_svertex_doc}, + {"get_mate", (PyCFunction)TVertex_get_mate, METH_VARARGS, TVertex_get_mate_doc}, + {NULL, NULL, 0, NULL} +}; + +/*----------------------TVertex get/setters ----------------------------*/ + +PyDoc_STRVAR(TVertex_front_svertex_doc, +"The SVertex that is closer to the viewpoint.\n" +"\n" +":type: :class:`SVertex`"); + +static PyObject *TVertex_front_svertex_get(BPy_TVertex *self, void *UNUSED(closure)) +{ + SVertex *v = self->tv->frontSVertex(); + if (v) + return BPy_SVertex_from_SVertex(*v); + Py_RETURN_NONE; +} + +static int TVertex_front_svertex_set(BPy_TVertex *self, PyObject *value, void *UNUSED(closure)) +{ + if (!BPy_SVertex_Check(value)) { + PyErr_SetString(PyExc_TypeError, "value must be an SVertex"); + return -1; + } + self->tv->setFrontSVertex(((BPy_SVertex *)value)->sv); + return 0; +} + +PyDoc_STRVAR(TVertex_back_svertex_doc, +"The SVertex that is further away from the viewpoint.\n" +"\n" +":type: :class:`SVertex`"); + +static PyObject *TVertex_back_svertex_get(BPy_TVertex *self, void *UNUSED(closure)) +{ + SVertex *v = self->tv->backSVertex(); + if (v) + return BPy_SVertex_from_SVertex(*v); + Py_RETURN_NONE; +} + +static int TVertex_back_svertex_set(BPy_TVertex *self, PyObject *value, void *UNUSED(closure)) +{ + if (!BPy_SVertex_Check(value)) { + PyErr_SetString(PyExc_TypeError, "value must be an SVertex"); + return -1; + } + self->tv->setBackSVertex(((BPy_SVertex *)value)->sv); + return 0; +} + +PyDoc_STRVAR(TVertex_id_doc, +"The Id of this TVertex.\n" +"\n" +":type: :class:`Id`"); + +static PyObject *TVertex_id_get(BPy_TVertex *self, void *UNUSED(closure)) +{ + Id id(self->tv->getId()); + return BPy_Id_from_Id(id); // return a copy +} + +static int TVertex_id_set(BPy_TVertex *self, PyObject *value, void *UNUSED(closure)) +{ + if (!BPy_Id_Check(value)) { + PyErr_SetString(PyExc_TypeError, "value must be an Id"); + return -1; + } + self->tv->setId(*(((BPy_Id *)value)->id)); + return 0; +} + +static PyGetSetDef BPy_TVertex_getseters[] = { + {(char *)"front_svertex", (getter)TVertex_front_svertex_get, (setter)TVertex_front_svertex_set, (char *)TVertex_front_svertex_doc, NULL}, + {(char *)"back_svertex", (getter)TVertex_back_svertex_get, (setter)TVertex_back_svertex_set, (char *)TVertex_back_svertex_doc, NULL}, + {(char *)"id", (getter)TVertex_id_get, (setter)TVertex_id_set, (char *)TVertex_id_doc, NULL}, + {NULL, NULL, NULL, NULL, NULL} /* Sentinel */ +}; + +/*-----------------------BPy_TVertex type definition ------------------------------*/ +PyTypeObject TVertex_Type = { + PyVarObject_HEAD_INIT(NULL, 0) + "TVertex", /* tp_name */ + sizeof(BPy_TVertex), /* tp_basicsize */ + 0, /* tp_itemsize */ + 0, /* tp_dealloc */ + 0, /* tp_print */ + 0, /* tp_getattr */ + 0, /* tp_setattr */ + 0, /* tp_reserved */ + 0, /* tp_repr */ + 0, /* tp_as_number */ + 0, /* tp_as_sequence */ + 0, /* tp_as_mapping */ + 0, /* tp_hash */ + 0, /* tp_call */ + 0, /* tp_str */ + 0, /* tp_getattro */ + 0, /* tp_setattro */ + 0, /* tp_as_buffer */ + Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE, /* tp_flags */ + TVertex_doc, /* tp_doc */ + 0, /* tp_traverse */ + 0, /* tp_clear */ + 0, /* tp_richcompare */ + 0, /* tp_weaklistoffset */ + 0, /* tp_iter */ + 0, /* tp_iternext */ + BPy_TVertex_methods, /* tp_methods */ + 0, /* tp_members */ + BPy_TVertex_getseters, /* tp_getset */ + &ViewVertex_Type, /* tp_base */ + 0, /* tp_dict */ + 0, /* tp_descr_get */ + 0, /* tp_descr_set */ + 0, /* tp_dictoffset */ + (initproc)TVertex_init, /* tp_init */ + 0, /* tp_alloc */ + 0, /* tp_new */ +}; + +/////////////////////////////////////////////////////////////////////////////////////////// + +#ifdef __cplusplus +} +#endif diff --git a/source/blender/freestyle/intern/python/Interface0D/ViewVertex/BPy_TVertex.h b/source/blender/freestyle/intern/python/Interface0D/ViewVertex/BPy_TVertex.h new file mode 100644 index 00000000000..12fe5c0cb43 --- /dev/null +++ b/source/blender/freestyle/intern/python/Interface0D/ViewVertex/BPy_TVertex.h @@ -0,0 +1,31 @@ +#ifndef FREESTYLE_PYTHON_TVERTEX_H +#define FREESTYLE_PYTHON_TVERTEX_H + +#include "../BPy_ViewVertex.h" +#include "../../../view_map/ViewMap.h" + +#ifdef __cplusplus +extern "C" { +#endif + +/////////////////////////////////////////////////////////////////////////////////////////// + +#include <Python.h> + +extern PyTypeObject TVertex_Type; + +#define BPy_TVertex_Check(v) ( PyObject_IsInstance( (PyObject *) v, (PyObject *) &TVertex_Type) ) + +/*---------------------------Python BPy_TVertex structure definition----------*/ +typedef struct { + BPy_ViewVertex py_vv; + TVertex *tv; +} BPy_TVertex; + +/////////////////////////////////////////////////////////////////////////////////////////// + +#ifdef __cplusplus +} +#endif + +#endif /* FREESTYLE_PYTHON_TVERTEX_H */ |