[Bf-blender-cvs] [840891e] master: D545: Freestyle Python API: new methods for Stroke and StrokeVertexIterator.

Tamito Kajiyama noreply at git.blender.org
Mon Jun 16 03:13:37 CEST 2014


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 */




More information about the Bf-blender-cvs mailing list