diff options
Diffstat (limited to 'source/blender/freestyle/intern/python')
8 files changed, 86 insertions, 39 deletions
diff --git a/source/blender/freestyle/intern/python/BPy_Convert.cpp b/source/blender/freestyle/intern/python/BPy_Convert.cpp index 78c3599b7cd..dbd836bc562 100644 --- a/source/blender/freestyle/intern/python/BPy_Convert.cpp +++ b/source/blender/freestyle/intern/python/BPy_Convert.cpp @@ -387,9 +387,14 @@ PyObject *BPy_IntegrationType_from_IntegrationType(IntegrationType i) PyObject *BPy_CurvePoint_from_CurvePoint(CurvePoint& cp) { PyObject *py_cp = CurvePoint_Type.tp_new(&CurvePoint_Type, 0, 0); - ((BPy_CurvePoint *) py_cp)->cp = &cp; + // CurvePointIterator::operator*() returns a reference of a class data + // member whose value is mutable upon iteration over different CurvePoints. + // It is likely that such a mutable reference is passed to this function, + // so that a new allocated CurvePoint instance is created here to avoid + // nasty bugs (cf. T41464). + ((BPy_CurvePoint *) py_cp)->cp = new CurvePoint(cp); ((BPy_CurvePoint *) py_cp)->py_if0D.if0D = ((BPy_CurvePoint *)py_cp)->cp; - ((BPy_CurvePoint *) py_cp)->py_if0D.borrowed = true; + ((BPy_CurvePoint *) py_cp)->py_if0D.borrowed = false; return py_cp; } diff --git a/source/blender/freestyle/intern/python/BPy_Freestyle.cpp b/source/blender/freestyle/intern/python/BPy_Freestyle.cpp index 2cfd3658189..5b8d50eb5eb 100644 --- a/source/blender/freestyle/intern/python/BPy_Freestyle.cpp +++ b/source/blender/freestyle/intern/python/BPy_Freestyle.cpp @@ -60,6 +60,7 @@ extern "C" { #include "FRS_freestyle.h" #include "RNA_access.h" +#include "DNA_scene_types.h" #include "bpy_rna.h" /* pyrna_struct_CreatePyObject() */ static char Freestyle_getCurrentScene___doc__[] = @@ -77,7 +78,7 @@ static PyObject *Freestyle_getCurrentScene(PyObject *self) return NULL; } PointerRNA ptr_scene; - RNA_pointer_create(NULL, &RNA_Scene, freestyle_scene, &ptr_scene); + RNA_pointer_create(&freestyle_scene->id, &RNA_Scene, freestyle_scene, &ptr_scene); return pyrna_struct_CreatePyObject(&ptr_scene); } diff --git a/source/blender/freestyle/intern/python/Interface0D/BPy_CurvePoint.cpp b/source/blender/freestyle/intern/python/Interface0D/BPy_CurvePoint.cpp index 36cdb1b92ff..1ef29792d56 100644 --- a/source/blender/freestyle/intern/python/Interface0D/BPy_CurvePoint.cpp +++ b/source/blender/freestyle/intern/python/Interface0D/BPy_CurvePoint.cpp @@ -178,6 +178,19 @@ static int CurvePoint_second_svertex_set(BPy_CurvePoint *self, PyObject *value, return 0; } +PyDoc_STRVAR(CurvePoint_fedge_doc, +"Gets the FEdge for the two SVertices that given CurvePoints consists out of.\n" +"A shortcut for CurvePoint.first_svertex.get_fedge(CurvePoint.second_svertex).\n" +"\n" +":type: :class:`FEdge`"); + +static PyObject *CurvePoint_fedge_get(BPy_CurvePoint *self, void *UNUSED(closure)) +{ + SVertex *A = self->cp->A(); + Interface0D *B = (Interface0D *)self->cp->B(); + return Any_BPy_Interface1D_from_Interface1D(*(A->getFEdge(*B))); +} + PyDoc_STRVAR(CurvePoint_t2d_doc, "The 2D interpolation parameter.\n" "\n" @@ -204,6 +217,8 @@ static PyGetSetDef BPy_CurvePoint_getseters[] = { (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 *)"fedge", (getter)CurvePoint_fedge_get, NULL, + CurvePoint_fedge_doc, NULL}, {(char *)"t2d", (getter)CurvePoint_t2d_get, (setter)CurvePoint_t2d_set, (char *)CurvePoint_t2d_doc, NULL}, {NULL, NULL, NULL, NULL, NULL} /* Sentinel */ }; diff --git a/source/blender/freestyle/intern/python/Interface0D/BPy_SVertex.cpp b/source/blender/freestyle/intern/python/Interface0D/BPy_SVertex.cpp index af9f7198748..6f47ce93ca8 100644 --- a/source/blender/freestyle/intern/python/Interface0D/BPy_SVertex.cpp +++ b/source/blender/freestyle/intern/python/Interface0D/BPy_SVertex.cpp @@ -268,7 +268,7 @@ void SVertex_mathutils_register_callback() PyDoc_STRVAR(SVertex_point_3d_doc, "The 3D coordinates of the SVertex.\n" "\n" -":type: mathutils.Vector"); +":type: :class:`mathutils.Vector`"); static PyObject *SVertex_point_3d_get(BPy_SVertex *self, void *UNUSED(closure)) { @@ -291,7 +291,7 @@ static int SVertex_point_3d_set(BPy_SVertex *self, PyObject *value, void *UNUSED PyDoc_STRVAR(SVertex_point_2d_doc, "The projected 3D coordinates of the SVertex.\n" "\n" -":type: mathutils.Vector"); +":type: :class:`mathutils.Vector`"); static PyObject *SVertex_point_2d_get(BPy_SVertex *self, void *UNUSED(closure)) { diff --git a/source/blender/freestyle/intern/python/Iterator/BPy_Interface0DIterator.cpp b/source/blender/freestyle/intern/python/Iterator/BPy_Interface0DIterator.cpp index faf99e90111..fca4c979bbb 100644 --- a/source/blender/freestyle/intern/python/Iterator/BPy_Interface0DIterator.cpp +++ b/source/blender/freestyle/intern/python/Iterator/BPy_Interface0DIterator.cpp @@ -120,19 +120,14 @@ static PyObject *Interface0DIterator_iternext(BPy_Interface0DIterator *self) self->if0D_it->decrement(); } else { - if (self->if0D_it->isEnd()) { + if (self->if0D_it->atLast() || self->if0D_it->isEnd()) { PyErr_SetNone(PyExc_StopIteration); return NULL; } if (self->at_start) self->at_start = false; - else { + else self->if0D_it->increment(); - if (self->if0D_it->isEnd()) { - PyErr_SetNone(PyExc_StopIteration); - return NULL; - } - } } Interface0D *if0D = self->if0D_it->operator->(); return Any_BPy_Interface0D_from_Interface0D(*if0D); @@ -177,11 +172,24 @@ static PyObject *Interface0DIterator_u_get(BPy_Interface0DIterator *self, void * return PyFloat_FromDouble(self->if0D_it->u()); } +PyDoc_STRVAR(Interface0DIterator_at_last_doc, +"True if the interator points to the last valid element.\n" +"For its counterpart (pointing to the first valid element), use it.is_begin.\n" +"\n" +":type: bool"); + +static PyObject *Interface0DIterator_at_last_get(BPy_Interface0DIterator *self, void *UNUSED(closure)) +{ + return PyBool_from_bool(self->if0D_it->atLast()); +} + static PyGetSetDef BPy_Interface0DIterator_getseters[] = { {(char *)"object", (getter)Interface0DIterator_object_get, (setter)NULL, (char *)Interface0DIterator_object_doc, NULL}, {(char *)"t", (getter)Interface0DIterator_t_get, (setter)NULL, (char *)Interface0DIterator_t_doc, NULL}, {(char *)"u", (getter)Interface0DIterator_u_get, (setter)NULL, (char *)Interface0DIterator_u_doc, NULL}, + {(char *)"at_last", (getter)Interface0DIterator_at_last_get, (setter)NULL, + (char *)Interface0DIterator_at_last_doc, NULL}, {NULL, NULL, NULL, NULL, NULL} /* Sentinel */ }; diff --git a/source/blender/freestyle/intern/python/Iterator/BPy_StrokeVertexIterator.cpp b/source/blender/freestyle/intern/python/Iterator/BPy_StrokeVertexIterator.cpp index 2906f20be06..18d1b37eb3b 100644 --- a/source/blender/freestyle/intern/python/Iterator/BPy_StrokeVertexIterator.cpp +++ b/source/blender/freestyle/intern/python/Iterator/BPy_StrokeVertexIterator.cpp @@ -102,8 +102,8 @@ static PyObject *StrokeVertexIterator_iter(BPy_StrokeVertexIterator *self) static PyObject *StrokeVertexIterator_iternext(BPy_StrokeVertexIterator *self) { /* Because Freestyle iterators for which it.isEnd() holds true have no valid object - * (referencing it.object in this case leads to a crash), we must check if it.object - * is valid after incrementing, to prevent crashes in Python. + * (they point to the past-the-end element and can't be dereferenced), we have to check + * iterators for validity. * Additionally, the at_start attribute is used to keep Freestyle iterator objects * and Python for loops in sync. */ @@ -115,7 +115,10 @@ static PyObject *StrokeVertexIterator_iternext(BPy_StrokeVertexIterator *self) self->sv_it->decrement(); } else { - if (self->sv_it->isEnd()) { + /* if sv_it.isEnd() is true, the iterator can't be incremented. if sv_it.isLast() is true, + * the iterator is currently pointing to the final valid argument. Incrementing it further would + * give a python object that can't be dereferenced. */ + if (self->sv_it->atLast() || self->sv_it->isEnd()) { PyErr_SetNone(PyExc_StopIteration); return NULL; } @@ -123,15 +126,8 @@ static PyObject *StrokeVertexIterator_iternext(BPy_StrokeVertexIterator *self) * and don't increment, to keep for-loops in sync */ if (self->at_start) self->at_start = false; - /* after incrementing, check if the iterator is at its end - * exit the loop if it is. not doing so will result in a crash */ - else { + else self->sv_it->increment(); - if (self->sv_it->isEnd()) { - PyErr_SetNone(PyExc_StopIteration); - return NULL; - } - } } StrokeVertex *sv = self->sv_it->operator->(); return BPy_StrokeVertex_from_StrokeVertex(*sv); @@ -194,7 +190,7 @@ static PyObject *StrokeVertexIterator_reversed(BPy_StrokeVertexIterator *self) } static PyMethodDef BPy_StrokeVertexIterator_methods[] = { - {"incremented", (PyCFunction) StrokeVertexIterator_incremented, METH_NOARGS, StrokeVertexIterator_incremented_doc}, + {"incremented", (PyCFunction)StrokeVertexIterator_incremented, METH_NOARGS, StrokeVertexIterator_incremented_doc}, {"decremented", (PyCFunction)StrokeVertexIterator_decremented, METH_NOARGS, StrokeVertexIterator_decremented_doc}, {"reversed", (PyCFunction)StrokeVertexIterator_reversed, METH_NOARGS, StrokeVertexIterator_reversed_doc}, {NULL, NULL, 0, NULL} @@ -239,11 +235,25 @@ static PyObject *StrokeVertexIterator_u_get(BPy_StrokeVertexIterator *self, void return PyFloat_FromDouble(self->sv_it->u()); } +PyDoc_STRVAR(StrokeVertexIterator_at_last_doc, +"True if the interator points to the last valid element.\n" +"For its counterpart (pointing to the first valid element), use it.is_begin.\n" +"\n" +":type: bool"); + +static PyObject *StrokeVertexIterator_at_last_get(BPy_StrokeVertexIterator *self) +{ + return PyBool_from_bool(self->sv_it->atLast()); + +} + static PyGetSetDef BPy_StrokeVertexIterator_getseters[] = { {(char *)"object", (getter)StrokeVertexIterator_object_get, (setter)NULL, (char *)StrokeVertexIterator_object_doc, NULL}, {(char *)"t", (getter)StrokeVertexIterator_t_get, (setter)NULL, (char *)StrokeVertexIterator_t_doc, NULL}, {(char *)"u", (getter)StrokeVertexIterator_u_get, (setter)NULL, (char *)StrokeVertexIterator_u_doc, NULL}, + {(char *)"at_last", (getter)StrokeVertexIterator_at_last_get, (setter)NULL, + (char *)StrokeVertexIterator_at_last_doc, NULL}, {NULL, NULL, NULL, NULL, NULL} /* Sentinel */ }; diff --git a/source/blender/freestyle/intern/python/Iterator/BPy_orientedViewEdgeIterator.cpp b/source/blender/freestyle/intern/python/Iterator/BPy_orientedViewEdgeIterator.cpp index e4476cf9bcf..d879ac53aaa 100644 --- a/source/blender/freestyle/intern/python/Iterator/BPy_orientedViewEdgeIterator.cpp +++ b/source/blender/freestyle/intern/python/Iterator/BPy_orientedViewEdgeIterator.cpp @@ -116,7 +116,7 @@ PyDoc_STRVAR(orientedViewEdgeIterator_object_doc, "value) currently pointed to by this iterator. If the boolean value is true,\n" "the ViewEdge is incoming.\n" "\n" -":type: (:class:`directedViewEdge`, bool)"); +":type: (:class:`ViewEdge`, bool)"); static PyObject *orientedViewEdgeIterator_object_get(BPy_orientedViewEdgeIterator *self, void *UNUSED(closure)) { diff --git a/source/blender/freestyle/intern/python/StrokeShader/BPy_BlenderTextureShader.cpp b/source/blender/freestyle/intern/python/StrokeShader/BPy_BlenderTextureShader.cpp index c8b9d7098e4..379fb7e1b12 100644 --- a/source/blender/freestyle/intern/python/StrokeShader/BPy_BlenderTextureShader.cpp +++ b/source/blender/freestyle/intern/python/StrokeShader/BPy_BlenderTextureShader.cpp @@ -41,38 +41,46 @@ static char BlenderTextureShader___doc__[] = "\n" "[Texture shader]\n" "\n" -".. method:: __init__(LineStyleTextureSlot)\n" +".. method:: __init__(texture)\n" "\n" " Builds a BlenderTextureShader object.\n" "\n" -" :arg mtex: texture slot to add to stroke shading.\n" -" :type mtex: LineStyleTextureSlot\n" - +" :arg texture: A line style texture slot or a shader node tree to define\n" +" a set of textures.\n" +" :type texture: :class:`LineStyleTextureSlot` or :class:`ShaderNodeTree`\n" "\n" ".. method:: shade(stroke)\n" "\n" -" Assigns a blender texture slot to the stroke shading\n" -" in order to simulate marks.\n" +" Assigns a blender texture slot to the stroke shading in order to\n" +" simulate marks.\n" "\n" " :arg stroke: A Stroke object.\n" " :type stroke: :class:`Stroke`\n"; static int BlenderTextureShader___init__(BPy_BlenderTextureShader *self, PyObject *args, PyObject *kwds) { - static const char *kwlist[] = {"LineStyleTextureSlot", NULL}; - PyObject *py_mtex; + static const char *kwlist[] = {"texture", NULL}; + PyObject *obj; MTex *_mtex; + bNodeTree *_nodetree; - if (!PyArg_ParseTupleAndKeywords(args, kwds, "O", (char **)kwlist, &py_mtex)) + if (!PyArg_ParseTupleAndKeywords(args, kwds, "O", (char **)kwlist, &obj)) return -1; - - _mtex = (MTex*)PyC_RNA_AsPointer(py_mtex, "LineStyleTextureSlot"); - + _mtex = (MTex *)PyC_RNA_AsPointer(obj, "LineStyleTextureSlot"); if (_mtex) { self->py_ss.ss = new StrokeShaders::BlenderTextureShader(_mtex); + return 0; } - - return 0; + PyErr_Clear(); + _nodetree = (bNodeTree *)PyC_RNA_AsPointer(obj, "ShaderNodeTree"); + if (_nodetree) { + self->py_ss.ss = new StrokeShaders::BlenderTextureShader(_nodetree); + return 0; + } + PyErr_Format(PyExc_TypeError, + "expected either 'LineStyleTextureSlot' or 'ShaderNodeTree', " + "found '%.200s' instead", Py_TYPE(obj)->tp_name); + return -1; } /*-----------------------BPy_BlenderTextureShader type definition ------------------------------*/ |