Blender V5.0
BPy_Operators.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
9#include "BPy_Operators.h"
10
12#include "BPy_Convert.h"
13#include "BPy_StrokeShader.h"
20
21#include "BLI_sys_types.h"
22
23#include <sstream>
24
25using namespace Freestyle;
26
28
29//-------------------MODULE INITIALIZATION--------------------------------
30int Operators_Init(PyObject *module)
31{
32 if (module == nullptr) {
33 return -1;
34 }
35
36 if (PyType_Ready(&Operators_Type) < 0) {
37 return -1;
38 }
39 PyModule_AddObjectRef(module, "Operators", (PyObject *)&Operators_Type);
40
41 return 0;
42}
43
44//------------------------INSTANCE METHODS ----------------------------------
45
47 /* Wrap. */
48 Operators_doc,
49 "Class defining the operators used in a style module. There are five\n"
50 "types of operators: Selection, chaining, splitting, sorting and\n"
51 "creation. All these operators are user controlled through functors,\n"
52 "predicates and shaders that are taken as arguments.\n");
54{
55 Py_TYPE(self)->tp_free((PyObject *)self);
56}
57
59 /* Wrap. */
60 Operators_select_doc,
61 ".. staticmethod:: select(pred)\n"
62 "\n"
63 " Selects the ViewEdges of the ViewMap verifying a specified\n"
64 " condition.\n"
65 "\n"
66 " :arg pred: The predicate expressing this condition.\n"
67 " :type pred: :class:`UnaryPredicate1D`\n");
68static PyObject *Operators_select(BPy_Operators * /*self*/, PyObject *args, PyObject *kwds)
69{
70 static const char *kwlist[] = {"pred", nullptr};
71 PyObject *obj = nullptr;
72
73 if (!PyArg_ParseTupleAndKeywords(
74 args, kwds, "O!", (char **)kwlist, &UnaryPredicate1D_Type, &obj))
75 {
76 return nullptr;
77 }
78 if (!((BPy_UnaryPredicate1D *)obj)->up1D) {
79 PyErr_SetString(PyExc_TypeError,
80 "Operators.select(): 1st argument: invalid UnaryPredicate1D object");
81 return nullptr;
82 }
83 if (Operators::select(*(((BPy_UnaryPredicate1D *)obj)->up1D)) < 0) {
84 if (!PyErr_Occurred()) {
85 PyErr_SetString(PyExc_RuntimeError, "Operators.select() failed");
86 }
87 return nullptr;
88 }
89 Py_RETURN_NONE;
90}
91
93 /* Wrap. */
94 Operators_chain_doc,
95 ".. staticmethod:: chain(it, pred, modifier)\n"
96 " chain(it, pred)\n"
97 "\n"
98 " Builds a set of chains from the current set of ViewEdges. Each\n"
99 " ViewEdge of the current list starts a new chain. The chaining\n"
100 " operator then iterates over the ViewEdges of the ViewMap using the\n"
101 " user specified iterator. This operator only iterates using the\n"
102 " increment operator and is therefore unidirectional.\n"
103 "\n"
104 " :arg it: The iterator on the ViewEdges of the ViewMap. It contains\n"
105 " the chaining rule.\n"
106 " :type it: :class:`ViewEdgeIterator`\n"
107 " :arg pred: The predicate on the ViewEdge that expresses the\n"
108 " stopping condition.\n"
109 " :type pred: :class:`UnaryPredicate1D`\n"
110 " :arg modifier: A function that takes a ViewEdge as argument and\n"
111 " that is used to modify the processed ViewEdge state (the\n"
112 " timestamp incrementation is a typical illustration of such a modifier).\n"
113 " If this argument is not given, the time stamp is automatically managed.\n"
114 " :type modifier: :class:`UnaryFunction1DVoid`\n");
115static PyObject *Operators_chain(BPy_Operators * /*self*/, PyObject *args, PyObject *kwds)
116{
117 static const char *kwlist[] = {"it", "pred", "modifier", nullptr};
118 PyObject *obj1 = nullptr, *obj2 = nullptr, *obj3 = nullptr;
119
120 if (!PyArg_ParseTupleAndKeywords(args,
121 kwds,
122 "O!O!|O!",
123 (char **)kwlist,
125 &obj1,
127 &obj2,
129 &obj3))
130 {
131 return nullptr;
132 }
133 if (!((BPy_ChainingIterator *)obj1)->c_it) {
134 PyErr_SetString(PyExc_TypeError,
135 "Operators.chain(): 1st argument: invalid ChainingIterator object");
136 return nullptr;
137 }
138 if (!((BPy_UnaryPredicate1D *)obj2)->up1D) {
139 PyErr_SetString(PyExc_TypeError,
140 "Operators.chain(): 2nd argument: invalid UnaryPredicate1D object");
141 return nullptr;
142 }
143 if (!obj3) {
144 if (Operators::chain(*(((BPy_ChainingIterator *)obj1)->c_it),
145 *(((BPy_UnaryPredicate1D *)obj2)->up1D)) < 0)
146 {
147 if (!PyErr_Occurred()) {
148 PyErr_SetString(PyExc_RuntimeError, "Operators.chain() failed");
149 }
150 return nullptr;
151 }
152 }
153 else {
154 if (!((BPy_UnaryFunction1DVoid *)obj3)->uf1D_void) {
155 PyErr_SetString(PyExc_TypeError,
156 "Operators.chain(): 3rd argument: invalid UnaryFunction1DVoid object");
157 return nullptr;
158 }
159 if (Operators::chain(*(((BPy_ChainingIterator *)obj1)->c_it),
160 *(((BPy_UnaryPredicate1D *)obj2)->up1D),
161 *(((BPy_UnaryFunction1DVoid *)obj3)->uf1D_void)) < 0)
162 {
163 if (!PyErr_Occurred()) {
164 PyErr_SetString(PyExc_RuntimeError, "Operators.chain() failed");
165 }
166 return nullptr;
167 }
168 }
169 Py_RETURN_NONE;
170}
171
173 /* Wrap. */
174 Operators_bidirectional_chain_doc,
175 ".. staticmethod:: bidirectional_chain(it, pred)\n"
176 " bidirectional_chain(it)\n"
177 "\n"
178 " Builds a set of chains from the current set of ViewEdges. Each\n"
179 " ViewEdge of the current list potentially starts a new chain. The\n"
180 " chaining operator then iterates over the ViewEdges of the ViewMap\n"
181 " using the user specified iterator. This operator iterates both using\n"
182 " the increment and decrement operators and is therefore bidirectional.\n"
183 " This operator works with a ChainingIterator which contains the\n"
184 " chaining rules. It is this last one which can be told to chain only\n"
185 " edges that belong to the selection or not to process twice a ViewEdge\n"
186 " during the chaining. Each time a ViewEdge is added to a chain, its\n"
187 " chaining time stamp is incremented. This allows you to keep track of\n"
188 " the number of chains to which a ViewEdge belongs to.\n"
189 "\n"
190 " :arg it: The ChainingIterator on the ViewEdges of the ViewMap. It\n"
191 " contains the chaining rule.\n"
192 " :type it: :class:`ChainingIterator`\n"
193 " :arg pred: The predicate on the ViewEdge that expresses the stopping condition.\n"
194 " This parameter is optional, you make not want to pass a stopping criterion\n"
195 " when the stopping criterion is already contained in the iterator definition.\n"
196 " :type pred: :class:`UnaryPredicate1D`\n");
198 PyObject *args,
199 PyObject *kwds)
200{
201 static const char *kwlist[] = {"it", "pred", nullptr};
202 PyObject *obj1 = nullptr, *obj2 = nullptr;
203
204 if (!PyArg_ParseTupleAndKeywords(args,
205 kwds,
206 "O!|O!",
207 (char **)kwlist,
209 &obj1,
211 &obj2))
212 {
213 return nullptr;
214 }
215 if (!((BPy_ChainingIterator *)obj1)->c_it) {
216 PyErr_SetString(
217 PyExc_TypeError,
218 "Operators.bidirectional_chain(): 1st argument: invalid ChainingIterator object");
219 return nullptr;
220 }
221 if (!obj2) {
222 if (Operators::bidirectionalChain(*(((BPy_ChainingIterator *)obj1)->c_it)) < 0) {
223 if (!PyErr_Occurred()) {
224 PyErr_SetString(PyExc_RuntimeError, "Operators.bidirectional_chain() failed");
225 }
226 return nullptr;
227 }
228 }
229 else {
230 if (!((BPy_UnaryPredicate1D *)obj2)->up1D) {
231 PyErr_SetString(
232 PyExc_TypeError,
233 "Operators.bidirectional_chain(): 2nd argument: invalid UnaryPredicate1D object");
234 return nullptr;
235 }
237 *(((BPy_UnaryPredicate1D *)obj2)->up1D)) < 0)
238 {
239 if (!PyErr_Occurred()) {
240 PyErr_SetString(PyExc_RuntimeError, "Operators.bidirectional_chain() failed");
241 }
242 return nullptr;
243 }
244 }
245 Py_RETURN_NONE;
246}
247
249 /* Wrap. */
250 Operators_sequential_split_doc,
251 ".. staticmethod:: sequential_split(starting_pred, stopping_pred, sampling=0.0)\n"
252 " sequential_split(pred, sampling=0.0)\n"
253 "\n"
254 " Splits each chain of the current set of chains in a sequential way.\n"
255 " The points of each chain are processed (with a specified sampling)\n"
256 " sequentially. The first point of the initial chain is the\n"
257 " first point of one of the resulting chains. The splitting ends when\n"
258 " no more chain can start.\n"
259 "\n"
260 " .. tip::\n"
261 "\n"
262 " By specifying a starting and stopping predicate allows\n"
263 " the chains to overlap rather than chains partitioning.\n"
264 "\n"
265 " :arg starting_pred: The predicate on a point that expresses the\n"
266 " starting condition. Each time this condition is verified, a new chain begins\n"
267 " :type starting_pred: :class:`UnaryPredicate0D`\n"
268 " :arg stopping_pred: The predicate on a point that expresses the\n"
269 " stopping condition. The chain ends as soon as this predicate is verified.\n"
270 " :type stopping_pred: :class:`UnaryPredicate0D`\n"
271 " :arg pred: The predicate on a point that expresses the splitting condition.\n"
272 " Each time the condition is verified, the chain is split into two chains.\n"
273 " The resulting set of chains is a partition of the initial chain\n"
274 " :type pred: :class:`UnaryPredicate0D`\n"
275 " :arg sampling: The resolution used to sample the chain for the\n"
276 " predicates evaluation. (The chain is not actually resampled;\n"
277 " a virtual point only progresses along the curve using this\n"
278 " resolution.)\n"
279 " :type sampling: float\n");
280static PyObject *Operators_sequential_split(BPy_Operators * /*self*/,
281 PyObject *args,
282 PyObject *kwds)
283{
284 static const char *kwlist_1[] = {"starting_pred", "stopping_pred", "sampling", nullptr};
285 static const char *kwlist_2[] = {"pred", "sampling", nullptr};
286 PyObject *obj1 = nullptr, *obj2 = nullptr;
287 float f = 0.0f;
288
289 if (PyArg_ParseTupleAndKeywords(args,
290 kwds,
291 "O!O!|f",
292 (char **)kwlist_1,
294 &obj1,
296 &obj2,
297 &f))
298 {
299 if (!((BPy_UnaryPredicate0D *)obj1)->up0D) {
300 PyErr_SetString(
301 PyExc_TypeError,
302 "Operators.sequential_split(): 1st argument: invalid UnaryPredicate0D object");
303 return nullptr;
304 }
305 if (!((BPy_UnaryPredicate0D *)obj2)->up0D) {
306 PyErr_SetString(
307 PyExc_TypeError,
308 "Operators.sequential_split(): 2nd argument: invalid UnaryPredicate0D object");
309 return nullptr;
310 }
312 *(((BPy_UnaryPredicate0D *)obj2)->up0D),
313 f) < 0)
314 {
315 if (!PyErr_Occurred()) {
316 PyErr_SetString(PyExc_RuntimeError, "Operators.sequential_split() failed");
317 }
318 return nullptr;
319 }
320 }
321 else if ((void)PyErr_Clear(),
322 (void)(f = 0.0f),
323 PyArg_ParseTupleAndKeywords(
324 args, kwds, "O!|f", (char **)kwlist_2, &UnaryPredicate0D_Type, &obj1, &f))
325 {
326 if (!((BPy_UnaryPredicate0D *)obj1)->up0D) {
327 PyErr_SetString(
328 PyExc_TypeError,
329 "Operators.sequential_split(): 1st argument: invalid UnaryPredicate0D object");
330 return nullptr;
331 }
332 if (Operators::sequentialSplit(*(((BPy_UnaryPredicate0D *)obj1)->up0D), f) < 0) {
333 if (!PyErr_Occurred()) {
334 PyErr_SetString(PyExc_RuntimeError, "Operators.sequential_split() failed");
335 }
336 return nullptr;
337 }
338 }
339 else {
340 PyErr_SetString(PyExc_TypeError, "invalid argument(s)");
341 return nullptr;
342 }
343 Py_RETURN_NONE;
344}
345
347 /* Wrap. */
348 Operators_recursive_split_doc,
349 ".. staticmethod:: recursive_split(func, pred_1d, sampling=0.0)\n"
350 " recursive_split(func, pred_0d, pred_1d, sampling=0.0)\n"
351 "\n"
352 " Splits the current set of chains in a recursive way. We process the\n"
353 " points of each chain (with a specified sampling) to find the point\n"
354 " minimizing a specified function. The chain is split in two at this\n"
355 " point and the two new chains are processed in the same way. The\n"
356 " recursivity level is controlled through a predicate 1D that expresses\n"
357 " a stopping condition on the chain that is about to be processed.\n"
358 "\n"
359 " The user can also specify a 0D predicate to make a first selection on the points\n"
360 " that can potentially be split. A point that doesn't verify the 0D\n"
361 " predicate won't be candidate in realizing the min.\n"
362 "\n"
363 " :arg func: The Unary Function evaluated at each point of the chain.\n"
364 " The splitting point is the point minimizing this function.\n"
365 " :type func: :class:`UnaryFunction0DDouble`\n"
366 " :arg pred_0d: The Unary Predicate 0D used to select the candidate\n"
367 " points where the split can occur. For example, it is very likely\n"
368 " that would rather have your chain splitting around its middle\n"
369 " point than around one of its extremities. A 0D predicate working\n"
370 " on the curvilinear abscissa allows to add this kind of constraints.\n"
371 " :type pred_0d: :class:`UnaryPredicate0D`\n"
372 " :arg pred_1d: The Unary Predicate expressing the recursivity stopping\n"
373 " condition. This predicate is evaluated for each curve before it\n"
374 " actually gets split. If pred_1d(chain) is true, the curve won't be\n"
375 " split anymore.\n"
376 " :type pred_1d: :class:`UnaryPredicate1D`\n"
377 " :arg sampling: The resolution used to sample the chain for the\n"
378 " predicates evaluation. (The chain is not actually resampled; a\n"
379 " virtual point only progresses along the curve using this\n"
380 " resolution.)\n"
381 " :type sampling: float\n");
382static PyObject *Operators_recursive_split(BPy_Operators * /*self*/,
383 PyObject *args,
384 PyObject *kwds)
385{
386 static const char *kwlist_1[] = {"func", "pred_1d", "sampling", nullptr};
387 static const char *kwlist_2[] = {"func", "pred_0d", "pred_1d", "sampling", nullptr};
388 PyObject *obj1 = nullptr, *obj2 = nullptr, *obj3 = nullptr;
389 float f = 0.0f;
390
391 if (PyArg_ParseTupleAndKeywords(args,
392 kwds,
393 "O!O!|f",
394 (char **)kwlist_1,
396 &obj1,
398 &obj2,
399 &f))
400 {
401 if (!((BPy_UnaryFunction0DDouble *)obj1)->uf0D_double) {
402 PyErr_SetString(
403 PyExc_TypeError,
404 "Operators.recursive_split(): 1st argument: invalid UnaryFunction0DDouble object");
405 return nullptr;
406 }
407 if (!((BPy_UnaryPredicate1D *)obj2)->up1D) {
408 PyErr_SetString(
409 PyExc_TypeError,
410 "Operators.recursive_split(): 2nd argument: invalid UnaryPredicate1D object");
411 return nullptr;
412 }
413 if (Operators::recursiveSplit(*(((BPy_UnaryFunction0DDouble *)obj1)->uf0D_double),
414 *(((BPy_UnaryPredicate1D *)obj2)->up1D),
415 f) < 0)
416 {
417 if (!PyErr_Occurred()) {
418 PyErr_SetString(PyExc_RuntimeError, "Operators.recursive_split() failed");
419 }
420 return nullptr;
421 }
422 }
423 else if ((void)PyErr_Clear(),
424 (void)(f = 0.0f),
425 PyArg_ParseTupleAndKeywords(args,
426 kwds,
427 "O!O!O!|f",
428 (char **)kwlist_2,
430 &obj1,
432 &obj2,
434 &obj3,
435 &f))
436 {
437 if (!((BPy_UnaryFunction0DDouble *)obj1)->uf0D_double) {
438 PyErr_SetString(
439 PyExc_TypeError,
440 "Operators.recursive_split(): 1st argument: invalid UnaryFunction0DDouble object");
441 return nullptr;
442 }
443 if (!((BPy_UnaryPredicate0D *)obj2)->up0D) {
444 PyErr_SetString(
445 PyExc_TypeError,
446 "Operators.recursive_split(): 2nd argument: invalid UnaryPredicate0D object");
447 return nullptr;
448 }
449 if (!((BPy_UnaryPredicate1D *)obj3)->up1D) {
450 PyErr_SetString(
451 PyExc_TypeError,
452 "Operators.recursive_split(): 3rd argument: invalid UnaryPredicate1D object");
453 return nullptr;
454 }
455 if (Operators::recursiveSplit(*(((BPy_UnaryFunction0DDouble *)obj1)->uf0D_double),
456 *(((BPy_UnaryPredicate0D *)obj2)->up0D),
457 *(((BPy_UnaryPredicate1D *)obj3)->up1D),
458 f) < 0)
459 {
460 if (!PyErr_Occurred()) {
461 PyErr_SetString(PyExc_RuntimeError, "Operators.recursive_split() failed");
462 }
463 return nullptr;
464 }
465 }
466 else {
467 PyErr_SetString(PyExc_TypeError, "invalid argument(s)");
468 return nullptr;
469 }
470 Py_RETURN_NONE;
471}
472
474 /* Wrap. */
475 Operators_sort_doc,
476 ".. staticmethod:: sort(pred)\n"
477 "\n"
478 " Sorts the current set of chains (or viewedges) according to the\n"
479 " comparison predicate given as argument.\n"
480 "\n"
481 " :arg pred: The binary predicate used for the comparison.\n"
482 " :type pred: :class:`BinaryPredicate1D`\n");
483static PyObject *Operators_sort(BPy_Operators * /*self*/, PyObject *args, PyObject *kwds)
484{
485 static const char *kwlist[] = {"pred", nullptr};
486 PyObject *obj = nullptr;
487
488 if (!PyArg_ParseTupleAndKeywords(
489 args, kwds, "O!", (char **)kwlist, &BinaryPredicate1D_Type, &obj))
490 {
491 return nullptr;
492 }
493 if (!((BPy_BinaryPredicate1D *)obj)->bp1D) {
494 PyErr_SetString(PyExc_TypeError,
495 "Operators.sort(): 1st argument: invalid BinaryPredicate1D object");
496 return nullptr;
497 }
498 if (Operators::sort(*(((BPy_BinaryPredicate1D *)obj)->bp1D)) < 0) {
499 if (!PyErr_Occurred()) {
500 PyErr_SetString(PyExc_RuntimeError, "Operators.sort() failed");
501 }
502 return nullptr;
503 }
504 Py_RETURN_NONE;
505}
506
508 /* Wrap. */
509 Operators_create_doc,
510 ".. staticmethod:: create(pred, shaders)\n"
511 "\n"
512 " Creates and shades the strokes from the current set of chains. A\n"
513 " predicate can be specified to make a selection pass on the chains.\n"
514 "\n"
515 " :arg pred: The predicate that a chain must verify in order to be\n"
516 " transform as a stroke.\n"
517 " :type pred: :class:`UnaryPredicate1D`\n"
518 " :arg shaders: The list of shaders used to shade the strokes.\n"
519 " :type shaders: list[:class:`StrokeShader`]\n");
520static PyObject *Operators_create(BPy_Operators * /*self*/, PyObject *args, PyObject *kwds)
521{
522 static const char *kwlist[] = {"pred", "shaders", nullptr};
523 PyObject *obj1 = nullptr, *obj2 = nullptr;
524
525 if (!PyArg_ParseTupleAndKeywords(
526 args, kwds, "O!O!", (char **)kwlist, &UnaryPredicate1D_Type, &obj1, &PyList_Type, &obj2))
527 {
528 return nullptr;
529 }
530 if (!((BPy_UnaryPredicate1D *)obj1)->up1D) {
531 PyErr_SetString(PyExc_TypeError,
532 "Operators.create(): 1st argument: invalid UnaryPredicate1D object");
533 return nullptr;
534 }
536 shaders.reserve(PyList_Size(obj2));
537 for (int i = 0; i < PyList_Size(obj2); i++) {
538 PyObject *py_ss = PyList_GET_ITEM(obj2, i);
539 if (!BPy_StrokeShader_Check(py_ss)) {
540 PyErr_SetString(PyExc_TypeError,
541 "Operators.create(): 2nd argument must be a list of StrokeShader objects");
542 return nullptr;
543 }
544 StrokeShader *shader = ((BPy_StrokeShader *)py_ss)->ss;
545 if (!shader) {
546 stringstream ss;
547 ss << "Operators.create(): item " << (i + 1)
548 << " of the shaders list is invalid likely due to missing call of "
549 "StrokeShader.__init__()";
550 PyErr_SetString(PyExc_TypeError, ss.str().c_str());
551 return nullptr;
552 }
553 shaders.push_back(shader);
554 }
555 if (Operators::create(*(((BPy_UnaryPredicate1D *)obj1)->up1D), shaders) < 0) {
556 if (!PyErr_Occurred()) {
557 PyErr_SetString(PyExc_RuntimeError, "Operators.create() failed");
558 }
559 return nullptr;
560 }
561 Py_RETURN_NONE;
562}
563
565 /* Wrap. */
566 Operators_reset_doc,
567 ".. staticmethod:: reset(delete_strokes=True)\n"
568 "\n"
569 " Resets the line stylization process to the initial state. The results of\n"
570 " stroke creation are accumulated if **delete_strokes** is set to False.\n"
571 "\n"
572 " :arg delete_strokes: Delete the strokes that are currently stored.\n"
573 " :type delete_strokes: bool\n");
574static PyObject *Operators_reset(BPy_Operators * /*self*/, PyObject *args, PyObject *kwds)
575{
576 static const char *kwlist[] = {"delete_strokes", nullptr};
577 PyObject *obj1 = nullptr;
578 if (PyArg_ParseTupleAndKeywords(args, kwds, "|O!", (char **)kwlist, &PyBool_Type, &obj1)) {
579 // true is the default
580 Operators::reset(obj1 ? bool_from_PyBool(obj1) : true);
581 }
582 else {
583 PyErr_SetString(PyExc_RuntimeError, "Operators.reset() failed");
584 return nullptr;
585 }
586 Py_RETURN_NONE;
587}
588
590 /* Wrap. */
591 Operators_get_viewedge_from_index_doc,
592 ".. staticmethod:: get_viewedge_from_index(i)\n"
593 "\n"
594 " Returns the ViewEdge at the index in the current set of ViewEdges.\n"
595 "\n"
596 " :arg i: index (0 <= i < Operators.get_view_edges_size()).\n"
597 " :type i: int\n"
598 " :return: The ViewEdge object.\n"
599 " :rtype: :class:`ViewEdge`\n");
601 PyObject *args,
602 PyObject *kwds)
603{
604 static const char *kwlist[] = {"i", nullptr};
605 uint i;
606
607 if (!PyArg_ParseTupleAndKeywords(args, kwds, "I", (char **)kwlist, &i)) {
608 return nullptr;
609 }
611 PyErr_SetString(PyExc_IndexError, "index out of range");
612 return nullptr;
613 }
615}
616
618 /* Wrap. */
619 Operators_get_chain_from_index_doc,
620 ".. staticmethod:: get_chain_from_index(i)\n"
621 "\n"
622 " Returns the Chain at the index in the current set of Chains.\n"
623 "\n"
624 " :arg i: index (0 <= i < Operators.get_chains_size()).\n"
625 " :type i: int\n"
626 " :return: The Chain object.\n"
627 " :rtype: :class:`Chain`\n");
629 PyObject *args,
630 PyObject *kwds)
631{
632 static const char *kwlist[] = {"i", nullptr};
633 uint i;
634
635 if (!PyArg_ParseTupleAndKeywords(args, kwds, "I", (char **)kwlist, &i)) {
636 return nullptr;
637 }
638 if (i >= Operators::getChainsSize()) {
639 PyErr_SetString(PyExc_IndexError, "index out of range");
640 return nullptr;
641 }
643}
644
646 /* Wrap. */
647 Operators_get_stroke_from_index_doc,
648 ".. staticmethod:: get_stroke_from_index(i)\n"
649 "\n"
650 " Returns the Stroke at the index in the current set of Strokes.\n"
651 "\n"
652 " :arg i: index (0 <= i < Operators.get_strokes_size()).\n"
653 " :type i: int\n"
654 " :return: The Stroke object.\n"
655 " :rtype: :class:`Stroke`\n");
657 PyObject *args,
658 PyObject *kwds)
659{
660 static const char *kwlist[] = {"i", nullptr};
661 uint i;
662
663 if (!PyArg_ParseTupleAndKeywords(args, kwds, "I", (char **)kwlist, &i)) {
664 return nullptr;
665 }
666 if (i >= Operators::getStrokesSize()) {
667 PyErr_SetString(PyExc_IndexError, "index out of range");
668 return nullptr;
669 }
671}
672
674 /* Wrap. */
675 Operators_get_view_edges_size_doc,
676 ".. staticmethod:: get_view_edges_size()\n"
677 "\n"
678 " Returns the number of ViewEdges.\n"
679 "\n"
680 " :return: The number of ViewEdges.\n"
681 " :rtype: int\n");
683{
684 return PyLong_FromLong(Operators::getViewEdgesSize());
685}
686
688 /* Wrap. */
689 Operators_get_chains_size_doc,
690 ".. staticmethod:: get_chains_size()\n"
691 "\n"
692 " Returns the number of Chains.\n"
693 "\n"
694 " :return: The number of Chains.\n"
695 " :rtype: int\n");
696static PyObject *Operators_get_chains_size(BPy_Operators * /*self*/)
697{
698 return PyLong_FromLong(Operators::getChainsSize());
699}
700
702 /* Wrap. */
703 Operators_get_strokes_size_doc,
704 ".. staticmethod:: get_strokes_size()\n"
705 "\n"
706 " Returns the number of Strokes.\n"
707 "\n"
708 " :return: The number of Strokes.\n"
709 " :rtype: int\n");
710static PyObject *Operators_get_strokes_size(BPy_Operators * /*self*/)
711{
712 return PyLong_FromLong(Operators::getStrokesSize());
713}
714
715/*----------------------Operators instance definitions ----------------------------*/
716
717#ifdef __GNUC__
718# ifdef __clang__
719# pragma clang diagnostic push
720# pragma clang diagnostic ignored "-Wcast-function-type"
721# else
722# pragma GCC diagnostic push
723# pragma GCC diagnostic ignored "-Wcast-function-type"
724# endif
725#endif
726
727static PyMethodDef BPy_Operators_methods[] = {
728 {"select",
729 (PyCFunction)Operators_select,
730 METH_VARARGS | METH_KEYWORDS | METH_STATIC,
731 Operators_select_doc},
732 {"chain",
733 (PyCFunction)Operators_chain,
734 METH_VARARGS | METH_KEYWORDS | METH_STATIC,
735 Operators_chain_doc},
736 {"bidirectional_chain",
738 METH_VARARGS | METH_KEYWORDS | METH_STATIC,
739 Operators_bidirectional_chain_doc},
740 {"sequential_split",
741 (PyCFunction)Operators_sequential_split,
742 METH_VARARGS | METH_KEYWORDS | METH_STATIC,
743 Operators_sequential_split_doc},
744 {"recursive_split",
745 (PyCFunction)Operators_recursive_split,
746 METH_VARARGS | METH_KEYWORDS | METH_STATIC,
747 Operators_recursive_split_doc},
748 {"sort",
749 (PyCFunction)Operators_sort,
750 METH_VARARGS | METH_KEYWORDS | METH_STATIC,
751 Operators_sort_doc},
752 {"create",
753 (PyCFunction)Operators_create,
754 METH_VARARGS | METH_KEYWORDS | METH_STATIC,
755 Operators_create_doc},
756 {"reset",
757 (PyCFunction)Operators_reset,
758 METH_VARARGS | METH_KEYWORDS | METH_STATIC,
759 Operators_reset_doc},
760 {"get_viewedge_from_index",
762 METH_VARARGS | METH_KEYWORDS | METH_STATIC,
763 Operators_get_viewedge_from_index_doc},
764 {"get_chain_from_index",
766 METH_VARARGS | METH_KEYWORDS | METH_STATIC,
767 Operators_get_chain_from_index_doc},
768 {"get_stroke_from_index",
770 METH_VARARGS | METH_KEYWORDS | METH_STATIC,
771 Operators_get_stroke_from_index_doc},
772 {"get_view_edges_size",
774 METH_NOARGS | METH_STATIC,
775 Operators_get_view_edges_size_doc},
776 {"get_chains_size",
777 (PyCFunction)Operators_get_chains_size,
778 METH_NOARGS | METH_STATIC,
779 Operators_get_chains_size_doc},
780 {"get_strokes_size",
781 (PyCFunction)Operators_get_strokes_size,
782 METH_NOARGS | METH_STATIC,
783 Operators_get_strokes_size_doc},
784 {nullptr, nullptr, 0, nullptr},
785};
786
787#ifdef __GNUC__
788# ifdef __clang__
789# pragma clang diagnostic pop
790# else
791# pragma GCC diagnostic pop
792# endif
793#endif
794
795/*-----------------------BPy_Operators type definition ------------------------------*/
796
797PyTypeObject Operators_Type = {
798 /*ob_base*/ PyVarObject_HEAD_INIT(nullptr, 0)
799 /*tp_name*/ "Operators",
800 /*tp_basicsize*/ sizeof(BPy_Operators),
801 /*tp_itemsize*/ 0,
802 /*tp_dealloc*/ (destructor)Operators_dealloc,
803 /*tp_vectorcall_offset*/ 0,
804 /*tp_getattr*/ nullptr,
805 /*tp_setattr*/ nullptr,
806 /*tp_as_async*/ nullptr,
807 /*tp_repr*/ nullptr,
808 /*tp_as_number*/ nullptr,
809 /*tp_as_sequence*/ nullptr,
810 /*tp_as_mapping*/ nullptr,
811 /*tp_hash*/ nullptr,
812 /*tp_call*/ nullptr,
813 /*tp_str*/ nullptr,
814 /*tp_getattro*/ nullptr,
815 /*tp_setattro*/ nullptr,
816 /*tp_as_buffer*/ nullptr,
817 /*tp_flags*/ Py_TPFLAGS_DEFAULT,
818 /*tp_doc*/ Operators_doc,
819 /*tp_traverse*/ nullptr,
820 /*tp_clear*/ nullptr,
821 /*tp_richcompare*/ nullptr,
822 /*tp_weaklistoffset*/ 0,
823 /*tp_iter*/ nullptr,
824 /*tp_iternext*/ nullptr,
825 /*tp_methods*/ BPy_Operators_methods,
826 /*tp_members*/ nullptr,
827 /*tp_getset*/ nullptr,
828 /*tp_base*/ nullptr,
829 /*tp_dict*/ nullptr,
830 /*tp_descr_get*/ nullptr,
831 /*tp_descr_set*/ nullptr,
832 /*tp_dictoffset*/ 0,
833 /*tp_init*/ nullptr,
834 /*tp_alloc*/ nullptr,
835 /*tp_new*/ PyType_GenericNew,
836};
837
unsigned int uint
PyTypeObject BinaryPredicate1D_Type
PyTypeObject ChainingIterator_Type
bool bool_from_PyBool(PyObject *b)
PyObject * BPy_Chain_from_Chain(Chain &c)
PyObject * BPy_Stroke_from_Stroke(Stroke &s)
PyObject * BPy_ViewEdge_from_ViewEdge(ViewEdge &ve)
static PyObject * Operators_select(BPy_Operators *, PyObject *args, PyObject *kwds)
static PyMethodDef BPy_Operators_methods[]
static PyObject * Operators_reset(BPy_Operators *, PyObject *args, PyObject *kwds)
static PyObject * Operators_recursive_split(BPy_Operators *, PyObject *args, PyObject *kwds)
int Operators_Init(PyObject *module)
static PyObject * Operators_get_chain_from_index(BPy_Operators *, PyObject *args, PyObject *kwds)
static PyObject * Operators_get_stroke_from_index(BPy_Operators *, PyObject *args, PyObject *kwds)
static PyObject * Operators_sort(BPy_Operators *, PyObject *args, PyObject *kwds)
PyDoc_STRVAR(Operators_doc, "Class defining the operators used in a style module. There are five\n" "types of operators: Selection, chaining, splitting, sorting and\n" "creation. All these operators are user controlled through functors,\n" "predicates and shaders that are taken as arguments.\n")
static PyObject * Operators_sequential_split(BPy_Operators *, PyObject *args, PyObject *kwds)
static PyObject * Operators_get_view_edges_size(BPy_Operators *)
static PyObject * Operators_get_strokes_size(BPy_Operators *)
static PyObject * Operators_get_viewedge_from_index(BPy_Operators *, PyObject *args, PyObject *kwds)
static void Operators_dealloc(BPy_Operators *self)
static PyObject * Operators_get_chains_size(BPy_Operators *)
PyTypeObject Operators_Type
static PyObject * Operators_create(BPy_Operators *, PyObject *args, PyObject *kwds)
static PyObject * Operators_chain(BPy_Operators *, PyObject *args, PyObject *kwds)
static PyObject * Operators_bidirectional_chain(BPy_Operators *, PyObject *args, PyObject *kwds)
#define BPy_StrokeShader_Check(v)
PyTypeObject UnaryFunction0DDouble_Type
PyTypeObject UnaryFunction1DVoid_Type
PyTypeObject UnaryPredicate0D_Type
PyTypeObject UnaryPredicate1D_Type
PyObject * self
static int sort(BinaryPredicate1D &pred)
static ViewEdge * getViewEdgeFromIndex(uint i)
Definition Operators.h:220
static int select(UnaryPredicate1D &pred)
Definition Operators.cpp:30
static int chain(ViewEdgeInternal::ViewEdgeIterator &it, UnaryPredicate1D &pred, UnaryFunction1D_void &modifier)
Definition Operators.cpp:72
static void reset(bool removeStrokes=true)
static uint getChainsSize()
Definition Operators.h:240
static uint getViewEdgesSize()
Definition Operators.h:235
static uint getStrokesSize()
Definition Operators.h:245
static int sequentialSplit(UnaryPredicate0D &startingPred, UnaryPredicate0D &stoppingPred, float sampling=0.0f)
static int recursiveSplit(UnaryFunction0D< double > &func, UnaryPredicate1D &pred, float sampling=0)
static int bidirectionalChain(ChainingIterator &it, UnaryPredicate1D &pred)
static Stroke * getStrokeFromIndex(uint i)
Definition Operators.h:230
static int create(UnaryPredicate1D &pred, vector< StrokeShader * > shaders)
static Chain * getChainFromIndex(uint i)
Definition Operators.h:225
inherits from class Rep
Definition AppCanvas.cpp:20
static struct PyModuleDef module
Definition python.cpp:796
i
Definition text_draw.cc:230