Welcome to mirror list, hosted at ThFree Co, Russian Federation.

git.blender.org/blender.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorTamito Kajiyama <rd6t-kjym@asahi-net.or.jp>2014-06-16 04:56:58 +0400
committerTamito Kajiyama <rd6t-kjym@asahi-net.or.jp>2014-06-16 05:12:51 +0400
commit840891e22a12c7bbb7c3b8d086ef0c6ff11a24d9 (patch)
tree15160b0453f7cda7d5170e22680c8dda71da97be /source/blender/freestyle/intern/python/Iterator
parentea3bca75d91d140df4c46b501809e4c6e4e8f2d5 (diff)
D545: Freestyle Python API: new methods for Stroke and StrokeVertexIterator.
This revision extends the Freestyle Python API to make for style module writing easier. - freestyle.types.Stroke: A proper support for reversed() is implemented. It works the same with other Python sequence objects (returns an iterator starting from the end). This is in effect equivalent to Stroke.stroke_vertices_end(). - freestyle.types.StrokeVertexIterator: An incremented, decremented and reversed method are added. The first two methods return a new StrokeVertexIterator object that has been incremented and decremented, respectively. The reversed method returns a new StrokeVertexIterator object that will traverse stroke vertices in the opposite direction. - freestyle.types.Interface0DIterator: Its constructor now accepts a Stroke object to create an Interface0DIterator that traverses stroke vertices. This is in effect equivalent to Stroke.vertices_begin(). The new API makes stroke shaders involving function calls much simpler as illustrated below: # in the old API it = stroke.stroke_vertices_begin() for vert in it: result = somefunc(Interface0DIterator(it)) # in the new API it = Interface0DIterator(stroke) for vert in it: result = somefunc(it) Differential Revision: https://developer.blender.org/D545 Reviewers: kjym3
Diffstat (limited to 'source/blender/freestyle/intern/python/Iterator')
-rw-r--r--source/blender/freestyle/intern/python/Iterator/BPy_Interface0DIterator.cpp15
-rw-r--r--source/blender/freestyle/intern/python/Iterator/BPy_StrokeVertexIterator.cpp74
2 files changed, 75 insertions, 14 deletions
diff --git a/source/blender/freestyle/intern/python/Iterator/BPy_Interface0DIterator.cpp b/source/blender/freestyle/intern/python/Iterator/BPy_Interface0DIterator.cpp
index a339e6653c6..faf99e90111 100644
--- a/source/blender/freestyle/intern/python/Iterator/BPy_Interface0DIterator.cpp
+++ b/source/blender/freestyle/intern/python/Iterator/BPy_Interface0DIterator.cpp
@@ -25,6 +25,7 @@
#include "BPy_Interface0DIterator.h"
#include "../BPy_Convert.h"
+#include "../BPy_Interface1D.h"
#ifdef __cplusplus
extern "C" {
@@ -70,9 +71,10 @@ static int convert_nested_it(PyObject *obj, void *v)
static int Interface0DIterator_init(BPy_Interface0DIterator *self, PyObject *args, PyObject *kwds)
{
static const char *kwlist_1[] = {"it", NULL};
- static const char *kwlist_2[] = {"brother", NULL};
+ static const char *kwlist_2[] = {"inter", NULL};
+ static const char *kwlist_3[] = {"brother", NULL};
Interface0DIteratorNested *nested_it;
- PyObject *brother;
+ PyObject *brother, *inter;
if (PyArg_ParseTupleAndKeywords(args, kwds, "O&", (char **)kwlist_1, convert_nested_it, &nested_it)) {
self->if0D_it = new Interface0DIterator(nested_it->copy());
@@ -80,7 +82,14 @@ static int Interface0DIterator_init(BPy_Interface0DIterator *self, PyObject *arg
self->reversed = false;
}
else if (PyErr_Clear(),
- PyArg_ParseTupleAndKeywords(args, kwds, "O!", (char **)kwlist_2, &Interface0DIterator_Type, &brother))
+ PyArg_ParseTupleAndKeywords(args, kwds, "O!", (char **)kwlist_2, &Interface1D_Type, &inter))
+ {
+ self->if0D_it = new Interface0DIterator(((BPy_Interface1D *)inter)->if1D->verticesBegin());
+ self->at_start = true;
+ self->reversed = false;
+ }
+ else if (PyErr_Clear(),
+ PyArg_ParseTupleAndKeywords(args, kwds, "O!", (char **)kwlist_3, &Interface0DIterator_Type, &brother))
{
self->if0D_it = new Interface0DIterator(*(((BPy_Interface0DIterator *)brother)->if0D_it));
self->at_start = ((BPy_Interface0DIterator *)brother)->at_start;
diff --git a/source/blender/freestyle/intern/python/Iterator/BPy_StrokeVertexIterator.cpp b/source/blender/freestyle/intern/python/Iterator/BPy_StrokeVertexIterator.cpp
index 3e5051049bd..a17ad0e39d8 100644
--- a/source/blender/freestyle/intern/python/Iterator/BPy_StrokeVertexIterator.cpp
+++ b/source/blender/freestyle/intern/python/Iterator/BPy_StrokeVertexIterator.cpp
@@ -25,6 +25,7 @@
#include "BPy_StrokeVertexIterator.h"
#include "../BPy_Convert.h"
+#include "../Interface1D/BPy_Stroke.h"
#include "BPy_Interface0DIterator.h"
#ifdef __cplusplus
@@ -63,20 +64,27 @@ PyDoc_STRVAR(StrokeVertexIterator_doc,
static int StrokeVertexIterator_init(BPy_StrokeVertexIterator *self, PyObject *args, PyObject *kwds)
{
- static const char *kwlist[] = {"brother", NULL};
- PyObject *brother = 0;
+ static const char *kwlist_1[] = {"brother", NULL};
+ static const char *kwlist_2[] = {"stroke", NULL};
+ PyObject *brother = 0, *stroke = 0;
- if (!PyArg_ParseTupleAndKeywords(args, kwds, "|O!", (char **)kwlist, &StrokeVertexIterator_Type, &brother))
- return -1;
- if (!brother) {
- self->sv_it = new StrokeInternal::StrokeVertexIterator();
+ if (PyArg_ParseTupleAndKeywords(args, kwds, "|O!", (char **)kwlist_1, &StrokeVertexIterator_Type, &brother)) {
+ self->sv_it = new StrokeInternal::StrokeVertexIterator(*(((BPy_StrokeVertexIterator *)brother)->sv_it));
+ self->reversed = ((BPy_StrokeVertexIterator *)brother)->reversed;
+ self->at_start = ((BPy_StrokeVertexIterator *)brother)->at_start;
+ }
+
+ else if (PyErr_Clear(),
+ PyArg_ParseTupleAndKeywords(args, kwds, "|O!", (char **)kwlist_2, &Stroke_Type, &stroke))
+ {
+ self->sv_it = new StrokeInternal::StrokeVertexIterator(((BPy_Stroke *)stroke)->s->strokeVerticesBegin());
self->reversed = false;
self->at_start = true;
}
else {
- self->sv_it = new StrokeInternal::StrokeVertexIterator(*(((BPy_StrokeVertexIterator *)brother)->sv_it));
- self->reversed = ((BPy_StrokeVertexIterator *)brother)->reversed;
- self->at_start = ((BPy_StrokeVertexIterator *)brother)->at_start;
+ self->sv_it = new StrokeInternal::StrokeVertexIterator();
+ self->reversed = false;
+ self->at_start = true;
}
self->py_it.it = self->sv_it;
return 0;
@@ -91,6 +99,12 @@ 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.
+ * Additionally, the at_start attribute is used to keep Freestyle iterator objects
+ * and Python for loops in sync. */
+
if (self->reversed) {
if (self->sv_it->isBegin()) {
PyErr_SetNone(PyExc_StopIteration);
@@ -121,6 +135,44 @@ static PyObject *StrokeVertexIterator_iternext(BPy_StrokeVertexIterator *self)
return BPy_StrokeVertex_from_StrokeVertex(*sv);
}
+/*----------------------StrokeVertexIterator methods ----------------------------*/
+
+static PyObject *StrokeVertexIterator_incremented(BPy_StrokeVertexIterator *self)
+{
+ if (self->sv_it->isEnd()) {
+ PyErr_SetString(PyExc_RuntimeError, "cannot increment any more");
+ return NULL;
+ }
+ StrokeInternal::StrokeVertexIterator *copy = new StrokeInternal::StrokeVertexIterator(*self->sv_it);
+ copy->increment();
+ return BPy_StrokeVertexIterator_from_StrokeVertexIterator(*copy, self->reversed);
+}
+
+static PyObject *StrokeVertexIterator_decremented(BPy_StrokeVertexIterator *self)
+{
+ if (self->sv_it->isBegin()) {
+ PyErr_SetString(PyExc_RuntimeError, "cannot decrement any more");
+ return NULL;
+ }
+
+ StrokeInternal::StrokeVertexIterator *copy = new StrokeInternal::StrokeVertexIterator(*self->sv_it);
+ copy->decrement();
+ return BPy_StrokeVertexIterator_from_StrokeVertexIterator(*copy, self->reversed);
+}
+
+static PyObject *StrokeVertexIterator_reversed(BPy_StrokeVertexIterator *self)
+{
+ StrokeInternal::StrokeVertexIterator *copy = new StrokeInternal::StrokeVertexIterator(*self->sv_it);
+ return BPy_StrokeVertexIterator_from_StrokeVertexIterator(*copy, !self->reversed);
+}
+
+static PyMethodDef BPy_StrokeVertexIterator_methods[] = {
+ {"incremented", (PyCFunction) StrokeVertexIterator_incremented, METH_NOARGS, NULL},
+ {"decremented", (PyCFunction) StrokeVertexIterator_decremented, METH_NOARGS, NULL},
+ {"reversed", (PyCFunction) StrokeVertexIterator_reversed, METH_NOARGS, NULL},
+ {NULL, NULL, 0, NULL}
+};
+
/*----------------------StrokeVertexIterator get/setters ----------------------------*/
PyDoc_STRVAR(StrokeVertexIterator_object_doc,
@@ -130,7 +182,7 @@ PyDoc_STRVAR(StrokeVertexIterator_object_doc,
static PyObject *StrokeVertexIterator_object_get(BPy_StrokeVertexIterator *self, void *UNUSED(closure))
{
- if (!self->reversed && self->sv_it->isEnd()) {
+ if (self->sv_it->isEnd()) {
PyErr_SetString(PyExc_RuntimeError, "iteration has stopped");
return NULL;
}
@@ -198,7 +250,7 @@ PyTypeObject StrokeVertexIterator_Type = {
0, /* tp_weaklistoffset */
(getiterfunc)StrokeVertexIterator_iter, /* tp_iter */
(iternextfunc)StrokeVertexIterator_iternext, /* tp_iternext */
- 0, /* tp_methods */
+ BPy_StrokeVertexIterator_methods, /* tp_methods */
0, /* tp_members */
BPy_StrokeVertexIterator_getseters, /* tp_getset */
&Iterator_Type, /* tp_base */