Blender V4.5
BPy_ChainingIterator.cpp
Go to the documentation of this file.
1/* SPDX-FileCopyrightText: 2004-2023 Blender Authors
2 *
3 * SPDX-License-Identifier: GPL-2.0-or-later */
4
8
10
11#include "../BPy_Convert.h"
15
16using namespace Freestyle;
17
19
20//------------------------INSTANCE METHODS ----------------------------------
21
23 /* Wrap. */
24 ChainingIterator_doc,
25 "Class hierarchy: :class:`Iterator` > :class:`ViewEdgeIterator` > :class:`ChainingIterator`\n"
26 "\n"
27 "Base class for chaining iterators. This class is designed to be\n"
28 "overloaded in order to describe chaining rules. It makes the\n"
29 "description of chaining rules easier. The two main methods that need\n"
30 "to overloaded are traverse() and init(). traverse() tells which\n"
31 ":class:`ViewEdge` to follow, among the adjacent ones. If you specify\n"
32 "restriction rules (such as \"Chain only ViewEdges of the selection\"),\n"
33 "they will be included in the adjacency iterator (i.e, the adjacent\n"
34 "iterator will only stop on \"valid\" edges).\n"
35 "\n"
36 ".. method:: __init__(restrict_to_selection=True, restrict_to_unvisited=True,"
37 " begin=None, orientation=True)\n"
38 " __init__(brother)\n"
39 "\n"
40 " Builds a Chaining Iterator from the first ViewEdge used for\n"
41 " iteration and its orientation or by using the copy constructor.\n"
42 "\n"
43 " :arg restrict_to_selection: Indicates whether to force the chaining\n"
44 " to stay within the set of selected ViewEdges or not.\n"
45 " :type restrict_to_selection: bool\n"
46 " :arg restrict_to_unvisited: Indicates whether a ViewEdge that has\n"
47 " already been chained must be ignored ot not.\n"
48 " :type restrict_to_unvisited: bool\n"
49 " :arg begin: The ViewEdge from which to start the chain.\n"
50 " :type begin: :class:`ViewEdge` | None\n"
51 " :arg orientation: The direction to follow to explore the graph. If\n"
52 " true, the direction indicated by the first ViewEdge is used.\n"
53 " :type orientation: bool\n"
54 " :arg brother: \n"
55 " :type brother: ChainingIterator");
56
57static int check_begin(PyObject *obj, void *v)
58{
59 if (obj != nullptr && obj != Py_None && !BPy_ViewEdge_Check(obj)) {
60 return 0;
61 }
62 *((PyObject **)v) = obj;
63 return 1;
64}
65
66static int ChainingIterator___init__(BPy_ChainingIterator *self, PyObject *args, PyObject *kwds)
67{
68 static const char *kwlist_1[] = {"brother", nullptr};
69 static const char *kwlist_2[] = {
70 "restrict_to_selection", "restrict_to_unvisited", "begin", "orientation", nullptr};
71 PyObject *obj1 = nullptr, *obj2 = nullptr, *obj3 = nullptr, *obj4 = nullptr;
72
73 if (PyArg_ParseTupleAndKeywords(
74 args, kwds, "O!", (char **)kwlist_1, &ChainingIterator_Type, &obj1))
75 {
76 self->c_it = new ChainingIterator(*(((BPy_ChainingIterator *)obj1)->c_it));
77 }
78 else if ((void)PyErr_Clear(),
79 (void)(obj1 = obj2 = obj3 = obj4 = nullptr),
80 PyArg_ParseTupleAndKeywords(args,
81 kwds,
82 "|O!O!O&O!",
83 (char **)kwlist_2,
84 &PyBool_Type,
85 &obj1,
86 &PyBool_Type,
87 &obj2,
89 &obj3,
90 &PyBool_Type,
91 &obj4))
92 {
93 bool restrict_to_selection = (!obj1) ? true : bool_from_PyBool(obj1);
94 bool restrict_to_unvisited = (!obj2) ? true : bool_from_PyBool(obj2);
95 ViewEdge *begin = (!obj3 || obj3 == Py_None) ? nullptr : ((BPy_ViewEdge *)obj3)->ve;
96 bool orientation = (!obj4) ? true : bool_from_PyBool(obj4);
97 self->c_it = new ChainingIterator(
98 restrict_to_selection, restrict_to_unvisited, begin, orientation);
99 }
100 else {
101 PyErr_SetString(PyExc_TypeError, "invalid argument(s)");
102 return -1;
103 }
104 self->py_ve_it.ve_it = self->c_it;
105 self->py_ve_it.py_it.it = self->c_it;
106
107 self->c_it->py_c_it = (PyObject *)self;
108
109 return 0;
110}
111
113 /* Wrap. */
114 ChainingIterator_init_doc,
115 ".. method:: init()\n"
116 "\n"
117 " Initializes the iterator context. This method is called each\n"
118 " time a new chain is started. It can be used to reset some\n"
119 " history information that you might want to keep.");
120
122{
123 if (typeid(*(self->c_it)) == typeid(ChainingIterator)) {
124 PyErr_SetString(PyExc_TypeError, "init() method not properly overridden");
125 return nullptr;
126 }
127 self->c_it->init();
128 Py_RETURN_NONE;
129}
130
132 /* Wrap. */
133 ChainingIterator_traverse_doc,
134 ".. method:: traverse(it)\n"
135 "\n"
136 " This method iterates over the potential next ViewEdges and returns\n"
137 " the one that will be followed next. Returns the next ViewEdge to\n"
138 " follow or None when the end of the chain is reached.\n"
139 "\n"
140 " :arg it: The iterator over the ViewEdges adjacent to the end vertex\n"
141 " of the current ViewEdge. The adjacency iterator reflects the\n"
142 " restriction rules by only iterating over the valid ViewEdges.\n"
143 " :type it: :class:`AdjacencyIterator`\n"
144 " :return: Returns the next ViewEdge to follow, or None if chaining ends.\n"
145 " :rtype: :class:`ViewEdge` | None");
146
148 PyObject *args,
149 PyObject *kwds)
150{
151 static const char *kwlist[] = {"it", nullptr};
152 PyObject *py_a_it;
153
154 if (typeid(*(self->c_it)) == typeid(ChainingIterator)) {
155 PyErr_SetString(PyExc_TypeError, "traverse() method not properly overridden");
156 return nullptr;
157 }
158 if (!PyArg_ParseTupleAndKeywords(
159 args, kwds, "O!", (char **)kwlist, &AdjacencyIterator_Type, &py_a_it))
160 {
161 return nullptr;
162 }
163 if (((BPy_AdjacencyIterator *)py_a_it)->a_it) {
164 self->c_it->traverse(*(((BPy_AdjacencyIterator *)py_a_it)->a_it));
165 }
166 Py_RETURN_NONE;
167}
168
169#ifdef __GNUC__
170# ifdef __clang__
171# pragma clang diagnostic push
172# pragma clang diagnostic ignored "-Wcast-function-type"
173# else
174# pragma GCC diagnostic push
175# pragma GCC diagnostic ignored "-Wcast-function-type"
176# endif
177#endif
178
179static PyMethodDef BPy_ChainingIterator_methods[] = {
180 {"init", (PyCFunction)ChainingIterator_init, METH_NOARGS, ChainingIterator_init_doc},
181 {"traverse",
182 (PyCFunction)ChainingIterator_traverse,
183 METH_VARARGS | METH_KEYWORDS,
184 ChainingIterator_traverse_doc},
185 {nullptr, nullptr, 0, nullptr},
186};
187
188#ifdef __GNUC__
189# ifdef __clang__
190# pragma clang diagnostic pop
191# else
192# pragma GCC diagnostic pop
193# endif
194#endif
195
196/*----------------------ChainingIterator get/setters ----------------------------*/
197
199 /* Wrap. */
200 ChainingIterator_object_doc,
201 "The ViewEdge object currently pointed by this iterator.\n"
202 "\n"
203 ":type: :class:`ViewEdge`");
204
205static PyObject *ChainingIterator_object_get(BPy_ChainingIterator *self, void * /*closure*/)
206{
207 if (self->c_it->isEnd()) {
208 PyErr_SetString(PyExc_RuntimeError, "iteration has stopped");
209 return nullptr;
210 }
211 ViewEdge *ve = self->c_it->operator*();
212 if (ve) {
213 return BPy_ViewEdge_from_ViewEdge(*ve);
214 }
215
216 Py_RETURN_NONE;
217}
218
220 /* Wrap. */
221 ChainingIterator_next_vertex_doc,
222 "The ViewVertex that is the next crossing.\n"
223 "\n"
224 ":type: :class:`ViewVertex`");
225
226static PyObject *ChainingIterator_next_vertex_get(BPy_ChainingIterator *self, void * /*closure*/)
227{
228 ViewVertex *v = self->c_it->getVertex();
229 if (v) {
231 }
232
233 Py_RETURN_NONE;
234}
235
237 /* Wrap. */
238 ChainingIterator_is_incrementing_doc,
239 "True if the current iteration is an incrementation.\n"
240 "\n"
241 ":type: bool");
242
244 void * /*closure*/)
245{
246 return PyBool_from_bool(self->c_it->isIncrementing());
247}
248
249static PyGetSetDef BPy_ChainingIterator_getseters[] = {
250 {"object",
252 (setter) nullptr,
253 ChainingIterator_object_doc,
254 nullptr},
255 {"next_vertex",
257 (setter) nullptr,
258 ChainingIterator_next_vertex_doc,
259 nullptr},
260 {"is_incrementing",
262 (setter) nullptr,
263 ChainingIterator_is_incrementing_doc,
264 nullptr},
265 {nullptr, nullptr, nullptr, nullptr, nullptr} /* Sentinel */
266};
267
268/*-----------------------BPy_ChainingIterator type definition ------------------------------*/
269
270PyTypeObject ChainingIterator_Type = {
271 /*ob_base*/ PyVarObject_HEAD_INIT(nullptr, 0)
272 /*tp_name*/ "ChainingIterator",
273 /*tp_basicsize*/ sizeof(BPy_ChainingIterator),
274 /*tp_itemsize*/ 0,
275 /*tp_dealloc*/ nullptr,
276 /*tp_vectorcall_offset*/ 0,
277 /*tp_getattr*/ nullptr,
278 /*tp_setattr*/ nullptr,
279 /*tp_as_async*/ nullptr,
280 /*tp_repr*/ nullptr,
281 /*tp_as_number*/ nullptr,
282 /*tp_as_sequence*/ nullptr,
283 /*tp_as_mapping*/ nullptr,
284 /*tp_hash*/ nullptr,
285 /*tp_call*/ nullptr,
286 /*tp_str*/ nullptr,
287 /*tp_getattro*/ nullptr,
288 /*tp_setattro*/ nullptr,
289 /*tp_as_buffer*/ nullptr,
290 /*tp_flags*/ Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE,
291 /*tp_doc*/ ChainingIterator_doc,
292 /*tp_traverse*/ nullptr,
293 /*tp_clear*/ nullptr,
294 /*tp_richcompare*/ nullptr,
295 /*tp_weaklistoffset*/ 0,
296 /*tp_iter*/ nullptr,
297 /*tp_iternext*/ nullptr,
298 /*tp_methods*/ BPy_ChainingIterator_methods,
299 /*tp_members*/ nullptr,
300 /*tp_getset*/ BPy_ChainingIterator_getseters,
301 /*tp_base*/ &ViewEdgeIterator_Type,
302 /*tp_dict*/ nullptr,
303 /*tp_descr_get*/ nullptr,
304 /*tp_descr_set*/ nullptr,
305 /*tp_dictoffset*/ 0,
306 /*tp_init*/ (initproc)ChainingIterator___init__,
307 /*tp_alloc*/ nullptr,
308 /*tp_new*/ nullptr,
309};
310
PyTypeObject AdjacencyIterator_Type
static int check_begin(PyObject *obj, void *v)
static int ChainingIterator___init__(BPy_ChainingIterator *self, PyObject *args, PyObject *kwds)
static PyObject * ChainingIterator_init(BPy_ChainingIterator *self)
static PyGetSetDef BPy_ChainingIterator_getseters[]
static PyObject * ChainingIterator_next_vertex_get(BPy_ChainingIterator *self, void *)
static PyObject * ChainingIterator_traverse(BPy_ChainingIterator *self, PyObject *args, PyObject *kwds)
static PyMethodDef BPy_ChainingIterator_methods[]
static PyObject * ChainingIterator_is_incrementing_get(BPy_ChainingIterator *self, void *)
static PyObject * ChainingIterator_object_get(BPy_ChainingIterator *self, void *)
PyDoc_STRVAR(ChainingIterator_doc, "Class hierarchy: :class:`Iterator` > :class:`ViewEdgeIterator` > :class:`ChainingIterator`\n" "\n" "Base class for chaining iterators. This class is designed to be\n" "overloaded in order to describe chaining rules. It makes the\n" "description of chaining rules easier. The two main methods that need\n" "to overloaded are traverse() and init(). traverse() tells which\n" ":class:`ViewEdge` to follow, among the adjacent ones. If you specify\n" "restriction rules (such as \"Chain only ViewEdges of the selection\"),\n" "they will be included in the adjacency iterator (i.e, the adjacent\n" "iterator will only stop on \"valid\" edges).\n" "\n" ".. method:: __init__(restrict_to_selection=True, restrict_to_unvisited=True," " begin=None, orientation=True)\n" " __init__(brother)\n" "\n" " Builds a Chaining Iterator from the first ViewEdge used for\n" " iteration and its orientation or by using the copy constructor.\n" "\n" " :arg restrict_to_selection: Indicates whether to force the chaining\n" " to stay within the set of selected ViewEdges or not.\n" " :type restrict_to_selection: bool\n" " :arg restrict_to_unvisited: Indicates whether a ViewEdge that has\n" " already been chained must be ignored ot not.\n" " :type restrict_to_unvisited: bool\n" " :arg begin: The ViewEdge from which to start the chain.\n" " :type begin: :class:`ViewEdge` | None\n" " :arg orientation: The direction to follow to explore the graph. If\n" " true, the direction indicated by the first ViewEdge is used.\n" " :type orientation: bool\n" " :arg brother: \n" " :type brother: ChainingIterator")
PyTypeObject ChainingIterator_Type
bool bool_from_PyBool(PyObject *b)
PyObject * Any_BPy_ViewVertex_from_ViewVertex(ViewVertex &vv)
PyObject * BPy_ViewEdge_from_ViewEdge(ViewEdge &ve)
PyObject * PyBool_from_bool(bool b)
PyTypeObject ViewEdgeIterator_Type
#define BPy_ViewEdge_Check(v)
iter begin(iter)
ATTR_WARN_UNUSED_RESULT const BMVert * v
PyObject * self
inherits from class Rep
Definition AppCanvas.cpp:20