Commit: 840891e22a12c7bbb7c3b8d086ef0c6ff11a24d9
Author: Tamito Kajiyama
Date:   Mon Jun 16 09:56:58 2014 +0900
https://developer.blender.org/rB840891e22a12c7bbb7c3b8d086ef0c6ff11a24d9

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

===================================================================

M       source/blender/freestyle/intern/python/Interface1D/BPy_Stroke.cpp
M       
source/blender/freestyle/intern/python/Iterator/BPy_Interface0DIterator.cpp
M       
source/blender/freestyle/intern/python/Iterator/BPy_StrokeVertexIterator.cpp

===================================================================

diff --git a/source/blender/freestyle/intern/python/Interface1D/BPy_Stroke.cpp 
b/source/blender/freestyle/intern/python/Interface1D/BPy_Stroke.cpp
index aa8c90c..9deaf1a 100644
--- a/source/blender/freestyle/intern/python/Interface1D/BPy_Stroke.cpp
+++ b/source/blender/freestyle/intern/python/Interface1D/BPy_Stroke.cpp
@@ -286,6 +286,21 @@ static PyObject *Stroke_stroke_vertices_end(BPy_Stroke 
*self)
        return BPy_StrokeVertexIterator_from_StrokeVertexIterator(sv_it, true);
 }
 
+PyDoc_STRVAR(Stroke_reversed_doc,
+       ".. method:: __reversed__()\n"
+       "\n"
+       "   Returns a StrokeVertexIterator iterating over the vertices of the 
Stroke\n"
+       "   in the reversed order (from the last to the first).\n"
+       "\n"
+       "   :return: A StrokeVertexIterator pointing after the last 
StrokeVertex.\n"
+       "   :rtype: :class:`StrokeVertexIterator`");
+
+static PyObject *Stroke_reversed(BPy_Stroke *self)
+{
+       StrokeInternal::StrokeVertexIterator 
sv_it(self->s->strokeVerticesEnd());
+       return BPy_StrokeVertexIterator_from_StrokeVertexIterator(sv_it, true);
+}
+
 PyDoc_STRVAR(Stroke_stroke_vertices_size_doc,
 ".. method:: stroke_vertices_size()\n"
 "\n"
@@ -310,6 +325,7 @@ static PyMethodDef BPy_Stroke_methods[] = {
        {"stroke_vertices_begin", (PyCFunction)Stroke_stroke_vertices_begin, 
METH_VARARGS | METH_KEYWORDS,
                                  Stroke_stroke_vertices_begin_doc},
        {"stroke_vertices_end", (PyCFunction)Stroke_stroke_vertices_end, 
METH_NOARGS, Stroke_stroke_vertices_end_doc},
+       {"__reversed__", (PyCFunction)Stroke_reversed, METH_NOARGS, 
Stroke_reversed_doc},
        {"stroke_vertices_size", (PyCFunction)Stroke_stroke_vertices_size, 
METH_NOARGS, Stroke_stroke_vertices_size_doc},
        {NULL, NULL, 0, NULL}
 };
diff --git 
a/source/blender/freestyle/intern/python/Iterator/BPy_Interface0DIterator.cpp 
b/source/blender/freestyle/intern/python/Iterator/BPy_Interface0DIterator.cpp
index a339e66..faf99e9 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 3e50510..a17ad0e 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 */

_______________________________________________
Bf-blender-cvs mailing list
[email protected]
http://lists.blender.org/mailman/listinfo/bf-blender-cvs

Reply via email to