Add Chromium-only Blender WebEngine parity work

This commit is contained in:
mes123456
2026-08-12 04:47:48 -04:00
commit 9fd26010f6
18225 changed files with 11622124 additions and 0 deletions

View File

@@ -0,0 +1,106 @@
/* SPDX-FileCopyrightText: 2004-2022 Blender Authors
*
* SPDX-License-Identifier: GPL-2.0-or-later */
/** \file
* \ingroup freestyle
*/
#include "BPy_BBox.h"
using namespace Freestyle;
using namespace Freestyle::Geometry;
///////////////////////////////////////////////////////////////////////////////////////////
//-------------------MODULE INITIALIZATION--------------------------------
int BBox_Init(PyObject *module)
{
if (module == nullptr) {
return -1;
}
if (PyType_Ready(&BBox_Type) < 0) {
return -1;
}
PyModule_AddObjectRef(module, "BBox", (PyObject *)&BBox_Type);
return 0;
}
//------------------------INSTANCE METHODS ----------------------------------
PyDoc_STRVAR(
/* Wrap. */
BBox_doc,
"Class for representing a bounding box.\n"
"\n"
".. method:: __init__()\n"
"\n"
" Default constructor.\n");
static int BBox_init(BPy_BBox *self, PyObject *args, PyObject *kwds)
{
static const char *kwlist[] = {nullptr};
if (!PyArg_ParseTupleAndKeywords(args, kwds, "", (char **)kwlist)) {
return -1;
}
self->bb = new BBox<Vec3r>();
return 0;
}
static void BBox_dealloc(BPy_BBox *self)
{
delete self->bb;
Py_TYPE(self)->tp_free((PyObject *)self);
}
static PyObject *BBox_repr(BPy_BBox *self)
{
return PyUnicode_FromFormat("BBox - address: %p", self->bb);
}
/*-----------------------BPy_BBox type definition ------------------------------*/
PyTypeObject BBox_Type = {
/*ob_base*/ PyVarObject_HEAD_INIT(nullptr, 0)
/*tp_name*/ "BBox",
/*tp_basicsize*/ sizeof(BPy_BBox),
/*tp_itemsize*/ 0,
/*tp_dealloc*/ (destructor)BBox_dealloc,
/*tp_vectorcall_offset*/ 0,
/*tp_getattr*/ nullptr,
/*tp_setattr*/ nullptr,
/*tp_as_async*/ nullptr,
/*tp_repr*/ (reprfunc)BBox_repr,
/*tp_as_number*/ nullptr,
/*tp_as_sequence*/ nullptr,
/*tp_as_mapping*/ nullptr,
/*tp_hash*/ nullptr,
/*tp_call*/ nullptr,
/*tp_str*/ nullptr,
/*tp_getattro*/ nullptr,
/*tp_setattro*/ nullptr,
/*tp_as_buffer*/ nullptr,
/*tp_flags*/ Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE,
/*tp_doc*/ BBox_doc,
/*tp_traverse*/ nullptr,
/*tp_clear*/ nullptr,
/*tp_richcompare*/ nullptr,
/*tp_weaklistoffset*/ 0,
/*tp_iter*/ nullptr,
/*tp_iternext*/ nullptr,
/*tp_methods*/ nullptr,
/*tp_members*/ nullptr,
/*tp_getset*/ nullptr,
/*tp_base*/ nullptr,
/*tp_dict*/ nullptr,
/*tp_descr_get*/ nullptr,
/*tp_descr_set*/ nullptr,
/*tp_dictoffset*/ 0,
/*tp_init*/ (initproc)BBox_init,
/*tp_alloc*/ nullptr,
/*tp_new*/ PyType_GenericNew,
};
///////////////////////////////////////////////////////////////////////////////////////////

View File

@@ -0,0 +1,34 @@
/* SPDX-FileCopyrightText: 2023 Blender Authors
*
* SPDX-License-Identifier: GPL-2.0-or-later */
/** \file
* \ingroup freestyle
*/
#pragma once
extern "C" {
#include <Python.h>
}
#include "../geometry/BBox.h"
#include "../geometry/Geom.h"
///////////////////////////////////////////////////////////////////////////////////////////
extern PyTypeObject BBox_Type;
#define BPy_BBox_Check(v) (PyObject_IsInstance((PyObject *)v, (PyObject *)&BBox_Type))
/*---------------------------Python BPy_BBox structure definition----------*/
struct BPy_BBox {
PyObject_HEAD
Freestyle::BBox<Freestyle::Geometry::Vec3r> *bb;
};
/*---------------------------Python BPy_BBox visible prototypes-----------*/
int BBox_Init(PyObject *module);
///////////////////////////////////////////////////////////////////////////////////////////

View File

@@ -0,0 +1,174 @@
/* SPDX-FileCopyrightText: 2004-2023 Blender Authors
*
* SPDX-License-Identifier: GPL-2.0-or-later */
/** \file
* \ingroup freestyle
*/
#include "BPy_BinaryPredicate0D.h"
#include "BPy_Convert.h"
#include "BPy_Interface0D.h"
using namespace Freestyle;
///////////////////////////////////////////////////////////////////////////////////////////
//-------------------MODULE INITIALIZATION--------------------------------
int BinaryPredicate0D_Init(PyObject *module)
{
if (module == nullptr) {
return -1;
}
if (PyType_Ready(&BinaryPredicate0D_Type) < 0) {
return -1;
}
PyModule_AddObjectRef(module, "BinaryPredicate0D", (PyObject *)&BinaryPredicate0D_Type);
return 0;
}
//------------------------INSTANCE METHODS ----------------------------------
PyDoc_STRVAR(
/* Wrap. */
BinaryPredicate0D___doc__,
"Base class for binary predicates working on :class:`Interface0D`\n"
"objects. A BinaryPredicate0D is typically an ordering relation\n"
"between two Interface0D objects. The predicate evaluates a relation\n"
"between the two Interface0D instances and returns a boolean value (true\n"
"or false). It is used by invoking the __call__() method.\n"
"\n"
".. method:: __init__()\n"
"\n"
" Default constructor.\n"
"\n"
".. method:: __call__(inter1, inter2)\n"
"\n"
" Must be overload by inherited classes. It evaluates a relation\n"
" between two Interface0D objects.\n"
"\n"
" :param inter1: The first Interface0D object.\n"
" :type inter1: :class:`Interface0D`\n"
" :param inter2: The second Interface0D object.\n"
" :type inter2: :class:`Interface0D`\n"
" :return: True or false.\n"
" :rtype: bool\n");
static int BinaryPredicate0D___init__(BPy_BinaryPredicate0D *self, PyObject *args, PyObject *kwds)
{
static const char *kwlist[] = {nullptr};
if (!PyArg_ParseTupleAndKeywords(args, kwds, "", (char **)kwlist)) {
return -1;
}
self->bp0D = new BinaryPredicate0D();
self->bp0D->py_bp0D = (PyObject *)self;
return 0;
}
static void BinaryPredicate0D___dealloc__(BPy_BinaryPredicate0D *self)
{
delete self->bp0D;
Py_TYPE(self)->tp_free((PyObject *)self);
}
static PyObject *BinaryPredicate0D___repr__(BPy_BinaryPredicate0D *self)
{
return PyUnicode_FromFormat("type: %s - address: %p", Py_TYPE(self)->tp_name, self->bp0D);
}
static PyObject *BinaryPredicate0D___call__(BPy_BinaryPredicate0D *self,
PyObject *args,
PyObject *kwds)
{
static const char *kwlist[] = {"inter1", "inter2", nullptr};
BPy_Interface0D *obj1, *obj2;
if (!PyArg_ParseTupleAndKeywords(
args, kwds, "O!O!", (char **)kwlist, &Interface0D_Type, &obj1, &Interface0D_Type, &obj2))
{
return nullptr;
}
if (typeid(*(self->bp0D)) == typeid(BinaryPredicate0D)) {
PyErr_SetString(PyExc_TypeError, "__call__ method not properly overridden");
return nullptr;
}
if (self->bp0D->operator()(*(obj1->if0D), *(obj2->if0D)) < 0) {
if (!PyErr_Occurred()) {
string class_name(Py_TYPE(self)->tp_name);
PyErr_SetString(PyExc_RuntimeError, (class_name + " __call__ method failed").c_str());
}
return nullptr;
}
return PyBool_from_bool(self->bp0D->result);
}
/*----------------------BinaryPredicate0D get/setters ----------------------------*/
PyDoc_STRVAR(
/* Wrap. */
BinaryPredicate0D_name_doc,
"The name of the binary 0D predicate.\n"
"\n"
":type: str\n");
static PyObject *BinaryPredicate0D_name_get(BPy_BinaryPredicate0D *self, void * /*closure*/)
{
return PyUnicode_FromString(Py_TYPE(self)->tp_name);
}
static PyGetSetDef BPy_BinaryPredicate0D_getseters[] = {
{"name",
(getter)BinaryPredicate0D_name_get,
(setter) nullptr,
BinaryPredicate0D_name_doc,
nullptr},
{nullptr, nullptr, nullptr, nullptr, nullptr} /* Sentinel */
};
/*-----------------------BPy_BinaryPredicate0D type definition ------------------------------*/
PyTypeObject BinaryPredicate0D_Type = {
/*ob_base*/ PyVarObject_HEAD_INIT(nullptr, 0)
/*tp_name*/ "BinaryPredicate0D",
/*tp_basicsize*/ sizeof(BPy_BinaryPredicate0D),
/*tp_itemsize*/ 0,
/*tp_dealloc*/ (destructor)BinaryPredicate0D___dealloc__,
/*tp_vectorcall_offset*/ 0,
/*tp_getattr*/ nullptr,
/*tp_setattr*/ nullptr,
/*tp_as_async*/ nullptr,
/*tp_repr*/ (reprfunc)BinaryPredicate0D___repr__,
/*tp_as_number*/ nullptr,
/*tp_as_sequence*/ nullptr,
/*tp_as_mapping*/ nullptr,
/*tp_hash*/ nullptr,
/*tp_call*/ (ternaryfunc)BinaryPredicate0D___call__,
/*tp_str*/ nullptr,
/*tp_getattro*/ nullptr,
/*tp_setattro*/ nullptr,
/*tp_as_buffer*/ nullptr,
/*tp_flags*/ Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE,
/*tp_doc*/ BinaryPredicate0D___doc__,
/*tp_traverse*/ nullptr,
/*tp_clear*/ nullptr,
/*tp_richcompare*/ nullptr,
/*tp_weaklistoffset*/ 0,
/*tp_iter*/ nullptr,
/*tp_iternext*/ nullptr,
/*tp_methods*/ nullptr,
/*tp_members*/ nullptr,
/*tp_getset*/ BPy_BinaryPredicate0D_getseters,
/*tp_base*/ nullptr,
/*tp_dict*/ nullptr,
/*tp_descr_get*/ nullptr,
/*tp_descr_set*/ nullptr,
/*tp_dictoffset*/ 0,
/*tp_init*/ (initproc)BinaryPredicate0D___init__,
/*tp_alloc*/ nullptr,
/*tp_new*/ PyType_GenericNew,
};
///////////////////////////////////////////////////////////////////////////////////////////

View File

@@ -0,0 +1,34 @@
/* SPDX-FileCopyrightText: 2023 Blender Authors
*
* SPDX-License-Identifier: GPL-2.0-or-later */
/** \file
* \ingroup freestyle
*/
#pragma once
extern "C" {
#include <Python.h>
}
#include "../stroke/Predicates0D.h"
///////////////////////////////////////////////////////////////////////////////////////////
extern PyTypeObject BinaryPredicate0D_Type;
#define BPy_BinaryPredicate0D_Check(v) \
(PyObject_IsInstance((PyObject *)v, (PyObject *)&BinaryPredicate0D_Type))
/*---------------------------Python BPy_BinaryPredicate0D structure definition----------*/
struct BPy_BinaryPredicate0D {
PyObject_HEAD
Freestyle::BinaryPredicate0D *bp0D;
};
/*---------------------------Python BPy_BinaryPredicate0D visible prototypes-----------*/
int BinaryPredicate0D_Init(PyObject *module);
///////////////////////////////////////////////////////////////////////////////////////////

View File

@@ -0,0 +1,205 @@
/* SPDX-FileCopyrightText: 2004-2023 Blender Authors
*
* SPDX-License-Identifier: GPL-2.0-or-later */
/** \file
* \ingroup freestyle
*/
#include "BPy_BinaryPredicate1D.h"
#include "BPy_Convert.h"
#include "BPy_Interface1D.h"
#include "BinaryPredicate1D/BPy_FalseBP1D.h"
#include "BinaryPredicate1D/BPy_Length2DBP1D.h"
#include "BinaryPredicate1D/BPy_SameShapeIdBP1D.h"
#include "BinaryPredicate1D/BPy_TrueBP1D.h"
#include "BinaryPredicate1D/BPy_ViewMapGradientNormBP1D.h"
using namespace Freestyle;
///////////////////////////////////////////////////////////////////////////////////////////
//-------------------MODULE INITIALIZATION--------------------------------
int BinaryPredicate1D_Init(PyObject *module)
{
if (module == nullptr) {
return -1;
}
if (PyType_Ready(&BinaryPredicate1D_Type) < 0) {
return -1;
}
PyModule_AddObjectRef(module, "BinaryPredicate1D", (PyObject *)&BinaryPredicate1D_Type);
if (PyType_Ready(&FalseBP1D_Type) < 0) {
return -1;
}
PyModule_AddObjectRef(module, "FalseBP1D", (PyObject *)&FalseBP1D_Type);
if (PyType_Ready(&Length2DBP1D_Type) < 0) {
return -1;
}
PyModule_AddObjectRef(module, "Length2DBP1D", (PyObject *)&Length2DBP1D_Type);
if (PyType_Ready(&SameShapeIdBP1D_Type) < 0) {
return -1;
}
PyModule_AddObjectRef(module, "SameShapeIdBP1D", (PyObject *)&SameShapeIdBP1D_Type);
if (PyType_Ready(&TrueBP1D_Type) < 0) {
return -1;
}
PyModule_AddObjectRef(module, "TrueBP1D", (PyObject *)&TrueBP1D_Type);
if (PyType_Ready(&ViewMapGradientNormBP1D_Type) < 0) {
return -1;
}
PyModule_AddObjectRef(
module, "ViewMapGradientNormBP1D", (PyObject *)&ViewMapGradientNormBP1D_Type);
return 0;
}
//------------------------INSTANCE METHODS ----------------------------------
PyDoc_STRVAR(
/* Wrap. */
BinaryPredicate1D___doc__,
"Base class for binary predicates working on :class:`Interface1D`\n"
"objects. A BinaryPredicate1D is typically an ordering relation\n"
"between two Interface1D objects. The predicate evaluates a relation\n"
"between the two Interface1D instances and returns a boolean value (true\n"
"or false). It is used by invoking the __call__() method.\n"
"\n"
".. method:: __init__()\n"
"\n"
" Default constructor.\n"
"\n"
".. method:: __call__(inter1, inter2)\n"
"\n"
" Must be overload by inherited classes. It evaluates a relation\n"
" between two Interface1D objects.\n"
"\n"
" :param inter1: The first Interface1D object.\n"
" :type inter1: :class:`Interface1D`\n"
" :param inter2: The second Interface1D object.\n"
" :type inter2: :class:`Interface1D`\n"
" :return: True or false.\n"
" :rtype: bool\n");
static int BinaryPredicate1D___init__(BPy_BinaryPredicate1D *self, PyObject *args, PyObject *kwds)
{
static const char *kwlist[] = {nullptr};
if (!PyArg_ParseTupleAndKeywords(args, kwds, "", (char **)kwlist)) {
return -1;
}
self->bp1D = new BinaryPredicate1D();
self->bp1D->py_bp1D = (PyObject *)self;
return 0;
}
static void BinaryPredicate1D___dealloc__(BPy_BinaryPredicate1D *self)
{
delete self->bp1D;
Py_TYPE(self)->tp_free((PyObject *)self);
}
static PyObject *BinaryPredicate1D___repr__(BPy_BinaryPredicate1D *self)
{
return PyUnicode_FromFormat("type: %s - address: %p", Py_TYPE(self)->tp_name, self->bp1D);
}
static PyObject *BinaryPredicate1D___call__(BPy_BinaryPredicate1D *self,
PyObject *args,
PyObject *kwds)
{
static const char *kwlist[] = {"inter1", "inter2", nullptr};
BPy_Interface1D *obj1, *obj2;
if (!PyArg_ParseTupleAndKeywords(
args, kwds, "O!O!", (char **)kwlist, &Interface1D_Type, &obj1, &Interface1D_Type, &obj2))
{
return nullptr;
}
if (typeid(*(self->bp1D)) == typeid(BinaryPredicate1D)) {
PyErr_SetString(PyExc_TypeError, "__call__ method not properly overridden");
return nullptr;
}
if (self->bp1D->operator()(*(obj1->if1D), *(obj2->if1D)) < 0) {
if (!PyErr_Occurred()) {
string class_name(Py_TYPE(self)->tp_name);
PyErr_SetString(PyExc_RuntimeError, (class_name + " __call__ method failed").c_str());
}
return nullptr;
}
return PyBool_from_bool(self->bp1D->result);
}
/*----------------------BinaryPredicate0D get/setters ----------------------------*/
PyDoc_STRVAR(
/* Wrap. */
BinaryPredicate1D_name_doc,
"The name of the binary 1D predicate.\n"
"\n"
":type: str\n");
static PyObject *BinaryPredicate1D_name_get(BPy_BinaryPredicate1D *self, void * /*closure*/)
{
return PyUnicode_FromString(Py_TYPE(self)->tp_name);
}
static PyGetSetDef BPy_BinaryPredicate1D_getseters[] = {
{"name",
(getter)BinaryPredicate1D_name_get,
(setter) nullptr,
BinaryPredicate1D_name_doc,
nullptr},
{nullptr, nullptr, nullptr, nullptr, nullptr} /* Sentinel */
};
/*-----------------------BPy_BinaryPredicate1D type definition ------------------------------*/
PyTypeObject BinaryPredicate1D_Type = {
/*ob_base*/ PyVarObject_HEAD_INIT(nullptr, 0)
/*tp_name*/ "BinaryPredicate1D",
/*tp_basicsize*/ sizeof(BPy_BinaryPredicate1D),
/*tp_itemsize*/ 0,
/*tp_dealloc*/ (destructor)BinaryPredicate1D___dealloc__,
/*tp_vectorcall_offset*/ 0,
/*tp_getattr*/ nullptr,
/*tp_setattr*/ nullptr,
/*tp_as_async*/ nullptr,
/*tp_repr*/ (reprfunc)BinaryPredicate1D___repr__,
/*tp_as_number*/ nullptr,
/*tp_as_sequence*/ nullptr,
/*tp_as_mapping*/ nullptr,
/*tp_hash*/ nullptr,
/*tp_call*/ (ternaryfunc)BinaryPredicate1D___call__,
/*tp_str*/ nullptr,
/*tp_getattro*/ nullptr,
/*tp_setattro*/ nullptr,
/*tp_as_buffer*/ nullptr,
/*tp_flags*/ Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE,
/*tp_doc*/ BinaryPredicate1D___doc__,
/*tp_traverse*/ nullptr,
/*tp_clear*/ nullptr,
/*tp_richcompare*/ nullptr,
/*tp_weaklistoffset*/ 0,
/*tp_iter*/ nullptr,
/*tp_iternext*/ nullptr,
/*tp_methods*/ nullptr,
/*tp_members*/ nullptr,
/*tp_getset*/ BPy_BinaryPredicate1D_getseters,
/*tp_base*/ nullptr,
/*tp_dict*/ nullptr,
/*tp_descr_get*/ nullptr,
/*tp_descr_set*/ nullptr,
/*tp_dictoffset*/ 0,
/*tp_init*/ (initproc)BinaryPredicate1D___init__,
/*tp_alloc*/ nullptr,
/*tp_new*/ PyType_GenericNew,
};
///////////////////////////////////////////////////////////////////////////////////////////

View File

@@ -0,0 +1,34 @@
/* SPDX-FileCopyrightText: 2023 Blender Authors
*
* SPDX-License-Identifier: GPL-2.0-or-later */
/** \file
* \ingroup freestyle
*/
#pragma once
extern "C" {
#include <Python.h>
}
#include "../stroke/Predicates1D.h"
///////////////////////////////////////////////////////////////////////////////////////////
extern PyTypeObject BinaryPredicate1D_Type;
#define BPy_BinaryPredicate1D_Check(v) \
(PyObject_IsInstance((PyObject *)v, (PyObject *)&BinaryPredicate1D_Type))
/*---------------------------Python BPy_BinaryPredicate1D structure definition----------*/
struct BPy_BinaryPredicate1D {
PyObject_HEAD
Freestyle::BinaryPredicate1D *bp1D;
};
/*---------------------------Python BPy_BinaryPredicate1D visible prototypes-----------*/
int BinaryPredicate1D_Init(PyObject *module);
///////////////////////////////////////////////////////////////////////////////////////////

View File

@@ -0,0 +1,342 @@
/* SPDX-FileCopyrightText: 2009-2023 Blender Authors
*
* SPDX-License-Identifier: GPL-2.0-or-later */
/** \file
* \ingroup freestyle
*/
#include "BPy_ContextFunctions.h"
#include "BPy_Convert.h"
#include "../stroke/ContextFunctions.h"
#include "BLI_sys_types.h"
using namespace Freestyle;
///////////////////////////////////////////////////////////////////////////////////////////
//------------------------ MODULE FUNCTIONS ----------------------------------
PyDoc_STRVAR(
/* Wrap. */
ContextFunctions_get_time_stamp___doc__,
".. function:: get_time_stamp()\n"
"\n"
" Returns the system time stamp.\n"
"\n"
" :return: The system time stamp.\n"
" :rtype: int\n");
static PyObject *ContextFunctions_get_time_stamp(PyObject * /*self*/)
{
return PyLong_FromLong(ContextFunctions::GetTimeStampCF());
}
PyDoc_STRVAR(
/* Wrap. */
ContextFunctions_get_canvas_width___doc__,
".. function:: get_canvas_width()\n"
"\n"
" Returns the canvas width.\n"
"\n"
" :return: The canvas width.\n"
" :rtype: int\n");
static PyObject *ContextFunctions_get_canvas_width(PyObject * /*self*/)
{
return PyLong_FromLong(ContextFunctions::GetCanvasWidthCF());
}
PyDoc_STRVAR(
/* Wrap. */
ContextFunctions_get_canvas_height___doc__,
".. function:: get_canvas_height()\n"
"\n"
" Returns the canvas height.\n"
"\n"
" :return: The canvas height.\n"
" :rtype: int\n");
static PyObject *ContextFunctions_get_canvas_height(PyObject * /*self*/)
{
return PyLong_FromLong(ContextFunctions::GetCanvasHeightCF());
}
PyDoc_STRVAR(
/* Wrap. */
ContextFunctions_get_border___doc__,
".. function:: get_border()\n"
"\n"
" Returns the border.\n"
"\n"
" :return: A tuple of 4 numbers (xmin, ymin, xmax, ymax).\n"
" :rtype: tuple[int, int, int, int]\n");
static PyObject *ContextFunctions_get_border(PyObject * /*self*/)
{
BBox<Vec2i> border(ContextFunctions::GetBorderCF());
PyObject *v = PyTuple_New(4);
PyTuple_SET_ITEMS(v,
PyLong_FromLong(border.getMin().x()),
PyLong_FromLong(border.getMin().y()),
PyLong_FromLong(border.getMax().x()),
PyLong_FromLong(border.getMax().y()));
return v;
}
PyDoc_STRVAR(
/* Wrap. */
ContextFunctions_load_map___doc__,
".. function:: load_map(file_name, map_name, num_levels=4, sigma=1.0)\n"
"\n"
" Loads an image map for further reading.\n"
"\n"
" :param file_name: The name of the image file.\n"
" :type file_name: str\n"
" :param map_name: The name that will be used to access this image.\n"
" :type map_name: str\n"
" :param num_levels: The number of levels in the map pyramid\n"
" (default = 4). If num_levels == 0, the complete pyramid is\n"
" built.\n"
" :type num_levels: int\n"
" :param sigma: The sigma value of the gaussian function.\n"
" :type sigma: float\n");
static PyObject *ContextFunctions_load_map(PyObject * /*self*/, PyObject *args, PyObject *kwds)
{
static const char *kwlist[] = {"file_name", "map_name", "num_levels", "sigma", nullptr};
char *fileName, *mapName;
uint nbLevels = 4;
float sigma = 1.0;
if (!PyArg_ParseTupleAndKeywords(
args, kwds, "ss|If", (char **)kwlist, &fileName, &mapName, &nbLevels, &sigma))
{
return nullptr;
}
ContextFunctions::LoadMapCF(fileName, mapName, nbLevels, sigma);
Py_RETURN_NONE;
}
PyDoc_STRVAR(
/* Wrap. */
ContextFunctions_read_map_pixel___doc__,
".. function:: read_map_pixel(map_name, level, x, y)\n"
"\n"
" Reads a pixel in a user-defined map.\n"
"\n"
" :param map_name: The name of the map.\n"
" :type map_name: str\n"
" :param level: The level of the pyramid in which we wish to read the\n"
" pixel.\n"
" :type level: int\n"
" :param x: The x coordinate of the pixel we wish to read. The origin\n"
" is in the lower-left corner.\n"
" :type x: int\n"
" :param y: The y coordinate of the pixel we wish to read. The origin\n"
" is in the lower-left corner.\n"
" :type y: int\n"
" :return: The floating-point value stored for that pixel.\n"
" :rtype: float\n");
static PyObject *ContextFunctions_read_map_pixel(PyObject * /*self*/,
PyObject *args,
PyObject *kwds)
{
static const char *kwlist[] = {"map_name", "level", "x", "y", nullptr};
char *mapName;
int level;
uint x, y;
if (!PyArg_ParseTupleAndKeywords(args, kwds, "siII", (char **)kwlist, &mapName, &level, &x, &y))
{
return nullptr;
}
return PyFloat_FromDouble(ContextFunctions::ReadMapPixelCF(mapName, level, x, y));
}
PyDoc_STRVAR(
/* Wrap. */
ContextFunctions_read_complete_view_map_pixel___doc__,
".. function:: read_complete_view_map_pixel(level, x, y)\n"
"\n"
" Reads a pixel in the complete view map.\n"
"\n"
" :param level: The level of the pyramid in which we wish to read the\n"
" pixel.\n"
" :type level: int\n"
" :param x: The x coordinate of the pixel we wish to read. The origin\n"
" is in the lower-left corner.\n"
" :type x: int\n"
" :param y: The y coordinate of the pixel we wish to read. The origin\n"
" is in the lower-left corner.\n"
" :type y: int\n"
" :return: The floating-point value stored for that pixel.\n"
" :rtype: float\n");
static PyObject *ContextFunctions_read_complete_view_map_pixel(PyObject * /*self*/,
PyObject *args,
PyObject *kwds)
{
static const char *kwlist[] = {"level", "x", "y", nullptr};
int level;
uint x, y;
if (!PyArg_ParseTupleAndKeywords(args, kwds, "iII", (char **)kwlist, &level, &x, &y)) {
return nullptr;
}
return PyFloat_FromDouble(ContextFunctions::ReadCompleteViewMapPixelCF(level, x, y));
}
PyDoc_STRVAR(
/* Wrap. */
ContextFunctions_read_directional_view_map_pixel___doc__,
".. function:: read_directional_view_map_pixel(orientation, level, x, y)\n"
"\n"
" Reads a pixel in one of the oriented view map images.\n"
"\n"
" :param orientation: The number telling which orientation we want to\n"
" check.\n"
" :type orientation: int\n"
" :param level: The level of the pyramid in which we wish to read the\n"
" pixel.\n"
" :type level: int\n"
" :param x: The x coordinate of the pixel we wish to read. The origin\n"
" is in the lower-left corner.\n"
" :type x: int\n"
" :param y: The y coordinate of the pixel we wish to read. The origin\n"
" is in the lower-left corner.\n"
" :type y: int\n"
" :return: The floating-point value stored for that pixel.\n"
" :rtype: float\n");
static PyObject *ContextFunctions_read_directional_view_map_pixel(PyObject * /*self*/,
PyObject *args,
PyObject *kwds)
{
static const char *kwlist[] = {"orientation", "level", "x", "y", nullptr};
int orientation, level;
uint x, y;
if (!PyArg_ParseTupleAndKeywords(
args, kwds, "iiII", (char **)kwlist, &orientation, &level, &x, &y))
{
return nullptr;
}
return PyFloat_FromDouble(
ContextFunctions::ReadDirectionalViewMapPixelCF(orientation, level, x, y));
}
PyDoc_STRVAR(
/* Wrap. */
ContextFunctions_get_selected_fedge___doc__,
".. function:: get_selected_fedge()\n"
"\n"
" Returns the selected FEdge.\n"
"\n"
" :return: The selected FEdge.\n"
" :rtype: :class:`FEdge`\n");
static PyObject *ContextFunctions_get_selected_fedge(PyObject * /*self*/)
{
FEdge *fe = ContextFunctions::GetSelectedFEdgeCF();
if (fe) {
return Any_BPy_FEdge_from_FEdge(*fe);
}
Py_RETURN_NONE;
}
/*-----------------------ContextFunctions module docstring-------------------------------*/
PyDoc_STRVAR(
/* Wrap. */
module_docstring,
"The Blender Freestyle.ContextFunctions submodule\n"
"\n");
/*-----------------------ContextFunctions module functions definitions-------------------*/
#ifdef __GNUC__
# ifdef __clang__
# pragma clang diagnostic push
# pragma clang diagnostic ignored "-Wcast-function-type"
# else
# pragma GCC diagnostic push
# pragma GCC diagnostic ignored "-Wcast-function-type"
# endif
#endif
static PyMethodDef module_functions[] = {
{"get_time_stamp",
(PyCFunction)ContextFunctions_get_time_stamp,
METH_NOARGS,
ContextFunctions_get_time_stamp___doc__},
{"get_canvas_width",
(PyCFunction)ContextFunctions_get_canvas_width,
METH_NOARGS,
ContextFunctions_get_canvas_width___doc__},
{"get_canvas_height",
(PyCFunction)ContextFunctions_get_canvas_height,
METH_NOARGS,
ContextFunctions_get_canvas_height___doc__},
{"get_border",
(PyCFunction)ContextFunctions_get_border,
METH_NOARGS,
ContextFunctions_get_border___doc__},
{"load_map",
(PyCFunction)ContextFunctions_load_map,
METH_VARARGS | METH_KEYWORDS,
ContextFunctions_load_map___doc__},
{"read_map_pixel",
(PyCFunction)ContextFunctions_read_map_pixel,
METH_VARARGS | METH_KEYWORDS,
ContextFunctions_read_map_pixel___doc__},
{"read_complete_view_map_pixel",
(PyCFunction)ContextFunctions_read_complete_view_map_pixel,
METH_VARARGS | METH_KEYWORDS,
ContextFunctions_read_complete_view_map_pixel___doc__},
{"read_directional_view_map_pixel",
(PyCFunction)ContextFunctions_read_directional_view_map_pixel,
METH_VARARGS | METH_KEYWORDS,
ContextFunctions_read_directional_view_map_pixel___doc__},
{"get_selected_fedge",
(PyCFunction)ContextFunctions_get_selected_fedge,
METH_NOARGS,
ContextFunctions_get_selected_fedge___doc__},
{nullptr, nullptr, 0, nullptr},
};
#ifdef __GNUC__
# ifdef __clang__
# pragma clang diagnostic pop
# else
# pragma GCC diagnostic pop
# endif
#endif
/*-----------------------ContextFunctions module definition--------------------------------*/
static PyModuleDef module_definition = {
/*m_base*/ PyModuleDef_HEAD_INIT,
/*m_name*/ "Freestyle.ContextFunctions",
/*m_doc*/ module_docstring,
/*m_size*/ -1,
/*m_methods*/ module_functions,
/*m_slots*/ nullptr,
/*m_traverse*/ nullptr,
/*m_clear*/ nullptr,
/*m_free*/ nullptr,
};
//------------------- MODULE INITIALIZATION --------------------------------
int ContextFunctions_Init(PyObject *module)
{
PyObject *m;
if (module == nullptr) {
return -1;
}
m = PyModule_Create(&module_definition);
if (m == nullptr) {
return -1;
}
PyModule_AddObjectRef(module, "ContextFunctions", m);
return 0;
}
///////////////////////////////////////////////////////////////////////////////////////////

View File

@@ -0,0 +1,17 @@
/* SPDX-FileCopyrightText: 2023 Blender Authors
*
* SPDX-License-Identifier: GPL-2.0-or-later */
/** \file
* \ingroup freestyle
*/
#pragma once
extern "C" {
#include <Python.h>
}
/*---------------------------Python BPy_ContextFunctions visible prototypes-----------*/
int ContextFunctions_Init(PyObject *module);

View File

@@ -0,0 +1,825 @@
/* SPDX-FileCopyrightText: 2008-2023 Blender Authors
*
* SPDX-License-Identifier: GPL-2.0-or-later */
/** \file
* \ingroup freestyle
*/
#include "BPy_Convert.h"
#include "BPy_BBox.h"
#include "BPy_FrsMaterial.h"
#include "BPy_Id.h"
#include "BPy_IntegrationType.h"
#include "BPy_Interface0D.h"
#include "BPy_Interface1D.h"
#include "BPy_MediumType.h"
#include "BPy_Nature.h"
#include "BPy_SShape.h"
#include "BPy_StrokeAttribute.h"
#include "BPy_ViewShape.h"
#include "Interface0D/BPy_CurvePoint.h"
#include "Interface0D/BPy_SVertex.h"
#include "Interface0D/BPy_ViewVertex.h"
#include "Interface0D/CurvePoint/BPy_StrokeVertex.h"
#include "Interface0D/ViewVertex/BPy_NonTVertex.h"
#include "Interface0D/ViewVertex/BPy_TVertex.h"
#include "Interface1D/BPy_FEdge.h"
#include "Interface1D/BPy_Stroke.h"
#include "Interface1D/BPy_ViewEdge.h"
#include "Interface1D/Curve/BPy_Chain.h"
#include "Interface1D/FEdge/BPy_FEdgeSharp.h"
#include "Interface1D/FEdge/BPy_FEdgeSmooth.h"
#include "Iterator/BPy_AdjacencyIterator.h"
#include "Iterator/BPy_ChainPredicateIterator.h"
#include "Iterator/BPy_ChainSilhouetteIterator.h"
#include "Iterator/BPy_ChainingIterator.h"
#include "Iterator/BPy_CurvePointIterator.h"
#include "Iterator/BPy_Interface0DIterator.h"
#include "Iterator/BPy_SVertexIterator.h"
#include "Iterator/BPy_StrokeVertexIterator.h"
#include "Iterator/BPy_ViewEdgeIterator.h"
#include "Iterator/BPy_orientedViewEdgeIterator.h"
#include "../stroke/StrokeRep.h"
using namespace Freestyle;
using namespace Freestyle::Geometry;
///////////////////////////////////////////////////////////////////////////////////////////
//==============================
// C++ => Python
//==============================
PyObject *PyBool_from_bool(bool b)
{
return PyBool_FromLong(b ? 1 : 0);
}
PyObject *PyLong_subtype_new(PyTypeObject *ty, long value)
{
BLI_assert(ty->tp_basicsize == sizeof(PyLongObject));
PyLongObject *result = PyObject_NewVar(PyLongObject, ty, 1);
PyLongObject *value_py = (PyLongObject *)PyLong_FromLong(value);
memcpy(&result->long_value, &value_py->long_value, sizeof(result->long_value));
Py_DECREF(value_py);
return (PyObject *)result;
}
void PyLong_subtype_add_to_dict(PyObject *dict, PyTypeObject *ty, const char *attr, long value)
{
PyObject *result = PyLong_subtype_new(ty, value);
PyDict_SetItemString(dict, attr, result);
/* Owned by the dictionary. */
Py_DECREF(result);
}
PyObject *Vector_from_Vec2f(Vec2f &vec)
{
float vec_data[2]; // because vec->_coord is protected
vec_data[0] = vec.x();
vec_data[1] = vec.y();
return blender::Vector_CreatePyObject(vec_data, 2, nullptr);
}
PyObject *Vector_from_Vec3f(Vec3f &vec)
{
float vec_data[3]; // because vec->_coord is protected
vec_data[0] = vec.x();
vec_data[1] = vec.y();
vec_data[2] = vec.z();
return blender::Vector_CreatePyObject(vec_data, 3, nullptr);
}
PyObject *Vector_from_Vec3r(Vec3r &vec)
{
float vec_data[3]; // because vec->_coord is protected
vec_data[0] = vec.x();
vec_data[1] = vec.y();
vec_data[2] = vec.z();
return blender::Vector_CreatePyObject(vec_data, 3, nullptr);
}
PyObject *BPy_Id_from_Id(Id &id)
{
PyObject *py_id = Id_Type.tp_new(&Id_Type, nullptr, nullptr);
((BPy_Id *)py_id)->id = new Id(id.getFirst(), id.getSecond());
return py_id;
}
PyObject *Any_BPy_Interface0D_from_Interface0D(Interface0D &if0D)
{
if (typeid(if0D) == typeid(CurvePoint)) {
return BPy_CurvePoint_from_CurvePoint(dynamic_cast<CurvePoint &>(if0D));
}
if (typeid(if0D) == typeid(StrokeVertex)) {
return BPy_StrokeVertex_from_StrokeVertex(dynamic_cast<StrokeVertex &>(if0D));
}
if (typeid(if0D) == typeid(SVertex)) {
return BPy_SVertex_from_SVertex(dynamic_cast<SVertex &>(if0D));
}
if (typeid(if0D) == typeid(ViewVertex)) {
return BPy_ViewVertex_from_ViewVertex(dynamic_cast<ViewVertex &>(if0D));
}
if (typeid(if0D) == typeid(NonTVertex)) {
return BPy_NonTVertex_from_NonTVertex(dynamic_cast<NonTVertex &>(if0D));
}
if (typeid(if0D) == typeid(TVertex)) {
return BPy_TVertex_from_TVertex(dynamic_cast<TVertex &>(if0D));
}
if (typeid(if0D) == typeid(Interface0D)) {
return BPy_Interface0D_from_Interface0D(if0D);
}
string msg("unexpected type: " + if0D.getExactTypeName());
PyErr_SetString(PyExc_TypeError, msg.c_str());
return nullptr;
}
PyObject *Any_BPy_Interface1D_from_Interface1D(Interface1D &if1D)
{
if (typeid(if1D) == typeid(ViewEdge)) {
return BPy_ViewEdge_from_ViewEdge(dynamic_cast<ViewEdge &>(if1D));
}
if (typeid(if1D) == typeid(Chain)) {
return BPy_Chain_from_Chain(dynamic_cast<Chain &>(if1D));
}
if (typeid(if1D) == typeid(Stroke)) {
return BPy_Stroke_from_Stroke(dynamic_cast<Stroke &>(if1D));
}
if (typeid(if1D) == typeid(FEdgeSharp)) {
return BPy_FEdgeSharp_from_FEdgeSharp(dynamic_cast<FEdgeSharp &>(if1D));
}
if (typeid(if1D) == typeid(FEdgeSmooth)) {
return BPy_FEdgeSmooth_from_FEdgeSmooth(dynamic_cast<FEdgeSmooth &>(if1D));
}
if (typeid(if1D) == typeid(FEdge)) {
return BPy_FEdge_from_FEdge(dynamic_cast<FEdge &>(if1D));
}
if (typeid(if1D) == typeid(Interface1D)) {
return BPy_Interface1D_from_Interface1D(if1D);
}
string msg("unexpected type: " + if1D.getExactTypeName());
PyErr_SetString(PyExc_TypeError, msg.c_str());
return nullptr;
}
PyObject *Any_BPy_FEdge_from_FEdge(FEdge &fe)
{
if (typeid(fe) == typeid(FEdgeSharp)) {
return BPy_FEdgeSharp_from_FEdgeSharp(dynamic_cast<FEdgeSharp &>(fe));
}
if (typeid(fe) == typeid(FEdgeSmooth)) {
return BPy_FEdgeSmooth_from_FEdgeSmooth(dynamic_cast<FEdgeSmooth &>(fe));
}
if (typeid(fe) == typeid(FEdge)) {
return BPy_FEdge_from_FEdge(fe);
}
string msg("unexpected type: " + fe.getExactTypeName());
PyErr_SetString(PyExc_TypeError, msg.c_str());
return nullptr;
}
PyObject *Any_BPy_ViewVertex_from_ViewVertex(ViewVertex &vv)
{
if (typeid(vv) == typeid(NonTVertex)) {
return BPy_NonTVertex_from_NonTVertex(dynamic_cast<NonTVertex &>(vv));
}
if (typeid(vv) == typeid(TVertex)) {
return BPy_TVertex_from_TVertex(dynamic_cast<TVertex &>(vv));
}
if (typeid(vv) == typeid(ViewVertex)) {
return BPy_ViewVertex_from_ViewVertex(vv);
}
string msg("unexpected type: " + vv.getExactTypeName());
PyErr_SetString(PyExc_TypeError, msg.c_str());
return nullptr;
}
PyObject *BPy_Interface0D_from_Interface0D(Interface0D &if0D)
{
PyObject *py_if0D = Interface0D_Type.tp_new(&Interface0D_Type, nullptr, nullptr);
((BPy_Interface0D *)py_if0D)->if0D = &if0D;
((BPy_Interface0D *)py_if0D)->borrowed = true;
return py_if0D;
}
PyObject *BPy_Interface1D_from_Interface1D(Interface1D &if1D)
{
PyObject *py_if1D = Interface1D_Type.tp_new(&Interface1D_Type, nullptr, nullptr);
((BPy_Interface1D *)py_if1D)->if1D = &if1D;
((BPy_Interface1D *)py_if1D)->borrowed = true;
return py_if1D;
}
PyObject *BPy_SVertex_from_SVertex(SVertex &sv)
{
PyObject *py_sv = SVertex_Type.tp_new(&SVertex_Type, nullptr, nullptr);
((BPy_SVertex *)py_sv)->sv = &sv;
((BPy_SVertex *)py_sv)->py_if0D.if0D = ((BPy_SVertex *)py_sv)->sv;
((BPy_SVertex *)py_sv)->py_if0D.borrowed = true;
return py_sv;
}
PyObject *BPy_FEdgeSharp_from_FEdgeSharp(FEdgeSharp &fes)
{
PyObject *py_fe = FEdgeSharp_Type.tp_new(&FEdgeSharp_Type, nullptr, nullptr);
((BPy_FEdgeSharp *)py_fe)->fes = &fes;
((BPy_FEdgeSharp *)py_fe)->py_fe.fe = ((BPy_FEdgeSharp *)py_fe)->fes;
((BPy_FEdgeSharp *)py_fe)->py_fe.py_if1D.if1D = ((BPy_FEdgeSharp *)py_fe)->fes;
((BPy_FEdgeSharp *)py_fe)->py_fe.py_if1D.borrowed = true;
return py_fe;
}
PyObject *BPy_FEdgeSmooth_from_FEdgeSmooth(FEdgeSmooth &fes)
{
PyObject *py_fe = FEdgeSmooth_Type.tp_new(&FEdgeSmooth_Type, nullptr, nullptr);
((BPy_FEdgeSmooth *)py_fe)->fes = &fes;
((BPy_FEdgeSmooth *)py_fe)->py_fe.fe = ((BPy_FEdgeSmooth *)py_fe)->fes;
((BPy_FEdgeSmooth *)py_fe)->py_fe.py_if1D.if1D = ((BPy_FEdgeSmooth *)py_fe)->fes;
((BPy_FEdgeSmooth *)py_fe)->py_fe.py_if1D.borrowed = true;
return py_fe;
}
PyObject *BPy_FEdge_from_FEdge(FEdge &fe)
{
PyObject *py_fe = FEdge_Type.tp_new(&FEdge_Type, nullptr, nullptr);
((BPy_FEdge *)py_fe)->fe = &fe;
((BPy_FEdge *)py_fe)->py_if1D.if1D = ((BPy_FEdge *)py_fe)->fe;
((BPy_FEdge *)py_fe)->py_if1D.borrowed = true;
return py_fe;
}
PyObject *BPy_Nature_from_Nature(ushort n)
{
PyObject *args = PyTuple_New(1);
PyTuple_SET_ITEM(args, 0, PyLong_FromLong(n));
PyObject *py_n = Nature_Type.tp_new(&Nature_Type, args, nullptr);
Py_DECREF(args);
return py_n;
}
PyObject *BPy_Stroke_from_Stroke(Stroke &s)
{
PyObject *py_s = Stroke_Type.tp_new(&Stroke_Type, nullptr, nullptr);
((BPy_Stroke *)py_s)->s = &s;
((BPy_Stroke *)py_s)->py_if1D.if1D = ((BPy_Stroke *)py_s)->s;
((BPy_Stroke *)py_s)->py_if1D.borrowed = true;
return py_s;
}
PyObject *BPy_StrokeAttribute_from_StrokeAttribute(StrokeAttribute &sa)
{
PyObject *py_sa = StrokeAttribute_Type.tp_new(&StrokeAttribute_Type, nullptr, nullptr);
((BPy_StrokeAttribute *)py_sa)->sa = &sa;
((BPy_StrokeAttribute *)py_sa)->borrowed = true;
return py_sa;
}
PyObject *BPy_MediumType_from_MediumType(Stroke::MediumType n)
{
PyObject *args = PyTuple_New(1);
PyTuple_SET_ITEM(args, 0, PyLong_FromLong(n));
PyObject *py_mt = MediumType_Type.tp_new(&MediumType_Type, args, nullptr);
Py_DECREF(args);
return py_mt;
}
PyObject *BPy_StrokeVertex_from_StrokeVertex(StrokeVertex &sv)
{
PyObject *py_sv = StrokeVertex_Type.tp_new(&StrokeVertex_Type, nullptr, nullptr);
((BPy_StrokeVertex *)py_sv)->sv = &sv;
((BPy_StrokeVertex *)py_sv)->py_cp.cp = ((BPy_StrokeVertex *)py_sv)->sv;
((BPy_StrokeVertex *)py_sv)->py_cp.py_if0D.if0D = ((BPy_StrokeVertex *)py_sv)->sv;
((BPy_StrokeVertex *)py_sv)->py_cp.py_if0D.borrowed = true;
return py_sv;
}
PyObject *BPy_ViewVertex_from_ViewVertex(ViewVertex &vv)
{
PyObject *py_vv = ViewVertex_Type.tp_new(&ViewVertex_Type, nullptr, nullptr);
((BPy_ViewVertex *)py_vv)->vv = &vv;
((BPy_ViewVertex *)py_vv)->py_if0D.if0D = ((BPy_ViewVertex *)py_vv)->vv;
((BPy_ViewVertex *)py_vv)->py_if0D.borrowed = true;
return py_vv;
}
PyObject *BPy_NonTVertex_from_NonTVertex(NonTVertex &ntv)
{
PyObject *py_ntv = NonTVertex_Type.tp_new(&NonTVertex_Type, nullptr, nullptr);
((BPy_NonTVertex *)py_ntv)->ntv = &ntv;
((BPy_NonTVertex *)py_ntv)->py_vv.vv = ((BPy_NonTVertex *)py_ntv)->ntv;
((BPy_NonTVertex *)py_ntv)->py_vv.py_if0D.if0D = ((BPy_NonTVertex *)py_ntv)->ntv;
((BPy_NonTVertex *)py_ntv)->py_vv.py_if0D.borrowed = true;
return py_ntv;
}
PyObject *BPy_TVertex_from_TVertex(TVertex &tv)
{
PyObject *py_tv = TVertex_Type.tp_new(&TVertex_Type, nullptr, nullptr);
((BPy_TVertex *)py_tv)->tv = &tv;
((BPy_TVertex *)py_tv)->py_vv.vv = ((BPy_TVertex *)py_tv)->tv;
((BPy_TVertex *)py_tv)->py_vv.py_if0D.if0D = ((BPy_TVertex *)py_tv)->tv;
((BPy_TVertex *)py_tv)->py_vv.py_if0D.borrowed = true;
return py_tv;
}
PyObject *BPy_BBox_from_BBox(const BBox<Vec3r> &bb)
{
PyObject *py_bb = BBox_Type.tp_new(&BBox_Type, nullptr, nullptr);
((BPy_BBox *)py_bb)->bb = new BBox<Vec3r>(bb);
return py_bb;
}
PyObject *BPy_ViewEdge_from_ViewEdge(ViewEdge &ve)
{
PyObject *py_ve = ViewEdge_Type.tp_new(&ViewEdge_Type, nullptr, nullptr);
((BPy_ViewEdge *)py_ve)->ve = &ve;
((BPy_ViewEdge *)py_ve)->py_if1D.if1D = ((BPy_ViewEdge *)py_ve)->ve;
((BPy_ViewEdge *)py_ve)->py_if1D.borrowed = true;
return py_ve;
}
PyObject *BPy_Chain_from_Chain(Chain &c)
{
PyObject *py_c = Chain_Type.tp_new(&Chain_Type, nullptr, nullptr);
((BPy_Chain *)py_c)->c = &c;
((BPy_Chain *)py_c)->py_c.c = ((BPy_Chain *)py_c)->c;
((BPy_Chain *)py_c)->py_c.py_if1D.if1D = ((BPy_Chain *)py_c)->c;
((BPy_Chain *)py_c)->py_c.py_if1D.borrowed = true;
return py_c;
}
PyObject *BPy_SShape_from_SShape(SShape &ss)
{
PyObject *py_ss = SShape_Type.tp_new(&SShape_Type, nullptr, nullptr);
((BPy_SShape *)py_ss)->ss = &ss;
((BPy_SShape *)py_ss)->borrowed = true;
return py_ss;
}
PyObject *BPy_ViewShape_from_ViewShape(ViewShape &vs)
{
PyObject *py_vs = ViewShape_Type.tp_new(&ViewShape_Type, nullptr, nullptr);
((BPy_ViewShape *)py_vs)->vs = &vs;
((BPy_ViewShape *)py_vs)->borrowed = true;
((BPy_ViewShape *)py_vs)->py_ss = nullptr;
return py_vs;
}
PyObject *BPy_FrsMaterial_from_FrsMaterial(const FrsMaterial &m)
{
PyObject *py_m = FrsMaterial_Type.tp_new(&FrsMaterial_Type, nullptr, nullptr);
((BPy_FrsMaterial *)py_m)->m = new FrsMaterial(m);
return py_m;
}
PyObject *BPy_IntegrationType_from_IntegrationType(IntegrationType i)
{
PyObject *args = PyTuple_New(1);
PyTuple_SET_ITEM(args, 0, PyLong_FromLong(i));
PyObject *py_it = IntegrationType_Type.tp_new(&IntegrationType_Type, args, nullptr);
Py_DECREF(args);
return py_it;
}
PyObject *BPy_CurvePoint_from_CurvePoint(CurvePoint &cp)
{
PyObject *py_cp = CurvePoint_Type.tp_new(&CurvePoint_Type, nullptr, nullptr);
// CurvePointIterator::operator*() returns a reference of a class data
// member whose value is mutable upon iteration over different CurvePoints.
// It is likely that such a mutable reference is passed to this function,
// so that a new allocated CurvePoint instance is created here to avoid
// nasty bugs (cf. #41464).
((BPy_CurvePoint *)py_cp)->cp = new CurvePoint(cp);
((BPy_CurvePoint *)py_cp)->py_if0D.if0D = ((BPy_CurvePoint *)py_cp)->cp;
((BPy_CurvePoint *)py_cp)->py_if0D.borrowed = false;
return py_cp;
}
PyObject *BPy_directedViewEdge_from_directedViewEdge(ViewVertex::directedViewEdge &dve)
{
PyObject *py_dve = PyTuple_New(2);
PyTuple_SET_ITEMS(
py_dve, BPy_ViewEdge_from_ViewEdge(*(dve.first)), PyBool_from_bool(dve.second));
return py_dve;
}
//==============================
// Iterators
//==============================
PyObject *BPy_AdjacencyIterator_from_AdjacencyIterator(AdjacencyIterator &a_it)
{
PyObject *py_a_it = AdjacencyIterator_Type.tp_new(&AdjacencyIterator_Type, nullptr, nullptr);
((BPy_AdjacencyIterator *)py_a_it)->a_it = new AdjacencyIterator(a_it);
((BPy_AdjacencyIterator *)py_a_it)->py_it.it = ((BPy_AdjacencyIterator *)py_a_it)->a_it;
((BPy_AdjacencyIterator *)py_a_it)->at_start = true;
return py_a_it;
}
PyObject *BPy_Interface0DIterator_from_Interface0DIterator(Interface0DIterator &if0D_it,
bool reversed)
{
PyObject *py_if0D_it = Interface0DIterator_Type.tp_new(
&Interface0DIterator_Type, nullptr, nullptr);
((BPy_Interface0DIterator *)py_if0D_it)->if0D_it = new Interface0DIterator(if0D_it);
((BPy_Interface0DIterator *)py_if0D_it)->py_it.it =
((BPy_Interface0DIterator *)py_if0D_it)->if0D_it;
((BPy_Interface0DIterator *)py_if0D_it)->at_start = true;
((BPy_Interface0DIterator *)py_if0D_it)->reversed = reversed;
return py_if0D_it;
}
PyObject *BPy_CurvePointIterator_from_CurvePointIterator(CurveInternal::CurvePointIterator &cp_it)
{
PyObject *py_cp_it = CurvePointIterator_Type.tp_new(&CurvePointIterator_Type, nullptr, nullptr);
((BPy_CurvePointIterator *)py_cp_it)->cp_it = new CurveInternal::CurvePointIterator(cp_it);
((BPy_CurvePointIterator *)py_cp_it)->py_it.it = ((BPy_CurvePointIterator *)py_cp_it)->cp_it;
return py_cp_it;
}
PyObject *BPy_StrokeVertexIterator_from_StrokeVertexIterator(
StrokeInternal::StrokeVertexIterator &sv_it, bool reversed)
{
PyObject *py_sv_it = StrokeVertexIterator_Type.tp_new(
&StrokeVertexIterator_Type, nullptr, nullptr);
((BPy_StrokeVertexIterator *)py_sv_it)->sv_it = new StrokeInternal::StrokeVertexIterator(sv_it);
((BPy_StrokeVertexIterator *)py_sv_it)->py_it.it = ((BPy_StrokeVertexIterator *)py_sv_it)->sv_it;
((BPy_StrokeVertexIterator *)py_sv_it)->at_start = true;
((BPy_StrokeVertexIterator *)py_sv_it)->reversed = reversed;
return py_sv_it;
}
PyObject *BPy_SVertexIterator_from_SVertexIterator(ViewEdgeInternal::SVertexIterator &sv_it)
{
PyObject *py_sv_it = SVertexIterator_Type.tp_new(&SVertexIterator_Type, nullptr, nullptr);
((BPy_SVertexIterator *)py_sv_it)->sv_it = new ViewEdgeInternal::SVertexIterator(sv_it);
((BPy_SVertexIterator *)py_sv_it)->py_it.it = ((BPy_SVertexIterator *)py_sv_it)->sv_it;
return py_sv_it;
}
PyObject *BPy_orientedViewEdgeIterator_from_orientedViewEdgeIterator(
ViewVertexInternal::orientedViewEdgeIterator &ove_it, bool reversed)
{
PyObject *py_ove_it = orientedViewEdgeIterator_Type.tp_new(
&orientedViewEdgeIterator_Type, nullptr, nullptr);
((BPy_orientedViewEdgeIterator *)py_ove_it)->ove_it =
new ViewVertexInternal::orientedViewEdgeIterator(ove_it);
((BPy_orientedViewEdgeIterator *)py_ove_it)->py_it.it =
((BPy_orientedViewEdgeIterator *)py_ove_it)->ove_it;
((BPy_orientedViewEdgeIterator *)py_ove_it)->at_start = true;
((BPy_orientedViewEdgeIterator *)py_ove_it)->reversed = reversed;
return py_ove_it;
}
PyObject *BPy_ViewEdgeIterator_from_ViewEdgeIterator(ViewEdgeInternal::ViewEdgeIterator &ve_it)
{
PyObject *py_ve_it = ViewEdgeIterator_Type.tp_new(&ViewEdgeIterator_Type, nullptr, nullptr);
((BPy_ViewEdgeIterator *)py_ve_it)->ve_it = new ViewEdgeInternal::ViewEdgeIterator(ve_it);
((BPy_ViewEdgeIterator *)py_ve_it)->py_it.it = ((BPy_ViewEdgeIterator *)py_ve_it)->ve_it;
return py_ve_it;
}
PyObject *BPy_ChainingIterator_from_ChainingIterator(ChainingIterator &c_it)
{
PyObject *py_c_it = ChainingIterator_Type.tp_new(&ChainingIterator_Type, nullptr, nullptr);
((BPy_ChainingIterator *)py_c_it)->c_it = new ChainingIterator(c_it);
((BPy_ChainingIterator *)py_c_it)->py_ve_it.py_it.it = ((BPy_ChainingIterator *)py_c_it)->c_it;
return py_c_it;
}
PyObject *BPy_ChainPredicateIterator_from_ChainPredicateIterator(ChainPredicateIterator &cp_it)
{
PyObject *py_cp_it = ChainPredicateIterator_Type.tp_new(
&ChainPredicateIterator_Type, nullptr, nullptr);
((BPy_ChainPredicateIterator *)py_cp_it)->cp_it = new ChainPredicateIterator(cp_it);
((BPy_ChainPredicateIterator *)py_cp_it)->py_c_it.py_ve_it.py_it.it =
((BPy_ChainPredicateIterator *)py_cp_it)->cp_it;
return py_cp_it;
}
PyObject *BPy_ChainSilhouetteIterator_from_ChainSilhouetteIterator(ChainSilhouetteIterator &cs_it)
{
PyObject *py_cs_it = ChainSilhouetteIterator_Type.tp_new(
&ChainSilhouetteIterator_Type, nullptr, nullptr);
((BPy_ChainSilhouetteIterator *)py_cs_it)->cs_it = new ChainSilhouetteIterator(cs_it);
((BPy_ChainSilhouetteIterator *)py_cs_it)->py_c_it.py_ve_it.py_it.it =
((BPy_ChainSilhouetteIterator *)py_cs_it)->cs_it;
return py_cs_it;
}
//==============================
// Python => C++
//==============================
bool bool_from_PyBool(PyObject *b)
{
return PyObject_IsTrue(b) != 0;
}
IntegrationType IntegrationType_from_BPy_IntegrationType(PyObject *obj)
{
return static_cast<IntegrationType>(PyLong_AsLong(obj));
}
Stroke::MediumType MediumType_from_BPy_MediumType(PyObject *obj)
{
return static_cast<Stroke::MediumType>(PyLong_AsLong(obj));
}
Nature::EdgeNature EdgeNature_from_BPy_Nature(PyObject *obj)
{
return static_cast<Nature::EdgeNature>(PyLong_AsLong(obj));
}
bool Vec2f_ptr_from_PyObject(PyObject *obj, Vec2f &vec)
{
if (Vec2f_ptr_from_Vector(obj, vec)) {
return true;
}
if (Vec2f_ptr_from_PyList(obj, vec)) {
return true;
}
if (Vec2f_ptr_from_PyTuple(obj, vec)) {
return true;
}
return false;
}
bool Vec3f_ptr_from_PyObject(PyObject *obj, Vec3f &vec)
{
if (Vec3f_ptr_from_Vector(obj, vec)) {
return true;
}
if (Vec3f_ptr_from_Color(obj, vec)) {
return true;
}
if (Vec3f_ptr_from_PyList(obj, vec)) {
return true;
}
if (Vec3f_ptr_from_PyTuple(obj, vec)) {
return true;
}
return false;
}
bool Vec3r_ptr_from_PyObject(PyObject *obj, Vec3r &vec)
{
if (Vec3r_ptr_from_Vector(obj, vec)) {
return true;
}
if (Vec3r_ptr_from_Color(obj, vec)) {
return true;
}
if (Vec3r_ptr_from_PyList(obj, vec)) {
return true;
}
if (Vec3r_ptr_from_PyTuple(obj, vec)) {
return true;
}
return false;
}
bool Vec2f_ptr_from_Vector(PyObject *obj, Vec2f &vec)
{
using namespace blender;
if (!VectorObject_Check(obj) || ((VectorObject *)obj)->vec_num != 2) {
return false;
}
if (BaseMath_ReadCallback((blender::BaseMathObject *)obj) == -1) {
return false;
}
vec[0] = ((VectorObject *)obj)->vec[0];
vec[1] = ((VectorObject *)obj)->vec[1];
return true;
}
bool Vec3f_ptr_from_Vector(PyObject *obj, Vec3f &vec)
{
using namespace blender;
if (!VectorObject_Check(obj) || ((VectorObject *)obj)->vec_num != 3) {
return false;
}
if (BaseMath_ReadCallback((blender::BaseMathObject *)obj) == -1) {
return false;
}
vec[0] = ((VectorObject *)obj)->vec[0];
vec[1] = ((VectorObject *)obj)->vec[1];
vec[2] = ((VectorObject *)obj)->vec[2];
return true;
}
bool Vec3r_ptr_from_Vector(PyObject *obj, Vec3r &vec)
{
using namespace blender;
if (!VectorObject_Check(obj) || ((VectorObject *)obj)->vec_num != 3) {
return false;
}
if (BaseMath_ReadCallback((blender::BaseMathObject *)obj) == -1) {
return false;
}
vec[0] = ((VectorObject *)obj)->vec[0];
vec[1] = ((VectorObject *)obj)->vec[1];
vec[2] = ((VectorObject *)obj)->vec[2];
return true;
}
bool Vec3f_ptr_from_Color(PyObject *obj, Vec3f &vec)
{
using namespace blender;
if (!ColorObject_Check(obj)) {
return false;
}
if (BaseMath_ReadCallback((blender::BaseMathObject *)obj) == -1) {
return false;
}
vec[0] = ((ColorObject *)obj)->col[0];
vec[1] = ((ColorObject *)obj)->col[1];
vec[2] = ((ColorObject *)obj)->col[2];
return true;
}
bool Vec3r_ptr_from_Color(PyObject *obj, Vec3r &vec)
{
using namespace blender;
if (!ColorObject_Check(obj)) {
return false;
}
if (BaseMath_ReadCallback((blender::BaseMathObject *)obj) == -1) {
return false;
}
vec[0] = ((ColorObject *)obj)->col[0];
vec[1] = ((ColorObject *)obj)->col[1];
vec[2] = ((ColorObject *)obj)->col[2];
return true;
}
static bool float_array_from_PyList(PyObject *obj, float *v, int n)
{
for (int i = 0; i < n; i++) {
v[i] = PyFloat_AsDouble(PyList_GET_ITEM(obj, i));
if (v[i] == -1.0f && PyErr_Occurred()) {
PyErr_SetString(PyExc_TypeError, "list elements must be a number");
return false;
}
}
return true;
}
bool Vec2f_ptr_from_PyList(PyObject *obj, Vec2f &vec)
{
float v[2];
if (!PyList_Check(obj) || PyList_GET_SIZE(obj) != 2) {
return false;
}
if (!float_array_from_PyList(obj, v, 2)) {
return false;
}
vec[0] = v[0];
vec[1] = v[1];
return true;
}
bool Vec3f_ptr_from_PyList(PyObject *obj, Vec3f &vec)
{
float v[3];
if (!PyList_Check(obj) || PyList_GET_SIZE(obj) != 3) {
return false;
}
if (!float_array_from_PyList(obj, v, 3)) {
return false;
}
vec[0] = v[0];
vec[1] = v[1];
vec[2] = v[2];
return true;
}
bool Vec3r_ptr_from_PyList(PyObject *obj, Vec3r &vec)
{
float v[3];
if (!PyList_Check(obj) || PyList_GET_SIZE(obj) != 3) {
return false;
}
if (!float_array_from_PyList(obj, v, 3)) {
return false;
}
vec[0] = v[0];
vec[1] = v[1];
vec[2] = v[2];
return true;
}
static bool float_array_from_PyTuple(PyObject *obj, float *v, int n)
{
for (int i = 0; i < n; i++) {
v[i] = PyFloat_AsDouble(PyTuple_GET_ITEM(obj, i));
if (v[i] == -1.0f && PyErr_Occurred()) {
PyErr_SetString(PyExc_TypeError, "tuple elements must be a number");
return false;
}
}
return true;
}
bool Vec2f_ptr_from_PyTuple(PyObject *obj, Vec2f &vec)
{
float v[2];
if (!PyTuple_Check(obj) || PyTuple_GET_SIZE(obj) != 2) {
return false;
}
if (!float_array_from_PyTuple(obj, v, 2)) {
return false;
}
vec[0] = v[0];
vec[1] = v[1];
return true;
}
bool Vec3f_ptr_from_PyTuple(PyObject *obj, Vec3f &vec)
{
float v[3];
if (!PyTuple_Check(obj) || PyTuple_GET_SIZE(obj) != 3) {
return false;
}
if (!float_array_from_PyTuple(obj, v, 3)) {
return false;
}
vec[0] = v[0];
vec[1] = v[1];
vec[2] = v[2];
return true;
}
bool Vec3r_ptr_from_PyTuple(PyObject *obj, Vec3r &vec)
{
float v[3];
if (!PyTuple_Check(obj) || PyTuple_GET_SIZE(obj) != 3) {
return false;
}
if (!float_array_from_PyTuple(obj, v, 3)) {
return false;
}
vec[0] = v[0];
vec[1] = v[1];
vec[2] = v[2];
return true;
}
// helpers for argument parsing
bool float_array_from_PyObject(PyObject *obj, float *v, int n)
{
using namespace blender;
if (VectorObject_Check(obj) && ((VectorObject *)obj)->vec_num == n) {
if (BaseMath_ReadCallback((blender::BaseMathObject *)obj) == -1) {
return false;
}
for (int i = 0; i < n; i++) {
v[i] = ((VectorObject *)obj)->vec[i];
}
return true;
}
if (ColorObject_Check(obj) && n == 3) {
if (BaseMath_ReadCallback((blender::BaseMathObject *)obj) == -1) {
return false;
}
for (int i = 0; i < n; i++) {
v[i] = ((ColorObject *)obj)->col[i];
}
return true;
}
if (PyList_Check(obj) && PyList_GET_SIZE(obj) == n) {
return float_array_from_PyList(obj, v, n);
}
if (PyTuple_Check(obj) && PyTuple_GET_SIZE(obj) == n) {
return float_array_from_PyTuple(obj, v, n);
}
return false;
}
int convert_v4(PyObject *obj, void *v)
{
return blender::mathutils_array_parse((float *)v, 4, 4, obj, "Error parsing 4D vector");
}
int convert_v3(PyObject *obj, void *v)
{
return blender::mathutils_array_parse((float *)v, 3, 3, obj, "Error parsing 3D vector");
}
int convert_v2(PyObject *obj, void *v)
{
return blender::mathutils_array_parse((float *)v, 2, 2, obj, "Error parsing 2D vector");
}
///////////////////////////////////////////////////////////////////////////////////////////

View File

@@ -0,0 +1,163 @@
/* SPDX-FileCopyrightText: 2023 Blender Authors
*
* SPDX-License-Identifier: GPL-2.0-or-later */
/** \file
* \ingroup freestyle
*/
#pragma once
extern "C" {
#include <Python.h>
}
#include <typeinfo>
#include "../geometry/Geom.h"
// BBox
#include "../geometry/BBox.h"
// FEdge, FEdgeSharp, FEdgeSmooth, SShape, SVertex, FEdgeInternal::SVertexIterator
#include "../view_map/Silhouette.h"
// Id
#include "../system/Id.h"
// Interface0D, Interface0DIteratorNested, Interface0DIterator
#include "../view_map/Interface0D.h"
// Interface1D
#include "../view_map/Interface1D.h"
// FrsMaterial
#include "../scene_graph/FrsMaterial.h"
// Nature::VertexNature, Nature::EdgeNature
#include "../winged_edge/Nature.h"
// Stroke, StrokeAttribute, StrokeVertex
#include "../stroke/Stroke.h"
// NonTVertex, TVertex, ViewEdge, ViewMap, ViewShape, ViewVertex
#include "../view_map/ViewMap.h"
// CurvePoint, Curve
#include "../stroke/Curve.h"
// Chain
#include "../stroke/Chain.h"
//====== ITERATORS
// AdjacencyIterator, ChainingIterator, ChainSilhouetteIterator, ChainPredicateIterator
#include "../stroke/ChainingIterators.h"
// ViewVertexInternal::orientedViewEdgeIterator
// ViewEdgeInternal::SVertexIterator
// ViewEdgeInternal::ViewEdgeIterator
#include "../view_map/ViewMapIterators.h"
// StrokeInternal::StrokeVertexIterator
#include "../stroke/StrokeIterators.h"
// CurveInternal::CurvePointIterator
#include "../stroke/CurveIterators.h"
///////////////////////////////////////////////////////////////////////////////////////////
#include "generic/python_utildefines.hh"
#include "mathutils/mathutils.hh"
//==============================
// C++ => Python
//==============================
PyObject *PyLong_subtype_new(PyTypeObject *ty, long value);
void PyLong_subtype_add_to_dict(PyObject *dict, PyTypeObject *ty, const char *attr, long value);
PyObject *PyBool_from_bool(bool b);
PyObject *Vector_from_Vec2f(Freestyle::Geometry::Vec2f &v);
PyObject *Vector_from_Vec3f(Freestyle::Geometry::Vec3f &v);
PyObject *Vector_from_Vec3r(Freestyle::Geometry::Vec3r &v);
PyObject *Any_BPy_Interface0D_from_Interface0D(Freestyle::Interface0D &if0D);
PyObject *Any_BPy_Interface1D_from_Interface1D(Freestyle::Interface1D &if1D);
PyObject *Any_BPy_FEdge_from_FEdge(Freestyle::FEdge &fe);
PyObject *Any_BPy_ViewVertex_from_ViewVertex(Freestyle::ViewVertex &vv);
PyObject *BPy_BBox_from_BBox(const Freestyle::BBox<Freestyle::Geometry::Vec3r> &bb);
PyObject *BPy_CurvePoint_from_CurvePoint(Freestyle::CurvePoint &cp);
PyObject *BPy_directedViewEdge_from_directedViewEdge(Freestyle::ViewVertex::directedViewEdge &dve);
PyObject *BPy_FEdge_from_FEdge(Freestyle::FEdge &fe);
PyObject *BPy_FEdgeSharp_from_FEdgeSharp(Freestyle::FEdgeSharp &fes);
PyObject *BPy_FEdgeSmooth_from_FEdgeSmooth(Freestyle::FEdgeSmooth &fes);
PyObject *BPy_Id_from_Id(Freestyle::Id &id);
PyObject *BPy_Interface0D_from_Interface0D(Freestyle::Interface0D &if0D);
PyObject *BPy_Interface1D_from_Interface1D(Freestyle::Interface1D &if1D);
PyObject *BPy_IntegrationType_from_IntegrationType(Freestyle::IntegrationType i);
PyObject *BPy_FrsMaterial_from_FrsMaterial(const Freestyle::FrsMaterial &m);
PyObject *BPy_Nature_from_Nature(ushort n);
PyObject *BPy_MediumType_from_MediumType(Freestyle::Stroke::MediumType n);
PyObject *BPy_SShape_from_SShape(Freestyle::SShape &ss);
PyObject *BPy_Stroke_from_Stroke(Freestyle::Stroke &s);
PyObject *BPy_StrokeAttribute_from_StrokeAttribute(Freestyle::StrokeAttribute &sa);
PyObject *BPy_StrokeVertex_from_StrokeVertex(Freestyle::StrokeVertex &sv);
PyObject *BPy_SVertex_from_SVertex(Freestyle::SVertex &sv);
PyObject *BPy_ViewVertex_from_ViewVertex(Freestyle::ViewVertex &vv);
PyObject *BPy_NonTVertex_from_NonTVertex(Freestyle::NonTVertex &ntv);
PyObject *BPy_TVertex_from_TVertex(Freestyle::TVertex &tv);
PyObject *BPy_ViewEdge_from_ViewEdge(Freestyle::ViewEdge &ve);
PyObject *BPy_Chain_from_Chain(Freestyle::Chain &c);
PyObject *BPy_ViewShape_from_ViewShape(Freestyle::ViewShape &vs);
PyObject *BPy_AdjacencyIterator_from_AdjacencyIterator(Freestyle::AdjacencyIterator &a_it);
PyObject *BPy_Interface0DIterator_from_Interface0DIterator(Freestyle::Interface0DIterator &if0D_it,
bool reversed);
PyObject *BPy_CurvePointIterator_from_CurvePointIterator(
Freestyle::CurveInternal::CurvePointIterator &cp_it);
PyObject *BPy_StrokeVertexIterator_from_StrokeVertexIterator(
Freestyle::StrokeInternal::StrokeVertexIterator &sv_it, bool reversed);
PyObject *BPy_SVertexIterator_from_SVertexIterator(
Freestyle::ViewEdgeInternal::SVertexIterator &sv_it);
PyObject *BPy_orientedViewEdgeIterator_from_orientedViewEdgeIterator(
Freestyle::ViewVertexInternal::orientedViewEdgeIterator &ove_it, bool reversed);
PyObject *BPy_ViewEdgeIterator_from_ViewEdgeIterator(
Freestyle::ViewEdgeInternal::ViewEdgeIterator &ve_it);
PyObject *BPy_ChainingIterator_from_ChainingIterator(Freestyle::ChainingIterator &c_it);
PyObject *BPy_ChainPredicateIterator_from_ChainPredicateIterator(
Freestyle::ChainPredicateIterator &cp_it);
PyObject *BPy_ChainSilhouetteIterator_from_ChainSilhouetteIterator(
Freestyle::ChainSilhouetteIterator &cs_it);
//==============================
// Python => C++
//==============================
bool bool_from_PyBool(PyObject *b);
Freestyle::IntegrationType IntegrationType_from_BPy_IntegrationType(PyObject *obj);
Freestyle::Stroke::MediumType MediumType_from_BPy_MediumType(PyObject *obj);
Freestyle::Nature::EdgeNature EdgeNature_from_BPy_Nature(PyObject *obj);
bool Vec2f_ptr_from_PyObject(PyObject *obj, Freestyle::Geometry::Vec2f &vec);
bool Vec3f_ptr_from_PyObject(PyObject *obj, Freestyle::Geometry::Vec3f &vec);
bool Vec3r_ptr_from_PyObject(PyObject *obj, Freestyle::Geometry::Vec3r &vec);
bool Vec2f_ptr_from_Vector(PyObject *obj, Freestyle::Geometry::Vec2f &vec);
bool Vec3f_ptr_from_Vector(PyObject *obj, Freestyle::Geometry::Vec3f &vec);
bool Vec3r_ptr_from_Vector(PyObject *obj, Freestyle::Geometry::Vec3r &vec);
bool Vec3f_ptr_from_Color(PyObject *obj, Freestyle::Geometry::Vec3f &vec);
bool Vec3r_ptr_from_Color(PyObject *obj, Freestyle::Geometry::Vec3r &vec);
bool Vec2f_ptr_from_PyList(PyObject *obj, Freestyle::Geometry::Vec2f &vec);
bool Vec3f_ptr_from_PyList(PyObject *obj, Freestyle::Geometry::Vec3f &vec);
bool Vec3r_ptr_from_PyList(PyObject *obj, Freestyle::Geometry::Vec3r &vec);
bool Vec2f_ptr_from_PyTuple(PyObject *obj, Freestyle::Geometry::Vec2f &vec);
bool Vec3f_ptr_from_PyTuple(PyObject *obj, Freestyle::Geometry::Vec3f &vec);
bool Vec3r_ptr_from_PyTuple(PyObject *obj, Freestyle::Geometry::Vec3r &vec);
bool float_array_from_PyObject(PyObject *obj, float *v, int n);
int convert_v4(PyObject *obj, void *v);
int convert_v3(PyObject *obj, void *v);
int convert_v2(PyObject *obj, void *v);
///////////////////////////////////////////////////////////////////////////////////////////

View File

@@ -0,0 +1,612 @@
/* SPDX-FileCopyrightText: 2008-2023 Blender Authors
*
* SPDX-License-Identifier: GPL-2.0-or-later */
/** \file
* \ingroup freestyle
*/
#include "BPy_Freestyle.h"
#include "BPy_BBox.h"
#include "BPy_BinaryPredicate0D.h"
#include "BPy_BinaryPredicate1D.h"
#include "BPy_ContextFunctions.h"
#include "BPy_Convert.h"
#include "BPy_FrsMaterial.h"
#include "BPy_FrsNoise.h"
#include "BPy_Id.h"
#include "BPy_IntegrationType.h"
#include "BPy_Interface0D.h"
#include "BPy_Interface1D.h"
#include "BPy_Iterator.h"
#include "BPy_MediumType.h"
#include "BPy_Nature.h"
#include "BPy_Operators.h"
#include "BPy_SShape.h"
#include "BPy_StrokeAttribute.h"
#include "BPy_StrokeShader.h"
#include "BPy_UnaryFunction0D.h"
#include "BPy_UnaryFunction1D.h"
#include "BPy_UnaryPredicate0D.h"
#include "BPy_UnaryPredicate1D.h"
#include "BPy_ViewMap.h"
#include "BPy_ViewShape.h"
#include "BKE_appdir.hh"
#include "DNA_scene_types.h"
#include "FRS_freestyle.h"
#include "RNA_access.hh"
#include "RNA_prototypes.hh"
#include "bpy_rna.hh" /* pyrna_struct_CreatePyObject() */
#include "../generic/py_capi_utils.hh" /* #PyC_UnicodeFromBytes */
#include "BKE_colorband.hh" /* BKE_colorband_evaluate() */
#include "BKE_colortools.hh" /* BKE_curvemapping_evaluateF() */
#include "BKE_material.hh" /* ramp_blend() */
///////////////////////////////////////////////////////////////////////////////////////////
//------------------------ MODULE FUNCTIONS ----------------------------------
PyDoc_STRVAR(
/* Wrap. */
Freestyle_getCurrentScene___doc__,
".. function:: getCurrentScene()\n"
"\n"
" Returns the current scene.\n"
"\n"
" :return: The current scene.\n"
" :rtype: :class:`bpy.types.Scene`\n");
static PyObject *Freestyle_getCurrentScene(PyObject * /*self*/)
{
blender::Scene *scene = blender::g_freestyle.scene;
if (!scene) {
PyErr_SetString(PyExc_TypeError, "current scene not available");
return nullptr;
}
blender::PointerRNA ptr_scene = RNA_pointer_create_discrete(
&scene->id, blender::RNA_Scene, scene);
return pyrna_struct_CreatePyObject(&ptr_scene);
}
#include "DNA_material_types.h"
static int ramp_blend_type(const char *type)
{
if (STREQ(type, "MIX")) {
return blender::MA_RAMP_BLEND;
}
if (STREQ(type, "ADD")) {
return blender::MA_RAMP_ADD;
}
if (STREQ(type, "MULTIPLY")) {
return blender::MA_RAMP_MULT;
}
if (STREQ(type, "SUBTRACT")) {
return blender::MA_RAMP_SUB;
}
if (STREQ(type, "SCREEN")) {
return blender::MA_RAMP_SCREEN;
}
if (STREQ(type, "DIVIDE")) {
return blender::MA_RAMP_DIV;
}
if (STREQ(type, "DIFFERENCE")) {
return blender::MA_RAMP_DIFF;
}
if (STREQ(type, "EXCLUSION")) {
return blender::MA_RAMP_EXCLUSION;
}
if (STREQ(type, "DARKEN")) {
return blender::MA_RAMP_DARK;
}
if (STREQ(type, "LIGHTEN")) {
return blender::MA_RAMP_LIGHT;
}
if (STREQ(type, "OVERLAY")) {
return blender::MA_RAMP_OVERLAY;
}
if (STREQ(type, "DODGE")) {
return blender::MA_RAMP_DODGE;
}
if (STREQ(type, "BURN")) {
return blender::MA_RAMP_BURN;
}
if (STREQ(type, "HUE")) {
return blender::MA_RAMP_HUE;
}
if (STREQ(type, "SATURATION")) {
return blender::MA_RAMP_SAT;
}
if (STREQ(type, "VALUE")) {
return blender::MA_RAMP_VAL;
}
if (STREQ(type, "COLOR")) {
return blender::MA_RAMP_COLOR;
}
if (STREQ(type, "SOFT_LIGHT")) {
return blender::MA_RAMP_SOFT;
}
if (STREQ(type, "LINEAR_LIGHT")) {
return blender::MA_RAMP_LINEAR;
}
return -1;
}
PyDoc_STRVAR(
/* Wrap. */
Freestyle_blendRamp___doc__,
".. function:: blendRamp(type, color1, fac, color2)\n"
"\n"
" Blend two colors according to a ramp blend type.\n"
"\n"
" :param type: Ramp blend type.\n"
" :type type: int\n"
" :param color1: 1st color.\n"
" :type color1: :class:`mathutils.Vector` | tuple[float, float, float] | list[float]\n"
" :param fac: Blend factor.\n"
" :type fac: float\n"
" :param color2: 1st color.\n"
" :type color2: :class:`mathutils.Vector` | tuple[float, float, float] | list[float]\n"
" :return: Blended color in RGB format.\n"
" :rtype: :class:`mathutils.Vector`\n");
static PyObject *Freestyle_blendRamp(PyObject * /*self*/, PyObject *args)
{
PyObject *obj1, *obj2;
char *s;
int type;
float a[4], fac, b[4];
if (!PyArg_ParseTuple(args, "sOfO", &s, &obj1, &fac, &obj2)) {
return nullptr;
}
type = ramp_blend_type(s);
if (type < 0) {
PyErr_SetString(PyExc_TypeError, "argument 1 is an unknown ramp blend type");
return nullptr;
}
if (blender::mathutils_array_parse(a,
3,
3,
obj1,
"argument 2 must be a 3D vector "
"(either a tuple/list of 3 elements or Vector)") == -1)
{
return nullptr;
}
if (blender::mathutils_array_parse(b,
3,
3,
obj2,
"argument 4 must be a 3D vector "
"(either a tuple/list of 3 elements or Vector)") == -1)
{
return nullptr;
}
blender::ramp_blend(type, a, fac, b);
return blender::Vector_CreatePyObject(a, 3, nullptr);
}
PyDoc_STRVAR(
/* Wrap. */
Freestyle_evaluateColorRamp___doc__,
".. function:: evaluateColorRamp(ramp, in)\n"
"\n"
" Evaluate a color ramp at a point in the interval 0 to 1.\n"
"\n"
" :param ramp: Color ramp object.\n"
" :type ramp: :class:`bpy.types.ColorRamp`\n"
" :param in: Value in the interval 0 to 1.\n"
" :type in: float\n"
" :return: color in RGBA format.\n"
" :rtype: :class:`mathutils.Vector`\n");
static PyObject *Freestyle_evaluateColorRamp(PyObject * /*self*/, PyObject *args)
{
blender::BPy_StructRNA *py_srna;
blender::ColorBand *coba;
float in, out[4];
if (!PyArg_ParseTuple(args, "O!f", &blender::pyrna_struct_Type, &py_srna, &in)) {
return nullptr;
}
if (!RNA_struct_is_a(py_srna->ptr->type, blender::RNA_ColorRamp)) {
PyErr_SetString(PyExc_TypeError, "1st argument is not a ColorRamp object");
return nullptr;
}
coba = (blender::ColorBand *)py_srna->ptr->data;
if (!BKE_colorband_evaluate(coba, in, out)) {
PyErr_SetString(PyExc_ValueError, "failed to evaluate the color ramp");
return nullptr;
}
return blender::Vector_CreatePyObject(out, 4, nullptr);
}
#include "DNA_color_types.h"
PyDoc_STRVAR(
/* Wrap. */
Freestyle_evaluateCurveMappingF___doc__,
".. function:: evaluateCurveMappingF(cumap, cur, value)\n"
"\n"
" Evaluate a curve mapping at a point in the interval 0 to 1.\n"
"\n"
" :param cumap: Curve mapping object.\n"
" :type cumap: :class:`bpy.types.CurveMapping`\n"
" :param cur: Index of the curve to be used (0 <= cur <= 3).\n"
" :type cur: int\n"
" :param value: Input value in the interval 0 to 1.\n"
" :type value: float\n"
" :return: Mapped output value.\n"
" :rtype: float\n");
static PyObject *Freestyle_evaluateCurveMappingF(PyObject * /*self*/, PyObject *args)
{
blender::BPy_StructRNA *py_srna;
blender::CurveMapping *cumap;
int cur;
float value;
if (!PyArg_ParseTuple(args, "O!if", &blender::pyrna_struct_Type, &py_srna, &cur, &value)) {
return nullptr;
}
if (!RNA_struct_is_a(py_srna->ptr->type, blender::RNA_CurveMapping)) {
PyErr_SetString(PyExc_TypeError, "1st argument is not a CurveMapping object");
return nullptr;
}
if (cur < 0 || cur > 3) {
PyErr_SetString(PyExc_ValueError, "2nd argument is out of range");
return nullptr;
}
cumap = (blender::CurveMapping *)py_srna->ptr->data;
BKE_curvemapping_init(cumap);
/* disable extrapolation if enabled */
if (cumap->flag & blender::CUMA_EXTEND_EXTRAPOLATE) {
cumap->flag &= ~blender::CUMA_EXTEND_EXTRAPOLATE;
BKE_curvemapping_changed(cumap, false);
}
return PyFloat_FromDouble(BKE_curvemapping_evaluateF(cumap, cur, value));
}
/*-----------------------Freestyle module docstring----------------------------*/
PyDoc_STRVAR(
/* Force wrapped line. */
module_docstring,
"This module provides classes for defining line drawing rules (such as\n"
"predicates, functions, chaining iterators, and stroke shaders), as well\n"
"as helper functions for style module writing.\n"
"\n"
"Class hierarchy:\n"
"\n"
"- :class:`BBox`\n"
"- :class:`BinaryPredicate0D`\n"
"- :class:`BinaryPredicate1D`\n"
"\n"
" - :class:`FalseBP1D`\n"
" - :class:`Length2DBP1D`\n"
" - :class:`SameShapeIdBP1D`\n"
" - :class:`TrueBP1D`\n"
" - :class:`ViewMapGradientNormBP1D`\n"
"\n"
"- :class:`Id`\n"
"- :class:`Interface0D`\n"
"\n"
" - :class:`CurvePoint`\n"
"\n"
" - :class:`StrokeVertex`\n"
"\n"
" - :class:`SVertex`\n"
" - :class:`ViewVertex`\n"
"\n"
" - :class:`NonTVertex`\n"
" - :class:`TVertex`\n"
"\n"
"- :class:`Interface1D`\n"
"\n"
" - :class:`Curve`\n"
"\n"
" - :class:`Chain`\n"
"\n"
" - :class:`FEdge`\n"
"\n"
" - :class:`FEdgeSharp`\n"
" - :class:`FEdgeSmooth`\n"
"\n"
" - :class:`Stroke`\n"
" - :class:`ViewEdge`\n"
"\n"
"- :class:`Iterator`\n"
"\n"
" - :class:`AdjacencyIterator`\n"
" - :class:`CurvePointIterator`\n"
" - :class:`Interface0DIterator`\n"
" - :class:`SVertexIterator`\n"
" - :class:`StrokeVertexIterator`\n"
" - :class:`ViewEdgeIterator`\n"
"\n"
" - :class:`ChainingIterator`\n"
"\n"
" - :class:`ChainPredicateIterator`\n"
" - :class:`ChainSilhouetteIterator`\n"
"\n"
" - :class:`orientedViewEdgeIterator`\n"
"\n"
"- :class:`Material`\n"
"- :class:`Noise`\n"
"- :class:`Operators`\n"
"- :class:`SShape`\n"
"- :class:`StrokeAttribute`\n"
"- :class:`StrokeShader`\n"
"\n"
" - :class:`BackboneStretcherShader`\n"
" - :class:`BezierCurveShader`\n"
" - :class:`BlenderTextureShader`\n"
" - :class:`CalligraphicShader`\n"
" - :class:`ColorNoiseShader`\n"
" - :class:`ColorVariationPatternShader`\n"
" - :class:`ConstantColorShader`\n"
" - :class:`ConstantThicknessShader`\n"
" - :class:`ConstrainedIncreasingThicknessShader`\n"
" - :class:`GuidingLinesShader`\n"
" - :class:`IncreasingColorShader`\n"
" - :class:`IncreasingThicknessShader`\n"
" - :class:`PolygonalizationShader`\n"
" - :class:`SamplingShader`\n"
" - :class:`SmoothingShader`\n"
" - :class:`SpatialNoiseShader`\n"
" - :class:`StrokeTextureShader`\n"
" - :class:`StrokeTextureStepShader`\n"
" - :class:`TextureAssignerShader`\n"
" - :class:`ThicknessNoiseShader`\n"
" - :class:`ThicknessVariationPatternShader`\n"
" - :class:`TipRemoverShader`\n"
" - :class:`fstreamShader`\n"
" - :class:`streamShader`\n"
"\n"
"- :class:`UnaryFunction0D`\n"
"\n"
" - :class:`UnaryFunction0DDouble`\n"
"\n"
" - :class:`Curvature2DAngleF0D`\n"
" - :class:`DensityF0D`\n"
" - :class:`GetProjectedXF0D`\n"
" - :class:`GetProjectedYF0D`\n"
" - :class:`GetProjectedZF0D`\n"
" - :class:`GetXF0D`\n"
" - :class:`GetYF0D`\n"
" - :class:`GetZF0D`\n"
" - :class:`LocalAverageDepthF0D`\n"
" - :class:`ZDiscontinuityF0D`\n"
"\n"
" - :class:`UnaryFunction0DEdgeNature`\n"
"\n"
" - :class:`CurveNatureF0D`\n"
"\n"
" - :class:`UnaryFunction0DFloat`\n"
"\n"
" - :class:`GetCurvilinearAbscissaF0D`\n"
" - :class:`GetParameterF0D`\n"
" - :class:`GetViewMapGradientNormF0D`\n"
" - :class:`ReadCompleteViewMapPixelF0D`\n"
" - :class:`ReadMapPixelF0D`\n"
" - :class:`ReadSteerableViewMapPixelF0D`\n"
"\n"
" - :class:`UnaryFunction0DId`\n"
"\n"
" - :class:`ShapeIdF0D`\n"
"\n"
" - :class:`UnaryFunction0DMaterial`\n"
"\n"
" - :class:`MaterialF0D`\n"
"\n"
" - :class:`UnaryFunction0DUnsigned`\n"
"\n"
" - :class:`QuantitativeInvisibilityF0D`\n"
"\n"
" - :class:`UnaryFunction0DVec2f`\n"
"\n"
" - :class:`Normal2DF0D`\n"
" - :class:`VertexOrientation2DF0D`\n"
"\n"
" - :class:`UnaryFunction0DVec3f`\n"
"\n"
" - :class:`VertexOrientation3DF0D`\n"
"\n"
" - :class:`UnaryFunction0DVectorViewShape`\n"
"\n"
" - :class:`GetOccludersF0D`\n"
"\n"
" - :class:`UnaryFunction0DViewShape`\n"
"\n"
" - :class:`GetOccludeeF0D`\n"
" - :class:`GetShapeF0D`\n"
"\n"
"- :class:`UnaryFunction1D`\n"
"\n"
" - :class:`UnaryFunction1DDouble`\n"
"\n"
" - :class:`Curvature2DAngleF1D`\n"
" - :class:`DensityF1D`\n"
" - :class:`GetCompleteViewMapDensityF1D`\n"
" - :class:`GetDirectionalViewMapDensityF1D`\n"
" - :class:`GetProjectedXF1D`\n"
" - :class:`GetProjectedYF1D`\n"
" - :class:`GetProjectedZF1D`\n"
" - :class:`GetSteerableViewMapDensityF1D`\n"
" - :class:`GetViewMapGradientNormF1D`\n"
" - :class:`GetXF1D`\n"
" - :class:`GetYF1D`\n"
" - :class:`GetZF1D`\n"
" - :class:`LocalAverageDepthF1D`\n"
" - :class:`ZDiscontinuityF1D`\n"
"\n"
" - :class:`UnaryFunction1DEdgeNature`\n"
"\n"
" - :class:`CurveNatureF1D`\n"
"\n"
" - :class:`UnaryFunction1DFloat`\n"
" - :class:`UnaryFunction1DUnsigned`\n"
"\n"
" - :class:`QuantitativeInvisibilityF1D`\n"
"\n"
" - :class:`UnaryFunction1DVec2f`\n"
"\n"
" - :class:`Normal2DF1D`\n"
" - :class:`Orientation2DF1D`\n"
"\n"
" - :class:`UnaryFunction1DVec3f`\n"
"\n"
" - :class:`Orientation3DF1D`\n"
"\n"
" - :class:`UnaryFunction1DVectorViewShape`\n"
"\n"
" - :class:`GetOccludeeF1D`\n"
" - :class:`GetOccludersF1D`\n"
" - :class:`GetShapeF1D`\n"
"\n"
" - :class:`UnaryFunction1DVoid`\n"
"\n"
" - :class:`ChainingTimeStampF1D`\n"
" - :class:`IncrementChainingTimeStampF1D`\n"
" - :class:`TimeStampF1D`\n"
"\n"
"- :class:`UnaryPredicate0D`\n"
"\n"
" - :class:`FalseUP0D`\n"
" - :class:`TrueUP0D`\n"
"\n"
"- :class:`UnaryPredicate1D`\n"
"\n"
" - :class:`ContourUP1D`\n"
" - :class:`DensityLowerThanUP1D`\n"
" - :class:`EqualToChainingTimeStampUP1D`\n"
" - :class:`EqualToTimeStampUP1D`\n"
" - :class:`ExternalContourUP1D`\n"
" - :class:`FalseUP1D`\n"
" - :class:`QuantitativeInvisibilityUP1D`\n"
" - :class:`ShapeUP1D`\n"
" - :class:`TrueUP1D`\n"
" - :class:`WithinImageBoundaryUP1D`\n"
"\n"
"- :class:`ViewMap`\n"
"- :class:`ViewShape`\n"
"- :class:`IntegrationType`\n"
"- :class:`MediumType`\n"
"- :class:`Nature`\n"
"\n");
/*-----------------------Freestyle module method def---------------------------*/
#ifdef __GNUC__
# ifdef __clang__
# pragma clang diagnostic push
# pragma clang diagnostic ignored "-Wcast-function-type"
# else
# pragma GCC diagnostic push
# pragma GCC diagnostic ignored "-Wcast-function-type"
# endif
#endif
static PyMethodDef module_functions[] = {
{"getCurrentScene",
(PyCFunction)Freestyle_getCurrentScene,
METH_NOARGS,
Freestyle_getCurrentScene___doc__},
{"blendRamp", (PyCFunction)Freestyle_blendRamp, METH_VARARGS, Freestyle_blendRamp___doc__},
{"evaluateColorRamp",
(PyCFunction)Freestyle_evaluateColorRamp,
METH_VARARGS,
Freestyle_evaluateColorRamp___doc__},
{"evaluateCurveMappingF",
(PyCFunction)Freestyle_evaluateCurveMappingF,
METH_VARARGS,
Freestyle_evaluateCurveMappingF___doc__},
{nullptr, nullptr, 0, nullptr},
};
#ifdef __GNUC__
# ifdef __clang__
# pragma clang diagnostic pop
# else
# pragma GCC diagnostic pop
# endif
#endif
/*-----------------------Freestyle module definition---------------------------*/
static PyModuleDef module_definition = {
/*m_base*/ PyModuleDef_HEAD_INIT,
/*m_name*/ "_freestyle",
/*m_doc*/ module_docstring,
/*m_size*/ -1,
/*m_methods*/ module_functions,
/*m_slots*/ nullptr,
/*m_traverse*/ nullptr,
/*m_clear*/ nullptr,
/*m_free*/ nullptr,
};
//-------------------MODULE INITIALIZATION--------------------------------
PyObject *Freestyle_Init()
{
PyObject *module;
// initialize modules
module = PyModule_Create(&module_definition);
if (!module) {
return nullptr;
}
PyDict_SetItemString(PySys_GetObject("modules"), module_definition.m_name, module);
// update 'sys.path' for Freestyle Python API modules
const std::optional<std::string> path = BKE_appdir_folder_id(blender::BLENDER_SYSTEM_SCRIPTS,
"freestyle");
if (path.has_value()) {
char modpath[FILE_MAX];
blender::BLI_path_join(modpath, sizeof(modpath), path->c_str(), "modules");
PyObject *sys_path = PySys_GetObject("path"); /* borrow */
PyObject *py_modpath = blender::PyC_UnicodeFromBytes(modpath);
PyList_Append(sys_path, py_modpath);
Py_DECREF(py_modpath);
#if 0
printf("Adding Python path: %s\n", modpath);
#endif
}
else {
printf(
"Freestyle: couldn't find 'scripts/freestyle/modules', Freestyle won't work properly.\n");
}
// attach its classes (adding the object types to the module)
// those classes have to be initialized before the others
MediumType_Init(module);
Nature_Init(module);
BBox_Init(module);
BinaryPredicate0D_Init(module);
BinaryPredicate1D_Init(module);
ContextFunctions_Init(module);
FrsMaterial_Init(module);
FrsNoise_Init(module);
Id_Init(module);
IntegrationType_Init(module);
Interface0D_Init(module);
Interface1D_Init(module);
Iterator_Init(module);
Operators_Init(module);
SShape_Init(module);
StrokeAttribute_Init(module);
StrokeShader_Init(module);
UnaryFunction0D_Init(module);
UnaryFunction1D_Init(module);
UnaryPredicate0D_Init(module);
UnaryPredicate1D_Init(module);
ViewMap_Init(module);
ViewShape_Init(module);
return module;
}
///////////////////////////////////////////////////////////////////////////////////////////

View File

@@ -0,0 +1,19 @@
/* SPDX-FileCopyrightText: 2023 Blender Authors
*
* SPDX-License-Identifier: GPL-2.0-or-later */
/** \file
* \ingroup freestyle
*/
#pragma once
#include <Python.h>
///////////////////////////////////////////////////////////////////////////////////////////
/*---------------------------Python BPy_Freestyle visible prototypes-----------*/
PyObject *Freestyle_Init(void);
///////////////////////////////////////////////////////////////////////////////////////////

View File

@@ -0,0 +1,594 @@
/* SPDX-FileCopyrightText: 2004-2023 Blender Authors
*
* SPDX-License-Identifier: GPL-2.0-or-later */
/** \file
* \ingroup freestyle
*/
#include "BPy_FrsMaterial.h"
#include "BPy_Convert.h"
#include "BLI_hash_mm2a.hh"
#include "BLI_math_vector.h"
using namespace Freestyle;
///////////////////////////////////////////////////////////////////////////////////////////
//-------------------MODULE INITIALIZATION--------------------------------
int FrsMaterial_Init(PyObject *module)
{
if (module == nullptr) {
return -1;
}
if (PyType_Ready(&FrsMaterial_Type) < 0) {
return -1;
}
PyModule_AddObjectRef(module, "Material", (PyObject *)&FrsMaterial_Type);
FrsMaterial_mathutils_register_callback();
return 0;
}
//------------------------INSTANCE METHODS ----------------------------------
PyDoc_STRVAR(
/* Wrap. */
FrsMaterial_doc,
"Class defining a material.\n"
"\n"
".. method:: __init__(*args)\n"
"\n"
" Accepted call signatures:\n"
"\n"
" - ``__init__()``\n"
" - ``__init__(brother)``\n"
" - ``__init__(line, diffuse, ambient, specular, emission, shininess, priority)``\n"
"\n"
" Creates a :class:`FrsMaterial` using either default constructor,\n"
" copy constructor, or an overloaded constructor\n"
"\n"
" :param brother: A Material object to be used as a copy constructor.\n"
" :type brother: :class:`Material`\n"
" :param line: The line color.\n"
" :type line: :class:`mathutils.Vector` | tuple[float, float, float, float] | list[float]\n"
" :param diffuse: The diffuse color.\n"
" :type diffuse: \n"
" :param ambient: The ambient color.\n"
" :type ambient: :class:`mathutils.Vector` | tuple[float, float, float, float] | "
"list[float]\n"
" :param specular: The specular color.\n"
" :type specular: :class:`mathutils.Vector` | tuple[float, float, float, float] | "
"list[float]\n"
" :param emission: The emissive color.\n"
" :type emission: :class:`mathutils.Vector` | tuple[float, float, float, float] | "
"list[float]\n"
" :param shininess: The shininess coefficient.\n"
" :type shininess: float\n"
" :param priority: The line color priority.\n"
" :type priority: int\n");
static int FrsMaterial_init(BPy_FrsMaterial *self, PyObject *args, PyObject *kwds)
{
static const char *kwlist_1[] = {"brother", nullptr};
static const char *kwlist_2[] = {
"line", "diffuse", "ambient", "specular", "emission", "shininess", "priority", nullptr};
PyObject *brother = nullptr;
float line[4], diffuse[4], ambient[4], specular[4], emission[4], shininess;
int priority;
if (PyArg_ParseTupleAndKeywords(
args, kwds, "|O!", (char **)kwlist_1, &FrsMaterial_Type, &brother))
{
if (!brother) {
self->m = new FrsMaterial();
}
else {
FrsMaterial *m = ((BPy_FrsMaterial *)brother)->m;
if (!m) {
PyErr_SetString(PyExc_RuntimeError, "invalid Material object");
return -1;
}
self->m = new FrsMaterial(*m);
}
}
else if ((void)PyErr_Clear(),
PyArg_ParseTupleAndKeywords(args,
kwds,
"O&O&O&O&O&fi",
(char **)kwlist_2,
convert_v4,
line,
convert_v4,
diffuse,
convert_v4,
ambient,
convert_v4,
specular,
convert_v4,
emission,
&shininess,
&priority))
{
self->m = new FrsMaterial(line, diffuse, ambient, specular, emission, shininess, priority);
}
else {
PyErr_SetString(PyExc_TypeError, "invalid argument(s)");
return -1;
}
return 0;
}
static void FrsMaterial_dealloc(BPy_FrsMaterial *self)
{
delete self->m;
Py_TYPE(self)->tp_free((PyObject *)self);
}
static PyObject *FrsMaterial_repr(BPy_FrsMaterial *self)
{
return PyUnicode_FromFormat("Material - address: %p", self->m);
}
/*----------------------mathutils callbacks ----------------------------*/
/* subtype */
#define MATHUTILS_SUBTYPE_DIFFUSE 1
#define MATHUTILS_SUBTYPE_SPECULAR 2
#define MATHUTILS_SUBTYPE_AMBIENT 3
#define MATHUTILS_SUBTYPE_EMISSION 4
#define MATHUTILS_SUBTYPE_LINE 5
static int FrsMaterial_mathutils_check(blender::BaseMathObject *bmo)
{
if (!BPy_FrsMaterial_Check(bmo->cb_user)) {
return -1;
}
return 0;
}
static int FrsMaterial_mathutils_get(blender::BaseMathObject *bmo, int subtype)
{
BPy_FrsMaterial *self = (BPy_FrsMaterial *)bmo->cb_user;
switch (subtype) {
case MATHUTILS_SUBTYPE_LINE:
bmo->data[0] = self->m->lineR();
bmo->data[1] = self->m->lineG();
bmo->data[2] = self->m->lineB();
bmo->data[3] = self->m->lineA();
break;
case MATHUTILS_SUBTYPE_DIFFUSE:
bmo->data[0] = self->m->diffuseR();
bmo->data[1] = self->m->diffuseG();
bmo->data[2] = self->m->diffuseB();
bmo->data[3] = self->m->diffuseA();
break;
case MATHUTILS_SUBTYPE_SPECULAR:
bmo->data[0] = self->m->specularR();
bmo->data[1] = self->m->specularG();
bmo->data[2] = self->m->specularB();
bmo->data[3] = self->m->specularA();
break;
case MATHUTILS_SUBTYPE_AMBIENT:
bmo->data[0] = self->m->ambientR();
bmo->data[1] = self->m->ambientG();
bmo->data[2] = self->m->ambientB();
bmo->data[3] = self->m->ambientA();
break;
case MATHUTILS_SUBTYPE_EMISSION:
bmo->data[0] = self->m->emissionR();
bmo->data[1] = self->m->emissionG();
bmo->data[2] = self->m->emissionB();
bmo->data[3] = self->m->emissionA();
break;
default:
return -1;
}
return 0;
}
static int FrsMaterial_mathutils_set(blender::BaseMathObject *bmo, int subtype)
{
BPy_FrsMaterial *self = (BPy_FrsMaterial *)bmo->cb_user;
switch (subtype) {
case MATHUTILS_SUBTYPE_LINE:
self->m->setLine(bmo->data[0], bmo->data[1], bmo->data[2], bmo->data[3]);
break;
case MATHUTILS_SUBTYPE_DIFFUSE:
self->m->setDiffuse(bmo->data[0], bmo->data[1], bmo->data[2], bmo->data[3]);
break;
case MATHUTILS_SUBTYPE_SPECULAR:
self->m->setSpecular(bmo->data[0], bmo->data[1], bmo->data[2], bmo->data[3]);
break;
case MATHUTILS_SUBTYPE_AMBIENT:
self->m->setAmbient(bmo->data[0], bmo->data[1], bmo->data[2], bmo->data[3]);
break;
case MATHUTILS_SUBTYPE_EMISSION:
self->m->setEmission(bmo->data[0], bmo->data[1], bmo->data[2], bmo->data[3]);
break;
default:
return -1;
}
return 0;
}
static int FrsMaterial_mathutils_get_index(blender::BaseMathObject *bmo, int subtype, int index)
{
BPy_FrsMaterial *self = (BPy_FrsMaterial *)bmo->cb_user;
switch (subtype) {
case MATHUTILS_SUBTYPE_LINE: {
const float *color = self->m->line();
bmo->data[index] = color[index];
break;
}
case MATHUTILS_SUBTYPE_DIFFUSE: {
const float *color = self->m->diffuse();
bmo->data[index] = color[index];
break;
}
case MATHUTILS_SUBTYPE_SPECULAR: {
const float *color = self->m->specular();
bmo->data[index] = color[index];
break;
}
case MATHUTILS_SUBTYPE_AMBIENT: {
const float *color = self->m->ambient();
bmo->data[index] = color[index];
break;
}
case MATHUTILS_SUBTYPE_EMISSION: {
const float *color = self->m->emission();
bmo->data[index] = color[index];
break;
}
default:
return -1;
}
return 0;
}
static int FrsMaterial_mathutils_set_index(blender::BaseMathObject *bmo, int subtype, int index)
{
BPy_FrsMaterial *self = (BPy_FrsMaterial *)bmo->cb_user;
float color[4];
switch (subtype) {
case MATHUTILS_SUBTYPE_LINE:
blender::copy_v4_v4(color, self->m->line());
color[index] = bmo->data[index];
self->m->setLine(color[0], color[1], color[2], color[3]);
break;
case MATHUTILS_SUBTYPE_DIFFUSE:
blender::copy_v4_v4(color, self->m->diffuse());
color[index] = bmo->data[index];
self->m->setDiffuse(color[0], color[1], color[2], color[3]);
break;
case MATHUTILS_SUBTYPE_SPECULAR:
blender::copy_v4_v4(color, self->m->specular());
color[index] = bmo->data[index];
self->m->setSpecular(color[0], color[1], color[2], color[3]);
break;
case MATHUTILS_SUBTYPE_AMBIENT:
blender::copy_v4_v4(color, self->m->ambient());
color[index] = bmo->data[index];
self->m->setAmbient(color[0], color[1], color[2], color[3]);
break;
case MATHUTILS_SUBTYPE_EMISSION:
blender::copy_v4_v4(color, self->m->emission());
color[index] = bmo->data[index];
self->m->setEmission(color[0], color[1], color[2], color[3]);
break;
default:
return -1;
}
return 0;
}
static blender::Mathutils_Callback FrsMaterial_mathutils_cb = {
FrsMaterial_mathutils_check,
FrsMaterial_mathutils_get,
FrsMaterial_mathutils_set,
FrsMaterial_mathutils_get_index,
FrsMaterial_mathutils_set_index,
};
static uchar FrsMaterial_mathutils_cb_index = -1;
void FrsMaterial_mathutils_register_callback()
{
FrsMaterial_mathutils_cb_index = Mathutils_RegisterCallback(&FrsMaterial_mathutils_cb);
}
/*----------------------FrsMaterial get/setters ----------------------------*/
PyDoc_STRVAR(
/* Wrap. */
FrsMaterial_line_doc,
"RGBA components of the line color of the material.\n"
"\n"
":type: :class:`mathutils.Vector`\n");
static PyObject *FrsMaterial_line_get(BPy_FrsMaterial *self, void * /*closure*/)
{
return blender::Vector_CreatePyObject_cb(
(PyObject *)self, 4, FrsMaterial_mathutils_cb_index, MATHUTILS_SUBTYPE_LINE);
}
static int FrsMaterial_line_set(BPy_FrsMaterial *self, PyObject *value, void * /*closure*/)
{
float color[4];
if (blender::mathutils_array_parse(color, 4, 4, value, "value must be a 4-dimensional vector") ==
-1)
{
return -1;
}
self->m->setLine(color[0], color[1], color[2], color[3]);
return 0;
}
PyDoc_STRVAR(
/* Wrap. */
FrsMaterial_diffuse_doc,
"RGBA components of the diffuse color of the material.\n"
"\n"
":type: :class:`mathutils.Vector`\n");
static PyObject *FrsMaterial_diffuse_get(BPy_FrsMaterial *self, void * /*closure*/)
{
return blender::Vector_CreatePyObject_cb(
(PyObject *)self, 4, FrsMaterial_mathutils_cb_index, MATHUTILS_SUBTYPE_DIFFUSE);
}
static int FrsMaterial_diffuse_set(BPy_FrsMaterial *self, PyObject *value, void * /*closure*/)
{
float color[4];
if (blender::mathutils_array_parse(color, 4, 4, value, "value must be a 4-dimensional vector") ==
-1)
{
return -1;
}
self->m->setDiffuse(color[0], color[1], color[2], color[3]);
return 0;
}
PyDoc_STRVAR(
/* Wrap. */
FrsMaterial_specular_doc,
"RGBA components of the specular color of the material.\n"
"\n"
":type: :class:`mathutils.Vector`\n");
static PyObject *FrsMaterial_specular_get(BPy_FrsMaterial *self, void * /*closure*/)
{
return blender::Vector_CreatePyObject_cb(
(PyObject *)self, 4, FrsMaterial_mathutils_cb_index, MATHUTILS_SUBTYPE_SPECULAR);
}
static int FrsMaterial_specular_set(BPy_FrsMaterial *self, PyObject *value, void * /*closure*/)
{
float color[4];
if (blender::mathutils_array_parse(color, 4, 4, value, "value must be a 4-dimensional vector") ==
-1)
{
return -1;
}
self->m->setSpecular(color[0], color[1], color[2], color[3]);
return 0;
}
PyDoc_STRVAR(
/* Wrap. */
FrsMaterial_ambient_doc,
"RGBA components of the ambient color of the material.\n"
"\n"
":type: :class:`mathutils.Color`\n");
static PyObject *FrsMaterial_ambient_get(BPy_FrsMaterial *self, void * /*closure*/)
{
return blender::Vector_CreatePyObject_cb(
(PyObject *)self, 4, FrsMaterial_mathutils_cb_index, MATHUTILS_SUBTYPE_AMBIENT);
}
static int FrsMaterial_ambient_set(BPy_FrsMaterial *self, PyObject *value, void * /*closure*/)
{
float color[4];
if (blender::mathutils_array_parse(color, 4, 4, value, "value must be a 4-dimensional vector") ==
-1)
{
return -1;
}
self->m->setAmbient(color[0], color[1], color[2], color[3]);
return 0;
}
PyDoc_STRVAR(
/* Wrap. */
FrsMaterial_emission_doc,
"RGBA components of the emissive color of the material.\n"
"\n"
":type: :class:`mathutils.Color`\n");
static PyObject *FrsMaterial_emission_get(BPy_FrsMaterial *self, void * /*closure*/)
{
return blender::Vector_CreatePyObject_cb(
(PyObject *)self, 4, FrsMaterial_mathutils_cb_index, MATHUTILS_SUBTYPE_EMISSION);
}
static int FrsMaterial_emission_set(BPy_FrsMaterial *self, PyObject *value, void * /*closure*/)
{
float color[4];
if (blender::mathutils_array_parse(color, 4, 4, value, "value must be a 4-dimensional vector") ==
-1)
{
return -1;
}
self->m->setEmission(color[0], color[1], color[2], color[3]);
return 0;
}
PyDoc_STRVAR(
/* Wrap. */
FrsMaterial_shininess_doc,
"Shininess coefficient of the material.\n"
"\n"
":type: float\n");
static PyObject *FrsMaterial_shininess_get(BPy_FrsMaterial *self, void * /*closure*/)
{
return PyFloat_FromDouble(self->m->shininess());
}
static int FrsMaterial_shininess_set(BPy_FrsMaterial *self, PyObject *value, void * /*closure*/)
{
float scalar;
if ((scalar = PyFloat_AsDouble(value)) == -1.0f && PyErr_Occurred()) {
/* parsed item not a number */
PyErr_SetString(PyExc_TypeError, "value must be a number");
return -1;
}
self->m->setShininess(scalar);
return 0;
}
PyDoc_STRVAR(
/* Wrap. */
FrsMaterial_priority_doc,
"Line color priority of the material.\n"
"\n"
":type: int\n");
static PyObject *FrsMaterial_priority_get(BPy_FrsMaterial *self, void * /*closure*/)
{
return PyLong_FromLong(self->m->priority());
}
static int FrsMaterial_priority_set(BPy_FrsMaterial *self, PyObject *value, void * /*closure*/)
{
int scalar;
if ((scalar = PyLong_AsLong(value)) == -1 && PyErr_Occurred()) {
PyErr_SetString(PyExc_TypeError, "value must be an integer");
return -1;
}
self->m->setPriority(scalar);
return 0;
}
static PyGetSetDef BPy_FrsMaterial_getseters[] = {
{"line",
(getter)FrsMaterial_line_get,
(setter)FrsMaterial_line_set,
FrsMaterial_line_doc,
nullptr},
{"diffuse",
(getter)FrsMaterial_diffuse_get,
(setter)FrsMaterial_diffuse_set,
FrsMaterial_diffuse_doc,
nullptr},
{"specular",
(getter)FrsMaterial_specular_get,
(setter)FrsMaterial_specular_set,
FrsMaterial_specular_doc,
nullptr},
{"ambient",
(getter)FrsMaterial_ambient_get,
(setter)FrsMaterial_ambient_set,
FrsMaterial_ambient_doc,
nullptr},
{"emission",
(getter)FrsMaterial_emission_get,
(setter)FrsMaterial_emission_set,
FrsMaterial_emission_doc,
nullptr},
{"shininess",
(getter)FrsMaterial_shininess_get,
(setter)FrsMaterial_shininess_set,
FrsMaterial_shininess_doc,
nullptr},
{"priority",
(getter)FrsMaterial_priority_get,
(setter)FrsMaterial_priority_set,
FrsMaterial_priority_doc,
nullptr},
{nullptr, nullptr, nullptr, nullptr, nullptr} /* Sentinel */
};
static PyObject *BPy_FrsMaterial_richcmpr(PyObject *objectA,
PyObject *objectB,
int comparison_type)
{
const BPy_FrsMaterial *matA = nullptr, *matB = nullptr;
bool result = false;
if (!BPy_FrsMaterial_Check(objectA) || !BPy_FrsMaterial_Check(objectB)) {
if (comparison_type == Py_NE) {
Py_RETURN_TRUE;
}
Py_RETURN_FALSE;
}
matA = (BPy_FrsMaterial *)objectA;
matB = (BPy_FrsMaterial *)objectB;
switch (comparison_type) {
case Py_NE:
result = (*matA->m) != (*matB->m);
break;
case Py_EQ:
result = (*matA->m) == (*matB->m);
break;
default:
PyErr_SetString(PyExc_TypeError, "Material does not support this comparison type");
return nullptr;
}
if (result == true) {
Py_RETURN_TRUE;
}
Py_RETURN_FALSE;
}
static Py_hash_t FrsMaterial_hash(PyObject *self)
{
return (Py_uhash_t)blender::BLI_hash_mm2((const uchar *)self, sizeof(*self), 0);
}
/*-----------------------BPy_FrsMaterial type definition ------------------------------*/
PyTypeObject FrsMaterial_Type = {
/*ob_base*/ PyVarObject_HEAD_INIT(nullptr, 0)
/*tp_name*/ "Material",
/*tp_basicsize*/ sizeof(BPy_FrsMaterial),
/*tp_itemsize*/ 0,
/*tp_dealloc*/ (destructor)FrsMaterial_dealloc,
/*tp_vectorcall_offset*/ 0,
/*tp_getattr*/ nullptr,
/*tp_setattr*/ nullptr,
/*tp_as_async*/ nullptr,
/*tp_repr*/ (reprfunc)FrsMaterial_repr,
/*tp_as_number*/ nullptr,
/*tp_as_sequence*/ nullptr,
/*tp_as_mapping*/ nullptr,
/*tp_hash*/ (hashfunc)FrsMaterial_hash,
/*tp_call*/ nullptr,
/*tp_str*/ nullptr,
/*tp_getattro*/ nullptr,
/*tp_setattro*/ nullptr,
/*tp_as_buffer*/ nullptr,
/*tp_flags*/ Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE,
/*tp_doc*/ FrsMaterial_doc,
/*tp_traverse*/ nullptr,
/*tp_clear*/ nullptr,
/*tp_richcompare*/ (richcmpfunc)BPy_FrsMaterial_richcmpr,
/*tp_weaklistoffset*/ 0,
/*tp_iter*/ nullptr,
/*tp_iternext*/ nullptr,
/*tp_methods*/ nullptr,
/*tp_members*/ nullptr,
/*tp_getset*/ BPy_FrsMaterial_getseters,
/*tp_base*/ nullptr,
/*tp_dict*/ nullptr,
/*tp_descr_get*/ nullptr,
/*tp_descr_set*/ nullptr,
/*tp_dictoffset*/ 0,
/*tp_init*/ (initproc)FrsMaterial_init,
/*tp_alloc*/ nullptr,
/*tp_new*/ PyType_GenericNew,
};
///////////////////////////////////////////////////////////////////////////////////////////

View File

@@ -0,0 +1,35 @@
/* SPDX-FileCopyrightText: 2023 Blender Authors
*
* SPDX-License-Identifier: GPL-2.0-or-later */
/** \file
* \ingroup freestyle
*/
#pragma once
extern "C" {
#include <Python.h>
}
#include "../scene_graph/FrsMaterial.h"
///////////////////////////////////////////////////////////////////////////////////////////
extern PyTypeObject FrsMaterial_Type;
#define BPy_FrsMaterial_Check(v) \
(PyObject_IsInstance((PyObject *)v, (PyObject *)&FrsMaterial_Type))
/*---------------------------Python BPy_FrsMaterial structure definition----------*/
struct BPy_FrsMaterial {
PyObject_HEAD
Freestyle::FrsMaterial *m;
};
/*---------------------------Python BPy_FrsMaterial visible prototypes-----------*/
int FrsMaterial_Init(PyObject *module);
void FrsMaterial_mathutils_register_callback();
///////////////////////////////////////////////////////////////////////////////////////////

View File

@@ -0,0 +1,381 @@
/* SPDX-FileCopyrightText: 2004-2022 Blender Authors
*
* SPDX-License-Identifier: GPL-2.0-or-later */
/** \file
* \ingroup freestyle
*/
#include "BPy_FrsNoise.h"
#include "BPy_Convert.h"
#include "../system/RandGen.h"
#include "BLI_sys_types.h"
#include <sstream>
using namespace Freestyle;
///////////////////////////////////////////////////////////////////////////////////////////
//-------------------MODULE INITIALIZATION--------------------------------
int FrsNoise_Init(PyObject *module)
{
if (module == nullptr) {
return -1;
}
if (PyType_Ready(&FrsNoise_Type) < 0) {
return -1;
}
PyModule_AddObjectRef(module, "Noise", (PyObject *)&FrsNoise_Type);
return 0;
}
//------------------------INSTANCE METHODS ----------------------------------
PyDoc_STRVAR(
/* Wrap. */
FrsNoise_doc,
"Class to provide Perlin noise functionalities.\n"
"\n"
".. method:: __init__(seed = -1)\n"
"\n"
" Builds a Noise object. Seed is an optional argument. The seed value is used\n"
" as a seed for random number generation if it is equal to or greater than zero;\n"
" otherwise, time is used as a seed.\n"
"\n"
" :param seed: Seed for random number generation.\n"
" :type seed: int\n");
static int FrsNoise_init(BPy_FrsNoise *self, PyObject *args, PyObject *kwds)
{
static const char *kwlist[] = {"seed", nullptr};
long seed = -1;
if (!PyArg_ParseTupleAndKeywords(args, kwds, "|l", (char **)kwlist, &seed)) {
return -1;
}
self->n = new Noise(seed);
self->pn = new PseudoNoise();
return 0;
}
static void FrsNoise_dealloc(BPy_FrsNoise *self)
{
delete self->n;
delete self->pn;
Py_TYPE(self)->tp_free((PyObject *)self);
}
static PyObject *FrsNoise_repr(BPy_FrsNoise *self)
{
return PyUnicode_FromFormat("Noise - address: %p", self->n);
}
PyDoc_STRVAR(
/* Wrap. */
FrsNoise_turbulence1_doc,
".. method:: turbulence1(v, freq, amp, oct=4)\n"
"\n"
" Returns a noise value for a 1D element.\n"
"\n"
" :param v: One-dimensional sample point.\n"
" :type v: float\n"
" :param freq: Noise frequency.\n"
" :type freq: float\n"
" :param amp: Amplitude.\n"
" :type amp: float\n"
" :param oct: Number of octaves.\n"
" :type oct: int\n"
" :return: A noise value.\n"
" :rtype: float\n");
static PyObject *FrsNoise_drand(BPy_FrsNoise * /*self*/, PyObject *args, PyObject *kwds)
{
static const char *kwlist[] = {"seed", nullptr};
long seed = 0;
if (!PyArg_ParseTupleAndKeywords(args, kwds, "|I", (char **)kwlist, &seed)) {
PyErr_SetString(PyExc_TypeError, "optional argument 1 must be of type int");
return nullptr;
}
if (seed) {
RandGen::srand48(seed);
}
return PyFloat_FromDouble(RandGen::drand48());
}
static PyObject *FrsNoise_turbulence_smooth(BPy_FrsNoise *self, PyObject *args, PyObject *kwds)
{
static const char *kwlist[] = {"v", "oct", nullptr};
double x; // NOTE: this has to be a double (not float)
uint nbOctaves = 8;
if (!PyArg_ParseTupleAndKeywords(args, kwds, "d|I", (char **)kwlist, &x, &nbOctaves)) {
return nullptr;
}
return PyFloat_FromDouble(self->pn->turbulenceSmooth(x, nbOctaves));
}
static PyObject *FrsNoise_turbulence1(BPy_FrsNoise *self, PyObject *args, PyObject *kwds)
{
static const char *kwlist[] = {"v", "freq", "amp", "oct", nullptr};
float f1, f2, f3;
uint i = 4;
if (!PyArg_ParseTupleAndKeywords(args, kwds, "fff|I", (char **)kwlist, &f1, &f2, &f3, &i)) {
return nullptr;
}
return PyFloat_FromDouble(self->n->turbulence1(f1, f2, f3, i));
}
PyDoc_STRVAR(
/* Wrap. */
FrsNoise_turbulence2_doc,
".. method:: turbulence2(v, freq, amp, oct=4)\n"
"\n"
" Returns a noise value for a 2D element.\n"
"\n"
" :param v: Two-dimensional sample point.\n"
" :type v: :class:`mathutils.Vector` | tuple[float, float] | list[float]\n"
" :param freq: Noise frequency.\n"
" :type freq: float\n"
" :param amp: Amplitude.\n"
" :type amp: float\n"
" :param oct: Number of octaves.\n"
" :type oct: int\n"
" :return: A noise value.\n"
" :rtype: float\n");
static PyObject *FrsNoise_turbulence2(BPy_FrsNoise *self, PyObject *args, PyObject *kwds)
{
static const char *kwlist[] = {"v", "freq", "amp", "oct", nullptr};
PyObject *obj1;
float f2, f3;
uint i = 4;
Vec2f vec;
if (!PyArg_ParseTupleAndKeywords(args, kwds, "Off|I", (char **)kwlist, &obj1, &f2, &f3, &i)) {
return nullptr;
}
if (!Vec2f_ptr_from_PyObject(obj1, vec)) {
PyErr_SetString(PyExc_TypeError,
"argument 1 must be a 2D vector (either a list of 2 elements or Vector)");
return nullptr;
}
float t = self->n->turbulence2(vec, f2, f3, i);
return PyFloat_FromDouble(t);
}
PyDoc_STRVAR(
/* Wrap. */
FrsNoise_turbulence3_doc,
".. method:: turbulence3(v, freq, amp, oct=4)\n"
"\n"
" Returns a noise value for a 3D element.\n"
"\n"
" :param v: Three-dimensional sample point.\n"
" :type v: :class:`mathutils.Vector` | tuple[float, float, float] | list[float]\n"
" :param freq: Noise frequency.\n"
" :type freq: float\n"
" :param amp: Amplitude.\n"
" :type amp: float\n"
" :param oct: Number of octaves.\n"
" :type oct: int\n"
" :return: A noise value.\n"
" :rtype: float\n");
static PyObject *FrsNoise_turbulence3(BPy_FrsNoise *self, PyObject *args, PyObject *kwds)
{
static const char *kwlist[] = {"v", "freq", "amp", "oct", nullptr};
PyObject *obj1;
float f2, f3;
uint i = 4;
Vec3f vec;
if (!PyArg_ParseTupleAndKeywords(args, kwds, "Off|I", (char **)kwlist, &obj1, &f2, &f3, &i)) {
return nullptr;
}
if (!Vec3f_ptr_from_PyObject(obj1, vec)) {
PyErr_SetString(PyExc_TypeError,
"argument 1 must be a 3D vector (either a list of 3 elements or Vector)");
return nullptr;
}
float t = self->n->turbulence3(vec, f2, f3, i);
return PyFloat_FromDouble(t);
}
PyDoc_STRVAR(
/* Wrap. */
FrsNoise_smoothNoise1_doc,
".. method:: smoothNoise1(v)\n"
"\n"
" Returns a smooth noise value for a 1D element.\n"
"\n"
" :param v: One-dimensional sample point.\n"
" :type v: float\n"
" :return: A smooth noise value.\n"
" :rtype: float\n");
static PyObject *FrsNoise_smoothNoise1(BPy_FrsNoise *self, PyObject *args, PyObject *kwds)
{
static const char *kwlist[] = {"v", nullptr};
float f;
if (!PyArg_ParseTupleAndKeywords(args, kwds, "f", (char **)kwlist, &f)) {
return nullptr;
}
return PyFloat_FromDouble(self->n->smoothNoise1(f));
}
PyDoc_STRVAR(
/* Wrap. */
FrsNoise_smoothNoise2_doc,
".. method:: smoothNoise2(v)\n"
"\n"
" Returns a smooth noise value for a 2D element.\n"
"\n"
" :param v: Two-dimensional sample point.\n"
" :type v: :class:`mathutils.Vector` | tuple[float, float] | list[float]\n"
" :return: A smooth noise value.\n"
" :rtype: float\n");
static PyObject *FrsNoise_smoothNoise2(BPy_FrsNoise *self, PyObject *args, PyObject *kwds)
{
static const char *kwlist[] = {"v", nullptr};
PyObject *obj;
Vec2f vec;
if (!PyArg_ParseTupleAndKeywords(args, kwds, "O", (char **)kwlist, &obj)) {
return nullptr;
}
if (!Vec2f_ptr_from_PyObject(obj, vec)) {
PyErr_SetString(PyExc_TypeError,
"argument 1 must be a 2D vector (either a list of 2 elements or Vector)");
return nullptr;
}
float t = self->n->smoothNoise2(vec);
return PyFloat_FromDouble(t);
}
PyDoc_STRVAR(
/* Wrap. */
FrsNoise_smoothNoise3_doc,
".. method:: smoothNoise3(v)\n"
"\n"
" Returns a smooth noise value for a 3D element.\n"
"\n"
" :param v: Three-dimensional sample point.\n"
" :type v: :class:`mathutils.Vector` | tuple[float, float, float] | list[float]\n"
" :return: A smooth noise value.\n"
" :rtype: float\n");
static PyObject *FrsNoise_smoothNoise3(BPy_FrsNoise *self, PyObject *args, PyObject *kwds)
{
static const char *kwlist[] = {"v", nullptr};
PyObject *obj;
Vec3f vec;
if (!PyArg_ParseTupleAndKeywords(args, kwds, "O", (char **)kwlist, &obj)) {
return nullptr;
}
if (!Vec3f_ptr_from_PyObject(obj, vec)) {
PyErr_SetString(PyExc_TypeError,
"argument 1 must be a 3D vector (either a list of 3 elements or Vector)");
return nullptr;
}
float t = self->n->smoothNoise3(vec);
return PyFloat_FromDouble(t);
}
#ifdef __GNUC__
# ifdef __clang__
# pragma clang diagnostic push
# pragma clang diagnostic ignored "-Wcast-function-type"
# else
# pragma GCC diagnostic push
# pragma GCC diagnostic ignored "-Wcast-function-type"
# endif
#endif
static PyMethodDef BPy_FrsNoise_methods[] = {
{"turbulence1",
(PyCFunction)FrsNoise_turbulence1,
METH_VARARGS | METH_KEYWORDS,
FrsNoise_turbulence1_doc},
{"turbulence2",
(PyCFunction)FrsNoise_turbulence2,
METH_VARARGS | METH_KEYWORDS,
FrsNoise_turbulence2_doc},
{"turbulence3",
(PyCFunction)FrsNoise_turbulence3,
METH_VARARGS | METH_KEYWORDS,
FrsNoise_turbulence3_doc},
{"smoothNoise1",
(PyCFunction)FrsNoise_smoothNoise1,
METH_VARARGS | METH_KEYWORDS,
FrsNoise_smoothNoise1_doc},
{"smoothNoise2",
(PyCFunction)FrsNoise_smoothNoise2,
METH_VARARGS | METH_KEYWORDS,
FrsNoise_smoothNoise2_doc},
{"smoothNoise3",
(PyCFunction)FrsNoise_smoothNoise3,
METH_VARARGS | METH_KEYWORDS,
FrsNoise_smoothNoise3_doc},
{"rand", (PyCFunction)FrsNoise_drand, METH_VARARGS | METH_KEYWORDS, nullptr},
{"turbulence_smooth",
(PyCFunction)FrsNoise_turbulence_smooth,
METH_VARARGS | METH_KEYWORDS,
nullptr},
{nullptr, nullptr, 0, nullptr},
};
#ifdef __GNUC__
# ifdef __clang__
# pragma clang diagnostic pop
# else
# pragma GCC diagnostic pop
# endif
#endif
/*-----------------------BPy_FrsNoise type definition ------------------------------*/
PyTypeObject FrsNoise_Type = {
/*ob_base*/ PyVarObject_HEAD_INIT(nullptr, 0)
/*tp_name*/ "Noise",
/*tp_basicsize*/ sizeof(BPy_FrsNoise),
/*tp_itemsize*/ 0,
/*tp_dealloc*/ (destructor)FrsNoise_dealloc,
/*tp_vectorcall_offset*/ 0,
/*tp_getattr*/ nullptr,
/*tp_setattr*/ nullptr,
/*tp_as_async*/ nullptr,
/*tp_repr*/ (reprfunc)FrsNoise_repr,
/*tp_as_number*/ nullptr,
/*tp_as_sequence*/ nullptr,
/*tp_as_mapping*/ nullptr,
/*tp_hash*/ nullptr,
/*tp_call*/ nullptr,
/*tp_str*/ nullptr,
/*tp_getattro*/ nullptr,
/*tp_setattro*/ nullptr,
/*tp_as_buffer*/ nullptr,
/*tp_flags*/ Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE,
/*tp_doc*/ FrsNoise_doc,
/*tp_traverse*/ nullptr,
/*tp_clear*/ nullptr,
/*tp_richcompare*/ nullptr,
/*tp_weaklistoffset*/ 0,
/*tp_iter*/ nullptr,
/*tp_iternext*/ nullptr,
/*tp_methods*/ BPy_FrsNoise_methods,
/*tp_members*/ nullptr,
/*tp_getset*/ nullptr,
/*tp_base*/ nullptr,
/*tp_dict*/ nullptr,
/*tp_descr_get*/ nullptr,
/*tp_descr_set*/ nullptr,
/*tp_dictoffset*/ 0,
/*tp_init*/ (initproc)FrsNoise_init,
/*tp_alloc*/ nullptr,
/*tp_new*/ PyType_GenericNew,
};
///////////////////////////////////////////////////////////////////////////////////////////

View File

@@ -0,0 +1,35 @@
/* SPDX-FileCopyrightText: 2023 Blender Authors
*
* SPDX-License-Identifier: GPL-2.0-or-later */
/** \file
* \ingroup freestyle
*/
#pragma once
extern "C" {
#include <Python.h>
}
#include "../geometry/Noise.h"
#include "../system/PseudoNoise.h"
///////////////////////////////////////////////////////////////////////////////////////////
extern PyTypeObject FrsNoise_Type;
#define BPy_FrsNoise_Check(v) (PyObject_IsInstance((PyObject *)v, (PyObject *)&FrsNoise_Type))
/*---------------------------Python BPy_FrsNoise structure definition----------*/
struct BPy_FrsNoise {
PyObject_HEAD
Freestyle::Noise *n;
Freestyle::PseudoNoise *pn;
};
/*---------------------------Python BPy_FrsNoise visible prototypes-----------*/
int FrsNoise_Init(PyObject *module);
///////////////////////////////////////////////////////////////////////////////////////////

View File

@@ -0,0 +1,202 @@
/* SPDX-FileCopyrightText: 2004-2023 Blender Authors
*
* SPDX-License-Identifier: GPL-2.0-or-later */
/** \file
* \ingroup freestyle
*/
#include "BPy_Id.h"
#include "BPy_Convert.h"
using namespace Freestyle;
///////////////////////////////////////////////////////////////////////////////////////////
//-------------------MODULE INITIALIZATION--------------------------------
int Id_Init(PyObject *module)
{
if (module == nullptr) {
return -1;
}
if (PyType_Ready(&Id_Type) < 0) {
return -1;
}
PyModule_AddObjectRef(module, "Id", (PyObject *)&Id_Type);
return 0;
}
//------------------------INSTANCE METHODS ----------------------------------
PyDoc_STRVAR(
/* Wrap. */
Id_doc,
"Class for representing an object Id.\n"
"\n"
".. method:: __init__(*args, **kwargs)\n"
"\n"
" Accepted call signatures:\n"
"\n"
" - ``__init__(brother)``\n"
" - ``__init__(first=0, second=0)``\n"
"\n"
" Build the Id from two numbers or another :class:`Id` using the copy constructor.\n"
"\n"
" :param brother: An Id object.\n"
" :type brother: :class:`Id`\n"
" :param first: The first number.\n"
" :type first: int\n"
" :param second: The second number.\n"
" :type second: int\n");
static int Id_init(BPy_Id *self, PyObject *args, PyObject *kwds)
{
static const char *kwlist_1[] = {"brother", nullptr};
static const char *kwlist_2[] = {"first", "second", nullptr};
PyObject *brother;
int first = 0, second = 0;
if (PyArg_ParseTupleAndKeywords(args, kwds, "O!", (char **)kwlist_1, &Id_Type, &brother)) {
self->id = new Id(*(((BPy_Id *)brother)->id));
}
else if ((void)PyErr_Clear(),
PyArg_ParseTupleAndKeywords(args, kwds, "|ii", (char **)kwlist_2, &first, &second))
{
self->id = new Id(first, second);
}
else {
PyErr_SetString(PyExc_TypeError, "invalid argument(s)");
return -1;
}
return 0;
}
static void Id_dealloc(BPy_Id *self)
{
delete self->id;
Py_TYPE(self)->tp_free((PyObject *)self);
}
static PyObject *Id_repr(BPy_Id *self)
{
return PyUnicode_FromFormat(
"[ first: %i, second: %i ](BPy_Id)", self->id->getFirst(), self->id->getSecond());
}
static PyObject *Id_RichCompare(BPy_Id *o1, BPy_Id *o2, int opid)
{
switch (opid) {
case Py_LT:
return PyBool_from_bool(o1->id->operator<(*(o2->id)));
case Py_LE:
return PyBool_from_bool(o1->id->operator<(*(o2->id)) || o1->id->operator==(*(o2->id)));
case Py_EQ:
return PyBool_from_bool(o1->id->operator==(*(o2->id)));
case Py_NE:
return PyBool_from_bool(o1->id->operator!=(*(o2->id)));
case Py_GT:
return PyBool_from_bool(!(o1->id->operator<(*(o2->id)) || o1->id->operator==(*(o2->id))));
case Py_GE:
return PyBool_from_bool(!o1->id->operator<(*(o2->id)));
}
Py_RETURN_NONE;
}
/*----------------------Id get/setters ----------------------------*/
PyDoc_STRVAR(
/* Wrap. */
Id_first_doc,
"The first number constituting the Id.\n"
"\n"
":type: int\n");
static PyObject *Id_first_get(BPy_Id *self, void * /*closure*/)
{
return PyLong_FromLong(self->id->getFirst());
}
static int Id_first_set(BPy_Id *self, PyObject *value, void * /*closure*/)
{
int scalar;
if ((scalar = PyLong_AsLong(value)) == -1 && PyErr_Occurred()) {
PyErr_SetString(PyExc_TypeError, "value must be an integer");
return -1;
}
self->id->setFirst(scalar);
return 0;
}
PyDoc_STRVAR(
/* Wrap. */
Id_second_doc,
"The second number constituting the Id.\n"
"\n"
":type: int\n");
static PyObject *Id_second_get(BPy_Id *self, void * /*closure*/)
{
return PyLong_FromLong(self->id->getSecond());
}
static int Id_second_set(BPy_Id *self, PyObject *value, void * /*closure*/)
{
int scalar;
if ((scalar = PyLong_AsLong(value)) == -1 && PyErr_Occurred()) {
PyErr_SetString(PyExc_TypeError, "value must be an integer");
return -1;
}
self->id->setSecond(scalar);
return 0;
}
static PyGetSetDef BPy_Id_getseters[] = {
{"first", (getter)Id_first_get, (setter)Id_first_set, Id_first_doc, nullptr},
{"second", (getter)Id_second_get, (setter)Id_second_set, Id_second_doc, nullptr},
{nullptr, nullptr, nullptr, nullptr, nullptr} /* Sentinel */
};
/*-----------------------BPy_Id type definition ------------------------------*/
PyTypeObject Id_Type = {
/*ob_base*/ PyVarObject_HEAD_INIT(nullptr, 0)
/*tp_name*/ "Id",
/*tp_basicsize*/ sizeof(BPy_Id),
/*tp_itemsize*/ 0,
/*tp_dealloc*/ (destructor)Id_dealloc,
/*tp_vectorcall_offset*/ 0,
/*tp_getattr*/ nullptr,
/*tp_setattr*/ nullptr,
/*tp_as_async*/ nullptr,
/*tp_repr*/ (reprfunc)Id_repr,
/*tp_as_number*/ nullptr,
/*tp_as_sequence*/ nullptr,
/*tp_as_mapping*/ nullptr,
/*tp_hash*/ nullptr,
/*tp_call*/ nullptr,
/*tp_str*/ nullptr,
/*tp_getattro*/ nullptr,
/*tp_setattro*/ nullptr,
/*tp_as_buffer*/ nullptr,
/*tp_flags*/ Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE,
/*tp_doc*/ Id_doc,
/*tp_traverse*/ nullptr,
/*tp_clear*/ nullptr,
/*tp_richcompare*/ (richcmpfunc)Id_RichCompare,
/*tp_weaklistoffset*/ 0,
/*tp_iter*/ nullptr,
/*tp_iternext*/ nullptr,
/*tp_methods*/ nullptr,
/*tp_members*/ nullptr,
/*tp_getset*/ BPy_Id_getseters,
/*tp_base*/ nullptr,
/*tp_dict*/ nullptr,
/*tp_descr_get*/ nullptr,
/*tp_descr_set*/ nullptr,
/*tp_dictoffset*/ 0,
/*tp_init*/ (initproc)Id_init,
/*tp_alloc*/ nullptr,
/*tp_new*/ PyType_GenericNew,
};
///////////////////////////////////////////////////////////////////////////////////////////

View File

@@ -0,0 +1,35 @@
/* SPDX-FileCopyrightText: 2023 Blender Authors
*
* SPDX-License-Identifier: GPL-2.0-or-later */
/** \file
* \ingroup freestyle
*/
#pragma once
extern "C" {
#include <Python.h>
}
#include <iostream>
#include "../system/Id.h"
///////////////////////////////////////////////////////////////////////////////////////////
extern PyTypeObject Id_Type;
#define BPy_Id_Check(v) (PyObject_IsInstance((PyObject *)v, (PyObject *)&Id_Type))
/*---------------------------Python BPy_Id structure definition----------*/
struct BPy_Id {
PyObject_HEAD
Freestyle::Id *id;
};
/*---------------------------Python BPy_Id visible prototypes-----------*/
int Id_Init(PyObject *module);
///////////////////////////////////////////////////////////////////////////////////////////

View File

@@ -0,0 +1,267 @@
/* SPDX-FileCopyrightText: 2004-2023 Blender Authors
*
* SPDX-License-Identifier: GPL-2.0-or-later */
/** \file
* \ingroup freestyle
*/
#include "BPy_IntegrationType.h"
#include "BPy_Convert.h"
#include "Iterator/BPy_Interface0DIterator.h"
#include "UnaryFunction0D/BPy_UnaryFunction0DDouble.h"
#include "UnaryFunction0D/BPy_UnaryFunction0DFloat.h"
#include "UnaryFunction0D/BPy_UnaryFunction0DUnsigned.h"
#include "BLI_sys_types.h"
using namespace Freestyle;
///////////////////////////////////////////////////////////////////////////////////////////
//------------------------ MODULE FUNCTIONS ----------------------------------
PyDoc_STRVAR(
/* Wrap. */
Integrator_integrate_doc,
".. function:: integrate(func, it, it_end, integration_type)\n"
"\n"
" Returns a single value from a set of values evaluated at each 0D\n"
" element of this 1D element.\n"
"\n"
" :param func: The UnaryFunction0D used to compute a value at each\n"
" Interface0D.\n"
" :type func: :class:`UnaryFunction0D`\n"
" :param it: The Interface0DIterator used to iterate over the 0D\n"
" elements of this 1D element. The integration will occur over\n"
" the 0D elements starting from the one pointed by it.\n"
" :type it: :class:`Interface0DIterator`\n"
" :param it_end: The Interface0DIterator pointing the end of the 0D\n"
" elements of the 1D element.\n"
" :type it_end: :class:`Interface0DIterator`\n"
" :param integration_type: The integration method used to compute a\n"
" single value from a set of values.\n"
" :type integration_type: :class:`IntegrationType`\n"
" :return: The single value obtained for the 1D element. The return\n"
" value type is float if func is of the :class:`UnaryFunction0DDouble`\n"
" or :class:`UnaryFunction0DFloat` type, and int if func is of the\n"
" :class:`UnaryFunction0DUnsigned` type.\n"
" :rtype: int | float\n");
static PyObject *Integrator_integrate(PyObject * /*self*/, PyObject *args, PyObject *kwds)
{
static const char *kwlist[] = {"func", "it", "it_end", "integration_type", nullptr};
PyObject *obj1, *obj4 = nullptr;
BPy_Interface0DIterator *obj2, *obj3;
if (!PyArg_ParseTupleAndKeywords(args,
kwds,
"O!O!O!|O!",
(char **)kwlist,
&UnaryFunction0D_Type,
&obj1,
&Interface0DIterator_Type,
&obj2,
&Interface0DIterator_Type,
&obj3,
&IntegrationType_Type,
&obj4))
{
return nullptr;
}
Interface0DIterator it(*(obj2->if0D_it)), it_end(*(obj3->if0D_it));
IntegrationType t = (obj4) ? IntegrationType_from_BPy_IntegrationType(obj4) : MEAN;
if (BPy_UnaryFunction0DDouble_Check(obj1)) {
UnaryFunction0D<double> *fun = ((BPy_UnaryFunction0DDouble *)obj1)->uf0D_double;
double res = integrate(*fun, it, it_end, t);
return PyFloat_FromDouble(res);
}
if (BPy_UnaryFunction0DFloat_Check(obj1)) {
UnaryFunction0D<float> *fun = ((BPy_UnaryFunction0DFloat *)obj1)->uf0D_float;
float res = integrate(*fun, it, it_end, t);
return PyFloat_FromDouble(res);
}
if (BPy_UnaryFunction0DUnsigned_Check(obj1)) {
UnaryFunction0D<uint> *fun = ((BPy_UnaryFunction0DUnsigned *)obj1)->uf0D_unsigned;
uint res = integrate(*fun, it, it_end, t);
return PyLong_FromLong(res);
}
string class_name(Py_TYPE(obj1)->tp_name);
PyErr_SetString(PyExc_TypeError, ("unsupported function type: " + class_name).c_str());
return nullptr;
}
/*-----------------------Integrator module docstring---------------------------------------*/
PyDoc_STRVAR(
/* Wrap. */
module_docstring,
"The Blender Freestyle.Integrator submodule\n"
"\n");
/*-----------------------Integrator module functions definitions---------------------------*/
#ifdef __GNUC__
# ifdef __clang__
# pragma clang diagnostic push
# pragma clang diagnostic ignored "-Wcast-function-type"
# else
# pragma GCC diagnostic push
# pragma GCC diagnostic ignored "-Wcast-function-type"
# endif
#endif
static PyMethodDef module_functions[] = {
{"integrate",
(PyCFunction)Integrator_integrate,
METH_VARARGS | METH_KEYWORDS,
Integrator_integrate_doc},
{nullptr, nullptr, 0, nullptr},
};
#ifdef __GNUC__
# ifdef __clang__
# pragma clang diagnostic pop
# else
# pragma GCC diagnostic pop
# endif
#endif
/*-----------------------Integrator module definition--------------------------------------*/
static PyModuleDef module_definition = {
/*m_base*/ PyModuleDef_HEAD_INIT,
/*m_name*/ "Freestyle.Integrator",
/*m_doc*/ module_docstring,
/*m_size*/ -1,
/*m_methods*/ module_functions,
/*m_slots*/ nullptr,
/*m_traverse*/ nullptr,
/*m_clear*/ nullptr,
/*m_free*/ nullptr,
};
/*-----------------------BPy_IntegrationType type definition ------------------------------*/
PyDoc_STRVAR(
/* Wrap. */
IntegrationType_doc,
"Class hierarchy: int > :class:`IntegrationType`\n"
"\n"
"Different integration methods that can be invoked to integrate into a\n"
"single value the set of values obtained from each 0D element of an 1D\n"
"element.\n"
"\n"
".. attribute:: MEAN\n"
"\n"
" The value computed for the 1D element is the mean of the values\n"
" obtained for the 0D elements.\n"
"\n"
".. attribute:: MIN\n"
"\n"
" The value computed for the 1D element is the minimum of the values\n"
" obtained for the 0D elements.\n"
"\n"
".. attribute:: MAX\n"
"\n"
" The value computed for the 1D element is the maximum of the values\n"
" obtained for the 0D elements.\n"
"\n"
".. attribute:: FIRST\n"
"\n"
" The value computed for the 1D element is the first of the values\n"
" obtained for the 0D elements.\n"
"\n"
".. attribute:: LAST\n"
"\n"
" The value computed for the 1D element is the last of the values\n"
" obtained for the 0D elements.\n");
PyTypeObject IntegrationType_Type = {
/*ob_base*/ PyVarObject_HEAD_INIT(nullptr, 0)
/*tp_name*/ "IntegrationType",
/*tp_basicsize*/ sizeof(PyLongObject),
/*tp_itemsize*/ 0,
/*tp_dealloc*/ nullptr,
/*tp_vectorcall_offset*/ 0,
/*tp_getattr*/ nullptr,
/*tp_setattr*/ nullptr,
/*tp_as_async*/ nullptr,
/*tp_repr*/ nullptr,
/*tp_as_number*/ nullptr,
/*tp_as_sequence*/ nullptr,
/*tp_as_mapping*/ nullptr,
/*tp_hash*/ nullptr,
/*tp_call*/ nullptr,
/*tp_str*/ nullptr,
/*tp_getattro*/ nullptr,
/*tp_setattro*/ nullptr,
/*tp_as_buffer*/ nullptr,
/*tp_flags*/ Py_TPFLAGS_DEFAULT,
/*tp_doc*/ IntegrationType_doc,
/*tp_traverse*/ nullptr,
/*tp_clear*/ nullptr,
/*tp_richcompare*/ nullptr,
/*tp_weaklistoffset*/ 0,
/*tp_iter*/ nullptr,
/*tp_iternext*/ nullptr,
/*tp_methods*/ nullptr,
/*tp_members*/ nullptr,
/*tp_getset*/ nullptr,
/*tp_base*/ &PyLong_Type,
/*tp_dict*/ nullptr,
/*tp_descr_get*/ nullptr,
/*tp_descr_set*/ nullptr,
/*tp_dictoffset*/ 0,
/*tp_init*/ nullptr,
/*tp_alloc*/ nullptr,
/*tp_new*/ nullptr,
};
/*-----------------------BPy_IntegrationType instance definitions -------------------------*/
//-------------------MODULE INITIALIZATION--------------------------------
int IntegrationType_Init(PyObject *module)
{
PyObject *m, *d, *f;
if (module == nullptr) {
return -1;
}
if (PyType_Ready(&IntegrationType_Type) < 0) {
return -1;
}
PyModule_AddObjectRef(module, "IntegrationType", (PyObject *)&IntegrationType_Type);
#define ADD_TYPE_CONST(id) \
PyLong_subtype_add_to_dict( \
IntegrationType_Type.tp_dict, &IntegrationType_Type, STRINGIFY(id), id)
ADD_TYPE_CONST(MEAN);
ADD_TYPE_CONST(MIN);
ADD_TYPE_CONST(MAX);
ADD_TYPE_CONST(FIRST);
ADD_TYPE_CONST(LAST);
#undef ADD_TYPE_CONST
m = PyModule_Create(&module_definition);
if (m == nullptr) {
return -1;
}
PyModule_AddObjectRef(module, "Integrator", m);
// from Integrator import *
d = PyModule_GetDict(m);
for (PyMethodDef *p = module_functions; p->ml_name; p++) {
f = PyDict_GetItemString(d, p->ml_name);
PyModule_AddObjectRef(module, p->ml_name, f);
}
return 0;
}
///////////////////////////////////////////////////////////////////////////////////////////

View File

@@ -0,0 +1,28 @@
/* SPDX-FileCopyrightText: 2023 Blender Authors
*
* SPDX-License-Identifier: GPL-2.0-or-later */
/** \file
* \ingroup freestyle
*/
#pragma once
extern "C" {
#include <Python.h>
}
#include "../view_map/Interface1D.h"
///////////////////////////////////////////////////////////////////////////////////////////
extern PyTypeObject IntegrationType_Type;
#define BPy_IntegrationType_Check(v) \
(PyObject_IsInstance((PyObject *)v, (PyObject *)&IntegrationType_Type))
/*---------------------------Python BPy_IntegrationType visible prototypes-----------*/
int IntegrationType_Init(PyObject *module);
///////////////////////////////////////////////////////////////////////////////////////////

View File

@@ -0,0 +1,359 @@
/* SPDX-FileCopyrightText: 2004-2023 Blender Authors
*
* SPDX-License-Identifier: GPL-2.0-or-later */
/** \file
* \ingroup freestyle
*/
#include "BPy_Interface0D.h"
#include "BPy_Convert.h"
#include "BPy_Nature.h"
#include "Interface0D/BPy_CurvePoint.h"
#include "Interface0D/BPy_SVertex.h"
#include "Interface0D/BPy_ViewVertex.h"
#include "Interface0D/CurvePoint/BPy_StrokeVertex.h"
#include "Interface0D/ViewVertex/BPy_NonTVertex.h"
#include "Interface0D/ViewVertex/BPy_TVertex.h"
#include "Interface1D/BPy_FEdge.h"
using namespace Freestyle;
///////////////////////////////////////////////////////////////////////////////////////////
//-------------------MODULE INITIALIZATION--------------------------------
int Interface0D_Init(PyObject *module)
{
if (module == nullptr) {
return -1;
}
if (PyType_Ready(&Interface0D_Type) < 0) {
return -1;
}
PyModule_AddObjectRef(module, "Interface0D", (PyObject *)&Interface0D_Type);
if (PyType_Ready(&CurvePoint_Type) < 0) {
return -1;
}
PyModule_AddObjectRef(module, "CurvePoint", (PyObject *)&CurvePoint_Type);
if (PyType_Ready(&SVertex_Type) < 0) {
return -1;
}
PyModule_AddObjectRef(module, "SVertex", (PyObject *)&SVertex_Type);
if (PyType_Ready(&ViewVertex_Type) < 0) {
return -1;
}
PyModule_AddObjectRef(module, "ViewVertex", (PyObject *)&ViewVertex_Type);
if (PyType_Ready(&StrokeVertex_Type) < 0) {
return -1;
}
PyModule_AddObjectRef(module, "StrokeVertex", (PyObject *)&StrokeVertex_Type);
if (PyType_Ready(&NonTVertex_Type) < 0) {
return -1;
}
PyModule_AddObjectRef(module, "NonTVertex", (PyObject *)&NonTVertex_Type);
if (PyType_Ready(&TVertex_Type) < 0) {
return -1;
}
PyModule_AddObjectRef(module, "TVertex", (PyObject *)&TVertex_Type);
SVertex_mathutils_register_callback();
StrokeVertex_mathutils_register_callback();
return 0;
}
/*----------------------Interface1D methods ----------------------------*/
PyDoc_STRVAR(
/* Wrap. */
Interface0D_doc,
"Base class for any 0D element.\n"
"\n"
".. method:: __init__()\n"
"\n"
" Default constructor.\n");
static int Interface0D_init(BPy_Interface0D *self, PyObject *args, PyObject *kwds)
{
static const char *kwlist[] = {nullptr};
if (!PyArg_ParseTupleAndKeywords(args, kwds, "", (char **)kwlist)) {
return -1;
}
self->if0D = new Interface0D();
self->borrowed = false;
return 0;
}
static void Interface0D_dealloc(BPy_Interface0D *self)
{
if (self->if0D && !self->borrowed) {
delete self->if0D;
}
Py_TYPE(self)->tp_free((PyObject *)self);
}
static PyObject *Interface0D_repr(BPy_Interface0D *self)
{
return PyUnicode_FromFormat(
"type: %s - address: %p", self->if0D->getExactTypeName().c_str(), self->if0D);
}
PyDoc_STRVAR(
/* Wrap. */
Interface0D_get_fedge_doc,
".. method:: get_fedge(inter)\n"
"\n"
" Returns the FEdge that lies between this 0D element and the 0D\n"
" element given as the argument.\n"
"\n"
" :param inter: A 0D element.\n"
" :type inter: :class:`Interface0D`\n"
" :return: The FEdge lying between the two 0D elements.\n"
" :rtype: :class:`FEdge`\n");
static PyObject *Interface0D_get_fedge(BPy_Interface0D *self, PyObject *args, PyObject *kwds)
{
static const char *kwlist[] = {"inter", nullptr};
PyObject *py_if0D;
if (!PyArg_ParseTupleAndKeywords(args, kwds, "O!", (char **)kwlist, &Interface0D_Type, &py_if0D))
{
return nullptr;
}
FEdge *fe = self->if0D->getFEdge(*(((BPy_Interface0D *)py_if0D)->if0D));
if (PyErr_Occurred()) {
return nullptr;
}
if (fe) {
return Any_BPy_FEdge_from_FEdge(*fe);
}
Py_RETURN_NONE;
}
#ifdef __GNUC__
# ifdef __clang__
# pragma clang diagnostic push
# pragma clang diagnostic ignored "-Wcast-function-type"
# else
# pragma GCC diagnostic push
# pragma GCC diagnostic ignored "-Wcast-function-type"
# endif
#endif
static PyMethodDef BPy_Interface0D_methods[] = {
{"get_fedge",
(PyCFunction)Interface0D_get_fedge,
METH_VARARGS | METH_KEYWORDS,
Interface0D_get_fedge_doc},
{nullptr, nullptr, 0, nullptr},
};
#ifdef __GNUC__
# ifdef __clang__
# pragma clang diagnostic pop
# else
# pragma GCC diagnostic pop
# endif
#endif
/*----------------------Interface1D get/setters ----------------------------*/
PyDoc_STRVAR(
/* Wrap. */
Interface0D_name_doc,
"The string of the name of this 0D element.\n"
"\n"
":type: str\n");
static PyObject *Interface0D_name_get(BPy_Interface0D *self, void * /*closure*/)
{
return PyUnicode_FromString(Py_TYPE(self)->tp_name);
}
PyDoc_STRVAR(
/* Wrap. */
Interface0D_point_3d_doc,
"The 3D point of this 0D element.\n"
"\n"
":type: :class:`mathutils.Vector`\n");
static PyObject *Interface0D_point_3d_get(BPy_Interface0D *self, void * /*closure*/)
{
Vec3f p(self->if0D->getPoint3D());
if (PyErr_Occurred()) {
return nullptr;
}
return Vector_from_Vec3f(p);
}
PyDoc_STRVAR(
/* Wrap. */
Interface0D_projected_x_doc,
"The X coordinate of the projected 3D point of this 0D element.\n"
"\n"
":type: float\n");
static PyObject *Interface0D_projected_x_get(BPy_Interface0D *self, void * /*closure*/)
{
real x = self->if0D->getProjectedX();
if (PyErr_Occurred()) {
return nullptr;
}
return PyFloat_FromDouble(x);
}
PyDoc_STRVAR(
/* Wrap. */
Interface0D_projected_y_doc,
"The Y coordinate of the projected 3D point of this 0D element.\n"
"\n"
":type: float\n");
static PyObject *Interface0D_projected_y_get(BPy_Interface0D *self, void * /*closure*/)
{
real y = self->if0D->getProjectedY();
if (PyErr_Occurred()) {
return nullptr;
}
return PyFloat_FromDouble(y);
}
PyDoc_STRVAR(
/* Wrap. */
Interface0D_projected_z_doc,
"The Z coordinate of the projected 3D point of this 0D element.\n"
"\n"
":type: float\n");
static PyObject *Interface0D_projected_z_get(BPy_Interface0D *self, void * /*closure*/)
{
real z = self->if0D->getProjectedZ();
if (PyErr_Occurred()) {
return nullptr;
}
return PyFloat_FromDouble(z);
}
PyDoc_STRVAR(
/* Wrap. */
Interface0D_point_2d_doc,
"The 2D point of this 0D element.\n"
"\n"
":type: :class:`mathutils.Vector`\n");
static PyObject *Interface0D_point_2d_get(BPy_Interface0D *self, void * /*closure*/)
{
Vec2f p(self->if0D->getPoint2D());
if (PyErr_Occurred()) {
return nullptr;
}
return Vector_from_Vec2f(p);
}
PyDoc_STRVAR(
/* Wrap. */
Interface0D_id_doc,
"The Id of this 0D element.\n"
"\n"
":type: :class:`Id`\n");
static PyObject *Interface0D_id_get(BPy_Interface0D *self, void * /*closure*/)
{
Id id(self->if0D->getId());
if (PyErr_Occurred()) {
return nullptr;
}
return BPy_Id_from_Id(id); // return a copy
}
PyDoc_STRVAR(
/* Wrap. */
Interface0D_nature_doc,
"The nature of this 0D element.\n"
"\n"
":type: :class:`Nature`\n");
static PyObject *Interface0D_nature_get(BPy_Interface0D *self, void * /*closure*/)
{
Nature::VertexNature nature = self->if0D->getNature();
if (PyErr_Occurred()) {
return nullptr;
}
return BPy_Nature_from_Nature(nature);
}
static PyGetSetDef BPy_Interface0D_getseters[] = {
{"name", (getter)Interface0D_name_get, (setter) nullptr, Interface0D_name_doc, nullptr},
{"point_3d",
(getter)Interface0D_point_3d_get,
(setter) nullptr,
Interface0D_point_3d_doc,
nullptr},
{"projected_x",
(getter)Interface0D_projected_x_get,
(setter) nullptr,
Interface0D_projected_x_doc,
nullptr},
{"projected_y",
(getter)Interface0D_projected_y_get,
(setter) nullptr,
Interface0D_projected_y_doc,
nullptr},
{"projected_z",
(getter)Interface0D_projected_z_get,
(setter) nullptr,
Interface0D_projected_z_doc,
nullptr},
{"point_2d",
(getter)Interface0D_point_2d_get,
(setter) nullptr,
Interface0D_point_2d_doc,
nullptr},
{"id", (getter)Interface0D_id_get, (setter) nullptr, Interface0D_id_doc, nullptr},
{"nature", (getter)Interface0D_nature_get, (setter) nullptr, Interface0D_nature_doc, nullptr},
{nullptr, nullptr, nullptr, nullptr, nullptr} /* Sentinel */
};
/*-----------------------BPy_Interface0D type definition ------------------------------*/
PyTypeObject Interface0D_Type = {
/*ob_base*/ PyVarObject_HEAD_INIT(nullptr, 0)
/*tp_name*/ "Interface0D",
/*tp_basicsize*/ sizeof(BPy_Interface0D),
/*tp_itemsize*/ 0,
/*tp_dealloc*/ (destructor)Interface0D_dealloc,
/*tp_vectorcall_offset*/ 0,
/*tp_getattr*/ nullptr,
/*tp_setattr*/ nullptr,
/*tp_as_async*/ nullptr,
/*tp_repr*/ (reprfunc)Interface0D_repr,
/*tp_as_number*/ nullptr,
/*tp_as_sequence*/ nullptr,
/*tp_as_mapping*/ nullptr,
/*tp_hash*/ nullptr,
/*tp_call*/ nullptr,
/*tp_str*/ nullptr,
/*tp_getattro*/ nullptr,
/*tp_setattro*/ nullptr,
/*tp_as_buffer*/ nullptr,
/*tp_flags*/ Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE,
/*tp_doc*/ Interface0D_doc,
/*tp_traverse*/ nullptr,
/*tp_clear*/ nullptr,
/*tp_richcompare*/ nullptr,
/*tp_weaklistoffset*/ 0,
/*tp_iter*/ nullptr,
/*tp_iternext*/ nullptr,
/*tp_methods*/ BPy_Interface0D_methods,
/*tp_members*/ nullptr,
/*tp_getset*/ BPy_Interface0D_getseters,
/*tp_base*/ nullptr,
/*tp_dict*/ nullptr,
/*tp_descr_get*/ nullptr,
/*tp_descr_set*/ nullptr,
/*tp_dictoffset*/ 0,
/*tp_init*/ (initproc)Interface0D_init,
/*tp_alloc*/ nullptr,
/*tp_new*/ PyType_GenericNew,
};
///////////////////////////////////////////////////////////////////////////////////////////

View File

@@ -0,0 +1,35 @@
/* SPDX-FileCopyrightText: 2023 Blender Authors
*
* SPDX-License-Identifier: GPL-2.0-or-later */
/** \file
* \ingroup freestyle
*/
#pragma once
extern "C" {
#include <Python.h>
}
#include "../view_map/Interface0D.h"
///////////////////////////////////////////////////////////////////////////////////////////
extern PyTypeObject Interface0D_Type;
#define BPy_Interface0D_Check(v) \
(PyObject_IsInstance((PyObject *)v, (PyObject *)&Interface0D_Type))
/*---------------------------Python BPy_Interface0D structure definition----------*/
struct BPy_Interface0D {
PyObject_HEAD
Freestyle::Interface0D *if0D;
bool borrowed; /* true if *if0D is a borrowed object */
};
/*---------------------------Python BPy_Interface0D visible prototypes-----------*/
int Interface0D_Init(PyObject *module);
///////////////////////////////////////////////////////////////////////////////////////////

View File

@@ -0,0 +1,387 @@
/* SPDX-FileCopyrightText: 2004-2022 Blender Authors
*
* SPDX-License-Identifier: GPL-2.0-or-later */
/** \file
* \ingroup freestyle
*/
#include "BPy_Interface1D.h"
#include "BPy_Convert.h"
#include "Interface1D/BPy_FEdge.h"
#include "Interface1D/BPy_FrsCurve.h"
#include "Interface1D/BPy_Stroke.h"
#include "Interface1D/BPy_ViewEdge.h"
#include "Interface1D/Curve/BPy_Chain.h"
#include "Interface1D/FEdge/BPy_FEdgeSharp.h"
#include "Interface1D/FEdge/BPy_FEdgeSmooth.h"
#include "BPy_MediumType.h"
using namespace Freestyle;
///////////////////////////////////////////////////////////////////////////////////////////
//-------------------MODULE INITIALIZATION--------------------------------
int Interface1D_Init(PyObject *module)
{
if (module == nullptr) {
return -1;
}
if (PyType_Ready(&Interface1D_Type) < 0) {
return -1;
}
PyModule_AddObjectRef(module, "Interface1D", (PyObject *)&Interface1D_Type);
if (PyType_Ready(&FrsCurve_Type) < 0) {
return -1;
}
PyModule_AddObjectRef(module, "Curve", (PyObject *)&FrsCurve_Type);
if (PyType_Ready(&Chain_Type) < 0) {
return -1;
}
PyModule_AddObjectRef(module, "Chain", (PyObject *)&Chain_Type);
if (PyType_Ready(&FEdge_Type) < 0) {
return -1;
}
PyModule_AddObjectRef(module, "FEdge", (PyObject *)&FEdge_Type);
if (PyType_Ready(&FEdgeSharp_Type) < 0) {
return -1;
}
PyModule_AddObjectRef(module, "FEdgeSharp", (PyObject *)&FEdgeSharp_Type);
if (PyType_Ready(&FEdgeSmooth_Type) < 0) {
return -1;
}
PyModule_AddObjectRef(module, "FEdgeSmooth", (PyObject *)&FEdgeSmooth_Type);
if (PyType_Ready(&Stroke_Type) < 0) {
return -1;
}
PyModule_AddObjectRef(module, "Stroke", (PyObject *)&Stroke_Type);
#define ADD_TYPE_CONST(id) \
PyLong_subtype_add_to_dict(Stroke_Type.tp_dict, &MediumType_Type, STRINGIFY(id), Stroke::id)
ADD_TYPE_CONST(DRY_MEDIUM);
ADD_TYPE_CONST(HUMID_MEDIUM);
ADD_TYPE_CONST(OPAQUE_MEDIUM);
#undef ADD_TYPE_CONST
if (PyType_Ready(&ViewEdge_Type) < 0) {
return -1;
}
PyModule_AddObjectRef(module, "ViewEdge", (PyObject *)&ViewEdge_Type);
FEdgeSharp_mathutils_register_callback();
FEdgeSmooth_mathutils_register_callback();
return 0;
}
/*----------------------Interface1D methods ----------------------------*/
PyDoc_STRVAR(
/* Wrap. */
Interface1D_doc,
"Base class for any 1D element.\n"
"\n"
".. method:: __init__()\n"
"\n"
" Default constructor.\n");
static int Interface1D_init(BPy_Interface1D *self, PyObject *args, PyObject *kwds)
{
static const char *kwlist[] = {nullptr};
if (!PyArg_ParseTupleAndKeywords(args, kwds, "", (char **)kwlist)) {
return -1;
}
self->if1D = new Interface1D();
self->borrowed = false;
return 0;
}
static void Interface1D_dealloc(BPy_Interface1D *self)
{
if (self->if1D && !self->borrowed) {
delete self->if1D;
}
Py_TYPE(self)->tp_free((PyObject *)self);
}
static PyObject *Interface1D_repr(BPy_Interface1D *self)
{
return PyUnicode_FromFormat(
"type: %s - address: %p", self->if1D->getExactTypeName().c_str(), self->if1D);
}
PyDoc_STRVAR(
/* Wrap. */
Interface1D_vertices_begin_doc,
".. method:: vertices_begin()\n"
"\n"
" Returns an iterator over the Interface1D vertices, pointing to the\n"
" first vertex.\n"
"\n"
" :return: An Interface0DIterator pointing to the first vertex.\n"
" :rtype: :class:`Interface0DIterator`\n");
static PyObject *Interface1D_vertices_begin(BPy_Interface1D *self)
{
Interface0DIterator if0D_it(self->if1D->verticesBegin());
return BPy_Interface0DIterator_from_Interface0DIterator(if0D_it, false);
}
PyDoc_STRVAR(
/* Wrap. */
Interface1D_vertices_end_doc,
".. method:: vertices_end()\n"
"\n"
" Returns an iterator over the Interface1D vertices, pointing after\n"
" the last vertex.\n"
"\n"
" :return: An Interface0DIterator pointing after the last vertex.\n"
" :rtype: :class:`Interface0DIterator`\n");
static PyObject *Interface1D_vertices_end(BPy_Interface1D *self)
{
Interface0DIterator if0D_it(self->if1D->verticesEnd());
return BPy_Interface0DIterator_from_Interface0DIterator(if0D_it, true);
}
PyDoc_STRVAR(
/* Wrap. */
Interface1D_points_begin_doc,
".. method:: points_begin(t=0.0)\n"
"\n"
" Returns an iterator over the Interface1D points, pointing to the\n"
" first point. The difference with vertices_begin() is that here we can\n"
" iterate over points of the 1D element at a any given sampling.\n"
" Indeed, for each iteration, a virtual point is created.\n"
"\n"
" :param t: A sampling with which we want to iterate over points of\n"
" this 1D element.\n"
" :type t: float\n"
" :return: An Interface0DIterator pointing to the first point.\n"
" :rtype: :class:`Interface0DIterator`\n");
static PyObject *Interface1D_points_begin(BPy_Interface1D *self, PyObject *args, PyObject *kwds)
{
static const char *kwlist[] = {"t", nullptr};
float f = 0.0f;
if (!PyArg_ParseTupleAndKeywords(args, kwds, "|f", (char **)kwlist, &f)) {
return nullptr;
}
Interface0DIterator if0D_it(self->if1D->pointsBegin(f));
return BPy_Interface0DIterator_from_Interface0DIterator(if0D_it, false);
}
PyDoc_STRVAR(
/* Wrap. */
Interface1D_points_end_doc,
".. method:: points_end(t=0.0)\n"
"\n"
" Returns an iterator over the Interface1D points, pointing after the\n"
" last point. The difference with vertices_end() is that here we can\n"
" iterate over points of the 1D element at a given sampling. Indeed,\n"
" for each iteration, a virtual point is created.\n"
"\n"
" :param t: A sampling with which we want to iterate over points of\n"
" this 1D element.\n"
" :type t: float\n"
" :return: An Interface0DIterator pointing after the last point.\n"
" :rtype: :class:`Interface0DIterator`\n");
static PyObject *Interface1D_points_end(BPy_Interface1D *self, PyObject *args, PyObject *kwds)
{
static const char *kwlist[] = {"t", nullptr};
float f = 0.0f;
if (!PyArg_ParseTupleAndKeywords(args, kwds, "|f", (char **)kwlist, &f)) {
return nullptr;
}
Interface0DIterator if0D_it(self->if1D->pointsEnd(f));
return BPy_Interface0DIterator_from_Interface0DIterator(if0D_it, true);
}
#ifdef __GNUC__
# ifdef __clang__
# pragma clang diagnostic push
# pragma clang diagnostic ignored "-Wcast-function-type"
# else
# pragma GCC diagnostic push
# pragma GCC diagnostic ignored "-Wcast-function-type"
# endif
#endif
static PyMethodDef BPy_Interface1D_methods[] = {
{"vertices_begin",
(PyCFunction)Interface1D_vertices_begin,
METH_NOARGS,
Interface1D_vertices_begin_doc},
{"vertices_end",
(PyCFunction)Interface1D_vertices_end,
METH_NOARGS,
Interface1D_vertices_end_doc},
{"points_begin",
(PyCFunction)Interface1D_points_begin,
METH_VARARGS | METH_KEYWORDS,
Interface1D_points_begin_doc},
{"points_end",
(PyCFunction)Interface1D_points_end,
METH_VARARGS | METH_KEYWORDS,
Interface1D_points_end_doc},
{nullptr, nullptr, 0, nullptr},
};
#ifdef __GNUC__
# ifdef __clang__
# pragma clang diagnostic pop
# else
# pragma GCC diagnostic pop
# endif
#endif
/*----------------------Interface1D get/setters ----------------------------*/
PyDoc_STRVAR(
/* Wrap. */
Interface1D_name_doc,
"The string of the name of the 1D element.\n"
"\n"
":type: str\n");
static PyObject *Interface1D_name_get(BPy_Interface1D *self, void * /*closure*/)
{
return PyUnicode_FromString(Py_TYPE(self)->tp_name);
}
PyDoc_STRVAR(
/* Wrap. */
Interface1D_id_doc,
"The Id of this Interface1D.\n"
"\n"
":type: :class:`Id`\n");
static PyObject *Interface1D_id_get(BPy_Interface1D *self, void * /*closure*/)
{
Id id(self->if1D->getId());
if (PyErr_Occurred()) {
return nullptr;
}
return BPy_Id_from_Id(id); // return a copy
}
PyDoc_STRVAR(
/* Wrap. */
Interface1D_nature_doc,
"The nature of this Interface1D.\n"
"\n"
":type: :class:`Nature`\n");
static PyObject *Interface1D_nature_get(BPy_Interface1D *self, void * /*closure*/)
{
Nature::VertexNature nature = self->if1D->getNature();
if (PyErr_Occurred()) {
return nullptr;
}
return BPy_Nature_from_Nature(nature);
}
PyDoc_STRVAR(
/* Wrap. */
Interface1D_length_2d_doc,
"The 2D length of this Interface1D.\n"
"\n"
":type: float\n");
static PyObject *Interface1D_length_2d_get(BPy_Interface1D *self, void * /*closure*/)
{
real length = self->if1D->getLength2D();
if (PyErr_Occurred()) {
return nullptr;
}
return PyFloat_FromDouble(double(length));
}
PyDoc_STRVAR(
/* Wrap. */
Interface1D_time_stamp_doc,
"The time stamp of the 1D element, mainly used for selection.\n"
"\n"
":type: int\n");
static PyObject *Interface1D_time_stamp_get(BPy_Interface1D *self, void * /*closure*/)
{
return PyLong_FromLong(self->if1D->getTimeStamp());
}
static int Interface1D_time_stamp_set(BPy_Interface1D *self, PyObject *value, void * /*closure*/)
{
int timestamp;
if ((timestamp = PyLong_AsLong(value)) == -1 && PyErr_Occurred()) {
PyErr_SetString(PyExc_TypeError, "value must be a number");
return -1;
}
self->if1D->setTimeStamp(timestamp);
return 0;
}
static PyGetSetDef BPy_Interface1D_getseters[] = {
{"name", (getter)Interface1D_name_get, (setter) nullptr, Interface1D_name_doc, nullptr},
{"id", (getter)Interface1D_id_get, (setter) nullptr, Interface1D_id_doc, nullptr},
{"nature", (getter)Interface1D_nature_get, (setter) nullptr, Interface1D_nature_doc, nullptr},
{"length_2d",
(getter)Interface1D_length_2d_get,
(setter) nullptr,
Interface1D_length_2d_doc,
nullptr},
{"time_stamp",
(getter)Interface1D_time_stamp_get,
(setter)Interface1D_time_stamp_set,
Interface1D_time_stamp_doc,
nullptr},
{nullptr, nullptr, nullptr, nullptr, nullptr} /* Sentinel */
};
/*-----------------------BPy_Interface1D type definition ------------------------------*/
PyTypeObject Interface1D_Type = {
/*ob_base*/ PyVarObject_HEAD_INIT(nullptr, 0)
/*tp_name*/ "Interface1D",
/*tp_basicsize*/ sizeof(BPy_Interface1D),
/*tp_itemsize*/ 0,
/*tp_dealloc*/ (destructor)Interface1D_dealloc,
/*tp_vectorcall_offset*/ 0,
/*tp_getattr*/ nullptr,
/*tp_setattr*/ nullptr,
/*tp_as_async*/ nullptr,
/*tp_repr*/ (reprfunc)Interface1D_repr,
/*tp_as_number*/ nullptr,
/*tp_as_sequence*/ nullptr,
/*tp_as_mapping*/ nullptr,
/*tp_hash*/ nullptr,
/*tp_call*/ nullptr,
/*tp_str*/ nullptr,
/*tp_getattro*/ nullptr,
/*tp_setattro*/ nullptr,
/*tp_as_buffer*/ nullptr,
/*tp_flags*/ Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE,
/*tp_doc*/ Interface1D_doc,
/*tp_traverse*/ nullptr,
/*tp_clear*/ nullptr,
/*tp_richcompare*/ nullptr,
/*tp_weaklistoffset*/ 0,
/*tp_iter*/ nullptr,
/*tp_iternext*/ nullptr,
/*tp_methods*/ BPy_Interface1D_methods,
/*tp_members*/ nullptr,
/*tp_getset*/ BPy_Interface1D_getseters,
/*tp_base*/ nullptr,
/*tp_dict*/ nullptr,
/*tp_descr_get*/ nullptr,
/*tp_descr_set*/ nullptr,
/*tp_dictoffset*/ 0,
/*tp_init*/ (initproc)Interface1D_init,
/*tp_alloc*/ nullptr,
/*tp_new*/ PyType_GenericNew,
};
///////////////////////////////////////////////////////////////////////////////////////////

View File

@@ -0,0 +1,35 @@
/* SPDX-FileCopyrightText: 2023 Blender Authors
*
* SPDX-License-Identifier: GPL-2.0-or-later */
/** \file
* \ingroup freestyle
*/
#pragma once
extern "C" {
#include <Python.h>
}
#include "../view_map/Interface1D.h"
///////////////////////////////////////////////////////////////////////////////////////////
extern PyTypeObject Interface1D_Type;
#define BPy_Interface1D_Check(v) \
(PyObject_IsInstance((PyObject *)v, (PyObject *)&Interface1D_Type))
/*---------------------------Python BPy_Interface1D structure definition----------*/
struct BPy_Interface1D {
PyObject_HEAD
Freestyle::Interface1D *if1D;
bool borrowed; /* true if *if1D is a borrowed object */
};
/*---------------------------Python BPy_Interface1D visible prototypes-----------*/
int Interface1D_Init(PyObject *module);
///////////////////////////////////////////////////////////////////////////////////////////

View File

@@ -0,0 +1,268 @@
/* SPDX-FileCopyrightText: 2004-2022 Blender Authors
*
* SPDX-License-Identifier: GPL-2.0-or-later */
/** \file
* \ingroup freestyle
*/
#include "BPy_Iterator.h"
#include "BPy_Convert.h"
#include "Iterator/BPy_AdjacencyIterator.h"
#include "Iterator/BPy_ChainPredicateIterator.h"
#include "Iterator/BPy_ChainSilhouetteIterator.h"
#include "Iterator/BPy_ChainingIterator.h"
#include "Iterator/BPy_CurvePointIterator.h"
#include "Iterator/BPy_Interface0DIterator.h"
#include "Iterator/BPy_SVertexIterator.h"
#include "Iterator/BPy_StrokeVertexIterator.h"
#include "Iterator/BPy_ViewEdgeIterator.h"
#include "Iterator/BPy_orientedViewEdgeIterator.h"
using namespace Freestyle;
///////////////////////////////////////////////////////////////////////////////////////////
//-------------------MODULE INITIALIZATION--------------------------------
int Iterator_Init(PyObject *module)
{
if (module == nullptr) {
return -1;
}
if (PyType_Ready(&Iterator_Type) < 0) {
return -1;
}
PyModule_AddObjectRef(module, "Iterator", (PyObject *)&Iterator_Type);
if (PyType_Ready(&AdjacencyIterator_Type) < 0) {
return -1;
}
PyModule_AddObjectRef(module, "AdjacencyIterator", (PyObject *)&AdjacencyIterator_Type);
if (PyType_Ready(&Interface0DIterator_Type) < 0) {
return -1;
}
PyModule_AddObjectRef(module, "Interface0DIterator", (PyObject *)&Interface0DIterator_Type);
if (PyType_Ready(&CurvePointIterator_Type) < 0) {
return -1;
}
PyModule_AddObjectRef(module, "CurvePointIterator", (PyObject *)&CurvePointIterator_Type);
if (PyType_Ready(&StrokeVertexIterator_Type) < 0) {
return -1;
}
PyModule_AddObjectRef(module, "StrokeVertexIterator", (PyObject *)&StrokeVertexIterator_Type);
if (PyType_Ready(&SVertexIterator_Type) < 0) {
return -1;
}
PyModule_AddObjectRef(module, "SVertexIterator", (PyObject *)&SVertexIterator_Type);
if (PyType_Ready(&orientedViewEdgeIterator_Type) < 0) {
return -1;
}
PyModule_AddObjectRef(
module, "orientedViewEdgeIterator", (PyObject *)&orientedViewEdgeIterator_Type);
if (PyType_Ready(&ViewEdgeIterator_Type) < 0) {
return -1;
}
PyModule_AddObjectRef(module, "ViewEdgeIterator", (PyObject *)&ViewEdgeIterator_Type);
if (PyType_Ready(&ChainingIterator_Type) < 0) {
return -1;
}
PyModule_AddObjectRef(module, "ChainingIterator", (PyObject *)&ChainingIterator_Type);
if (PyType_Ready(&ChainPredicateIterator_Type) < 0) {
return -1;
}
PyModule_AddObjectRef(
module, "ChainPredicateIterator", (PyObject *)&ChainPredicateIterator_Type);
if (PyType_Ready(&ChainSilhouetteIterator_Type) < 0) {
return -1;
}
PyModule_AddObjectRef(
module, "ChainSilhouetteIterator", (PyObject *)&ChainSilhouetteIterator_Type);
return 0;
}
//------------------------INSTANCE METHODS ----------------------------------
PyDoc_STRVAR(
/* Wrap. */
Iterator_doc,
"Base class to define iterators.\n"
"\n"
".. method:: __init__()\n"
"\n"
" Default constructor.\n");
static int Iterator_init(BPy_Iterator *self, PyObject *args, PyObject *kwds)
{
static const char *kwlist[] = {nullptr};
if (!PyArg_ParseTupleAndKeywords(args, kwds, "", (char **)kwlist)) {
return -1;
}
self->it = new Iterator();
return 0;
}
static void Iterator_dealloc(BPy_Iterator *self)
{
delete self->it;
Py_TYPE(self)->tp_free((PyObject *)self);
}
static PyObject *Iterator_repr(BPy_Iterator *self)
{
return PyUnicode_FromFormat("type: %s - address: %p", Py_TYPE(self)->tp_name, self->it);
}
PyDoc_STRVAR(
/* Wrap. */
Iterator_increment_doc,
".. method:: increment()\n"
"\n"
" Makes the iterator point the next element.\n");
static PyObject *Iterator_increment(BPy_Iterator *self)
{
if (self->it->isEnd()) {
PyErr_SetString(PyExc_RuntimeError, "cannot increment any more");
return nullptr;
}
self->it->increment();
Py_RETURN_NONE;
}
PyDoc_STRVAR(
/* Wrap. */
Iterator_decrement_doc,
".. method:: decrement()\n"
"\n"
" Makes the iterator point the previous element.\n");
static PyObject *Iterator_decrement(BPy_Iterator *self)
{
if (self->it->isBegin()) {
PyErr_SetString(PyExc_RuntimeError, "cannot decrement any more");
return nullptr;
}
self->it->decrement();
Py_RETURN_NONE;
}
#ifdef __GNUC__
# ifdef __clang__
# pragma clang diagnostic push
# pragma clang diagnostic ignored "-Wcast-function-type"
# else
# pragma GCC diagnostic push
# pragma GCC diagnostic ignored "-Wcast-function-type"
# endif
#endif
static PyMethodDef BPy_Iterator_methods[] = {
{"increment", (PyCFunction)Iterator_increment, METH_NOARGS, Iterator_increment_doc},
{"decrement", (PyCFunction)Iterator_decrement, METH_NOARGS, Iterator_decrement_doc},
{nullptr, nullptr, 0, nullptr},
};
#ifdef __GNUC__
# ifdef __clang__
# pragma clang diagnostic pop
# else
# pragma GCC diagnostic pop
# endif
#endif
/*----------------------Iterator get/setters ----------------------------*/
PyDoc_STRVAR(
/* Wrap. */
Iterator_name_doc,
"The string of the name of this iterator.\n"
"\n"
":type: str\n");
static PyObject *Iterator_name_get(BPy_Iterator *self, void * /*closure*/)
{
return PyUnicode_FromString(Py_TYPE(self)->tp_name);
}
PyDoc_STRVAR(
/* Wrap. */
Iterator_is_begin_doc,
"True if the iterator points to the first element.\n"
"\n"
":type: bool\n");
static PyObject *Iterator_is_begin_get(BPy_Iterator *self, void * /*closure*/)
{
return PyBool_from_bool(self->it->isBegin());
}
PyDoc_STRVAR(
/* Wrap. */
Iterator_is_end_doc,
"True if the iterator points to the last element.\n"
"\n"
":type: bool\n");
static PyObject *Iterator_is_end_get(BPy_Iterator *self, void * /*closure*/)
{
return PyBool_from_bool(self->it->isEnd());
}
static PyGetSetDef BPy_Iterator_getseters[] = {
{"name", (getter)Iterator_name_get, (setter) nullptr, Iterator_name_doc, nullptr},
{"is_begin", (getter)Iterator_is_begin_get, (setter) nullptr, Iterator_is_begin_doc, nullptr},
{"is_end", (getter)Iterator_is_end_get, (setter) nullptr, Iterator_is_end_doc, nullptr},
{nullptr, nullptr, nullptr, nullptr, nullptr} /* Sentinel */
};
/*-----------------------BPy_Iterator type definition ------------------------------*/
PyTypeObject Iterator_Type = {
/*ob_base*/ PyVarObject_HEAD_INIT(nullptr, 0)
/*tp_name*/ "Iterator",
/*tp_basicsize*/ sizeof(BPy_Iterator),
/*tp_itemsize*/ 0,
/*tp_dealloc*/ (destructor)Iterator_dealloc,
/*tp_vectorcall_offset*/ 0,
/*tp_getattr*/ nullptr,
/*tp_setattr*/ nullptr,
/*tp_as_async*/ nullptr,
/*tp_repr*/ (reprfunc)Iterator_repr,
/*tp_as_number*/ nullptr,
/*tp_as_sequence*/ nullptr,
/*tp_as_mapping*/ nullptr,
/*tp_hash*/ nullptr,
/*tp_call*/ nullptr,
/*tp_str*/ nullptr,
/*tp_getattro*/ nullptr,
/*tp_setattro*/ nullptr,
/*tp_as_buffer*/ nullptr,
/*tp_flags*/ Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE,
/*tp_doc*/ Iterator_doc,
/*tp_traverse*/ nullptr,
/*tp_clear*/ nullptr,
/*tp_richcompare*/ nullptr,
/*tp_weaklistoffset*/ 0,
/*tp_iter*/ nullptr,
/*tp_iternext*/ nullptr,
/*tp_methods*/ BPy_Iterator_methods,
/*tp_members*/ nullptr,
/*tp_getset*/ BPy_Iterator_getseters,
/*tp_base*/ nullptr,
/*tp_dict*/ nullptr,
/*tp_descr_get*/ nullptr,
/*tp_descr_set*/ nullptr,
/*tp_dictoffset*/ 0,
/*tp_init*/ (initproc)Iterator_init,
/*tp_alloc*/ nullptr,
/*tp_new*/ PyType_GenericNew,
};
///////////////////////////////////////////////////////////////////////////////////////////

View File

@@ -0,0 +1,33 @@
/* SPDX-FileCopyrightText: 2023 Blender Authors
*
* SPDX-License-Identifier: GPL-2.0-or-later */
/** \file
* \ingroup freestyle
*/
#pragma once
extern "C" {
#include <Python.h>
}
#include "../system/Iterator.h"
///////////////////////////////////////////////////////////////////////////////////////////
extern PyTypeObject Iterator_Type;
#define BPy_Iterator_Check(v) (PyObject_IsInstance((PyObject *)v, (PyObject *)&Iterator_Type))
/*---------------------------Python BPy_Iterator structure definition----------*/
struct BPy_Iterator {
PyObject_HEAD
Freestyle::Iterator *it;
};
/*---------------------------Python BPy_Iterator visible prototypes-----------*/
int Iterator_Init(PyObject *module);
///////////////////////////////////////////////////////////////////////////////////////////

View File

@@ -0,0 +1,89 @@
/* SPDX-FileCopyrightText: 2004-2022 Blender Authors
*
* SPDX-License-Identifier: GPL-2.0-or-later */
/** \file
* \ingroup freestyle
*/
#include "BPy_MediumType.h"
#include "BPy_Convert.h"
using namespace Freestyle;
///////////////////////////////////////////////////////////////////////////////////////////
/*-----------------------BPy_MediumType type definition ------------------------------*/
PyDoc_STRVAR(
/* Wrap. */
MediumType_doc,
"Class hierarchy: int > :class:`MediumType`\n"
"\n"
"The different blending modes available to simulate the interaction\n"
"media-medium:\n"
"\n"
"* Stroke.DRY_MEDIUM: To simulate a dry medium such as Pencil or Charcoal.\n"
"* Stroke.HUMID_MEDIUM: To simulate ink painting (color subtraction blending).\n"
"* Stroke.OPAQUE_MEDIUM: To simulate an opaque medium (oil, spray...).\n");
PyTypeObject MediumType_Type = {
/*ob_base*/ PyVarObject_HEAD_INIT(nullptr, 0)
/*tp_name*/ "MediumType",
/*tp_basicsize*/ sizeof(PyLongObject),
/*tp_itemsize*/ 0,
/*tp_dealloc*/ nullptr,
/*tp_vectorcall_offset*/ 0,
/*tp_getattr*/ nullptr,
/*tp_setattr*/ nullptr,
/*tp_as_async*/ nullptr,
/*tp_repr*/ nullptr,
/*tp_as_number*/ nullptr,
/*tp_as_sequence*/ nullptr,
/*tp_as_mapping*/ nullptr,
/*tp_hash*/ nullptr,
/*tp_call*/ nullptr,
/*tp_str*/ nullptr,
/*tp_getattro*/ nullptr,
/*tp_setattro*/ nullptr,
/*tp_as_buffer*/ nullptr,
/*tp_flags*/ Py_TPFLAGS_DEFAULT,
/*tp_doc*/ MediumType_doc,
/*tp_traverse*/ nullptr,
/*tp_clear*/ nullptr,
/*tp_richcompare*/ nullptr,
/*tp_weaklistoffset*/ 0,
/*tp_iter*/ nullptr,
/*tp_iternext*/ nullptr,
/*tp_methods*/ nullptr,
/*tp_members*/ nullptr,
/*tp_getset*/ nullptr,
/*tp_base*/ &PyLong_Type,
/*tp_dict*/ nullptr,
/*tp_descr_get*/ nullptr,
/*tp_descr_set*/ nullptr,
/*tp_dictoffset*/ 0,
/*tp_init*/ nullptr,
/*tp_alloc*/ nullptr,
/*tp_new*/ nullptr,
};
/*-----------------------BPy_IntegrationType instance definitions -------------------------*/
//-------------------MODULE INITIALIZATION--------------------------------
int MediumType_Init(PyObject *module)
{
if (module == nullptr) {
return -1;
}
if (PyType_Ready(&MediumType_Type) < 0) {
return -1;
}
PyModule_AddObjectRef(module, "MediumType", (PyObject *)&MediumType_Type);
return 0;
}
///////////////////////////////////////////////////////////////////////////////////////////

View File

@@ -0,0 +1,32 @@
/* SPDX-FileCopyrightText: 2023 Blender Authors
*
* SPDX-License-Identifier: GPL-2.0-or-later */
/** \file
* \ingroup freestyle
*/
#pragma once
extern "C" {
#include <Python.h>
}
#include "../stroke/Stroke.h"
///////////////////////////////////////////////////////////////////////////////////////////
extern PyTypeObject MediumType_Type;
#define BPy_MediumType_Check(v) (PyObject_IsInstance((PyObject *)v, (PyObject *)&MediumType_Type))
/*---------------------------Python BPy_MediumType structure definition----------*/
struct BPy_MediumType {
PyLongObject i;
};
/*---------------------------Python BPy_MediumType visible prototypes-----------*/
int MediumType_Init(PyObject *module);
///////////////////////////////////////////////////////////////////////////////////////////

View File

@@ -0,0 +1,265 @@
/* SPDX-FileCopyrightText: 2004-2023 Blender Authors
*
* SPDX-License-Identifier: GPL-2.0-or-later */
/** \file
* \ingroup freestyle
*/
#include "BPy_Nature.h"
#include "BPy_Convert.h"
using namespace Freestyle;
///////////////////////////////////////////////////////////////////////////////////////////
static PyObject *BPy_Nature_and(PyObject *a, PyObject *b);
static PyObject *BPy_Nature_xor(PyObject *a, PyObject *b);
static PyObject *BPy_Nature_or(PyObject *a, PyObject *b);
/*-----------------------BPy_Nature number method definitions --------------------*/
static PyNumberMethods nature_as_number = {
/*nb_add*/ nullptr,
/*nb_subtract*/ nullptr,
/*nb_multiply*/ nullptr,
/*nb_remainder*/ nullptr,
/*nb_divmod*/ nullptr,
/*nb_power*/ nullptr,
/*nb_negative*/ nullptr,
/*nb_positive*/ nullptr,
/*nb_absolute*/ nullptr,
/*nb_bool*/ nullptr,
/*nb_invert*/ nullptr,
/*nb_lshift*/ nullptr,
/*nb_rshift*/ nullptr,
/*nb_and*/ (binaryfunc)BPy_Nature_and,
/*nb_xor*/ (binaryfunc)BPy_Nature_xor,
/*nb_or*/ (binaryfunc)BPy_Nature_or,
/*nb_int*/ nullptr,
/*nb_reserved*/ nullptr,
/*nb_float*/ nullptr,
/*nb_inplace_add*/ nullptr,
/*nb_inplace_subtract*/ nullptr,
/*nb_inplace_multiply*/ nullptr,
/*nb_inplace_remainder*/ nullptr,
/*nb_inplace_power*/ nullptr,
/*nb_inplace_lshift*/ nullptr,
/*nb_inplace_rshift*/ nullptr,
/*nb_inplace_and*/ nullptr,
/*nb_inplace_xor*/ nullptr,
/*nb_inplace_or*/ nullptr,
/*nb_floor_divide*/ nullptr,
/*nb_true_divide*/ nullptr,
/*nb_inplace_floor_divide*/ nullptr,
/*nb_inplace_true_divide*/ nullptr,
/*nb_index*/ nullptr,
/*nb_matrix_multiply*/ nullptr,
/*nb_inplace_matrix_multiply*/ nullptr,
};
/*-----------------------BPy_Nature type definition ------------------------------*/
PyDoc_STRVAR(
/* Wrap. */
Nature_doc,
"Class hierarchy: int > :class:`Nature`\n"
"\n"
"Different possible natures of 0D and 1D elements of the ViewMap.\n"
"\n"
"Vertex natures:\n"
"\n"
".. attribute:: POINT\n"
"\n"
" True for any 0D element.\n"
"\n"
".. attribute:: S_VERTEX\n"
"\n"
" True for SVertex.\n"
"\n"
".. attribute:: VIEW_VERTEX\n"
"\n"
" True for ViewVertex.\n"
"\n"
".. attribute:: NON_T_VERTEX\n"
"\n"
" True for NonTVertex.\n"
"\n"
".. attribute:: T_VERTEX\n"
"\n"
" True for TVertex.\n"
"\n"
".. attribute:: CUSP\n"
"\n"
" True for CUSP.\n"
"\n"
"Edge natures:\n"
"\n"
".. attribute:: NO_FEATURE\n"
"\n"
" True for non feature edges (always false for 1D elements of the ViewMap).\n"
"\n"
".. attribute:: SILHOUETTE\n"
"\n"
" True for silhouettes.\n"
"\n"
".. attribute:: BORDER\n"
"\n"
" True for borders.\n"
"\n"
".. attribute:: CREASE\n"
"\n"
" True for creases.\n"
"\n"
".. attribute:: RIDGE\n"
"\n"
" True for ridges.\n"
"\n"
".. attribute:: VALLEY\n"
"\n"
" True for valleys.\n"
"\n"
".. attribute:: SUGGESTIVE_CONTOUR\n"
"\n"
" True for suggestive contours.\n"
"\n"
".. attribute:: MATERIAL_BOUNDARY\n"
"\n"
" True for edges at material boundaries.\n"
"\n"
".. attribute:: EDGE_MARK\n"
"\n"
" True for edges having user-defined edge marks.\n");
PyTypeObject Nature_Type = {
/*ob_base*/ PyVarObject_HEAD_INIT(nullptr, 0)
/*tp_name*/ "Nature",
/*tp_basicsize*/ sizeof(PyLongObject),
/*tp_itemsize*/ 0,
/*tp_dealloc*/ nullptr,
/*tp_vectorcall_offset*/ 0,
/*tp_getattr*/ nullptr,
/*tp_setattr*/ nullptr,
/*tp_as_async*/ nullptr,
/*tp_repr*/ nullptr,
/*tp_as_number*/ &nature_as_number,
/*tp_as_sequence*/ nullptr,
/*tp_as_mapping*/ nullptr,
/*tp_hash*/ nullptr,
/*tp_call*/ nullptr,
/*tp_str*/ nullptr,
/*tp_getattro*/ nullptr,
/*tp_setattro*/ nullptr,
/*tp_as_buffer*/ nullptr,
/*tp_flags*/ Py_TPFLAGS_DEFAULT,
/*tp_doc*/ Nature_doc,
/*tp_traverse*/ nullptr,
/*tp_clear*/ nullptr,
/*tp_richcompare*/ nullptr,
/*tp_weaklistoffset*/ 0,
/*tp_iter*/ nullptr,
/*tp_iternext*/ nullptr,
/*tp_methods*/ nullptr,
/*tp_members*/ nullptr,
/*tp_getset*/ nullptr,
/*tp_base*/ &PyLong_Type,
/*tp_dict*/ nullptr,
/*tp_descr_get*/ nullptr,
/*tp_descr_set*/ nullptr,
/*tp_dictoffset*/ 0,
/*tp_init*/ nullptr,
/*tp_alloc*/ nullptr,
/*tp_new*/ nullptr,
};
/*-----------------------BPy_Nature instance definitions ----------------------------------*/
//-------------------MODULE INITIALIZATION--------------------------------
int Nature_Init(PyObject *module)
{
if (module == nullptr) {
return -1;
}
if (PyType_Ready(&Nature_Type) < 0) {
return -1;
}
PyModule_AddObjectRef(module, "Nature", (PyObject *)&Nature_Type);
#define ADD_TYPE_CONST(id) \
PyLong_subtype_add_to_dict(Nature_Type.tp_dict, &Nature_Type, STRINGIFY(id), Nature::id)
// VertexNature
ADD_TYPE_CONST(POINT);
ADD_TYPE_CONST(S_VERTEX);
ADD_TYPE_CONST(VIEW_VERTEX);
ADD_TYPE_CONST(NON_T_VERTEX);
ADD_TYPE_CONST(T_VERTEX);
ADD_TYPE_CONST(CUSP);
// EdgeNature
ADD_TYPE_CONST(NO_FEATURE);
ADD_TYPE_CONST(SILHOUETTE);
ADD_TYPE_CONST(BORDER);
ADD_TYPE_CONST(CREASE);
ADD_TYPE_CONST(RIDGE);
ADD_TYPE_CONST(VALLEY);
ADD_TYPE_CONST(SUGGESTIVE_CONTOUR);
ADD_TYPE_CONST(MATERIAL_BOUNDARY);
ADD_TYPE_CONST(EDGE_MARK);
#undef ADD_TYPE_CONST
return 0;
}
static PyObject *BPy_Nature_bitwise(PyObject *a, int op, PyObject *b)
{
long op1, op2, v;
if (!BPy_Nature_Check(a) || !BPy_Nature_Check(b)) {
PyErr_SetString(PyExc_TypeError, "operands must be a Nature object");
return nullptr;
}
if ((op1 = PyLong_AsLong(a)) == -1 && PyErr_Occurred()) {
PyErr_SetString(PyExc_ValueError, "operand 1: unexpected Nature value");
return nullptr;
}
if ((op2 = PyLong_AsLong(b)) == -1 && PyErr_Occurred()) {
PyErr_SetString(PyExc_ValueError, "operand 2: unexpected Nature value");
return nullptr;
}
switch (op) {
case '&':
v = op1 & op2;
break;
case '^':
v = op1 ^ op2;
break;
case '|':
v = op1 | op2;
break;
default:
PyErr_BadArgument();
return nullptr;
}
return PyLong_subtype_new(&Nature_Type, v);
}
static PyObject *BPy_Nature_and(PyObject *a, PyObject *b)
{
return BPy_Nature_bitwise(a, '&', b);
}
static PyObject *BPy_Nature_xor(PyObject *a, PyObject *b)
{
return BPy_Nature_bitwise(a, '^', b);
}
static PyObject *BPy_Nature_or(PyObject *a, PyObject *b)
{
return BPy_Nature_bitwise(a, '|', b);
}
///////////////////////////////////////////////////////////////////////////////////////////

View File

@@ -0,0 +1,32 @@
/* SPDX-FileCopyrightText: 2023 Blender Authors
*
* SPDX-License-Identifier: GPL-2.0-or-later */
/** \file
* \ingroup freestyle
*/
#pragma once
extern "C" {
#include <Python.h>
}
#include "../winged_edge/Nature.h"
///////////////////////////////////////////////////////////////////////////////////////////
extern PyTypeObject Nature_Type;
#define BPy_Nature_Check(v) (PyObject_IsInstance((PyObject *)v, (PyObject *)&Nature_Type))
/*---------------------------Python BPy_Nature structure definition----------*/
struct BPy_Nature {
PyLongObject i;
};
/*---------------------------Python BPy_Nature visible prototypes-----------*/
int Nature_Init(PyObject *module);
///////////////////////////////////////////////////////////////////////////////////////////

View File

@@ -0,0 +1,854 @@
/* SPDX-FileCopyrightText: 2004-2023 Blender Authors
*
* SPDX-License-Identifier: GPL-2.0-or-later */
/** \file
* \ingroup freestyle
*/
#include "BPy_Operators.h"
#include "BPy_BinaryPredicate1D.h"
#include "BPy_Convert.h"
#include "BPy_StrokeShader.h"
#include "BPy_UnaryPredicate0D.h"
#include "BPy_UnaryPredicate1D.h"
#include "Iterator/BPy_ChainingIterator.h"
#include "Iterator/BPy_ViewEdgeIterator.h"
#include "UnaryFunction0D/BPy_UnaryFunction0DDouble.h"
#include "UnaryFunction1D/BPy_UnaryFunction1DVoid.h"
#include "BLI_sys_types.h"
#include <sstream>
using namespace Freestyle;
///////////////////////////////////////////////////////////////////////////////////////////
//-------------------MODULE INITIALIZATION--------------------------------
int Operators_Init(PyObject *module)
{
if (module == nullptr) {
return -1;
}
if (PyType_Ready(&Operators_Type) < 0) {
return -1;
}
PyModule_AddObjectRef(module, "Operators", (PyObject *)&Operators_Type);
return 0;
}
//------------------------INSTANCE METHODS ----------------------------------
PyDoc_STRVAR(
/* Wrap. */
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 void Operators_dealloc(BPy_Operators *self)
{
Py_TYPE(self)->tp_free((PyObject *)self);
}
PyDoc_STRVAR(
/* Wrap. */
Operators_select_doc,
".. staticmethod:: select(pred)\n"
"\n"
" Selects the ViewEdges of the ViewMap verifying a specified\n"
" condition.\n"
"\n"
" :param pred: The predicate expressing this condition.\n"
" :type pred: :class:`UnaryPredicate1D`\n");
static PyObject *Operators_select(BPy_Operators * /*self*/, PyObject *args, PyObject *kwds)
{
static const char *kwlist[] = {"pred", nullptr};
PyObject *obj = nullptr;
if (!PyArg_ParseTupleAndKeywords(
args, kwds, "O!", (char **)kwlist, &UnaryPredicate1D_Type, &obj))
{
return nullptr;
}
if (!((BPy_UnaryPredicate1D *)obj)->up1D) {
PyErr_SetString(PyExc_TypeError,
"Operators.select(): 1st argument: invalid UnaryPredicate1D object");
return nullptr;
}
if (Operators::select(*(((BPy_UnaryPredicate1D *)obj)->up1D)) < 0) {
if (!PyErr_Occurred()) {
PyErr_SetString(PyExc_RuntimeError, "Operators.select() failed");
}
return nullptr;
}
Py_RETURN_NONE;
}
PyDoc_STRVAR(
/* Wrap. */
Operators_chain_doc,
".. staticmethod:: chain(*args)\n"
"\n"
" Accepted call signatures:\n"
"\n"
" - ``chain(it, pred, modifier)``\n"
" - ``chain(it, pred)``\n"
"\n"
" Builds a set of chains from the current set of ViewEdges. Each\n"
" ViewEdge of the current list starts a new chain. The chaining\n"
" operator then iterates over the ViewEdges of the ViewMap using the\n"
" user specified iterator. This operator only iterates using the\n"
" increment operator and is therefore unidirectional.\n"
"\n"
" :param it: The iterator on the ViewEdges of the ViewMap. It contains\n"
" the chaining rule.\n"
" :type it: :class:`ViewEdgeIterator`\n"
" :param pred: The predicate on the ViewEdge that expresses the\n"
" stopping condition.\n"
" :type pred: :class:`UnaryPredicate1D`\n"
" :param modifier: A function that takes a ViewEdge as argument and\n"
" that is used to modify the processed ViewEdge state (the\n"
" timestamp incrementation is a typical illustration of such a modifier).\n"
" If this argument is not given, the time stamp is automatically managed.\n"
" :type modifier: :class:`UnaryFunction1DVoid`\n");
static PyObject *Operators_chain(BPy_Operators * /*self*/, PyObject *args, PyObject *kwds)
{
static const char *kwlist[] = {"it", "pred", "modifier", nullptr};
PyObject *obj1 = nullptr, *obj2 = nullptr, *obj3 = nullptr;
if (!PyArg_ParseTupleAndKeywords(args,
kwds,
"O!O!|O!",
(char **)kwlist,
&ChainingIterator_Type,
&obj1,
&UnaryPredicate1D_Type,
&obj2,
&UnaryFunction1DVoid_Type,
&obj3))
{
return nullptr;
}
if (!((BPy_ChainingIterator *)obj1)->c_it) {
PyErr_SetString(PyExc_TypeError,
"Operators.chain(): 1st argument: invalid ChainingIterator object");
return nullptr;
}
if (!((BPy_UnaryPredicate1D *)obj2)->up1D) {
PyErr_SetString(PyExc_TypeError,
"Operators.chain(): 2nd argument: invalid UnaryPredicate1D object");
return nullptr;
}
if (!obj3) {
if (Operators::chain(*(((BPy_ChainingIterator *)obj1)->c_it),
*(((BPy_UnaryPredicate1D *)obj2)->up1D)) < 0)
{
if (!PyErr_Occurred()) {
PyErr_SetString(PyExc_RuntimeError, "Operators.chain() failed");
}
return nullptr;
}
}
else {
if (!((BPy_UnaryFunction1DVoid *)obj3)->uf1D_void) {
PyErr_SetString(PyExc_TypeError,
"Operators.chain(): 3rd argument: invalid UnaryFunction1DVoid object");
return nullptr;
}
if (Operators::chain(*(((BPy_ChainingIterator *)obj1)->c_it),
*(((BPy_UnaryPredicate1D *)obj2)->up1D),
*(((BPy_UnaryFunction1DVoid *)obj3)->uf1D_void)) < 0)
{
if (!PyErr_Occurred()) {
PyErr_SetString(PyExc_RuntimeError, "Operators.chain() failed");
}
return nullptr;
}
}
Py_RETURN_NONE;
}
PyDoc_STRVAR(
/* Wrap. */
Operators_bidirectional_chain_doc,
".. staticmethod:: bidirectional_chain(*args)\n"
"\n"
" Accepted call signatures:\n"
"\n"
" - ``bidirectional_chain(it, pred)``\n"
" - ``bidirectional_chain(it)``\n"
"\n"
" Builds a set of chains from the current set of ViewEdges. Each\n"
" ViewEdge of the current list potentially starts a new chain. The\n"
" chaining operator then iterates over the ViewEdges of the ViewMap\n"
" using the user specified iterator. This operator iterates both using\n"
" the increment and decrement operators and is therefore bidirectional.\n"
" This operator works with a ChainingIterator which contains the\n"
" chaining rules. It is this last one which can be told to chain only\n"
" edges that belong to the selection or not to process twice a ViewEdge\n"
" during the chaining. Each time a ViewEdge is added to a chain, its\n"
" chaining time stamp is incremented. This allows you to keep track of\n"
" the number of chains to which a ViewEdge belongs to.\n"
"\n"
" :param it: The ChainingIterator on the ViewEdges of the ViewMap. It\n"
" contains the chaining rule.\n"
" :type it: :class:`ChainingIterator`\n"
" :param pred: The predicate on the ViewEdge that expresses the stopping condition.\n"
" This parameter is optional, you make not want to pass a stopping criterion\n"
" when the stopping criterion is already contained in the iterator definition.\n"
" :type pred: :class:`UnaryPredicate1D`\n");
static PyObject *Operators_bidirectional_chain(BPy_Operators * /*self*/,
PyObject *args,
PyObject *kwds)
{
static const char *kwlist[] = {"it", "pred", nullptr};
PyObject *obj1 = nullptr, *obj2 = nullptr;
if (!PyArg_ParseTupleAndKeywords(args,
kwds,
"O!|O!",
(char **)kwlist,
&ChainingIterator_Type,
&obj1,
&UnaryPredicate1D_Type,
&obj2))
{
return nullptr;
}
if (!((BPy_ChainingIterator *)obj1)->c_it) {
PyErr_SetString(
PyExc_TypeError,
"Operators.bidirectional_chain(): 1st argument: invalid ChainingIterator object");
return nullptr;
}
if (!obj2) {
if (Operators::bidirectionalChain(*(((BPy_ChainingIterator *)obj1)->c_it)) < 0) {
if (!PyErr_Occurred()) {
PyErr_SetString(PyExc_RuntimeError, "Operators.bidirectional_chain() failed");
}
return nullptr;
}
}
else {
if (!((BPy_UnaryPredicate1D *)obj2)->up1D) {
PyErr_SetString(
PyExc_TypeError,
"Operators.bidirectional_chain(): 2nd argument: invalid UnaryPredicate1D object");
return nullptr;
}
if (Operators::bidirectionalChain(*(((BPy_ChainingIterator *)obj1)->c_it),
*(((BPy_UnaryPredicate1D *)obj2)->up1D)) < 0)
{
if (!PyErr_Occurred()) {
PyErr_SetString(PyExc_RuntimeError, "Operators.bidirectional_chain() failed");
}
return nullptr;
}
}
Py_RETURN_NONE;
}
PyDoc_STRVAR(
/* Wrap. */
Operators_sequential_split_doc,
".. staticmethod:: sequential_split(*args, **kwargs)\n"
"\n"
" Accepted call signatures:\n"
"\n"
" - ``sequential_split(starting_pred, stopping_pred, sampling=0.0)``\n"
" - ``sequential_split(pred, sampling=0.0)``\n"
"\n"
" Splits each chain of the current set of chains in a sequential way.\n"
" The points of each chain are processed (with a specified sampling)\n"
" sequentially. The first point of the initial chain is the\n"
" first point of one of the resulting chains. The splitting ends when\n"
" no more chain can start.\n"
"\n"
" .. tip::\n"
"\n"
" By specifying a starting and stopping predicate allows\n"
" the chains to overlap rather than chains partitioning.\n"
"\n"
" :param starting_pred: The predicate on a point that expresses the\n"
" starting condition. Each time this condition is verified, a new chain begins\n"
" :type starting_pred: :class:`UnaryPredicate0D`\n"
" :param stopping_pred: The predicate on a point that expresses the\n"
" stopping condition. The chain ends as soon as this predicate is verified.\n"
" :type stopping_pred: :class:`UnaryPredicate0D`\n"
" :param pred: The predicate on a point that expresses the splitting condition.\n"
" Each time the condition is verified, the chain is split into two chains.\n"
" The resulting set of chains is a partition of the initial chain\n"
" :type pred: :class:`UnaryPredicate0D`\n"
" :param sampling: The resolution used to sample the chain for the\n"
" predicates evaluation. (The chain is not actually resampled;\n"
" a virtual point only progresses along the curve using this\n"
" resolution.)\n"
" :type sampling: float\n");
static PyObject *Operators_sequential_split(BPy_Operators * /*self*/,
PyObject *args,
PyObject *kwds)
{
static const char *kwlist_1[] = {"starting_pred", "stopping_pred", "sampling", nullptr};
static const char *kwlist_2[] = {"pred", "sampling", nullptr};
PyObject *obj1 = nullptr, *obj2 = nullptr;
float f = 0.0f;
if (PyArg_ParseTupleAndKeywords(args,
kwds,
"O!O!|f",
(char **)kwlist_1,
&UnaryPredicate0D_Type,
&obj1,
&UnaryPredicate0D_Type,
&obj2,
&f))
{
if (!((BPy_UnaryPredicate0D *)obj1)->up0D) {
PyErr_SetString(
PyExc_TypeError,
"Operators.sequential_split(): 1st argument: invalid UnaryPredicate0D object");
return nullptr;
}
if (!((BPy_UnaryPredicate0D *)obj2)->up0D) {
PyErr_SetString(
PyExc_TypeError,
"Operators.sequential_split(): 2nd argument: invalid UnaryPredicate0D object");
return nullptr;
}
if (Operators::sequentialSplit(*(((BPy_UnaryPredicate0D *)obj1)->up0D),
*(((BPy_UnaryPredicate0D *)obj2)->up0D),
f) < 0)
{
if (!PyErr_Occurred()) {
PyErr_SetString(PyExc_RuntimeError, "Operators.sequential_split() failed");
}
return nullptr;
}
}
else if ((void)PyErr_Clear(),
(void)(f = 0.0f),
PyArg_ParseTupleAndKeywords(
args, kwds, "O!|f", (char **)kwlist_2, &UnaryPredicate0D_Type, &obj1, &f))
{
if (!((BPy_UnaryPredicate0D *)obj1)->up0D) {
PyErr_SetString(
PyExc_TypeError,
"Operators.sequential_split(): 1st argument: invalid UnaryPredicate0D object");
return nullptr;
}
if (Operators::sequentialSplit(*(((BPy_UnaryPredicate0D *)obj1)->up0D), f) < 0) {
if (!PyErr_Occurred()) {
PyErr_SetString(PyExc_RuntimeError, "Operators.sequential_split() failed");
}
return nullptr;
}
}
else {
PyErr_SetString(PyExc_TypeError, "invalid argument(s)");
return nullptr;
}
Py_RETURN_NONE;
}
PyDoc_STRVAR(
/* Wrap. */
Operators_recursive_split_doc,
".. staticmethod:: recursive_split(*args, **kwargs)\n"
"\n"
" Accepted call signatures:\n"
"\n"
" - ``recursive_split(func, pred_1d, sampling=0.0)``\n"
" - ``recursive_split(func, pred_0d, pred_1d, sampling=0.0)``\n"
"\n"
" Splits the current set of chains in a recursive way. We process the\n"
" points of each chain (with a specified sampling) to find the point\n"
" minimizing a specified function. The chain is split in two at this\n"
" point and the two new chains are processed in the same way. The\n"
" recursivity level is controlled through a predicate 1D that expresses\n"
" a stopping condition on the chain that is about to be processed.\n"
"\n"
" The user can also specify a 0D predicate to make a first selection on the points\n"
" that can potentially be split. A point that doesn't verify the 0D\n"
" predicate won't be candidate in realizing the min.\n"
"\n"
" :param func: The Unary Function evaluated at each point of the chain.\n"
" The splitting point is the point minimizing this function.\n"
" :type func: :class:`UnaryFunction0DDouble`\n"
" :param pred_0d: The Unary Predicate 0D used to select the candidate\n"
" points where the split can occur. For example, it is very likely\n"
" that would rather have your chain splitting around its middle\n"
" point than around one of its extremities. A 0D predicate working\n"
" on the curvilinear abscissa allows to add this kind of constraints.\n"
" :type pred_0d: :class:`UnaryPredicate0D`\n"
" :param pred_1d: The Unary Predicate expressing the recursivity stopping\n"
" condition. This predicate is evaluated for each curve before it\n"
" actually gets split. If pred_1d(chain) is true, the curve won't be\n"
" split anymore.\n"
" :type pred_1d: :class:`UnaryPredicate1D`\n"
" :param sampling: The resolution used to sample the chain for the\n"
" predicates evaluation. (The chain is not actually resampled; a\n"
" virtual point only progresses along the curve using this\n"
" resolution.)\n"
" :type sampling: float\n");
static PyObject *Operators_recursive_split(BPy_Operators * /*self*/,
PyObject *args,
PyObject *kwds)
{
static const char *kwlist_1[] = {"func", "pred_1d", "sampling", nullptr};
static const char *kwlist_2[] = {"func", "pred_0d", "pred_1d", "sampling", nullptr};
PyObject *obj1 = nullptr, *obj2 = nullptr, *obj3 = nullptr;
float f = 0.0f;
if (PyArg_ParseTupleAndKeywords(args,
kwds,
"O!O!|f",
(char **)kwlist_1,
&UnaryFunction0DDouble_Type,
&obj1,
&UnaryPredicate1D_Type,
&obj2,
&f))
{
if (!((BPy_UnaryFunction0DDouble *)obj1)->uf0D_double) {
PyErr_SetString(
PyExc_TypeError,
"Operators.recursive_split(): 1st argument: invalid UnaryFunction0DDouble object");
return nullptr;
}
if (!((BPy_UnaryPredicate1D *)obj2)->up1D) {
PyErr_SetString(
PyExc_TypeError,
"Operators.recursive_split(): 2nd argument: invalid UnaryPredicate1D object");
return nullptr;
}
if (Operators::recursiveSplit(*(((BPy_UnaryFunction0DDouble *)obj1)->uf0D_double),
*(((BPy_UnaryPredicate1D *)obj2)->up1D),
f) < 0)
{
if (!PyErr_Occurred()) {
PyErr_SetString(PyExc_RuntimeError, "Operators.recursive_split() failed");
}
return nullptr;
}
}
else if ((void)PyErr_Clear(),
(void)(f = 0.0f),
PyArg_ParseTupleAndKeywords(args,
kwds,
"O!O!O!|f",
(char **)kwlist_2,
&UnaryFunction0DDouble_Type,
&obj1,
&UnaryPredicate0D_Type,
&obj2,
&UnaryPredicate1D_Type,
&obj3,
&f))
{
if (!((BPy_UnaryFunction0DDouble *)obj1)->uf0D_double) {
PyErr_SetString(
PyExc_TypeError,
"Operators.recursive_split(): 1st argument: invalid UnaryFunction0DDouble object");
return nullptr;
}
if (!((BPy_UnaryPredicate0D *)obj2)->up0D) {
PyErr_SetString(
PyExc_TypeError,
"Operators.recursive_split(): 2nd argument: invalid UnaryPredicate0D object");
return nullptr;
}
if (!((BPy_UnaryPredicate1D *)obj3)->up1D) {
PyErr_SetString(
PyExc_TypeError,
"Operators.recursive_split(): 3rd argument: invalid UnaryPredicate1D object");
return nullptr;
}
if (Operators::recursiveSplit(*(((BPy_UnaryFunction0DDouble *)obj1)->uf0D_double),
*(((BPy_UnaryPredicate0D *)obj2)->up0D),
*(((BPy_UnaryPredicate1D *)obj3)->up1D),
f) < 0)
{
if (!PyErr_Occurred()) {
PyErr_SetString(PyExc_RuntimeError, "Operators.recursive_split() failed");
}
return nullptr;
}
}
else {
PyErr_SetString(PyExc_TypeError, "invalid argument(s)");
return nullptr;
}
Py_RETURN_NONE;
}
PyDoc_STRVAR(
/* Wrap. */
Operators_sort_doc,
".. staticmethod:: sort(pred)\n"
"\n"
" Sorts the current set of chains (or viewedges) according to the\n"
" comparison predicate given as argument.\n"
"\n"
" :param pred: The binary predicate used for the comparison.\n"
" :type pred: :class:`BinaryPredicate1D`\n");
static PyObject *Operators_sort(BPy_Operators * /*self*/, PyObject *args, PyObject *kwds)
{
static const char *kwlist[] = {"pred", nullptr};
PyObject *obj = nullptr;
if (!PyArg_ParseTupleAndKeywords(
args, kwds, "O!", (char **)kwlist, &BinaryPredicate1D_Type, &obj))
{
return nullptr;
}
if (!((BPy_BinaryPredicate1D *)obj)->bp1D) {
PyErr_SetString(PyExc_TypeError,
"Operators.sort(): 1st argument: invalid BinaryPredicate1D object");
return nullptr;
}
if (Operators::sort(*(((BPy_BinaryPredicate1D *)obj)->bp1D)) < 0) {
if (!PyErr_Occurred()) {
PyErr_SetString(PyExc_RuntimeError, "Operators.sort() failed");
}
return nullptr;
}
Py_RETURN_NONE;
}
PyDoc_STRVAR(
/* Wrap. */
Operators_create_doc,
".. staticmethod:: create(pred, shaders)\n"
"\n"
" Creates and shades the strokes from the current set of chains. A\n"
" predicate can be specified to make a selection pass on the chains.\n"
"\n"
" :param pred: The predicate that a chain must verify in order to be\n"
" transform as a stroke.\n"
" :type pred: :class:`UnaryPredicate1D`\n"
" :param shaders: The list of shaders used to shade the strokes.\n"
" :type shaders: list[:class:`StrokeShader`]\n");
static PyObject *Operators_create(BPy_Operators * /*self*/, PyObject *args, PyObject *kwds)
{
static const char *kwlist[] = {"pred", "shaders", nullptr};
PyObject *obj1 = nullptr, *obj2 = nullptr;
if (!PyArg_ParseTupleAndKeywords(
args, kwds, "O!O!", (char **)kwlist, &UnaryPredicate1D_Type, &obj1, &PyList_Type, &obj2))
{
return nullptr;
}
if (!((BPy_UnaryPredicate1D *)obj1)->up1D) {
PyErr_SetString(PyExc_TypeError,
"Operators.create(): 1st argument: invalid UnaryPredicate1D object");
return nullptr;
}
vector<StrokeShader *> shaders;
shaders.reserve(PyList_Size(obj2));
for (int i = 0; i < PyList_Size(obj2); i++) {
PyObject *py_ss = PyList_GET_ITEM(obj2, i);
if (!BPy_StrokeShader_Check(py_ss)) {
PyErr_SetString(PyExc_TypeError,
"Operators.create(): 2nd argument must be a list of StrokeShader objects");
return nullptr;
}
StrokeShader *shader = ((BPy_StrokeShader *)py_ss)->ss;
if (!shader) {
stringstream ss;
ss << "Operators.create(): item " << (i + 1)
<< " of the shaders list is invalid likely due to missing call of "
"StrokeShader.__init__()";
PyErr_SetString(PyExc_TypeError, ss.str().c_str());
return nullptr;
}
shaders.push_back(shader);
}
if (Operators::create(*(((BPy_UnaryPredicate1D *)obj1)->up1D), shaders) < 0) {
if (!PyErr_Occurred()) {
PyErr_SetString(PyExc_RuntimeError, "Operators.create() failed");
}
return nullptr;
}
Py_RETURN_NONE;
}
PyDoc_STRVAR(
/* Wrap. */
Operators_reset_doc,
".. staticmethod:: reset(delete_strokes=True)\n"
"\n"
" Resets the line stylization process to the initial state. The results of\n"
" stroke creation are accumulated if **delete_strokes** is set to False.\n"
"\n"
" :param delete_strokes: Delete the strokes that are currently stored.\n"
" :type delete_strokes: bool\n");
static PyObject *Operators_reset(BPy_Operators * /*self*/, PyObject *args, PyObject *kwds)
{
static const char *kwlist[] = {"delete_strokes", nullptr};
PyObject *obj1 = nullptr;
if (PyArg_ParseTupleAndKeywords(args, kwds, "|O!", (char **)kwlist, &PyBool_Type, &obj1)) {
// true is the default
Operators::reset(obj1 ? bool_from_PyBool(obj1) : true);
}
else {
PyErr_SetString(PyExc_RuntimeError, "Operators.reset() failed");
return nullptr;
}
Py_RETURN_NONE;
}
PyDoc_STRVAR(
/* Wrap. */
Operators_get_viewedge_from_index_doc,
".. staticmethod:: get_viewedge_from_index(i)\n"
"\n"
" Returns the ViewEdge at the index in the current set of ViewEdges.\n"
"\n"
" :param i: index (0 <= i < Operators.get_view_edges_size()).\n"
" :type i: int\n"
" :return: The ViewEdge object.\n"
" :rtype: :class:`ViewEdge`\n");
static PyObject *Operators_get_viewedge_from_index(BPy_Operators * /*self*/,
PyObject *args,
PyObject *kwds)
{
static const char *kwlist[] = {"i", nullptr};
uint i;
if (!PyArg_ParseTupleAndKeywords(args, kwds, "I", (char **)kwlist, &i)) {
return nullptr;
}
if (i >= Operators::getViewEdgesSize()) {
PyErr_SetString(PyExc_IndexError, "index out of range");
return nullptr;
}
return BPy_ViewEdge_from_ViewEdge(*(Operators::getViewEdgeFromIndex(i)));
}
PyDoc_STRVAR(
/* Wrap. */
Operators_get_chain_from_index_doc,
".. staticmethod:: get_chain_from_index(i)\n"
"\n"
" Returns the Chain at the index in the current set of Chains.\n"
"\n"
" :param i: index (0 <= i < Operators.get_chains_size()).\n"
" :type i: int\n"
" :return: The Chain object.\n"
" :rtype: :class:`Chain`\n");
static PyObject *Operators_get_chain_from_index(BPy_Operators * /*self*/,
PyObject *args,
PyObject *kwds)
{
static const char *kwlist[] = {"i", nullptr};
uint i;
if (!PyArg_ParseTupleAndKeywords(args, kwds, "I", (char **)kwlist, &i)) {
return nullptr;
}
if (i >= Operators::getChainsSize()) {
PyErr_SetString(PyExc_IndexError, "index out of range");
return nullptr;
}
return BPy_Chain_from_Chain(*(Operators::getChainFromIndex(i)));
}
PyDoc_STRVAR(
/* Wrap. */
Operators_get_stroke_from_index_doc,
".. staticmethod:: get_stroke_from_index(i)\n"
"\n"
" Returns the Stroke at the index in the current set of Strokes.\n"
"\n"
" :param i: index (0 <= i < Operators.get_strokes_size()).\n"
" :type i: int\n"
" :return: The Stroke object.\n"
" :rtype: :class:`Stroke`\n");
static PyObject *Operators_get_stroke_from_index(BPy_Operators * /*self*/,
PyObject *args,
PyObject *kwds)
{
static const char *kwlist[] = {"i", nullptr};
uint i;
if (!PyArg_ParseTupleAndKeywords(args, kwds, "I", (char **)kwlist, &i)) {
return nullptr;
}
if (i >= Operators::getStrokesSize()) {
PyErr_SetString(PyExc_IndexError, "index out of range");
return nullptr;
}
return BPy_Stroke_from_Stroke(*(Operators::getStrokeFromIndex(i)));
}
PyDoc_STRVAR(
/* Wrap. */
Operators_get_view_edges_size_doc,
".. staticmethod:: get_view_edges_size()\n"
"\n"
" Returns the number of ViewEdges.\n"
"\n"
" :return: The number of ViewEdges.\n"
" :rtype: int\n");
static PyObject *Operators_get_view_edges_size(BPy_Operators * /*self*/)
{
return PyLong_FromLong(Operators::getViewEdgesSize());
}
PyDoc_STRVAR(
/* Wrap. */
Operators_get_chains_size_doc,
".. staticmethod:: get_chains_size()\n"
"\n"
" Returns the number of Chains.\n"
"\n"
" :return: The number of Chains.\n"
" :rtype: int\n");
static PyObject *Operators_get_chains_size(BPy_Operators * /*self*/)
{
return PyLong_FromLong(Operators::getChainsSize());
}
PyDoc_STRVAR(
/* Wrap. */
Operators_get_strokes_size_doc,
".. staticmethod:: get_strokes_size()\n"
"\n"
" Returns the number of Strokes.\n"
"\n"
" :return: The number of Strokes.\n"
" :rtype: int\n");
static PyObject *Operators_get_strokes_size(BPy_Operators * /*self*/)
{
return PyLong_FromLong(Operators::getStrokesSize());
}
/*----------------------Operators instance definitions ----------------------------*/
#ifdef __GNUC__
# ifdef __clang__
# pragma clang diagnostic push
# pragma clang diagnostic ignored "-Wcast-function-type"
# else
# pragma GCC diagnostic push
# pragma GCC diagnostic ignored "-Wcast-function-type"
# endif
#endif
static PyMethodDef BPy_Operators_methods[] = {
{"select",
(PyCFunction)Operators_select,
METH_VARARGS | METH_KEYWORDS | METH_STATIC,
Operators_select_doc},
{"chain",
(PyCFunction)Operators_chain,
METH_VARARGS | METH_KEYWORDS | METH_STATIC,
Operators_chain_doc},
{"bidirectional_chain",
(PyCFunction)Operators_bidirectional_chain,
METH_VARARGS | METH_KEYWORDS | METH_STATIC,
Operators_bidirectional_chain_doc},
{"sequential_split",
(PyCFunction)Operators_sequential_split,
METH_VARARGS | METH_KEYWORDS | METH_STATIC,
Operators_sequential_split_doc},
{"recursive_split",
(PyCFunction)Operators_recursive_split,
METH_VARARGS | METH_KEYWORDS | METH_STATIC,
Operators_recursive_split_doc},
{"sort",
(PyCFunction)Operators_sort,
METH_VARARGS | METH_KEYWORDS | METH_STATIC,
Operators_sort_doc},
{"create",
(PyCFunction)Operators_create,
METH_VARARGS | METH_KEYWORDS | METH_STATIC,
Operators_create_doc},
{"reset",
(PyCFunction)Operators_reset,
METH_VARARGS | METH_KEYWORDS | METH_STATIC,
Operators_reset_doc},
{"get_viewedge_from_index",
(PyCFunction)Operators_get_viewedge_from_index,
METH_VARARGS | METH_KEYWORDS | METH_STATIC,
Operators_get_viewedge_from_index_doc},
{"get_chain_from_index",
(PyCFunction)Operators_get_chain_from_index,
METH_VARARGS | METH_KEYWORDS | METH_STATIC,
Operators_get_chain_from_index_doc},
{"get_stroke_from_index",
(PyCFunction)Operators_get_stroke_from_index,
METH_VARARGS | METH_KEYWORDS | METH_STATIC,
Operators_get_stroke_from_index_doc},
{"get_view_edges_size",
(PyCFunction)Operators_get_view_edges_size,
METH_NOARGS | METH_STATIC,
Operators_get_view_edges_size_doc},
{"get_chains_size",
(PyCFunction)Operators_get_chains_size,
METH_NOARGS | METH_STATIC,
Operators_get_chains_size_doc},
{"get_strokes_size",
(PyCFunction)Operators_get_strokes_size,
METH_NOARGS | METH_STATIC,
Operators_get_strokes_size_doc},
{nullptr, nullptr, 0, nullptr},
};
#ifdef __GNUC__
# ifdef __clang__
# pragma clang diagnostic pop
# else
# pragma GCC diagnostic pop
# endif
#endif
/*-----------------------BPy_Operators type definition ------------------------------*/
PyTypeObject Operators_Type = {
/*ob_base*/ PyVarObject_HEAD_INIT(nullptr, 0)
/*tp_name*/ "Operators",
/*tp_basicsize*/ sizeof(BPy_Operators),
/*tp_itemsize*/ 0,
/*tp_dealloc*/ (destructor)Operators_dealloc,
/*tp_vectorcall_offset*/ 0,
/*tp_getattr*/ nullptr,
/*tp_setattr*/ nullptr,
/*tp_as_async*/ nullptr,
/*tp_repr*/ nullptr,
/*tp_as_number*/ nullptr,
/*tp_as_sequence*/ nullptr,
/*tp_as_mapping*/ nullptr,
/*tp_hash*/ nullptr,
/*tp_call*/ nullptr,
/*tp_str*/ nullptr,
/*tp_getattro*/ nullptr,
/*tp_setattro*/ nullptr,
/*tp_as_buffer*/ nullptr,
/*tp_flags*/ Py_TPFLAGS_DEFAULT,
/*tp_doc*/ Operators_doc,
/*tp_traverse*/ nullptr,
/*tp_clear*/ nullptr,
/*tp_richcompare*/ nullptr,
/*tp_weaklistoffset*/ 0,
/*tp_iter*/ nullptr,
/*tp_iternext*/ nullptr,
/*tp_methods*/ BPy_Operators_methods,
/*tp_members*/ nullptr,
/*tp_getset*/ nullptr,
/*tp_base*/ nullptr,
/*tp_dict*/ nullptr,
/*tp_descr_get*/ nullptr,
/*tp_descr_set*/ nullptr,
/*tp_dictoffset*/ 0,
/*tp_init*/ nullptr,
/*tp_alloc*/ nullptr,
/*tp_new*/ PyType_GenericNew,
};
///////////////////////////////////////////////////////////////////////////////////////////

View File

@@ -0,0 +1,32 @@
/* SPDX-FileCopyrightText: 2023 Blender Authors
*
* SPDX-License-Identifier: GPL-2.0-or-later */
/** \file
* \ingroup freestyle
*/
#pragma once
extern "C" {
#include <Python.h>
}
#include "../stroke/Operators.h"
///////////////////////////////////////////////////////////////////////////////////////////
extern PyTypeObject Operators_Type;
#define BPy_Operators_Check(v) (PyObject_IsInstance((PyObject *)v, (PyObject *)&Operators_Type))
/*---------------------------Python BPy_Operators structure definition----------*/
struct BPy_Operators {
PyObject_HEAD
};
/*---------------------------Python BPy_Operators visible prototypes-----------*/
int Operators_Init(PyObject *module);
///////////////////////////////////////////////////////////////////////////////////////////

View File

@@ -0,0 +1,338 @@
/* SPDX-FileCopyrightText: 2004-2022 Blender Authors
*
* SPDX-License-Identifier: GPL-2.0-or-later */
/** \file
* \ingroup freestyle
*/
#include "BPy_SShape.h"
#include "BPy_BBox.h"
#include "BPy_Convert.h"
#include "BPy_Id.h"
#include "Interface0D/BPy_SVertex.h"
#include "Interface1D/BPy_FEdge.h"
#include "BLI_sys_types.h"
#include "../generic/py_capi_utils.hh"
using namespace Freestyle;
///////////////////////////////////////////////////////////////////////////////////////////
//-------------------MODULE INITIALIZATION--------------------------------
int SShape_Init(PyObject *module)
{
if (module == nullptr) {
return -1;
}
if (PyType_Ready(&SShape_Type) < 0) {
return -1;
}
PyModule_AddObjectRef(module, "SShape", (PyObject *)&SShape_Type);
return 0;
}
/*----------------------SShape methods ----------------------------*/
PyDoc_STRVAR(
/* Wrap. */
SShape_doc,
"Class to define a feature shape. It is the gathering of feature\n"
"elements from an identified input shape.\n"
"\n"
".. method:: __init__(*args)\n"
"\n"
" Accepted call signatures:\n"
"\n"
" - ``__init__()``\n"
" - ``__init__(brother)``\n"
"\n"
" Creates a :class:`SShape` class using either a default constructor or copy constructor.\n"
"\n"
" :param brother: An SShape object.\n"
" :type brother: :class:`SShape`\n");
static int SShape_init(BPy_SShape *self, PyObject *args, PyObject *kwds)
{
static const char *kwlist[] = {"brother", nullptr};
PyObject *brother = nullptr;
if (!PyArg_ParseTupleAndKeywords(args, kwds, "|O!", (char **)kwlist, &SShape_Type, &brother)) {
return -1;
}
if (!brother) {
self->ss = new SShape();
}
else {
self->ss = new SShape(*(((BPy_SShape *)brother)->ss));
}
self->borrowed = false;
return 0;
}
static void SShape_dealloc(BPy_SShape *self)
{
if (self->ss && !self->borrowed) {
delete self->ss;
}
Py_TYPE(self)->tp_free((PyObject *)self);
}
static PyObject *SShape_repr(BPy_SShape *self)
{
return PyUnicode_FromFormat("SShape - address: %p", self->ss);
}
static char SShape_add_edge_doc[] =
".. method:: add_edge(edge)\n"
"\n"
" Adds an FEdge to the list of FEdges.\n"
"\n"
" :param edge: An FEdge object.\n"
" :type edge: :class:`FEdge`\n";
static PyObject *SShape_add_edge(BPy_SShape *self, PyObject *args, PyObject *kwds)
{
static const char *kwlist[] = {"edge", nullptr};
PyObject *py_fe = nullptr;
if (!PyArg_ParseTupleAndKeywords(args, kwds, "O!", (char **)kwlist, &FEdge_Type, &py_fe)) {
return nullptr;
}
self->ss->AddEdge(((BPy_FEdge *)py_fe)->fe);
Py_RETURN_NONE;
}
PyDoc_STRVAR(
/* Wrap. */
SShape_add_vertex_doc,
".. method:: add_vertex(vertex)\n"
"\n"
" Adds an SVertex to the list of SVertex of this Shape. The SShape\n"
" attribute of the SVertex is also set to this SShape.\n"
"\n"
" :param vertex: An SVertex object.\n"
" :type vertex: :class:`SVertex`\n");
static PyObject *SShape_add_vertex(BPy_SShape *self, PyObject *args, PyObject *kwds)
{
static const char *kwlist[] = {"edge", nullptr};
PyObject *py_sv = nullptr;
if (!PyArg_ParseTupleAndKeywords(args, kwds, "O!", (char **)kwlist, &SVertex_Type, &py_sv)) {
return nullptr;
}
self->ss->AddNewVertex(((BPy_SVertex *)py_sv)->sv);
Py_RETURN_NONE;
}
PyDoc_STRVAR(
/* Wrap. */
SShape_compute_bbox_doc,
".. method:: compute_bbox()\n"
"\n"
" Compute the bbox of the SShape.\n");
static PyObject *SShape_compute_bbox(BPy_SShape *self)
{
self->ss->ComputeBBox();
Py_RETURN_NONE;
}
// const Material & material (uint i) const
// const vector< Material > & materials () const
// void SetMaterials (const vector< Material > &iMaterials)
#ifdef __GNUC__
# ifdef __clang__
# pragma clang diagnostic push
# pragma clang diagnostic ignored "-Wcast-function-type"
# else
# pragma GCC diagnostic push
# pragma GCC diagnostic ignored "-Wcast-function-type"
# endif
#endif
static PyMethodDef BPy_SShape_methods[] = {
{"add_edge", (PyCFunction)SShape_add_edge, METH_VARARGS | METH_KEYWORDS, SShape_add_edge_doc},
{"add_vertex",
(PyCFunction)SShape_add_vertex,
METH_VARARGS | METH_KEYWORDS,
SShape_add_vertex_doc},
{"compute_bbox", (PyCFunction)SShape_compute_bbox, METH_NOARGS, SShape_compute_bbox_doc},
{nullptr, nullptr, 0, nullptr},
};
#ifdef __GNUC__
# ifdef __clang__
# pragma clang diagnostic pop
# else
# pragma GCC diagnostic pop
# endif
#endif
/*----------------------SShape get/setters ----------------------------*/
PyDoc_STRVAR(
/* Wrap. */
SShape_id_doc,
"The Id of this SShape.\n"
"\n"
":type: :class:`Id`\n");
static PyObject *SShape_id_get(BPy_SShape *self, void * /*closure*/)
{
Id id(self->ss->getId());
return BPy_Id_from_Id(id); // return a copy
}
static int SShape_id_set(BPy_SShape *self, PyObject *value, void * /*closure*/)
{
if (!BPy_Id_Check(value)) {
PyErr_SetString(PyExc_TypeError, "value must be an Id");
return -1;
}
self->ss->setId(*(((BPy_Id *)value)->id));
return 0;
}
PyDoc_STRVAR(
/* Wrap. */
SShape_name_doc,
"The name of the SShape.\n"
"\n"
":type: str\n");
static PyObject *SShape_name_get(BPy_SShape *self, void * /*closure*/)
{
return blender::PyC_UnicodeFromStdStr(self->ss->getName());
}
static int SShape_name_set(BPy_SShape *self, PyObject *value, void * /*closure*/)
{
if (!PyUnicode_Check(value)) {
PyErr_SetString(PyExc_TypeError, "value must be a string");
return -1;
}
const char *name = PyUnicode_AsUTF8(value);
self->ss->setName(name);
return 0;
}
PyDoc_STRVAR(
/* Wrap. */
SShape_bbox_doc,
"The bounding box of the SShape.\n"
"\n"
":type: :class:`BBox`\n");
static PyObject *SShape_bbox_get(BPy_SShape *self, void * /*closure*/)
{
BBox<Vec3r> bb(self->ss->bbox());
return BPy_BBox_from_BBox(bb); // return a copy
}
static int SShape_bbox_set(BPy_SShape *self, PyObject *value, void * /*closure*/)
{
if (!BPy_BBox_Check(value)) {
PyErr_SetString(PyExc_TypeError, "value must be a BBox");
return -1;
}
self->ss->setBBox(*(((BPy_BBox *)value)->bb));
return 0;
}
PyDoc_STRVAR(
/* Wrap. */
SShape_vertices_doc,
"The list of vertices constituting this SShape.\n"
"\n"
":type: list[:class:`SVertex`]\n");
static PyObject *SShape_vertices_get(BPy_SShape *self, void * /*closure*/)
{
vector<SVertex *> vertices = self->ss->getVertexList();
vector<SVertex *>::iterator it;
PyObject *py_vertices = PyList_New(vertices.size());
uint i = 0;
for (it = vertices.begin(); it != vertices.end(); it++) {
PyList_SET_ITEM(py_vertices, i++, BPy_SVertex_from_SVertex(*(*it)));
}
return py_vertices;
}
PyDoc_STRVAR(
/* Wrap. */
SShape_edges_doc,
"The list of edges constituting this SShape.\n"
"\n"
":type: list[:class:`FEdge`]\n");
static PyObject *SShape_edges_get(BPy_SShape *self, void * /*closure*/)
{
vector<FEdge *> edges = self->ss->getEdgeList();
vector<FEdge *>::iterator it;
PyObject *py_edges = PyList_New(edges.size());
uint i = 0;
for (it = edges.begin(); it != edges.end(); it++) {
PyList_SET_ITEM(py_edges, i++, Any_BPy_FEdge_from_FEdge(*(*it)));
}
return py_edges;
}
static PyGetSetDef BPy_SShape_getseters[] = {
{"id", (getter)SShape_id_get, (setter)SShape_id_set, SShape_id_doc, nullptr},
{"name", (getter)SShape_name_get, (setter)SShape_name_set, SShape_name_doc, nullptr},
{"bbox", (getter)SShape_bbox_get, (setter)SShape_bbox_set, SShape_bbox_doc, nullptr},
{"edges", (getter)SShape_edges_get, (setter) nullptr, SShape_edges_doc, nullptr},
{"vertices", (getter)SShape_vertices_get, (setter) nullptr, SShape_vertices_doc, nullptr},
{nullptr, nullptr, nullptr, nullptr, nullptr} /* Sentinel */
};
/*-----------------------BPy_SShape type definition ------------------------------*/
PyTypeObject SShape_Type = {
/*ob_base*/ PyVarObject_HEAD_INIT(nullptr, 0)
/*tp_name*/ "SShape",
/*tp_basicsize*/ sizeof(BPy_SShape),
/*tp_itemsize*/ 0,
/*tp_dealloc*/ (destructor)SShape_dealloc,
/*tp_vectorcall_offset*/ 0,
/*tp_getattr*/ nullptr,
/*tp_setattr*/ nullptr,
/*tp_as_async*/ nullptr,
/*tp_repr*/ (reprfunc)SShape_repr,
/*tp_as_number*/ nullptr,
/*tp_as_sequence*/ nullptr,
/*tp_as_mapping*/ nullptr,
/*tp_hash*/ nullptr,
/*tp_call*/ nullptr,
/*tp_str*/ nullptr,
/*tp_getattro*/ nullptr,
/*tp_setattro*/ nullptr,
/*tp_as_buffer*/ nullptr,
/*tp_flags*/ Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE,
/*tp_doc*/ SShape_doc,
/*tp_traverse*/ nullptr,
/*tp_clear*/ nullptr,
/*tp_richcompare*/ nullptr,
/*tp_weaklistoffset*/ 0,
/*tp_iter*/ nullptr,
/*tp_iternext*/ nullptr,
/*tp_methods*/ BPy_SShape_methods,
/*tp_members*/ nullptr,
/*tp_getset*/ BPy_SShape_getseters,
/*tp_base*/ nullptr,
/*tp_dict*/ nullptr,
/*tp_descr_get*/ nullptr,
/*tp_descr_set*/ nullptr,
/*tp_dictoffset*/ 0,
/*tp_init*/ (initproc)SShape_init,
/*tp_alloc*/ nullptr,
/*tp_new*/ PyType_GenericNew,
};
///////////////////////////////////////////////////////////////////////////////////////////

View File

@@ -0,0 +1,34 @@
/* SPDX-FileCopyrightText: 2023 Blender Authors
*
* SPDX-License-Identifier: GPL-2.0-or-later */
/** \file
* \ingroup freestyle
*/
#pragma once
extern "C" {
#include <Python.h>
}
#include "../view_map/Silhouette.h"
///////////////////////////////////////////////////////////////////////////////////////////
extern PyTypeObject SShape_Type;
#define BPy_SShape_Check(v) (PyObject_IsInstance((PyObject *)v, (PyObject *)&SShape_Type))
/*---------------------------Python BPy_SShape structure definition----------*/
struct BPy_SShape {
PyObject_HEAD
Freestyle::SShape *ss;
bool borrowed; /* true if *ss is a borrowed object */
};
/*---------------------------Python BPy_SShape visible prototypes-----------*/
int SShape_Init(PyObject *module);
///////////////////////////////////////////////////////////////////////////////////////////

View File

@@ -0,0 +1,750 @@
/* SPDX-FileCopyrightText: 2004-2023 Blender Authors
*
* SPDX-License-Identifier: GPL-2.0-or-later */
/** \file
* \ingroup freestyle
*/
#include "BPy_StrokeAttribute.h"
#include "BPy_Convert.h"
#include "../generic/py_capi_utils.hh"
using namespace Freestyle;
///////////////////////////////////////////////////////////////////////////////////////////
//-------------------MODULE INITIALIZATION--------------------------------
int StrokeAttribute_Init(PyObject *module)
{
if (module == nullptr) {
return -1;
}
if (PyType_Ready(&StrokeAttribute_Type) < 0) {
return -1;
}
PyModule_AddObjectRef(module, "StrokeAttribute", (PyObject *)&StrokeAttribute_Type);
StrokeAttribute_mathutils_register_callback();
return 0;
}
//------------------------INSTANCE METHODS ----------------------------------
PyDoc_STRVAR(
/* Wrap. */
StrokeAttribute_doc,
"Class to define a set of attributes associated with a :class:`StrokeVertex`.\n"
"The attribute set stores the color, alpha and thickness values for a Stroke\n"
"Vertex.\n"
"\n"
".. method:: __init__(*args)\n"
"\n"
" Accepted call signatures:\n"
"\n"
" - ``__init__()``\n"
" - ``__init__(brother)``\n"
" - ``__init__(red, green, blue, alpha, thickness_right, thickness_left)``\n"
" - ``__init__(attribute1, attribute2, t)``\n"
"\n"
" Creates a :class:`StrokeAttribute` object using either a default constructor,\n"
" copy constructor, overloaded constructor, or and interpolation constructor\n"
" to interpolate between two :class:`StrokeAttribute` objects.\n"
"\n"
" :param brother: A StrokeAttribute object to be used as a copy constructor.\n"
" :type brother: :class:`StrokeAttribute`\n"
" :param red: Red component of a stroke color.\n"
" :type red: float\n"
" :param green: Green component of a stroke color.\n"
" :type green: float\n"
" :param blue: Blue component of a stroke color.\n"
" :type blue: float\n"
" :param alpha: Alpha component of a stroke color.\n"
" :type alpha: float\n"
" :param thickness_right: Stroke thickness on the right.\n"
" :type thickness_right: float\n"
" :param thickness_left: Stroke thickness on the left.\n"
" :type thickness_left: float\n"
" :param attribute1: The first StrokeAttribute object.\n"
" :type attribute1: :class:`StrokeAttribute`\n"
" :param attribute2: The second StrokeAttribute object.\n"
" :type attribute2: :class:`StrokeAttribute`\n"
" :param t: The interpolation parameter (0 <= t <= 1).\n"
" :type t: float\n");
static int StrokeAttribute_init(BPy_StrokeAttribute *self, PyObject *args, PyObject *kwds)
{
static const char *kwlist_1[] = {"brother", nullptr};
static const char *kwlist_2[] = {"attribute1", "attribute2", "t", nullptr};
static const char *kwlist_3[] = {
"red", "green", "blue", "alpha", "thickness_right", "thickness_left", nullptr};
PyObject *obj1 = nullptr, *obj2 = nullptr;
float red, green, blue, alpha, thickness_right, thickness_left, t;
if (PyArg_ParseTupleAndKeywords(
args, kwds, "|O!", (char **)kwlist_1, &StrokeAttribute_Type, &obj1))
{
if (!obj1) {
self->sa = new StrokeAttribute();
}
else {
self->sa = new StrokeAttribute(*(((BPy_StrokeAttribute *)obj1)->sa));
}
}
else if ((void)PyErr_Clear(),
PyArg_ParseTupleAndKeywords(args,
kwds,
"O!O!f",
(char **)kwlist_2,
&StrokeAttribute_Type,
&obj1,
&StrokeAttribute_Type,
&obj2,
&t))
{
self->sa = new StrokeAttribute(
*(((BPy_StrokeAttribute *)obj1)->sa), *(((BPy_StrokeAttribute *)obj2)->sa), t);
}
else if ((void)PyErr_Clear(),
PyArg_ParseTupleAndKeywords(args,
kwds,
"ffffff",
(char **)kwlist_3,
&red,
&green,
&blue,
&alpha,
&thickness_right,
&thickness_left))
{
self->sa = new StrokeAttribute(red, green, blue, alpha, thickness_right, thickness_left);
}
else {
PyErr_SetString(PyExc_TypeError, "invalid argument(s)");
return -1;
}
self->borrowed = false;
return 0;
}
static void StrokeAttribute_dealloc(BPy_StrokeAttribute *self)
{
if (self->sa && !self->borrowed) {
delete self->sa;
}
Py_TYPE(self)->tp_free((PyObject *)self);
}
static PyObject *StrokeAttribute_repr(BPy_StrokeAttribute *self)
{
stringstream repr("StrokeAttribute:");
repr << " r: " << self->sa->getColorR() << " g: " << self->sa->getColorG()
<< " b: " << self->sa->getColorB() << " a: " << self->sa->getAlpha()
<< " - R: " << self->sa->getThicknessR() << " L: " << self->sa->getThicknessL();
return blender::PyC_UnicodeFromStdStr(repr.str());
}
PyDoc_STRVAR(
/* Wrap. */
StrokeAttribute_get_attribute_real_doc,
".. method:: get_attribute_real(name)\n"
"\n"
" Returns an attribute of float type.\n"
"\n"
" :param name: The name of the attribute.\n"
" :type name: str\n"
" :return: The attribute value.\n"
" :rtype: float\n");
static PyObject *StrokeAttribute_get_attribute_real(BPy_StrokeAttribute *self,
PyObject *args,
PyObject *kwds)
{
static const char *kwlist[] = {"name", nullptr};
char *attr;
if (!PyArg_ParseTupleAndKeywords(args, kwds, "s", (char **)kwlist, &attr)) {
return nullptr;
}
double a = self->sa->getAttributeReal(attr);
return PyFloat_FromDouble(a);
}
PyDoc_STRVAR(
/* Wrap. */
StrokeAttribute_get_attribute_vec2_doc,
".. method:: get_attribute_vec2(name)\n"
"\n"
" Returns an attribute of two-dimensional vector type.\n"
"\n"
" :param name: The name of the attribute.\n"
" :type name: str\n"
" :return: The attribute value.\n"
" :rtype: :class:`mathutils.Vector`\n");
static PyObject *StrokeAttribute_get_attribute_vec2(BPy_StrokeAttribute *self,
PyObject *args,
PyObject *kwds)
{
static const char *kwlist[] = {"name", nullptr};
char *attr;
if (!PyArg_ParseTupleAndKeywords(args, kwds, "s", (char **)kwlist, &attr)) {
return nullptr;
}
Vec2f a = self->sa->getAttributeVec2f(attr);
return Vector_from_Vec2f(a);
}
PyDoc_STRVAR(
/* Wrap. */
StrokeAttribute_get_attribute_vec3_doc,
".. method:: get_attribute_vec3(name)\n"
"\n"
" Returns an attribute of three-dimensional vector type.\n"
"\n"
" :param name: The name of the attribute.\n"
" :type name: str\n"
" :return: The attribute value.\n"
" :rtype: :class:`mathutils.Vector`\n");
static PyObject *StrokeAttribute_get_attribute_vec3(BPy_StrokeAttribute *self,
PyObject *args,
PyObject *kwds)
{
static const char *kwlist[] = {"name", nullptr};
char *attr;
if (!PyArg_ParseTupleAndKeywords(args, kwds, "s", (char **)kwlist, &attr)) {
return nullptr;
}
Vec3f a = self->sa->getAttributeVec3f(attr);
return Vector_from_Vec3f(a);
}
PyDoc_STRVAR(
/* Wrap. */
StrokeAttribute_has_attribute_real_doc,
".. method:: has_attribute_real(name)\n"
"\n"
" Checks whether the attribute name of float type is available.\n"
"\n"
" :param name: The name of the attribute.\n"
" :type name: str\n"
" :return: True if the attribute is available.\n"
" :rtype: bool\n");
static PyObject *StrokeAttribute_has_attribute_real(BPy_StrokeAttribute *self,
PyObject *args,
PyObject *kwds)
{
static const char *kwlist[] = {"name", nullptr};
char *attr;
if (!PyArg_ParseTupleAndKeywords(args, kwds, "s", (char **)kwlist, &attr)) {
return nullptr;
}
return PyBool_from_bool(self->sa->isAttributeAvailableReal(attr));
}
PyDoc_STRVAR(
/* Wrap. */
StrokeAttribute_has_attribute_vec2_doc,
".. method:: has_attribute_vec2(name)\n"
"\n"
" Checks whether the attribute name of two-dimensional vector type\n"
" is available.\n"
"\n"
" :param name: The name of the attribute.\n"
" :type name: str\n"
" :return: True if the attribute is available.\n"
" :rtype: bool\n");
static PyObject *StrokeAttribute_has_attribute_vec2(BPy_StrokeAttribute *self,
PyObject *args,
PyObject *kwds)
{
static const char *kwlist[] = {"name", nullptr};
char *attr;
if (!PyArg_ParseTupleAndKeywords(args, kwds, "s", (char **)kwlist, &attr)) {
return nullptr;
}
return PyBool_from_bool(self->sa->isAttributeAvailableVec2f(attr));
}
PyDoc_STRVAR(
/* Wrap. */
StrokeAttribute_has_attribute_vec3_doc,
".. method:: has_attribute_vec3(name)\n"
"\n"
" Checks whether the attribute name of three-dimensional vector\n"
" type is available.\n"
"\n"
" :param name: The name of the attribute.\n"
" :type name: str\n"
" :return: True if the attribute is available.\n"
" :rtype: bool\n");
static PyObject *StrokeAttribute_has_attribute_vec3(BPy_StrokeAttribute *self,
PyObject *args,
PyObject *kwds)
{
static const char *kwlist[] = {"name", nullptr};
char *attr;
if (!PyArg_ParseTupleAndKeywords(args, kwds, "s", (char **)kwlist, &attr)) {
return nullptr;
}
return PyBool_from_bool(self->sa->isAttributeAvailableVec3f(attr));
}
PyDoc_STRVAR(
/* Wrap. */
StrokeAttribute_set_attribute_real_doc,
".. method:: set_attribute_real(name, value)\n"
"\n"
" Adds a user-defined attribute of float type. If there is no\n"
" attribute of the given name, it is added. Otherwise, the new value\n"
" replaces the old one.\n"
"\n"
" :param name: The name of the attribute.\n"
" :type name: str\n"
" :param value: The attribute value.\n"
" :type value: float\n");
static PyObject *StrokeAttribute_set_attribute_real(BPy_StrokeAttribute *self,
PyObject *args,
PyObject *kwds)
{
static const char *kwlist[] = {"name", "value", nullptr};
char *s = nullptr;
double d = 0;
if (!PyArg_ParseTupleAndKeywords(args, kwds, "sd", (char **)kwlist, &s, &d)) {
return nullptr;
}
self->sa->setAttributeReal(s, d);
Py_RETURN_NONE;
}
PyDoc_STRVAR(
/* Wrap. */
StrokeAttribute_set_attribute_vec2_doc,
".. method:: set_attribute_vec2(name, value)\n"
"\n"
" Adds a user-defined attribute of two-dimensional vector type. If\n"
" there is no attribute of the given name, it is added. Otherwise,\n"
" the new value replaces the old one.\n"
"\n"
" :param name: The name of the attribute.\n"
" :type name: str\n"
" :param value: The attribute value.\n"
" :type value: :class:`mathutils.Vector` | tuple[float, float, float] | list[float]\n");
static PyObject *StrokeAttribute_set_attribute_vec2(BPy_StrokeAttribute *self,
PyObject *args,
PyObject *kwds)
{
static const char *kwlist[] = {"name", "value", nullptr};
char *s;
PyObject *obj = nullptr;
Vec2f vec;
if (!PyArg_ParseTupleAndKeywords(args, kwds, "sO", (char **)kwlist, &s, &obj)) {
return nullptr;
}
if (!Vec2f_ptr_from_PyObject(obj, vec)) {
PyErr_SetString(PyExc_TypeError,
"argument 2 must be a 2D vector (either a list of 2 elements or Vector)");
return nullptr;
}
self->sa->setAttributeVec2f(s, vec);
Py_RETURN_NONE;
}
PyDoc_STRVAR(
/* Wrap. */
StrokeAttribute_set_attribute_vec3_doc,
".. method:: set_attribute_vec3(name, value)\n"
"\n"
" Adds a user-defined attribute of three-dimensional vector type.\n"
" If there is no attribute of the given name, it is added.\n"
" Otherwise, the new value replaces the old one.\n"
"\n"
" :param name: The name of the attribute.\n"
" :type name: str\n"
" :param value: The attribute value as a 3D vector.\n"
" :type value: :class:`mathutils.Vector` | tuple[float, float, float] | list[float]\n");
static PyObject *StrokeAttribute_set_attribute_vec3(BPy_StrokeAttribute *self,
PyObject *args,
PyObject *kwds)
{
static const char *kwlist[] = {"name", "value", nullptr};
char *s;
PyObject *obj = nullptr;
Vec3f vec;
if (!PyArg_ParseTupleAndKeywords(args, kwds, "sO", (char **)kwlist, &s, &obj)) {
return nullptr;
}
if (!Vec3f_ptr_from_PyObject(obj, vec)) {
PyErr_SetString(PyExc_TypeError,
"argument 2 must be a 3D vector (either a list of 3 elements or Vector)");
return nullptr;
}
self->sa->setAttributeVec3f(s, vec);
Py_RETURN_NONE;
}
#ifdef __GNUC__
# ifdef __clang__
# pragma clang diagnostic push
# pragma clang diagnostic ignored "-Wcast-function-type"
# else
# pragma GCC diagnostic push
# pragma GCC diagnostic ignored "-Wcast-function-type"
# endif
#endif
static PyMethodDef BPy_StrokeAttribute_methods[] = {
{"get_attribute_real",
(PyCFunction)StrokeAttribute_get_attribute_real,
METH_VARARGS | METH_KEYWORDS,
StrokeAttribute_get_attribute_real_doc},
{"get_attribute_vec2",
(PyCFunction)StrokeAttribute_get_attribute_vec2,
METH_VARARGS | METH_KEYWORDS,
StrokeAttribute_get_attribute_vec2_doc},
{"get_attribute_vec3",
(PyCFunction)StrokeAttribute_get_attribute_vec3,
METH_VARARGS | METH_KEYWORDS,
StrokeAttribute_get_attribute_vec3_doc},
{"has_attribute_real",
(PyCFunction)StrokeAttribute_has_attribute_real,
METH_VARARGS | METH_KEYWORDS,
StrokeAttribute_has_attribute_real_doc},
{"has_attribute_vec2",
(PyCFunction)StrokeAttribute_has_attribute_vec2,
METH_VARARGS | METH_KEYWORDS,
StrokeAttribute_has_attribute_vec2_doc},
{"has_attribute_vec3",
(PyCFunction)StrokeAttribute_has_attribute_vec3,
METH_VARARGS | METH_KEYWORDS,
StrokeAttribute_has_attribute_vec3_doc},
{"set_attribute_real",
(PyCFunction)StrokeAttribute_set_attribute_real,
METH_VARARGS | METH_KEYWORDS,
StrokeAttribute_set_attribute_real_doc},
{"set_attribute_vec2",
(PyCFunction)StrokeAttribute_set_attribute_vec2,
METH_VARARGS | METH_KEYWORDS,
StrokeAttribute_set_attribute_vec2_doc},
{"set_attribute_vec3",
(PyCFunction)StrokeAttribute_set_attribute_vec3,
METH_VARARGS | METH_KEYWORDS,
StrokeAttribute_set_attribute_vec3_doc},
{nullptr, nullptr, 0, nullptr},
};
#ifdef __GNUC__
# ifdef __clang__
# pragma clang diagnostic pop
# else
# pragma GCC diagnostic pop
# endif
#endif
/*----------------------mathutils callbacks ----------------------------*/
/* subtype */
#define MATHUTILS_SUBTYPE_COLOR 1
#define MATHUTILS_SUBTYPE_THICKNESS 2
static int StrokeAttribute_mathutils_check(blender::BaseMathObject *bmo)
{
if (!BPy_StrokeAttribute_Check(bmo->cb_user)) {
return -1;
}
return 0;
}
static int StrokeAttribute_mathutils_get(blender::BaseMathObject *bmo, int subtype)
{
BPy_StrokeAttribute *self = (BPy_StrokeAttribute *)bmo->cb_user;
switch (subtype) {
case MATHUTILS_SUBTYPE_COLOR:
bmo->data[0] = self->sa->getColorR();
bmo->data[1] = self->sa->getColorG();
bmo->data[2] = self->sa->getColorB();
break;
case MATHUTILS_SUBTYPE_THICKNESS:
bmo->data[0] = self->sa->getThicknessR();
bmo->data[1] = self->sa->getThicknessL();
break;
default:
return -1;
}
return 0;
}
static int StrokeAttribute_mathutils_set(blender::BaseMathObject *bmo, int subtype)
{
BPy_StrokeAttribute *self = (BPy_StrokeAttribute *)bmo->cb_user;
switch (subtype) {
case MATHUTILS_SUBTYPE_COLOR:
self->sa->setColor(bmo->data[0], bmo->data[1], bmo->data[2]);
break;
case MATHUTILS_SUBTYPE_THICKNESS:
self->sa->setThickness(bmo->data[0], bmo->data[1]);
break;
default:
return -1;
}
return 0;
}
static int StrokeAttribute_mathutils_get_index(blender::BaseMathObject *bmo,
int subtype,
int index)
{
BPy_StrokeAttribute *self = (BPy_StrokeAttribute *)bmo->cb_user;
switch (subtype) {
case MATHUTILS_SUBTYPE_COLOR:
switch (index) {
case 0:
bmo->data[0] = self->sa->getColorR();
break;
case 1:
bmo->data[1] = self->sa->getColorG();
break;
case 2:
bmo->data[2] = self->sa->getColorB();
break;
default:
return -1;
}
break;
case MATHUTILS_SUBTYPE_THICKNESS:
switch (index) {
case 0:
bmo->data[0] = self->sa->getThicknessR();
break;
case 1:
bmo->data[1] = self->sa->getThicknessL();
break;
default:
return -1;
}
break;
default:
return -1;
}
return 0;
}
static int StrokeAttribute_mathutils_set_index(blender::BaseMathObject *bmo,
int subtype,
int index)
{
BPy_StrokeAttribute *self = (BPy_StrokeAttribute *)bmo->cb_user;
switch (subtype) {
case MATHUTILS_SUBTYPE_COLOR: {
float r = (index == 0) ? bmo->data[0] : self->sa->getColorR();
float g = (index == 1) ? bmo->data[1] : self->sa->getColorG();
float b = (index == 2) ? bmo->data[2] : self->sa->getColorB();
self->sa->setColor(r, g, b);
break;
}
case MATHUTILS_SUBTYPE_THICKNESS: {
float tr = (index == 0) ? bmo->data[0] : self->sa->getThicknessR();
float tl = (index == 1) ? bmo->data[1] : self->sa->getThicknessL();
self->sa->setThickness(tr, tl);
break;
}
default:
return -1;
}
return 0;
}
static blender::Mathutils_Callback StrokeAttribute_mathutils_cb = {
StrokeAttribute_mathutils_check,
StrokeAttribute_mathutils_get,
StrokeAttribute_mathutils_set,
StrokeAttribute_mathutils_get_index,
StrokeAttribute_mathutils_set_index,
};
static uchar StrokeAttribute_mathutils_cb_index = -1;
void StrokeAttribute_mathutils_register_callback()
{
StrokeAttribute_mathutils_cb_index = Mathutils_RegisterCallback(&StrokeAttribute_mathutils_cb);
}
/*----------------------StrokeAttribute get/setters ----------------------------*/
PyDoc_STRVAR(
/* Wrap. */
StrokeAttribute_alpha_doc,
"Alpha component of the stroke color.\n"
"\n"
":type: float\n");
static PyObject *StrokeAttribute_alpha_get(BPy_StrokeAttribute *self, void * /*closure*/)
{
return PyFloat_FromDouble(self->sa->getAlpha());
}
static int StrokeAttribute_alpha_set(BPy_StrokeAttribute *self,
PyObject *value,
void * /*closure*/)
{
float scalar;
if ((scalar = PyFloat_AsDouble(value)) == -1.0f && PyErr_Occurred()) {
/* parsed item not a number */
PyErr_SetString(PyExc_TypeError, "value must be a number");
return -1;
}
self->sa->setAlpha(scalar);
return 0;
}
PyDoc_STRVAR(
/* Wrap. */
StrokeAttribute_color_doc,
"RGB components of the stroke color.\n"
"\n"
":type: :class:`mathutils.Color`\n");
static PyObject *StrokeAttribute_color_get(BPy_StrokeAttribute *self, void * /*closure*/)
{
return blender::Color_CreatePyObject_cb(
(PyObject *)self, StrokeAttribute_mathutils_cb_index, MATHUTILS_SUBTYPE_COLOR);
}
static int StrokeAttribute_color_set(BPy_StrokeAttribute *self,
PyObject *value,
void * /*closure*/)
{
float v[3];
if (blender::mathutils_array_parse(v, 3, 3, value, "value must be a 3-dimensional vector") == -1)
{
return -1;
}
self->sa->setColor(v[0], v[1], v[2]);
return 0;
}
PyDoc_STRVAR(
/* Wrap. */
StrokeAttribute_thickness_doc,
"Right and left components of the stroke thickness.\n"
"The right (left) component is the thickness on the right (left) of the vertex\n"
"when following the stroke.\n"
"\n"
":type: :class:`mathutils.Vector`\n");
static PyObject *StrokeAttribute_thickness_get(BPy_StrokeAttribute *self, void * /*closure*/)
{
return blender::Vector_CreatePyObject_cb(
(PyObject *)self, 2, StrokeAttribute_mathutils_cb_index, MATHUTILS_SUBTYPE_THICKNESS);
}
static int StrokeAttribute_thickness_set(BPy_StrokeAttribute *self,
PyObject *value,
void * /*closure*/)
{
float v[2];
if (blender::mathutils_array_parse(v, 2, 2, value, "value must be a 2-dimensional vector") == -1)
{
return -1;
}
self->sa->setThickness(v[0], v[1]);
return 0;
}
PyDoc_STRVAR(
/* Wrap. */
StrokeAttribute_visible_doc,
"The visibility flag. True if the StrokeVertex is visible.\n"
"\n"
":type: bool\n");
static PyObject *StrokeAttribute_visible_get(BPy_StrokeAttribute *self, void * /*closure*/)
{
return PyBool_from_bool(self->sa->isVisible());
}
static int StrokeAttribute_visible_set(BPy_StrokeAttribute *self,
PyObject *value,
void * /*closure*/)
{
if (!PyBool_Check(value)) {
PyErr_SetString(PyExc_TypeError, "value must be boolean");
return -1;
}
self->sa->setVisible(bool_from_PyBool(value));
return 0;
}
static PyGetSetDef BPy_StrokeAttribute_getseters[] = {
{"alpha",
(getter)StrokeAttribute_alpha_get,
(setter)StrokeAttribute_alpha_set,
StrokeAttribute_alpha_doc,
nullptr},
{"color",
(getter)StrokeAttribute_color_get,
(setter)StrokeAttribute_color_set,
StrokeAttribute_color_doc,
nullptr},
{"thickness",
(getter)StrokeAttribute_thickness_get,
(setter)StrokeAttribute_thickness_set,
StrokeAttribute_thickness_doc,
nullptr},
{"visible",
(getter)StrokeAttribute_visible_get,
(setter)StrokeAttribute_visible_set,
StrokeAttribute_visible_doc,
nullptr},
{nullptr, nullptr, nullptr, nullptr, nullptr} /* Sentinel */
};
/*-----------------------BPy_StrokeAttribute type definition ------------------------------*/
PyTypeObject StrokeAttribute_Type = {
/*ob_base*/ PyVarObject_HEAD_INIT(nullptr, 0)
/*tp_name*/ "StrokeAttribute",
/*tp_basicsize*/ sizeof(BPy_StrokeAttribute),
/*tp_itemsize*/ 0,
/*tp_dealloc*/ (destructor)StrokeAttribute_dealloc,
/*tp_vectorcall_offset*/ 0,
/*tp_getattr*/ nullptr,
/*tp_setattr*/ nullptr,
/*tp_as_async*/ nullptr,
/*tp_repr*/ (reprfunc)StrokeAttribute_repr,
/*tp_as_number*/ nullptr,
/*tp_as_sequence*/ nullptr,
/*tp_as_mapping*/ nullptr,
/*tp_hash*/ nullptr,
/*tp_call*/ nullptr,
/*tp_str*/ nullptr,
/*tp_getattro*/ nullptr,
/*tp_setattro*/ nullptr,
/*tp_as_buffer*/ nullptr,
/*tp_flags*/ Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE,
/*tp_doc*/ StrokeAttribute_doc,
/*tp_traverse*/ nullptr,
/*tp_clear*/ nullptr,
/*tp_richcompare*/ nullptr,
/*tp_weaklistoffset*/ 0,
/*tp_iter*/ nullptr,
/*tp_iternext*/ nullptr,
/*tp_methods*/ BPy_StrokeAttribute_methods,
/*tp_members*/ nullptr,
/*tp_getset*/ BPy_StrokeAttribute_getseters,
/*tp_base*/ nullptr,
/*tp_dict*/ nullptr,
/*tp_descr_get*/ nullptr,
/*tp_descr_set*/ nullptr,
/*tp_dictoffset*/ 0,
/*tp_init*/ (initproc)StrokeAttribute_init,
/*tp_alloc*/ nullptr,
/*tp_new*/ PyType_GenericNew,
};
///////////////////////////////////////////////////////////////////////////////////////////

View File

@@ -0,0 +1,36 @@
/* SPDX-FileCopyrightText: 2023 Blender Authors
*
* SPDX-License-Identifier: GPL-2.0-or-later */
/** \file
* \ingroup freestyle
*/
#pragma once
extern "C" {
#include <Python.h>
}
#include "../stroke/Stroke.h"
///////////////////////////////////////////////////////////////////////////////////////////
extern PyTypeObject StrokeAttribute_Type;
#define BPy_StrokeAttribute_Check(v) \
(PyObject_IsInstance((PyObject *)v, (PyObject *)&StrokeAttribute_Type))
/*---------------------------Python BPy_StrokeAttribute structure definition----------*/
struct BPy_StrokeAttribute {
PyObject_HEAD
Freestyle::StrokeAttribute *sa;
bool borrowed; /* true if *sa is a borrowed reference */
};
/*---------------------------Python BPy_StrokeAttribute visible prototypes-----------*/
int StrokeAttribute_Init(PyObject *module);
void StrokeAttribute_mathutils_register_callback();
///////////////////////////////////////////////////////////////////////////////////////////

View File

@@ -0,0 +1,313 @@
/* SPDX-FileCopyrightText: 2004-2022 Blender Authors
*
* SPDX-License-Identifier: GPL-2.0-or-later */
/** \file
* \ingroup freestyle
*/
#include "BPy_StrokeShader.h"
#include "BPy_Convert.h"
#include "Interface1D/BPy_Stroke.h"
#include "StrokeShader/BPy_BackboneStretcherShader.h"
#include "StrokeShader/BPy_BezierCurveShader.h"
#include "StrokeShader/BPy_BlenderTextureShader.h"
#include "StrokeShader/BPy_CalligraphicShader.h"
#include "StrokeShader/BPy_ColorNoiseShader.h"
#include "StrokeShader/BPy_ConstantColorShader.h"
#include "StrokeShader/BPy_ConstantThicknessShader.h"
#include "StrokeShader/BPy_ConstrainedIncreasingThicknessShader.h"
#include "StrokeShader/BPy_GuidingLinesShader.h"
#include "StrokeShader/BPy_IncreasingColorShader.h"
#include "StrokeShader/BPy_IncreasingThicknessShader.h"
#include "StrokeShader/BPy_PolygonalizationShader.h"
#include "StrokeShader/BPy_SamplingShader.h"
#include "StrokeShader/BPy_SmoothingShader.h"
#include "StrokeShader/BPy_SpatialNoiseShader.h"
#include "StrokeShader/BPy_StrokeTextureStepShader.h"
#include "StrokeShader/BPy_ThicknessNoiseShader.h"
#include "StrokeShader/BPy_TipRemoverShader.h"
using namespace Freestyle;
///////////////////////////////////////////////////////////////////////////////////////////
//-------------------MODULE INITIALIZATION--------------------------------
int StrokeShader_Init(PyObject *module)
{
if (module == nullptr) {
return -1;
}
if (PyType_Ready(&StrokeShader_Type) < 0) {
return -1;
}
PyModule_AddObjectRef(module, "StrokeShader", (PyObject *)&StrokeShader_Type);
if (PyType_Ready(&BackboneStretcherShader_Type) < 0) {
return -1;
}
PyModule_AddObjectRef(
module, "BackboneStretcherShader", (PyObject *)&BackboneStretcherShader_Type);
if (PyType_Ready(&BezierCurveShader_Type) < 0) {
return -1;
}
PyModule_AddObjectRef(module, "BezierCurveShader", (PyObject *)&BezierCurveShader_Type);
if (PyType_Ready(&BlenderTextureShader_Type) < 0) {
return -1;
}
PyModule_AddObjectRef(module, "BlenderTextureShader", (PyObject *)&BlenderTextureShader_Type);
if (PyType_Ready(&CalligraphicShader_Type) < 0) {
return -1;
}
PyModule_AddObjectRef(module, "CalligraphicShader", (PyObject *)&CalligraphicShader_Type);
if (PyType_Ready(&ColorNoiseShader_Type) < 0) {
return -1;
}
PyModule_AddObjectRef(module, "ColorNoiseShader", (PyObject *)&ColorNoiseShader_Type);
if (PyType_Ready(&ConstantColorShader_Type) < 0) {
return -1;
}
PyModule_AddObjectRef(module, "ConstantColorShader", (PyObject *)&ConstantColorShader_Type);
if (PyType_Ready(&ConstantThicknessShader_Type) < 0) {
return -1;
}
PyModule_AddObjectRef(
module, "ConstantThicknessShader", (PyObject *)&ConstantThicknessShader_Type);
if (PyType_Ready(&ConstrainedIncreasingThicknessShader_Type) < 0) {
return -1;
}
PyModule_AddObjectRef(module,
"ConstrainedIncreasingThicknessShader",
(PyObject *)&ConstrainedIncreasingThicknessShader_Type);
if (PyType_Ready(&GuidingLinesShader_Type) < 0) {
return -1;
}
PyModule_AddObjectRef(module, "GuidingLinesShader", (PyObject *)&GuidingLinesShader_Type);
if (PyType_Ready(&IncreasingColorShader_Type) < 0) {
return -1;
}
PyModule_AddObjectRef(module, "IncreasingColorShader", (PyObject *)&IncreasingColorShader_Type);
if (PyType_Ready(&IncreasingThicknessShader_Type) < 0) {
return -1;
}
PyModule_AddObjectRef(
module, "IncreasingThicknessShader", (PyObject *)&IncreasingThicknessShader_Type);
if (PyType_Ready(&PolygonalizationShader_Type) < 0) {
return -1;
}
PyModule_AddObjectRef(
module, "PolygonalizationShader", (PyObject *)&PolygonalizationShader_Type);
if (PyType_Ready(&SamplingShader_Type) < 0) {
return -1;
}
PyModule_AddObjectRef(module, "SamplingShader", (PyObject *)&SamplingShader_Type);
if (PyType_Ready(&SmoothingShader_Type) < 0) {
return -1;
}
PyModule_AddObjectRef(module, "SmoothingShader", (PyObject *)&SmoothingShader_Type);
if (PyType_Ready(&SpatialNoiseShader_Type) < 0) {
return -1;
}
PyModule_AddObjectRef(module, "SpatialNoiseShader", (PyObject *)&SpatialNoiseShader_Type);
if (PyType_Ready(&StrokeTextureStepShader_Type) < 0) {
return -1;
}
PyModule_AddObjectRef(
module, "StrokeTextureStepShader", (PyObject *)&StrokeTextureStepShader_Type);
if (PyType_Ready(&ThicknessNoiseShader_Type) < 0) {
return -1;
}
PyModule_AddObjectRef(module, "ThicknessNoiseShader", (PyObject *)&ThicknessNoiseShader_Type);
if (PyType_Ready(&TipRemoverShader_Type) < 0) {
return -1;
}
PyModule_AddObjectRef(module, "TipRemoverShader", (PyObject *)&TipRemoverShader_Type);
return 0;
}
//------------------------INSTANCE METHODS ----------------------------------
PyDoc_STRVAR(
/* Wrap. */
StrokeShader___doc__,
"Base class for stroke shaders. Any stroke shader must inherit from\n"
"this class and overload the shade() method. A StrokeShader is\n"
"designed to modify stroke attributes such as thickness, color,\n"
"geometry, texture, blending mode, and so on. The basic way for this\n"
"operation is to iterate over the stroke vertices of the :class:`Stroke`\n"
"and to modify the :class:`StrokeAttribute` of each vertex. Here is a\n"
"code example of such an iteration::\n"
"\n"
" it = ioStroke.strokeVerticesBegin()\n"
" while not it.is_end:\n"
" att = it.object.attribute\n"
" ## perform here any attribute modification\n"
" it.increment()\n"
"\n"
".. method:: __init__()\n"
"\n"
" Default constructor.\n");
static int StrokeShader___init__(BPy_StrokeShader *self, PyObject *args, PyObject *kwds)
{
static const char *kwlist[] = {nullptr};
if (!PyArg_ParseTupleAndKeywords(args, kwds, "", (char **)kwlist)) {
return -1;
}
self->ss = new StrokeShader();
self->ss->py_ss = (PyObject *)self;
return 0;
}
static void StrokeShader___dealloc__(BPy_StrokeShader *self)
{
delete self->ss;
Py_TYPE(self)->tp_free((PyObject *)self);
}
static PyObject *StrokeShader___repr__(BPy_StrokeShader *self)
{
return PyUnicode_FromFormat("type: %s - address: %p", Py_TYPE(self)->tp_name, self->ss);
}
PyDoc_STRVAR(
/* Wrap. */
StrokeShader_shade___doc__,
".. method:: shade(stroke)\n"
"\n"
" The shading method. Must be overloaded by inherited classes.\n"
"\n"
" :param stroke: A Stroke object.\n"
" :type stroke: :class:`Stroke`\n");
static PyObject *StrokeShader_shade(BPy_StrokeShader *self, PyObject *args, PyObject *kwds)
{
static const char *kwlist[] = {"stroke", nullptr};
PyObject *py_s = nullptr;
if (!PyArg_ParseTupleAndKeywords(args, kwds, "O!", (char **)kwlist, &Stroke_Type, &py_s)) {
return nullptr;
}
if (typeid(*(self->ss)) == typeid(StrokeShader)) {
PyErr_SetString(PyExc_TypeError, "shade method not properly overridden");
return nullptr;
}
if (self->ss->shade(*(((BPy_Stroke *)py_s)->s)) < 0) {
if (!PyErr_Occurred()) {
string class_name(Py_TYPE(self)->tp_name);
PyErr_SetString(PyExc_RuntimeError, (class_name + " shade method failed").c_str());
}
return nullptr;
}
Py_RETURN_NONE;
}
#ifdef __GNUC__
# ifdef __clang__
# pragma clang diagnostic push
# pragma clang diagnostic ignored "-Wcast-function-type"
# else
# pragma GCC diagnostic push
# pragma GCC diagnostic ignored "-Wcast-function-type"
# endif
#endif
static PyMethodDef BPy_StrokeShader_methods[] = {
{"shade",
(PyCFunction)StrokeShader_shade,
METH_VARARGS | METH_KEYWORDS,
StrokeShader_shade___doc__},
{nullptr, nullptr, 0, nullptr},
};
#ifdef __GNUC__
# ifdef __clang__
# pragma clang diagnostic pop
# else
# pragma GCC diagnostic pop
# endif
#endif
/*----------------------StrokeShader get/setters ----------------------------*/
PyDoc_STRVAR(
/* Wrap. */
StrokeShader_name_doc,
"The name of the stroke shader.\n"
"\n"
":type: str\n");
static PyObject *StrokeShader_name_get(BPy_StrokeShader *self, void * /*closure*/)
{
return PyUnicode_FromString(Py_TYPE(self)->tp_name);
}
static PyGetSetDef BPy_StrokeShader_getseters[] = {
{"name", (getter)StrokeShader_name_get, (setter) nullptr, StrokeShader_name_doc, nullptr},
{nullptr, nullptr, nullptr, nullptr, nullptr} /* Sentinel */
};
/*-----------------------BPy_StrokeShader type definition ------------------------------*/
PyTypeObject StrokeShader_Type = {
/*ob_base*/ PyVarObject_HEAD_INIT(nullptr, 0)
/*tp_name*/ "StrokeShader",
/*tp_basicsize*/ sizeof(BPy_StrokeShader),
/*tp_itemsize*/ 0,
/*tp_dealloc*/ (destructor)StrokeShader___dealloc__,
/*tp_vectorcall_offset*/ 0,
/*tp_getattr*/ nullptr,
/*tp_setattr*/ nullptr,
/*tp_as_async*/ nullptr,
/*tp_repr*/ (reprfunc)StrokeShader___repr__,
/*tp_as_number*/ nullptr,
/*tp_as_sequence*/ nullptr,
/*tp_as_mapping*/ nullptr,
/*tp_hash*/ nullptr,
/*tp_call*/ nullptr,
/*tp_str*/ nullptr,
/*tp_getattro*/ nullptr,
/*tp_setattro*/ nullptr,
/*tp_as_buffer*/ nullptr,
/*tp_flags*/ Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE,
/*tp_doc*/ StrokeShader___doc__,
/*tp_traverse*/ nullptr,
/*tp_clear*/ nullptr,
/*tp_richcompare*/ nullptr,
/*tp_weaklistoffset*/ 0,
/*tp_iter*/ nullptr,
/*tp_iternext*/ nullptr,
/*tp_methods*/ BPy_StrokeShader_methods,
/*tp_members*/ nullptr,
/*tp_getset*/ BPy_StrokeShader_getseters,
/*tp_base*/ nullptr,
/*tp_dict*/ nullptr,
/*tp_descr_get*/ nullptr,
/*tp_descr_set*/ nullptr,
/*tp_dictoffset*/ 0,
/*tp_init*/ (initproc)StrokeShader___init__,
/*tp_alloc*/ nullptr,
/*tp_new*/ PyType_GenericNew,
};
///////////////////////////////////////////////////////////////////////////////////////////

View File

@@ -0,0 +1,36 @@
/* SPDX-FileCopyrightText: 2023 Blender Authors
*
* SPDX-License-Identifier: GPL-2.0-or-later */
/** \file
* \ingroup freestyle
*/
#pragma once
extern "C" {
#include <Python.h>
}
#include "../system/FreestyleConfig.h"
#include "../stroke/StrokeShader.h"
///////////////////////////////////////////////////////////////////////////////////////////
extern PyTypeObject StrokeShader_Type;
#define BPy_StrokeShader_Check(v) \
(PyObject_IsInstance((PyObject *)v, (PyObject *)&StrokeShader_Type))
/*---------------------------Python BPy_StrokeShader structure definition----------*/
struct BPy_StrokeShader {
PyObject_HEAD
Freestyle::StrokeShader *ss;
};
/*---------------------------Python BPy_StrokeShader visible prototypes-----------*/
int StrokeShader_Init(PyObject *module);
///////////////////////////////////////////////////////////////////////////////////////////

View File

@@ -0,0 +1,150 @@
/* SPDX-FileCopyrightText: 2004-2022 Blender Authors
*
* SPDX-License-Identifier: GPL-2.0-or-later */
/** \file
* \ingroup freestyle
*/
#include "BPy_UnaryFunction0D.h"
#include "UnaryFunction0D/BPy_UnaryFunction0DDouble.h"
#include "UnaryFunction0D/BPy_UnaryFunction0DEdgeNature.h"
#include "UnaryFunction0D/BPy_UnaryFunction0DFloat.h"
#include "UnaryFunction0D/BPy_UnaryFunction0DId.h"
#include "UnaryFunction0D/BPy_UnaryFunction0DMaterial.h"
#include "UnaryFunction0D/BPy_UnaryFunction0DUnsigned.h"
#include "UnaryFunction0D/BPy_UnaryFunction0DVec2f.h"
#include "UnaryFunction0D/BPy_UnaryFunction0DVec3f.h"
#include "UnaryFunction0D/BPy_UnaryFunction0DVectorViewShape.h"
#include "UnaryFunction0D/BPy_UnaryFunction0DViewShape.h"
using namespace Freestyle;
///////////////////////////////////////////////////////////////////////////////////////////
//-------------------MODULE INITIALIZATION--------------------------------
int UnaryFunction0D_Init(PyObject *module)
{
if (module == nullptr) {
return -1;
}
if (PyType_Ready(&UnaryFunction0D_Type) < 0) {
return -1;
}
PyModule_AddObjectRef(module, "UnaryFunction0D", (PyObject *)&UnaryFunction0D_Type);
UnaryFunction0DDouble_Init(module);
UnaryFunction0DEdgeNature_Init(module);
UnaryFunction0DFloat_Init(module);
UnaryFunction0DId_Init(module);
UnaryFunction0DMaterial_Init(module);
UnaryFunction0DUnsigned_Init(module);
UnaryFunction0DVec2f_Init(module);
UnaryFunction0DVec3f_Init(module);
UnaryFunction0DVectorViewShape_Init(module);
UnaryFunction0DViewShape_Init(module);
return 0;
}
//------------------------INSTANCE METHODS ----------------------------------
PyDoc_STRVAR(
/* Wrap. */
UnaryFunction0D___doc__,
"Base class for Unary Functions (functors) working on\n"
":class:`Interface0DIterator`. A unary function will be used by\n"
"invoking __call__() on an Interface0DIterator. In Python, several\n"
"different subclasses of UnaryFunction0D are used depending on the\n"
"types of functors' return values. For example, you would inherit from\n"
"a :class:`UnaryFunction0DDouble` if you wish to define a function that\n"
"returns a double value. Available UnaryFunction0D subclasses are:\n"
"\n"
"* :class:`UnaryFunction0DDouble`\n"
"* :class:`UnaryFunction0DEdgeNature`\n"
"* :class:`UnaryFunction0DFloat`\n"
"* :class:`UnaryFunction0DId`\n"
"* :class:`UnaryFunction0DMaterial`\n"
"* :class:`UnaryFunction0DUnsigned`\n"
"* :class:`UnaryFunction0DVec2f`\n"
"* :class:`UnaryFunction0DVec3f`\n"
"* :class:`UnaryFunction0DVectorViewShape`\n"
"* :class:`UnaryFunction0DViewShape`\n");
static void UnaryFunction0D___dealloc__(BPy_UnaryFunction0D *self)
{
Py_TYPE(self)->tp_free((PyObject *)self);
}
static PyObject *UnaryFunction0D___repr__(BPy_UnaryFunction0D * /*self*/)
{
return PyUnicode_FromString("UnaryFunction0D");
}
/*----------------------UnaryFunction0D get/setters ----------------------------*/
PyDoc_STRVAR(
/* Wrap. */
UnaryFunction0D_name_doc,
"The name of the unary 0D function.\n"
"\n"
":type: str\n");
static PyObject *UnaryFunction0D_name_get(BPy_UnaryFunction0D *self, void * /*closure*/)
{
return PyUnicode_FromString(Py_TYPE(self)->tp_name);
}
static PyGetSetDef BPy_UnaryFunction0D_getseters[] = {
{"name",
(getter)UnaryFunction0D_name_get,
(setter) nullptr,
UnaryFunction0D_name_doc,
nullptr},
{nullptr, nullptr, nullptr, nullptr, nullptr} /* Sentinel */
};
/*-----------------------BPy_UnaryFunction0D type definition ------------------------------*/
PyTypeObject UnaryFunction0D_Type = {
/*ob_base*/ PyVarObject_HEAD_INIT(nullptr, 0)
/*tp_name*/ "UnaryFunction0D",
/*tp_basicsize*/ sizeof(BPy_UnaryFunction0D),
/*tp_itemsize*/ 0,
/*tp_dealloc*/ (destructor)UnaryFunction0D___dealloc__,
/*tp_vectorcall_offset*/ 0,
/*tp_getattr*/ nullptr,
/*tp_setattr*/ nullptr,
/*tp_as_async*/ nullptr,
/*tp_repr*/ (reprfunc)UnaryFunction0D___repr__,
/*tp_as_number*/ nullptr,
/*tp_as_sequence*/ nullptr,
/*tp_as_mapping*/ nullptr,
/*tp_hash*/ nullptr,
/*tp_call*/ nullptr,
/*tp_str*/ nullptr,
/*tp_getattro*/ nullptr,
/*tp_setattro*/ nullptr,
/*tp_as_buffer*/ nullptr,
/*tp_flags*/ Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE,
/*tp_doc*/ UnaryFunction0D___doc__,
/*tp_traverse*/ nullptr,
/*tp_clear*/ nullptr,
/*tp_richcompare*/ nullptr,
/*tp_weaklistoffset*/ 0,
/*tp_iter*/ nullptr,
/*tp_iternext*/ nullptr,
/*tp_methods*/ nullptr,
/*tp_members*/ nullptr,
/*tp_getset*/ BPy_UnaryFunction0D_getseters,
/*tp_base*/ nullptr,
/*tp_dict*/ nullptr,
/*tp_descr_get*/ nullptr,
/*tp_descr_set*/ nullptr,
/*tp_dictoffset*/ 0,
/*tp_init*/ nullptr,
/*tp_alloc*/ nullptr,
/*tp_new*/ PyType_GenericNew,
};
///////////////////////////////////////////////////////////////////////////////////////////

View File

@@ -0,0 +1,34 @@
/* SPDX-FileCopyrightText: 2023 Blender Authors
*
* SPDX-License-Identifier: GPL-2.0-or-later */
/** \file
* \ingroup freestyle
*/
#pragma once
extern "C" {
#include <Python.h>
}
#include "../view_map/Functions0D.h"
///////////////////////////////////////////////////////////////////////////////////////////
extern PyTypeObject UnaryFunction0D_Type;
#define BPy_UnaryFunction0D_Check(v) \
(PyObject_IsInstance((PyObject *)v, (PyObject *)&UnaryFunction0D_Type))
/*---------------------------Python BPy_UnaryFunction0D structure definition----------*/
struct BPy_UnaryFunction0D {
PyObject_HEAD
PyObject *py_uf0D;
};
/*---------------------------Python BPy_UnaryFunction0D visible prototypes-----------*/
int UnaryFunction0D_Init(PyObject *module);
///////////////////////////////////////////////////////////////////////////////////////////

View File

@@ -0,0 +1,144 @@
/* SPDX-FileCopyrightText: 2004-2022 Blender Authors
*
* SPDX-License-Identifier: GPL-2.0-or-later */
/** \file
* \ingroup freestyle
*/
#include "BPy_UnaryFunction1D.h"
#include "UnaryFunction1D/BPy_UnaryFunction1DDouble.h"
#include "UnaryFunction1D/BPy_UnaryFunction1DEdgeNature.h"
#include "UnaryFunction1D/BPy_UnaryFunction1DFloat.h"
#include "UnaryFunction1D/BPy_UnaryFunction1DUnsigned.h"
#include "UnaryFunction1D/BPy_UnaryFunction1DVec2f.h"
#include "UnaryFunction1D/BPy_UnaryFunction1DVec3f.h"
#include "UnaryFunction1D/BPy_UnaryFunction1DVectorViewShape.h"
#include "UnaryFunction1D/BPy_UnaryFunction1DVoid.h"
using namespace Freestyle;
///////////////////////////////////////////////////////////////////////////////////////////
//-------------------MODULE INITIALIZATION--------------------------------
int UnaryFunction1D_Init(PyObject *module)
{
if (module == nullptr) {
return -1;
}
if (PyType_Ready(&UnaryFunction1D_Type) < 0) {
return -1;
}
PyModule_AddObjectRef(module, "UnaryFunction1D", (PyObject *)&UnaryFunction1D_Type);
UnaryFunction1DDouble_Init(module);
UnaryFunction1DEdgeNature_Init(module);
UnaryFunction1DFloat_Init(module);
UnaryFunction1DUnsigned_Init(module);
UnaryFunction1DVec2f_Init(module);
UnaryFunction1DVec3f_Init(module);
UnaryFunction1DVectorViewShape_Init(module);
UnaryFunction1DVoid_Init(module);
return 0;
}
//------------------------INSTANCE METHODS ----------------------------------
PyDoc_STRVAR(
/* Wrap. */
UnaryFunction1D___doc__,
"Base class for Unary Functions (functors) working on\n"
":class:`Interface1D`. A unary function will be used by invoking\n"
"__call__() on an Interface1D. In Python, several different subclasses\n"
"of UnaryFunction1D are used depending on the types of functors' return\n"
"values. For example, you would inherit from a\n"
":class:`UnaryFunction1DDouble` if you wish to define a function that\n"
"returns a double value. Available UnaryFunction1D subclasses are:\n"
"\n"
"* :class:`UnaryFunction1DDouble`\n"
"* :class:`UnaryFunction1DEdgeNature`\n"
"* :class:`UnaryFunction1DFloat`\n"
"* :class:`UnaryFunction1DUnsigned`\n"
"* :class:`UnaryFunction1DVec2f`\n"
"* :class:`UnaryFunction1DVec3f`\n"
"* :class:`UnaryFunction1DVectorViewShape`\n"
"* :class:`UnaryFunction1DVoid`\n");
static void UnaryFunction1D___dealloc__(BPy_UnaryFunction1D *self)
{
Py_TYPE(self)->tp_free((PyObject *)self);
}
static PyObject *UnaryFunction1D___repr__(BPy_UnaryFunction1D * /*self*/)
{
return PyUnicode_FromString("UnaryFunction1D");
}
/*----------------------UnaryFunction1D get/setters ----------------------------*/
PyDoc_STRVAR(
/* Wrap. */
UnaryFunction1D_name_doc,
"The name of the unary 1D function.\n"
"\n"
":type: str\n");
static PyObject *UnaryFunction1D_name_get(BPy_UnaryFunction1D *self, void * /*closure*/)
{
return PyUnicode_FromString(Py_TYPE(self)->tp_name);
}
static PyGetSetDef BPy_UnaryFunction1D_getseters[] = {
{"name",
(getter)UnaryFunction1D_name_get,
(setter) nullptr,
UnaryFunction1D_name_doc,
nullptr},
{nullptr, nullptr, nullptr, nullptr, nullptr} /* Sentinel */
};
/*-----------------------BPy_UnaryFunction1D type definition ------------------------------*/
PyTypeObject UnaryFunction1D_Type = {
/*ob_base*/ PyVarObject_HEAD_INIT(nullptr, 0)
/*tp_name*/ "UnaryFunction1D",
/*tp_basicsize*/ sizeof(BPy_UnaryFunction1D),
/*tp_itemsize*/ 0,
/*tp_dealloc*/ (destructor)UnaryFunction1D___dealloc__,
/*tp_vectorcall_offset*/ 0,
/*tp_getattr*/ nullptr,
/*tp_setattr*/ nullptr,
/*tp_as_async*/ nullptr,
/*tp_repr*/ (reprfunc)UnaryFunction1D___repr__,
/*tp_as_number*/ nullptr,
/*tp_as_sequence*/ nullptr,
/*tp_as_mapping*/ nullptr,
/*tp_hash*/ nullptr,
/*tp_call*/ nullptr,
/*tp_str*/ nullptr,
/*tp_getattro*/ nullptr,
/*tp_setattro*/ nullptr,
/*tp_as_buffer*/ nullptr,
/*tp_flags*/ Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE,
/*tp_doc*/ UnaryFunction1D___doc__,
/*tp_traverse*/ nullptr,
/*tp_clear*/ nullptr,
/*tp_richcompare*/ nullptr,
/*tp_weaklistoffset*/ 0,
/*tp_iter*/ nullptr,
/*tp_iternext*/ nullptr,
/*tp_methods*/ nullptr,
/*tp_members*/ nullptr,
/*tp_getset*/ BPy_UnaryFunction1D_getseters,
/*tp_base*/ nullptr,
/*tp_dict*/ nullptr,
/*tp_descr_get*/ nullptr,
/*tp_descr_set*/ nullptr,
/*tp_dictoffset*/ 0,
/*tp_init*/ nullptr,
/*tp_alloc*/ nullptr,
/*tp_new*/ PyType_GenericNew,
};
///////////////////////////////////////////////////////////////////////////////////////////

View File

@@ -0,0 +1,34 @@
/* SPDX-FileCopyrightText: 2023 Blender Authors
*
* SPDX-License-Identifier: GPL-2.0-or-later */
/** \file
* \ingroup freestyle
*/
#pragma once
extern "C" {
#include <Python.h>
}
#include "../view_map/Functions1D.h"
///////////////////////////////////////////////////////////////////////////////////////////
extern PyTypeObject UnaryFunction1D_Type;
#define BPy_UnaryFunction1D_Check(v) \
(PyObject_IsInstance((PyObject *)v, (PyObject *)&UnaryFunction1D_Type))
/*---------------------------Python BPy_UnaryFunction1D structure definition----------*/
struct BPy_UnaryFunction1D {
PyObject_HEAD
PyObject *py_uf1D;
};
/*---------------------------Python BPy_UnaryFunction1D visible prototypes-----------*/
int UnaryFunction1D_Init(PyObject *module);
///////////////////////////////////////////////////////////////////////////////////////////

View File

@@ -0,0 +1,192 @@
/* SPDX-FileCopyrightText: 2004-2023 Blender Authors
*
* SPDX-License-Identifier: GPL-2.0-or-later */
/** \file
* \ingroup freestyle
*/
#include "BPy_UnaryPredicate0D.h"
#include "BPy_Convert.h"
#include "Iterator/BPy_Interface0DIterator.h"
#include "UnaryPredicate0D/BPy_FalseUP0D.h"
#include "UnaryPredicate0D/BPy_TrueUP0D.h"
using namespace Freestyle;
///////////////////////////////////////////////////////////////////////////////////////////
//-------------------MODULE INITIALIZATION--------------------------------
int UnaryPredicate0D_Init(PyObject *module)
{
if (module == nullptr) {
return -1;
}
if (PyType_Ready(&UnaryPredicate0D_Type) < 0) {
return -1;
}
PyModule_AddObjectRef(module, "UnaryPredicate0D", (PyObject *)&UnaryPredicate0D_Type);
if (PyType_Ready(&FalseUP0D_Type) < 0) {
return -1;
}
PyModule_AddObjectRef(module, "FalseUP0D", (PyObject *)&FalseUP0D_Type);
if (PyType_Ready(&TrueUP0D_Type) < 0) {
return -1;
}
PyModule_AddObjectRef(module, "TrueUP0D", (PyObject *)&TrueUP0D_Type);
return 0;
}
//------------------------INSTANCE METHODS ----------------------------------
PyDoc_STRVAR(
/* Wrap. */
UnaryPredicate0D___doc__,
"Base class for unary predicates that work on\n"
":class:`Interface0DIterator`. A UnaryPredicate0D is a functor that\n"
"evaluates a condition on an Interface0DIterator and returns true or\n"
"false depending on whether this condition is satisfied or not. The\n"
"UnaryPredicate0D is used by invoking its __call__() method. Any\n"
"inherited class must overload the __call__() method.\n"
"\n"
".. method:: __init__()\n"
"\n"
" Default constructor.\n"
"\n"
".. method:: __call__(it)\n"
"\n"
" Must be overload by inherited classes.\n"
"\n"
" :param it: The Interface0DIterator pointing onto the Interface0D at\n"
" which we wish to evaluate the predicate.\n"
" :type it: :class:`Interface0DIterator`\n"
" :return: True if the condition is satisfied, false otherwise.\n"
" :rtype: bool\n");
static int UnaryPredicate0D___init__(BPy_UnaryPredicate0D *self, PyObject *args, PyObject *kwds)
{
static const char *kwlist[] = {nullptr};
if (!PyArg_ParseTupleAndKeywords(args, kwds, "", (char **)kwlist)) {
return -1;
}
self->up0D = new UnaryPredicate0D();
self->up0D->py_up0D = (PyObject *)self;
return 0;
}
static void UnaryPredicate0D___dealloc__(BPy_UnaryPredicate0D *self)
{
delete self->up0D;
Py_TYPE(self)->tp_free((PyObject *)self);
}
static PyObject *UnaryPredicate0D___repr__(BPy_UnaryPredicate0D *self)
{
return PyUnicode_FromFormat("type: %s - address: %p", Py_TYPE(self)->tp_name, self->up0D);
}
static PyObject *UnaryPredicate0D___call__(BPy_UnaryPredicate0D *self,
PyObject *args,
PyObject *kwds)
{
static const char *kwlist[] = {"it", nullptr};
PyObject *py_if0D_it;
if (!PyArg_ParseTupleAndKeywords(
args, kwds, "O!", (char **)kwlist, &Interface0DIterator_Type, &py_if0D_it))
{
return nullptr;
}
Interface0DIterator *if0D_it = ((BPy_Interface0DIterator *)py_if0D_it)->if0D_it;
if (!if0D_it) {
string class_name(Py_TYPE(self)->tp_name);
PyErr_SetString(PyExc_RuntimeError, (class_name + " has no Interface0DIterator").c_str());
return nullptr;
}
if (typeid(*(self->up0D)) == typeid(UnaryPredicate0D)) {
PyErr_SetString(PyExc_TypeError, "__call__ method not properly overridden");
return nullptr;
}
if (self->up0D->operator()(*if0D_it) < 0) {
if (!PyErr_Occurred()) {
string class_name(Py_TYPE(self)->tp_name);
PyErr_SetString(PyExc_RuntimeError, (class_name + " __call__ method failed").c_str());
}
return nullptr;
}
return PyBool_from_bool(self->up0D->result);
}
/*----------------------UnaryPredicate0D get/setters ----------------------------*/
PyDoc_STRVAR(
/* Wrap. */
UnaryPredicate0D_name_doc,
"The name of the unary 0D predicate.\n"
"\n"
":type: str\n");
static PyObject *UnaryPredicate0D_name_get(BPy_UnaryPredicate0D *self, void * /*closure*/)
{
return PyUnicode_FromString(Py_TYPE(self)->tp_name);
}
static PyGetSetDef BPy_UnaryPredicate0D_getseters[] = {
{"name",
(getter)UnaryPredicate0D_name_get,
(setter) nullptr,
UnaryPredicate0D_name_doc,
nullptr},
{nullptr, nullptr, nullptr, nullptr, nullptr} /* Sentinel */
};
/*-----------------------BPy_UnaryPredicate0D type definition ------------------------------*/
PyTypeObject UnaryPredicate0D_Type = {
/*ob_base*/ PyVarObject_HEAD_INIT(nullptr, 0)
/*tp_name*/ "UnaryPredicate0D",
/*tp_basicsize*/ sizeof(BPy_UnaryPredicate0D),
/*tp_itemsize*/ 0,
/*tp_dealloc*/ (destructor)UnaryPredicate0D___dealloc__,
/*tp_vectorcall_offset*/ 0,
/*tp_getattr*/ nullptr,
/*tp_setattr*/ nullptr,
/*tp_as_async*/ nullptr,
/*tp_repr*/ (reprfunc)UnaryPredicate0D___repr__,
/*tp_as_number*/ nullptr,
/*tp_as_sequence*/ nullptr,
/*tp_as_mapping*/ nullptr,
/*tp_hash*/ nullptr,
/*tp_call*/ (ternaryfunc)UnaryPredicate0D___call__,
/*tp_str*/ nullptr,
/*tp_getattro*/ nullptr,
/*tp_setattro*/ nullptr,
/*tp_as_buffer*/ nullptr,
/*tp_flags*/ Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE,
/*tp_doc*/ UnaryPredicate0D___doc__,
/*tp_traverse*/ nullptr,
/*tp_clear*/ nullptr,
/*tp_richcompare*/ nullptr,
/*tp_weaklistoffset*/ 0,
/*tp_iter*/ nullptr,
/*tp_iternext*/ nullptr,
/*tp_methods*/ nullptr,
/*tp_members*/ nullptr,
/*tp_getset*/ BPy_UnaryPredicate0D_getseters,
/*tp_base*/ nullptr,
/*tp_dict*/ nullptr,
/*tp_descr_get*/ nullptr,
/*tp_descr_set*/ nullptr,
/*tp_dictoffset*/ 0,
/*tp_init*/ (initproc)UnaryPredicate0D___init__,
/*tp_alloc*/ nullptr,
/*tp_new*/ PyType_GenericNew,
};
///////////////////////////////////////////////////////////////////////////////////////////

View File

@@ -0,0 +1,34 @@
/* SPDX-FileCopyrightText: 2023 Blender Authors
*
* SPDX-License-Identifier: GPL-2.0-or-later */
/** \file
* \ingroup freestyle
*/
#pragma once
extern "C" {
#include <Python.h>
}
#include "../stroke/Predicates0D.h"
///////////////////////////////////////////////////////////////////////////////////////////
extern PyTypeObject UnaryPredicate0D_Type;
#define BPy_UnaryPredicate0D_Check(v) \
(PyObject_IsInstance((PyObject *)v, (PyObject *)&UnaryPredicate0D_Type))
/*---------------------------Python BPy_UnaryPredicate0D structure definition----------*/
struct BPy_UnaryPredicate0D {
PyObject_HEAD
Freestyle::UnaryPredicate0D *up0D;
};
/*---------------------------Python BPy_UnaryPredicate0D visible prototypes-----------*/
int UnaryPredicate0D_Init(PyObject *module);
///////////////////////////////////////////////////////////////////////////////////////////

View File

@@ -0,0 +1,242 @@
/* SPDX-FileCopyrightText: 2004-2023 Blender Authors
*
* SPDX-License-Identifier: GPL-2.0-or-later */
/** \file
* \ingroup freestyle
*/
#include "BPy_UnaryPredicate1D.h"
#include "BPy_Convert.h"
#include "BPy_Interface1D.h"
#include "UnaryPredicate1D/BPy_ContourUP1D.h"
#include "UnaryPredicate1D/BPy_DensityLowerThanUP1D.h"
#include "UnaryPredicate1D/BPy_EqualToChainingTimeStampUP1D.h"
#include "UnaryPredicate1D/BPy_EqualToTimeStampUP1D.h"
#include "UnaryPredicate1D/BPy_ExternalContourUP1D.h"
#include "UnaryPredicate1D/BPy_FalseUP1D.h"
#include "UnaryPredicate1D/BPy_QuantitativeInvisibilityUP1D.h"
#include "UnaryPredicate1D/BPy_ShapeUP1D.h"
#include "UnaryPredicate1D/BPy_TrueUP1D.h"
#include "UnaryPredicate1D/BPy_WithinImageBoundaryUP1D.h"
using namespace Freestyle;
///////////////////////////////////////////////////////////////////////////////////////////
//-------------------MODULE INITIALIZATION--------------------------------
int UnaryPredicate1D_Init(PyObject *module)
{
if (module == nullptr) {
return -1;
}
if (PyType_Ready(&UnaryPredicate1D_Type) < 0) {
return -1;
}
PyModule_AddObjectRef(module, "UnaryPredicate1D", (PyObject *)&UnaryPredicate1D_Type);
if (PyType_Ready(&ContourUP1D_Type) < 0) {
return -1;
}
PyModule_AddObjectRef(module, "ContourUP1D", (PyObject *)&ContourUP1D_Type);
if (PyType_Ready(&DensityLowerThanUP1D_Type) < 0) {
return -1;
}
PyModule_AddObjectRef(module, "DensityLowerThanUP1D", (PyObject *)&DensityLowerThanUP1D_Type);
if (PyType_Ready(&EqualToChainingTimeStampUP1D_Type) < 0) {
return -1;
}
PyModule_AddObjectRef(
module, "EqualToChainingTimeStampUP1D", (PyObject *)&EqualToChainingTimeStampUP1D_Type);
if (PyType_Ready(&EqualToTimeStampUP1D_Type) < 0) {
return -1;
}
PyModule_AddObjectRef(module, "EqualToTimeStampUP1D", (PyObject *)&EqualToTimeStampUP1D_Type);
if (PyType_Ready(&ExternalContourUP1D_Type) < 0) {
return -1;
}
PyModule_AddObjectRef(module, "ExternalContourUP1D", (PyObject *)&ExternalContourUP1D_Type);
if (PyType_Ready(&FalseUP1D_Type) < 0) {
return -1;
}
PyModule_AddObjectRef(module, "FalseUP1D", (PyObject *)&FalseUP1D_Type);
if (PyType_Ready(&QuantitativeInvisibilityUP1D_Type) < 0) {
return -1;
}
PyModule_AddObjectRef(
module, "QuantitativeInvisibilityUP1D", (PyObject *)&QuantitativeInvisibilityUP1D_Type);
if (PyType_Ready(&ShapeUP1D_Type) < 0) {
return -1;
}
PyModule_AddObjectRef(module, "ShapeUP1D", (PyObject *)&ShapeUP1D_Type);
if (PyType_Ready(&TrueUP1D_Type) < 0) {
return -1;
}
PyModule_AddObjectRef(module, "TrueUP1D", (PyObject *)&TrueUP1D_Type);
if (PyType_Ready(&WithinImageBoundaryUP1D_Type) < 0) {
return -1;
}
PyModule_AddObjectRef(
module, "WithinImageBoundaryUP1D", (PyObject *)&WithinImageBoundaryUP1D_Type);
return 0;
}
//------------------------INSTANCE METHODS ----------------------------------
PyDoc_STRVAR(
/* Wrap. */
UnaryPredicate1D___doc__,
"Base class for unary predicates that work on :class:`Interface1D`. A\n"
"UnaryPredicate1D is a functor that evaluates a condition on a\n"
"Interface1D and returns true or false depending on whether this\n"
"condition is satisfied or not. The UnaryPredicate1D is used by\n"
"invoking its __call__() method. Any inherited class must overload the\n"
"__call__() method.\n"
"\n"
".. method:: __init__()\n"
"\n"
" Default constructor.\n"
"\n"
".. method:: __call__(inter)\n"
"\n"
" Must be overload by inherited classes.\n"
"\n"
" :param inter: The Interface1D on which we wish to evaluate the predicate.\n"
" :type inter: :class:`Interface1D`\n"
" :return: True if the condition is satisfied, false otherwise.\n"
" :rtype: bool\n");
static int UnaryPredicate1D___init__(BPy_UnaryPredicate1D *self, PyObject *args, PyObject *kwds)
{
static const char *kwlist[] = {nullptr};
if (!PyArg_ParseTupleAndKeywords(args, kwds, "", (char **)kwlist)) {
return -1;
}
self->up1D = new UnaryPredicate1D();
self->up1D->py_up1D = (PyObject *)self;
return 0;
}
static void UnaryPredicate1D___dealloc__(BPy_UnaryPredicate1D *self)
{
delete self->up1D;
Py_TYPE(self)->tp_free((PyObject *)self);
}
static PyObject *UnaryPredicate1D___repr__(BPy_UnaryPredicate1D *self)
{
return PyUnicode_FromFormat("type: %s - address: %p", Py_TYPE(self)->tp_name, self->up1D);
}
static PyObject *UnaryPredicate1D___call__(BPy_UnaryPredicate1D *self,
PyObject *args,
PyObject *kwds)
{
static const char *kwlist[] = {"inter", nullptr};
PyObject *py_if1D;
if (!PyArg_ParseTupleAndKeywords(args, kwds, "O!", (char **)kwlist, &Interface1D_Type, &py_if1D))
{
return nullptr;
}
Interface1D *if1D = ((BPy_Interface1D *)py_if1D)->if1D;
if (!if1D) {
string class_name(Py_TYPE(self)->tp_name);
PyErr_SetString(PyExc_RuntimeError, (class_name + " has no Interface1D").c_str());
return nullptr;
}
if (typeid(*(self->up1D)) == typeid(UnaryPredicate1D)) {
PyErr_SetString(PyExc_TypeError, "__call__ method not properly overridden");
return nullptr;
}
if (self->up1D->operator()(*if1D) < 0) {
if (!PyErr_Occurred()) {
string class_name(Py_TYPE(self)->tp_name);
PyErr_SetString(PyExc_RuntimeError, (class_name + " __call__ method failed").c_str());
}
return nullptr;
}
return PyBool_from_bool(self->up1D->result);
}
/*----------------------UnaryPredicate1D get/setters ----------------------------*/
PyDoc_STRVAR(
/* Wrap. */
UnaryPredicate1D_name_doc,
"The name of the unary 1D predicate.\n"
"\n"
":type: str\n");
static PyObject *UnaryPredicate1D_name_get(BPy_UnaryPredicate1D *self, void * /*closure*/)
{
return PyUnicode_FromString(Py_TYPE(self)->tp_name);
}
static PyGetSetDef BPy_UnaryPredicate1D_getseters[] = {
{"name",
(getter)UnaryPredicate1D_name_get,
(setter) nullptr,
UnaryPredicate1D_name_doc,
nullptr},
{nullptr, nullptr, nullptr, nullptr, nullptr} /* Sentinel */
};
/*-----------------------BPy_UnaryPredicate1D type definition ------------------------------*/
PyTypeObject UnaryPredicate1D_Type = {
/*ob_base*/ PyVarObject_HEAD_INIT(nullptr, 0)
/*tp_name*/ "UnaryPredicate1D",
/*tp_basicsize*/ sizeof(BPy_UnaryPredicate1D),
/*tp_itemsize*/ 0,
/*tp_dealloc*/ (destructor)UnaryPredicate1D___dealloc__,
/*tp_vectorcall_offset*/ 0,
/*tp_getattr*/ nullptr,
/*tp_setattr*/ nullptr,
/*tp_as_async*/ nullptr,
/*tp_repr*/ (reprfunc)UnaryPredicate1D___repr__,
/*tp_as_number*/ nullptr,
/*tp_as_sequence*/ nullptr,
/*tp_as_mapping*/ nullptr,
/*tp_hash*/ nullptr,
/*tp_call*/ (ternaryfunc)UnaryPredicate1D___call__,
/*tp_str*/ nullptr,
/*tp_getattro*/ nullptr,
/*tp_setattro*/ nullptr,
/*tp_as_buffer*/ nullptr,
/*tp_flags*/ Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE,
/*tp_doc*/ UnaryPredicate1D___doc__,
/*tp_traverse*/ nullptr,
/*tp_clear*/ nullptr,
/*tp_richcompare*/ nullptr,
/*tp_weaklistoffset*/ 0,
/*tp_iter*/ nullptr,
/*tp_iternext*/ nullptr,
/*tp_methods*/ nullptr,
/*tp_members*/ nullptr,
/*tp_getset*/ BPy_UnaryPredicate1D_getseters,
/*tp_base*/ nullptr,
/*tp_dict*/ nullptr,
/*tp_descr_get*/ nullptr,
/*tp_descr_set*/ nullptr,
/*tp_dictoffset*/ 0,
/*tp_init*/ (initproc)UnaryPredicate1D___init__,
/*tp_alloc*/ nullptr,
/*tp_new*/ PyType_GenericNew,
};
///////////////////////////////////////////////////////////////////////////////////////////

View File

@@ -0,0 +1,34 @@
/* SPDX-FileCopyrightText: 2023 Blender Authors
*
* SPDX-License-Identifier: GPL-2.0-or-later */
/** \file
* \ingroup freestyle
*/
#pragma once
extern "C" {
#include <Python.h>
}
#include "../stroke/Predicates1D.h"
///////////////////////////////////////////////////////////////////////////////////////////
extern PyTypeObject UnaryPredicate1D_Type;
#define BPy_UnaryPredicate1D_Check(v) \
(PyObject_IsInstance((PyObject *)v, (PyObject *)&UnaryPredicate1D_Type))
/*---------------------------Python BPy_UnaryPredicate1D structure definition----------*/
struct BPy_UnaryPredicate1D {
PyObject_HEAD
Freestyle::UnaryPredicate1D *up1D;
};
/*---------------------------Python BPy_UnaryPredicate1D visible prototypes-----------*/
int UnaryPredicate1D_Init(PyObject *module);
///////////////////////////////////////////////////////////////////////////////////////////

View File

@@ -0,0 +1,230 @@
/* SPDX-FileCopyrightText: 2004-2022 Blender Authors
*
* SPDX-License-Identifier: GPL-2.0-or-later */
/** \file
* \ingroup freestyle
*/
#include "BPy_ViewMap.h"
#include "BPy_BBox.h"
#include "BPy_Convert.h"
#include "Interface1D/BPy_FEdge.h"
#include "Interface1D/BPy_ViewEdge.h"
using namespace Freestyle;
///////////////////////////////////////////////////////////////////////////////////////////
//-------------------MODULE INITIALIZATION--------------------------------
int ViewMap_Init(PyObject *module)
{
if (module == nullptr) {
return -1;
}
if (PyType_Ready(&ViewMap_Type) < 0) {
return -1;
}
PyModule_AddObjectRef(module, "ViewMap", (PyObject *)&ViewMap_Type);
return 0;
}
/*----------------------ViewMap methods----------------------------*/
PyDoc_STRVAR(
/* Wrap. */
ViewMap_doc,
"Class defining the ViewMap.\n"
"\n"
".. method:: __init__()\n"
"\n"
" Default constructor.\n");
static int ViewMap_init(BPy_ViewMap *self, PyObject *args, PyObject *kwds)
{
static const char *kwlist[] = {nullptr};
if (!PyArg_ParseTupleAndKeywords(args, kwds, "", (char **)kwlist)) {
return -1;
}
self->vm = new ViewMap();
return 0;
}
static void ViewMap_dealloc(BPy_ViewMap *self)
{
delete self->vm;
Py_TYPE(self)->tp_free((PyObject *)self);
}
static PyObject *ViewMap_repr(BPy_ViewMap *self)
{
return PyUnicode_FromFormat("ViewMap - address: %p", self->vm);
}
PyDoc_STRVAR(
/* Wrap. */
ViewMap_get_closest_viewedge_doc,
".. method:: get_closest_viewedge(x, y)\n"
"\n"
" Gets the ViewEdge nearest to the 2D point specified as arguments.\n"
"\n"
" :param x: X coordinate of a 2D point.\n"
" :type x: float\n"
" :param y: Y coordinate of a 2D point.\n"
" :type y: float\n"
" :return: The ViewEdge nearest to the specified 2D point.\n"
" :rtype: :class:`ViewEdge`\n");
static PyObject *ViewMap_get_closest_viewedge(BPy_ViewMap *self, PyObject *args, PyObject *kwds)
{
static const char *kwlist[] = {"x", "y", nullptr};
double x, y;
if (!PyArg_ParseTupleAndKeywords(args, kwds, "dd", (char **)kwlist, &x, &y)) {
return nullptr;
}
ViewEdge *ve = const_cast<ViewEdge *>(self->vm->getClosestViewEdge(x, y));
if (ve) {
return BPy_ViewEdge_from_ViewEdge(*ve);
}
Py_RETURN_NONE;
}
PyDoc_STRVAR(
/* Wrap. */
ViewMap_get_closest_fedge_doc,
".. method:: get_closest_fedge(x, y)\n"
"\n"
" Gets the FEdge nearest to the 2D point specified as arguments.\n"
"\n"
" :param x: X coordinate of a 2D point.\n"
" :type x: float\n"
" :param y: Y coordinate of a 2D point.\n"
" :type y: float\n"
" :return: The FEdge nearest to the specified 2D point.\n"
" :rtype: :class:`FEdge`\n");
static PyObject *ViewMap_get_closest_fedge(BPy_ViewMap *self, PyObject *args, PyObject *kwds)
{
static const char *kwlist[] = {"x", "y", nullptr};
double x, y;
if (!PyArg_ParseTupleAndKeywords(args, kwds, "dd", (char **)kwlist, &x, &y)) {
return nullptr;
}
FEdge *fe = const_cast<FEdge *>(self->vm->getClosestFEdge(x, y));
if (fe) {
return Any_BPy_FEdge_from_FEdge(*fe);
}
Py_RETURN_NONE;
}
// static ViewMap *getInstance ();
#ifdef __GNUC__
# ifdef __clang__
# pragma clang diagnostic push
# pragma clang diagnostic ignored "-Wcast-function-type"
# else
# pragma GCC diagnostic push
# pragma GCC diagnostic ignored "-Wcast-function-type"
# endif
#endif
static PyMethodDef BPy_ViewMap_methods[] = {
{"get_closest_viewedge",
(PyCFunction)ViewMap_get_closest_viewedge,
METH_VARARGS | METH_KEYWORDS,
ViewMap_get_closest_viewedge_doc},
{"get_closest_fedge",
(PyCFunction)ViewMap_get_closest_fedge,
METH_VARARGS | METH_KEYWORDS,
ViewMap_get_closest_fedge_doc},
{nullptr, nullptr, 0, nullptr},
};
#ifdef __GNUC__
# ifdef __clang__
# pragma clang diagnostic pop
# else
# pragma GCC diagnostic pop
# endif
#endif
/*----------------------ViewMap get/setters ----------------------------*/
PyDoc_STRVAR(
/* Wrap. */
ViewMap_scene_bbox_doc,
"The 3D bounding box of the scene.\n"
"\n"
":type: :class:`BBox`\n");
static PyObject *ViewMap_scene_bbox_get(BPy_ViewMap *self, void * /*closure*/)
{
return BPy_BBox_from_BBox(self->vm->getScene3dBBox());
}
static int ViewMap_scene_bbox_set(BPy_ViewMap *self, PyObject *value, void * /*closure*/)
{
if (!BPy_BBox_Check(value)) {
PyErr_SetString(PyExc_TypeError, "value must be a BBox");
return -1;
}
self->vm->setScene3dBBox(*(((BPy_BBox *)value)->bb));
return 0;
}
static PyGetSetDef BPy_ViewMap_getseters[] = {
{"scene_bbox",
(getter)ViewMap_scene_bbox_get,
(setter)ViewMap_scene_bbox_set,
ViewMap_scene_bbox_doc,
nullptr},
{nullptr, nullptr, nullptr, nullptr, nullptr} /* Sentinel */
};
/*-----------------------BPy_ViewMap type definition ------------------------------*/
PyTypeObject ViewMap_Type = {
/*ob_base*/ PyVarObject_HEAD_INIT(nullptr, 0)
/*tp_name*/ "ViewMap",
/*tp_basicsize*/ sizeof(BPy_ViewMap),
/*tp_itemsize*/ 0,
/*tp_dealloc*/ (destructor)ViewMap_dealloc,
/*tp_vectorcall_offset*/ 0,
/*tp_getattr*/ nullptr,
/*tp_setattr*/ nullptr,
/*tp_as_async*/ nullptr,
/*tp_repr*/ (reprfunc)ViewMap_repr,
/*tp_as_number*/ nullptr,
/*tp_as_sequence*/ nullptr,
/*tp_as_mapping*/ nullptr,
/*tp_hash*/ nullptr,
/*tp_call*/ nullptr,
/*tp_str*/ nullptr,
/*tp_getattro*/ nullptr,
/*tp_setattro*/ nullptr,
/*tp_as_buffer*/ nullptr,
/*tp_flags*/ Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE,
/*tp_doc*/ ViewMap_doc,
/*tp_traverse*/ nullptr,
/*tp_clear*/ nullptr,
/*tp_richcompare*/ nullptr,
/*tp_weaklistoffset*/ 0,
/*tp_iter*/ nullptr,
/*tp_iternext*/ nullptr,
/*tp_methods*/ BPy_ViewMap_methods,
/*tp_members*/ nullptr,
/*tp_getset*/ BPy_ViewMap_getseters,
/*tp_base*/ nullptr,
/*tp_dict*/ nullptr,
/*tp_descr_get*/ nullptr,
/*tp_descr_set*/ nullptr,
/*tp_dictoffset*/ 0,
/*tp_init*/ (initproc)ViewMap_init,
/*tp_alloc*/ nullptr,
/*tp_new*/ PyType_GenericNew,
};
///////////////////////////////////////////////////////////////////////////////////////////

View File

@@ -0,0 +1,33 @@
/* SPDX-FileCopyrightText: 2023 Blender Authors
*
* SPDX-License-Identifier: GPL-2.0-or-later */
/** \file
* \ingroup freestyle
*/
#pragma once
extern "C" {
#include <Python.h>
}
#include "../view_map/ViewMap.h"
///////////////////////////////////////////////////////////////////////////////////////////
extern PyTypeObject ViewMap_Type;
#define BPy_ViewMap_Check(v) (PyObject_IsInstance((PyObject *)v, (PyObject *)&ViewMap_Type))
/*---------------------------Python BPy_ViewMap structure definition----------*/
struct BPy_ViewMap {
PyObject_HEAD
Freestyle::ViewMap *vm;
};
/*---------------------------Python BPy_ViewMap visible prototypes-----------*/
int ViewMap_Init(PyObject *module);
///////////////////////////////////////////////////////////////////////////////////////////

View File

@@ -0,0 +1,413 @@
/* SPDX-FileCopyrightText: 2004-2023 Blender Authors
*
* SPDX-License-Identifier: GPL-2.0-or-later */
/** \file
* \ingroup freestyle
*/
#include "BPy_ViewShape.h"
#include "BPy_Convert.h"
#include "BPy_SShape.h"
#include "Interface0D/BPy_ViewVertex.h"
#include "Interface1D/BPy_ViewEdge.h"
#include "BLI_sys_types.h"
#include "../generic/py_capi_utils.hh"
using namespace Freestyle;
///////////////////////////////////////////////////////////////////////////////////////////
//-------------------MODULE INITIALIZATION--------------------------------
int ViewShape_Init(PyObject *module)
{
if (module == nullptr) {
return -1;
}
if (PyType_Ready(&ViewShape_Type) < 0) {
return -1;
}
PyModule_AddObjectRef(module, "ViewShape", (PyObject *)&ViewShape_Type);
return 0;
}
/*----------------------ViewShape methods ----------------------------*/
PyDoc_STRVAR(
/* Wrap. */
ViewShape_doc,
"Class gathering the elements of the ViewMap (i.e., :class:`ViewVertex`\n"
"and :class:`ViewEdge`) that are issued from the same input shape.\n"
"\n"
".. method:: __init__(*args)\n"
"\n"
" Accepted call signatures:\n"
"\n"
" - ``__init__()``\n"
" - ``__init__(brother)``\n"
" - ``__init__(sshape)``\n"
"\n"
" Builds a :class:`ViewShape` using the default constructor,\n"
" copy constructor, or from a :class:`SShape`.\n"
"\n"
" :param brother: A ViewShape object.\n"
" :type brother: :class:`ViewShape`\n"
" :param sshape: An SShape object.\n"
" :type sshape: :class:`SShape`\n");
static int ViewShape_init(BPy_ViewShape *self, PyObject *args, PyObject *kwds)
{
static const char *kwlist_1[] = {"brother", nullptr};
static const char *kwlist_2[] = {"sshape", nullptr};
PyObject *obj = nullptr;
if (PyArg_ParseTupleAndKeywords(args, kwds, "|O!", (char **)kwlist_1, &ViewShape_Type, &obj)) {
if (!obj) {
self->vs = new ViewShape();
self->py_ss = nullptr;
}
else {
self->vs = new ViewShape(*(((BPy_ViewShape *)obj)->vs));
self->py_ss = ((BPy_ViewShape *)obj)->py_ss;
}
}
else if ((void)PyErr_Clear(),
PyArg_ParseTupleAndKeywords(args, kwds, "O!", (char **)kwlist_2, &SShape_Type, &obj))
{
BPy_SShape *py_ss = (BPy_SShape *)obj;
self->vs = new ViewShape(py_ss->ss);
self->py_ss = (!py_ss->borrowed) ? py_ss : nullptr;
}
else {
PyErr_SetString(PyExc_TypeError, "invalid argument(s)");
return -1;
}
self->borrowed = false;
Py_XINCREF(self->py_ss);
return 0;
}
static void ViewShape_dealloc(BPy_ViewShape *self)
{
if (self->py_ss) {
self->vs->setSShape((SShape *)nullptr);
Py_DECREF(self->py_ss);
}
if (self->vs && !self->borrowed) {
delete self->vs;
}
Py_TYPE(self)->tp_free((PyObject *)self);
}
static PyObject *ViewShape_repr(BPy_ViewShape *self)
{
return PyUnicode_FromFormat("ViewShape - address: %p", self->vs);
}
PyDoc_STRVAR(
/* Wrap. */
ViewShape_add_edge_doc,
".. method:: add_edge(edge)\n"
"\n"
" Adds a ViewEdge to the list of ViewEdge objects.\n"
"\n"
" :param edge: A ViewEdge object.\n"
" :type edge: :class:`ViewEdge`\n");
static PyObject *ViewShape_add_edge(BPy_ViewShape *self, PyObject *args, PyObject *kwds)
{
static const char *kwlist[] = {"edge", nullptr};
PyObject *py_ve = nullptr;
if (PyArg_ParseTupleAndKeywords(args, kwds, "O!", (char **)kwlist, &ViewEdge_Type, &py_ve)) {
return nullptr;
}
self->vs->AddEdge(((BPy_ViewEdge *)py_ve)->ve);
Py_RETURN_NONE;
}
PyDoc_STRVAR(
/* Wrap. */
ViewShape_add_vertex_doc,
".. method:: add_vertex(vertex)\n"
"\n"
" Adds a ViewVertex to the list of the ViewVertex objects.\n"
"\n"
" :param vertex: A ViewVertex object.\n"
" :type vertex: :class:`ViewVertex`\n");
static PyObject *ViewShape_add_vertex(BPy_ViewShape *self, PyObject *args, PyObject *kwds)
{
static const char *kwlist[] = {"vertex", nullptr};
PyObject *py_vv = nullptr;
if (PyArg_ParseTupleAndKeywords(args, kwds, "O!", (char **)kwlist, &ViewVertex_Type, &py_vv)) {
return nullptr;
}
self->vs->AddVertex(((BPy_ViewVertex *)py_vv)->vv);
Py_RETURN_NONE;
}
// virtual ViewShape *duplicate()
#ifdef __GNUC__
# ifdef __clang__
# pragma clang diagnostic push
# pragma clang diagnostic ignored "-Wcast-function-type"
# else
# pragma GCC diagnostic push
# pragma GCC diagnostic ignored "-Wcast-function-type"
# endif
#endif
static PyMethodDef BPy_ViewShape_methods[] = {
{"add_edge",
(PyCFunction)ViewShape_add_edge,
METH_VARARGS | METH_KEYWORDS,
ViewShape_add_edge_doc},
{"add_vertex",
(PyCFunction)ViewShape_add_vertex,
METH_VARARGS | METH_KEYWORDS,
ViewShape_add_vertex_doc},
{nullptr, nullptr, 0, nullptr},
};
#ifdef __GNUC__
# ifdef __clang__
# pragma clang diagnostic pop
# else
# pragma GCC diagnostic pop
# endif
#endif
/*----------------------ViewShape get/setters ----------------------------*/
PyDoc_STRVAR(
/* Wrap. */
ViewShape_sshape_doc,
"The SShape on top of which this ViewShape is built.\n"
"\n"
":type: :class:`SShape`\n");
static PyObject *ViewShape_sshape_get(BPy_ViewShape *self, void * /*closure*/)
{
SShape *ss = self->vs->sshape();
if (!ss) {
Py_RETURN_NONE;
}
return BPy_SShape_from_SShape(*ss);
}
static int ViewShape_sshape_set(BPy_ViewShape *self, PyObject *value, void * /*closure*/)
{
if (!BPy_SShape_Check(value)) {
PyErr_SetString(PyExc_TypeError, "value must be an SShape");
return -1;
}
BPy_SShape *py_ss = (BPy_SShape *)value;
self->vs->setSShape(py_ss->ss);
if (self->py_ss) {
Py_DECREF(self->py_ss);
}
if (!py_ss->borrowed) {
self->py_ss = py_ss;
Py_INCREF(self->py_ss);
}
return 0;
}
PyDoc_STRVAR(
/* Wrap. */
ViewShape_vertices_doc,
"The list of ViewVertex objects contained in this ViewShape.\n"
"\n"
":type: list[:class:`ViewVertex`]\n");
static PyObject *ViewShape_vertices_get(BPy_ViewShape *self, void * /*closure*/)
{
vector<ViewVertex *> vertices = self->vs->vertices();
vector<ViewVertex *>::iterator it;
PyObject *py_vertices = PyList_New(vertices.size());
uint i = 0;
for (it = vertices.begin(); it != vertices.end(); it++) {
PyList_SET_ITEM(py_vertices, i++, Any_BPy_ViewVertex_from_ViewVertex(*(*it)));
}
return py_vertices;
}
static int ViewShape_vertices_set(BPy_ViewShape *self, PyObject *value, void * /*closure*/)
{
PyObject *item;
vector<ViewVertex *> v;
if (!PyList_Check(value)) {
PyErr_SetString(PyExc_TypeError, "value must be a list of ViewVertex objects");
return -1;
}
v.reserve(PyList_GET_SIZE(value));
for (uint i = 0; i < PyList_GET_SIZE(value); i++) {
item = PyList_GET_ITEM(value, i);
if (BPy_ViewVertex_Check(item)) {
v.push_back(((BPy_ViewVertex *)item)->vv);
}
else {
PyErr_SetString(PyExc_TypeError, "value must be a list of ViewVertex objects");
return -1;
}
}
self->vs->setVertices(v);
return 0;
}
PyDoc_STRVAR(
/* Wrap. */
ViewShape_edges_doc,
"The list of ViewEdge objects contained in this ViewShape.\n"
"\n"
":type: list[:class:`ViewEdge`]\n");
static PyObject *ViewShape_edges_get(BPy_ViewShape *self, void * /*closure*/)
{
vector<ViewEdge *> edges = self->vs->edges();
vector<ViewEdge *>::iterator it;
PyObject *py_edges = PyList_New(edges.size());
uint i = 0;
for (it = edges.begin(); it != edges.end(); it++) {
PyList_SET_ITEM(py_edges, i++, BPy_ViewEdge_from_ViewEdge(*(*it)));
}
return py_edges;
}
static int ViewShape_edges_set(BPy_ViewShape *self, PyObject *value, void * /*closure*/)
{
PyObject *item;
vector<ViewEdge *> v;
if (!PyList_Check(value)) {
PyErr_SetString(PyExc_TypeError, "value must be a list of ViewEdge objects");
return -1;
}
v.reserve(PyList_GET_SIZE(value));
for (int i = 0; i < PyList_GET_SIZE(value); i++) {
item = PyList_GET_ITEM(value, i);
if (BPy_ViewEdge_Check(item)) {
v.push_back(((BPy_ViewEdge *)item)->ve);
}
else {
PyErr_SetString(PyExc_TypeError, "argument must be list of ViewEdge objects");
return -1;
}
}
self->vs->setEdges(v);
return 0;
}
PyDoc_STRVAR(
/* Wrap. */
ViewShape_name_doc,
"The name of the ViewShape.\n"
"\n"
":type: str\n");
static PyObject *ViewShape_name_get(BPy_ViewShape *self, void * /*closure*/)
{
return blender::PyC_UnicodeFromStdStr(self->vs->getName());
}
PyDoc_STRVAR(
/* Wrap. */
ViewShape_library_path_doc,
"The library path of the ViewShape, or None if the ViewShape is not part of\n"
"a library.\n"
"\n"
":type: str | None\n");
static PyObject *ViewShape_library_path_get(BPy_ViewShape *self, void * /*closure*/)
{
return blender::PyC_UnicodeFromStdStr(self->vs->getLibraryPath());
}
PyDoc_STRVAR(
/* Wrap. */
ViewShape_id_doc,
"The Id of this ViewShape.\n"
"\n"
":type: :class:`Id`\n");
static PyObject *ViewShape_id_get(BPy_ViewShape *self, void * /*closure*/)
{
Id id(self->vs->getId());
return BPy_Id_from_Id(id); // return a copy
}
static PyGetSetDef BPy_ViewShape_getseters[] = {
{"sshape",
(getter)ViewShape_sshape_get,
(setter)ViewShape_sshape_set,
ViewShape_sshape_doc,
nullptr},
{"vertices",
(getter)ViewShape_vertices_get,
(setter)ViewShape_vertices_set,
ViewShape_vertices_doc,
nullptr},
{"edges",
(getter)ViewShape_edges_get,
(setter)ViewShape_edges_set,
ViewShape_edges_doc,
nullptr},
{"name", (getter)ViewShape_name_get, (setter) nullptr, ViewShape_name_doc, nullptr},
{"library_path",
(getter)ViewShape_library_path_get,
(setter) nullptr,
ViewShape_library_path_doc,
nullptr},
{"id", (getter)ViewShape_id_get, (setter) nullptr, ViewShape_id_doc, nullptr},
{nullptr, nullptr, nullptr, nullptr, nullptr} /* Sentinel */
};
/*-----------------------BPy_ViewShape type definition ------------------------------*/
PyTypeObject ViewShape_Type = {
/*ob_base*/ PyVarObject_HEAD_INIT(nullptr, 0)
/*tp_name*/ "ViewShape",
/*tp_basicsize*/ sizeof(BPy_ViewShape),
/*tp_itemsize*/ 0,
/*tp_dealloc*/ (destructor)ViewShape_dealloc,
/*tp_vectorcall_offset*/ 0,
/*tp_getattr*/ nullptr,
/*tp_setattr*/ nullptr,
/*tp_as_async*/ nullptr,
/*tp_repr*/ (reprfunc)ViewShape_repr,
/*tp_as_number*/ nullptr,
/*tp_as_sequence*/ nullptr,
/*tp_as_mapping*/ nullptr,
/*tp_hash*/ nullptr,
/*tp_call*/ nullptr,
/*tp_str*/ nullptr,
/*tp_getattro*/ nullptr,
/*tp_setattro*/ nullptr,
/*tp_as_buffer*/ nullptr,
/*tp_flags*/ Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE,
/*tp_doc*/ ViewShape_doc,
/*tp_traverse*/ nullptr,
/*tp_clear*/ nullptr,
/*tp_richcompare*/ nullptr,
/*tp_weaklistoffset*/ 0,
/*tp_iter*/ nullptr,
/*tp_iternext*/ nullptr,
/*tp_methods*/ BPy_ViewShape_methods,
/*tp_members*/ nullptr,
/*tp_getset*/ BPy_ViewShape_getseters,
/*tp_base*/ nullptr,
/*tp_dict*/ nullptr,
/*tp_descr_get*/ nullptr,
/*tp_descr_set*/ nullptr,
/*tp_dictoffset*/ 0,
/*tp_init*/ (initproc)ViewShape_init,
/*tp_alloc*/ nullptr,
/*tp_new*/ PyType_GenericNew,
};
///////////////////////////////////////////////////////////////////////////////////////////

View File

@@ -0,0 +1,37 @@
/* SPDX-FileCopyrightText: 2023 Blender Authors
*
* SPDX-License-Identifier: GPL-2.0-or-later */
/** \file
* \ingroup freestyle
*/
#pragma once
extern "C" {
#include <Python.h>
}
#include "../view_map/ViewMap.h"
#include "BPy_SShape.h"
///////////////////////////////////////////////////////////////////////////////////////////
extern PyTypeObject ViewShape_Type;
#define BPy_ViewShape_Check(v) (PyObject_IsInstance((PyObject *)v, (PyObject *)&ViewShape_Type))
/*---------------------------Python BPy_ViewShape structure definition----------*/
struct BPy_ViewShape {
PyObject_HEAD
Freestyle::ViewShape *vs;
bool borrowed; /* true if *vs a borrowed object */
BPy_SShape *py_ss;
};
/*---------------------------Python BPy_ViewShape visible prototypes-----------*/
int ViewShape_Init(PyObject *module);
///////////////////////////////////////////////////////////////////////////////////////////

View File

@@ -0,0 +1,86 @@
/* SPDX-FileCopyrightText: 2004-2022 Blender Authors
*
* SPDX-License-Identifier: GPL-2.0-or-later */
/** \file
* \ingroup freestyle
*/
#include "BPy_FalseBP1D.h"
using namespace Freestyle;
///////////////////////////////////////////////////////////////////////////////////////////
//------------------------INSTANCE METHODS ----------------------------------
PyDoc_STRVAR(
/* Wrap. */
FalseBP1D___doc__,
"Class hierarchy: :class:`freestyle.types.BinaryPredicate1D` > :class:`FalseBP1D`\n"
"\n"
".. method:: __call__(inter1, inter2)\n"
"\n"
" Always returns false.\n"
"\n"
" :param inter1: The first Interface1D object.\n"
" :type inter1: :class:`freestyle.types.Interface1D`\n"
" :param inter2: The second Interface1D object.\n"
" :type inter2: :class:`freestyle.types.Interface1D`\n"
" :return: False.\n"
" :rtype: bool\n");
static int FalseBP1D___init__(BPy_FalseBP1D *self, PyObject *args, PyObject *kwds)
{
static const char *kwlist[] = {nullptr};
if (!PyArg_ParseTupleAndKeywords(args, kwds, "", (char **)kwlist)) {
return -1;
}
self->py_bp1D.bp1D = new Predicates1D::FalseBP1D();
return 0;
}
/*-----------------------BPy_FalseBP1D type definition ------------------------------*/
PyTypeObject FalseBP1D_Type = {
/*ob_base*/ PyVarObject_HEAD_INIT(nullptr, 0)
/*tp_name*/ "FalseBP1D",
/*tp_basicsize*/ sizeof(BPy_FalseBP1D),
/*tp_itemsize*/ 0,
/*tp_dealloc*/ nullptr,
/*tp_vectorcall_offset*/ 0,
/*tp_getattr*/ nullptr,
/*tp_setattr*/ nullptr,
/*tp_as_async*/ nullptr,
/*tp_repr*/ nullptr,
/*tp_as_number*/ nullptr,
/*tp_as_sequence*/ nullptr,
/*tp_as_mapping*/ nullptr,
/*tp_hash*/ nullptr,
/*tp_call*/ nullptr,
/*tp_str*/ nullptr,
/*tp_getattro*/ nullptr,
/*tp_setattro*/ nullptr,
/*tp_as_buffer*/ nullptr,
/*tp_flags*/ Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE,
/*tp_doc*/ FalseBP1D___doc__,
/*tp_traverse*/ nullptr,
/*tp_clear*/ nullptr,
/*tp_richcompare*/ nullptr,
/*tp_weaklistoffset*/ 0,
/*tp_iter*/ nullptr,
/*tp_iternext*/ nullptr,
/*tp_methods*/ nullptr,
/*tp_members*/ nullptr,
/*tp_getset*/ nullptr,
/*tp_base*/ &BinaryPredicate1D_Type,
/*tp_dict*/ nullptr,
/*tp_descr_get*/ nullptr,
/*tp_descr_set*/ nullptr,
/*tp_dictoffset*/ 0,
/*tp_init*/ (initproc)FalseBP1D___init__,
/*tp_alloc*/ nullptr,
/*tp_new*/ nullptr,
};
///////////////////////////////////////////////////////////////////////////////////////////

View File

@@ -0,0 +1,24 @@
/* SPDX-FileCopyrightText: 2023 Blender Authors
*
* SPDX-License-Identifier: GPL-2.0-or-later */
/** \file
* \ingroup freestyle
*/
#pragma once
#include "../BPy_BinaryPredicate1D.h"
///////////////////////////////////////////////////////////////////////////////////////////
extern PyTypeObject FalseBP1D_Type;
#define BPy_FalseBP1D_Check(v) (PyObject_IsInstance((PyObject *)v, (PyObject *)&FalseBP1D_Type))
/*---------------------------Python BPy_FalseBP1D structure definition----------*/
struct BPy_FalseBP1D {
BPy_BinaryPredicate1D py_bp1D;
};
///////////////////////////////////////////////////////////////////////////////////////////

View File

@@ -0,0 +1,87 @@
/* SPDX-FileCopyrightText: 2004-2022 Blender Authors
*
* SPDX-License-Identifier: GPL-2.0-or-later */
/** \file
* \ingroup freestyle
*/
#include "BPy_Length2DBP1D.h"
using namespace Freestyle;
///////////////////////////////////////////////////////////////////////////////////////////
//------------------------INSTANCE METHODS ----------------------------------
PyDoc_STRVAR(
/* Wrap. */
Length2DBP1D___doc__,
"Class hierarchy: :class:`freestyle.types.BinaryPredicate1D` > :class:`Length2DBP1D`\n"
"\n"
".. method:: __call__(inter1, inter2)\n"
"\n"
" Returns true if the 2D length of inter1 is less than the 2D length\n"
" of inter2.\n"
"\n"
" :param inter1: The first Interface1D object.\n"
" :type inter1: :class:`freestyle.types.Interface1D`\n"
" :param inter2: The second Interface1D object.\n"
" :type inter2: :class:`freestyle.types.Interface1D`\n"
" :return: True or false.\n"
" :rtype: bool\n");
static int Length2DBP1D___init__(BPy_Length2DBP1D *self, PyObject *args, PyObject *kwds)
{
static const char *kwlist[] = {nullptr};
if (!PyArg_ParseTupleAndKeywords(args, kwds, "", (char **)kwlist)) {
return -1;
}
self->py_bp1D.bp1D = new Predicates1D::Length2DBP1D();
return 0;
}
/*-----------------------BPy_Length2DBP1D type definition ------------------------------*/
PyTypeObject Length2DBP1D_Type = {
/*ob_base*/ PyVarObject_HEAD_INIT(nullptr, 0)
/*tp_name*/ "Length2DBP1D",
/*tp_basicsize*/ sizeof(BPy_Length2DBP1D),
/*tp_itemsize*/ 0,
/*tp_dealloc*/ nullptr,
/*tp_vectorcall_offset*/ 0,
/*tp_getattr*/ nullptr,
/*tp_setattr*/ nullptr,
/*tp_as_async*/ nullptr,
/*tp_repr*/ nullptr,
/*tp_as_number*/ nullptr,
/*tp_as_sequence*/ nullptr,
/*tp_as_mapping*/ nullptr,
/*tp_hash*/ nullptr,
/*tp_call*/ nullptr,
/*tp_str*/ nullptr,
/*tp_getattro*/ nullptr,
/*tp_setattro*/ nullptr,
/*tp_as_buffer*/ nullptr,
/*tp_flags*/ Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE,
/*tp_doc*/ Length2DBP1D___doc__,
/*tp_traverse*/ nullptr,
/*tp_clear*/ nullptr,
/*tp_richcompare*/ nullptr,
/*tp_weaklistoffset*/ 0,
/*tp_iter*/ nullptr,
/*tp_iternext*/ nullptr,
/*tp_methods*/ nullptr,
/*tp_members*/ nullptr,
/*tp_getset*/ nullptr,
/*tp_base*/ &BinaryPredicate1D_Type,
/*tp_dict*/ nullptr,
/*tp_descr_get*/ nullptr,
/*tp_descr_set*/ nullptr,
/*tp_dictoffset*/ 0,
/*tp_init*/ (initproc)Length2DBP1D___init__,
/*tp_alloc*/ nullptr,
/*tp_new*/ nullptr,
};
///////////////////////////////////////////////////////////////////////////////////////////

View File

@@ -0,0 +1,25 @@
/* SPDX-FileCopyrightText: 2023 Blender Authors
*
* SPDX-License-Identifier: GPL-2.0-or-later */
/** \file
* \ingroup freestyle
*/
#pragma once
#include "../BPy_BinaryPredicate1D.h"
///////////////////////////////////////////////////////////////////////////////////////////
extern PyTypeObject Length2DBP1D_Type;
#define BPy_Length2DBP1D_Check(v) \
(PyObject_IsInstance((PyObject *)v, (PyObject *)&Length2DBP1D_Type))
/*---------------------------Python BPy_Length2DBP1D structure definition----------*/
struct BPy_Length2DBP1D {
BPy_BinaryPredicate1D py_bp1D;
};
///////////////////////////////////////////////////////////////////////////////////////////

View File

@@ -0,0 +1,86 @@
/* SPDX-FileCopyrightText: 2004-2022 Blender Authors
*
* SPDX-License-Identifier: GPL-2.0-or-later */
/** \file
* \ingroup freestyle
*/
#include "BPy_SameShapeIdBP1D.h"
using namespace Freestyle;
///////////////////////////////////////////////////////////////////////////////////////////
//------------------------INSTANCE METHODS ----------------------------------
PyDoc_STRVAR(
/* Wrap. */
SameShapeIdBP1D___doc__,
"Class hierarchy: :class:`freestyle.types.BinaryPredicate1D` > :class:`SameShapeIdBP1D`\n"
"\n"
".. method:: __call__(inter1, inter2)\n"
"\n"
" Returns true if inter1 and inter2 belong to the same shape.\n"
"\n"
" :param inter1: The first Interface1D object.\n"
" :type inter1: :class:`freestyle.types.Interface1D`\n"
" :param inter2: The second Interface1D object.\n"
" :type inter2: :class:`freestyle.types.Interface1D`\n"
" :return: True or false.\n"
" :rtype: bool\n");
static int SameShapeIdBP1D___init__(BPy_SameShapeIdBP1D *self, PyObject *args, PyObject *kwds)
{
static const char *kwlist[] = {nullptr};
if (!PyArg_ParseTupleAndKeywords(args, kwds, "", (char **)kwlist)) {
return -1;
}
self->py_bp1D.bp1D = new Predicates1D::SameShapeIdBP1D();
return 0;
}
/*-----------------------BPy_SameShapeIdBP1D type definition ------------------------------*/
PyTypeObject SameShapeIdBP1D_Type = {
/*ob_base*/ PyVarObject_HEAD_INIT(nullptr, 0)
/*tp_name*/ "SameShapeIdBP1D",
/*tp_basicsize*/ sizeof(BPy_SameShapeIdBP1D),
/*tp_itemsize*/ 0,
/*tp_dealloc*/ nullptr,
/*tp_vectorcall_offset*/ 0,
/*tp_getattr*/ nullptr,
/*tp_setattr*/ nullptr,
/*tp_as_async*/ nullptr,
/*tp_repr*/ nullptr,
/*tp_as_number*/ nullptr,
/*tp_as_sequence*/ nullptr,
/*tp_as_mapping*/ nullptr,
/*tp_hash*/ nullptr,
/*tp_call*/ nullptr,
/*tp_str*/ nullptr,
/*tp_getattro*/ nullptr,
/*tp_setattro*/ nullptr,
/*tp_as_buffer*/ nullptr,
/*tp_flags*/ Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE,
/*tp_doc*/ SameShapeIdBP1D___doc__,
/*tp_traverse*/ nullptr,
/*tp_clear*/ nullptr,
/*tp_richcompare*/ nullptr,
/*tp_weaklistoffset*/ 0,
/*tp_iter*/ nullptr,
/*tp_iternext*/ nullptr,
/*tp_methods*/ nullptr,
/*tp_members*/ nullptr,
/*tp_getset*/ nullptr,
/*tp_base*/ &BinaryPredicate1D_Type,
/*tp_dict*/ nullptr,
/*tp_descr_get*/ nullptr,
/*tp_descr_set*/ nullptr,
/*tp_dictoffset*/ 0,
/*tp_init*/ (initproc)SameShapeIdBP1D___init__,
/*tp_alloc*/ nullptr,
/*tp_new*/ nullptr,
};
///////////////////////////////////////////////////////////////////////////////////////////

View File

@@ -0,0 +1,25 @@
/* SPDX-FileCopyrightText: 2023 Blender Authors
*
* SPDX-License-Identifier: GPL-2.0-or-later */
/** \file
* \ingroup freestyle
*/
#pragma once
#include "../BPy_BinaryPredicate1D.h"
///////////////////////////////////////////////////////////////////////////////////////////
extern PyTypeObject SameShapeIdBP1D_Type;
#define BPy_SameShapeIdBP1D_Check(v) \
(PyObject_IsInstance((PyObject *)v, (PyObject *)&SameShapeIdBP1D_Type))
/*---------------------------Python BPy_SameShapeIdBP1D structure definition----------*/
struct BPy_SameShapeIdBP1D {
BPy_BinaryPredicate1D py_bp1D;
};
///////////////////////////////////////////////////////////////////////////////////////////

View File

@@ -0,0 +1,86 @@
/* SPDX-FileCopyrightText: 2004-2022 Blender Authors
*
* SPDX-License-Identifier: GPL-2.0-or-later */
/** \file
* \ingroup freestyle
*/
#include "BPy_TrueBP1D.h"
using namespace Freestyle;
///////////////////////////////////////////////////////////////////////////////////////////
//------------------------INSTANCE METHODS ----------------------------------
PyDoc_STRVAR(
/* Wrap. */
TrueBP1D___doc__,
"Class hierarchy: :class:`freestyle.types.BinaryPredicate1D` > :class:`TrueBP1D`\n"
"\n"
".. method:: __call__(inter1, inter2)\n"
"\n"
" Always returns true.\n"
"\n"
" :param inter1: The first Interface1D object.\n"
" :type inter1: :class:`freestyle.types.Interface1D`\n"
" :param inter2: The second Interface1D object.\n"
" :type inter2: :class:`freestyle.types.Interface1D`\n"
" :return: True.\n"
" :rtype: bool\n");
static int TrueBP1D___init__(BPy_TrueBP1D *self, PyObject *args, PyObject *kwds)
{
static const char *kwlist[] = {nullptr};
if (!PyArg_ParseTupleAndKeywords(args, kwds, "", (char **)kwlist)) {
return -1;
}
self->py_bp1D.bp1D = new Predicates1D::TrueBP1D();
return 0;
}
/*-----------------------BPy_TrueBP1D type definition ------------------------------*/
PyTypeObject TrueBP1D_Type = {
/*ob_base*/ PyVarObject_HEAD_INIT(nullptr, 0)
/*tp_name*/ "TrueBP1D",
/*tp_basicsize*/ sizeof(BPy_TrueBP1D),
/*tp_itemsize*/ 0,
/*tp_dealloc*/ nullptr,
/*tp_vectorcall_offset*/ 0,
/*tp_getattr*/ nullptr,
/*tp_setattr*/ nullptr,
/*tp_as_async*/ nullptr,
/*tp_repr*/ nullptr,
/*tp_as_number*/ nullptr,
/*tp_as_sequence*/ nullptr,
/*tp_as_mapping*/ nullptr,
/*tp_hash*/ nullptr,
/*tp_call*/ nullptr,
/*tp_str*/ nullptr,
/*tp_getattro*/ nullptr,
/*tp_setattro*/ nullptr,
/*tp_as_buffer*/ nullptr,
/*tp_flags*/ Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE,
/*tp_doc*/ TrueBP1D___doc__,
/*tp_traverse*/ nullptr,
/*tp_clear*/ nullptr,
/*tp_richcompare*/ nullptr,
/*tp_weaklistoffset*/ 0,
/*tp_iter*/ nullptr,
/*tp_iternext*/ nullptr,
/*tp_methods*/ nullptr,
/*tp_members*/ nullptr,
/*tp_getset*/ nullptr,
/*tp_base*/ &BinaryPredicate1D_Type,
/*tp_dict*/ nullptr,
/*tp_descr_get*/ nullptr,
/*tp_descr_set*/ nullptr,
/*tp_dictoffset*/ 0,
/*tp_init*/ (initproc)TrueBP1D___init__,
/*tp_alloc*/ nullptr,
/*tp_new*/ nullptr,
};
///////////////////////////////////////////////////////////////////////////////////////////

View File

@@ -0,0 +1,24 @@
/* SPDX-FileCopyrightText: 2023 Blender Authors
*
* SPDX-License-Identifier: GPL-2.0-or-later */
/** \file
* \ingroup freestyle
*/
#pragma once
#include "../BPy_BinaryPredicate1D.h"
///////////////////////////////////////////////////////////////////////////////////////////
extern PyTypeObject TrueBP1D_Type;
#define BPy_TrueBP1D_Check(v) (PyObject_IsInstance((PyObject *)v, (PyObject *)&TrueBP1D_Type))
/*---------------------------Python BPy_TrueBP1D structure definition----------*/
struct BPy_TrueBP1D {
BPy_BinaryPredicate1D py_bp1D;
};
///////////////////////////////////////////////////////////////////////////////////////////

View File

@@ -0,0 +1,117 @@
/* SPDX-FileCopyrightText: 2004-2023 Blender Authors
*
* SPDX-License-Identifier: GPL-2.0-or-later */
/** \file
* \ingroup freestyle
*/
#include "BPy_ViewMapGradientNormBP1D.h"
#include "../BPy_Convert.h"
#include "../BPy_IntegrationType.h"
using namespace Freestyle;
///////////////////////////////////////////////////////////////////////////////////////////
//------------------------INSTANCE METHODS ----------------------------------
// ViewMapGradientNormBP1D(int level, IntegrationType iType=MEAN, float sampling=2.0)
PyDoc_STRVAR(
/* Wrap. */
ViewMapGradientNormBP1D___doc__,
"Class hierarchy: :class:`freestyle.types.BinaryPredicate1D` > "
":class:`ViewMapGradientNormBP1D`\n"
"\n"
".. method:: __init__(level, integration_type=IntegrationType.MEAN, sampling=2.0)\n"
"\n"
" Builds a ViewMapGradientNormBP1D object.\n"
"\n"
" :param level: The level of the pyramid from which the pixel must be\n"
" read.\n"
" :type level: int\n"
" :param integration_type: The integration method used to compute a single value\n"
" from a set of values.\n"
" :type integration_type: :class:`freestyle.types.IntegrationType`\n"
" :param sampling: The resolution used to sample the chain:\n"
" GetViewMapGradientNormF0D is evaluated at each sample point and\n"
" the result is obtained by combining the resulting values into a\n"
" single one, following the method specified by integration_type.\n"
" :type sampling: float\n"
"\n"
".. method:: __call__(inter1, inter2)\n"
"\n"
" Returns true if the evaluation of the Gradient norm Function is\n"
" higher for inter1 than for inter2.\n"
"\n"
" :param inter1: The first Interface1D object.\n"
" :type inter1: :class:`freestyle.types.Interface1D`\n"
" :param inter2: The second Interface1D object.\n"
" :type inter2: :class:`freestyle.types.Interface1D`\n"
" :return: True or false.\n"
" :rtype: bool\n");
static int ViewMapGradientNormBP1D___init__(BPy_ViewMapGradientNormBP1D *self,
PyObject *args,
PyObject *kwds)
{
static const char *kwlist[] = {"level", "integration_type", "sampling", nullptr};
PyObject *obj = nullptr;
int i;
float f = 2.0;
if (!PyArg_ParseTupleAndKeywords(
args, kwds, "i|O!f", (char **)kwlist, &i, &IntegrationType_Type, &obj, &f))
{
return -1;
}
IntegrationType t = (obj) ? IntegrationType_from_BPy_IntegrationType(obj) : MEAN;
self->py_bp1D.bp1D = new Predicates1D::ViewMapGradientNormBP1D(i, t, f);
return 0;
}
/*-----------------------BPy_ViewMapGradientNormBP1D type definition ----------------------------*/
PyTypeObject ViewMapGradientNormBP1D_Type = {
/*ob_base*/ PyVarObject_HEAD_INIT(nullptr, 0)
/*tp_name*/ "ViewMapGradientNormBP1D",
/*tp_basicsize*/ sizeof(BPy_ViewMapGradientNormBP1D),
/*tp_itemsize*/ 0,
/*tp_dealloc*/ nullptr,
/*tp_vectorcall_offset*/ 0,
/*tp_getattr*/ nullptr,
/*tp_setattr*/ nullptr,
/*tp_as_async*/ nullptr,
/*tp_repr*/ nullptr,
/*tp_as_number*/ nullptr,
/*tp_as_sequence*/ nullptr,
/*tp_as_mapping*/ nullptr,
/*tp_hash*/ nullptr,
/*tp_call*/ nullptr,
/*tp_str*/ nullptr,
/*tp_getattro*/ nullptr,
/*tp_setattro*/ nullptr,
/*tp_as_buffer*/ nullptr,
/*tp_flags*/ Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE,
/*tp_doc*/ ViewMapGradientNormBP1D___doc__,
/*tp_traverse*/ nullptr,
/*tp_clear*/ nullptr,
/*tp_richcompare*/ nullptr,
/*tp_weaklistoffset*/ 0,
/*tp_iter*/ nullptr,
/*tp_iternext*/ nullptr,
/*tp_methods*/ nullptr,
/*tp_members*/ nullptr,
/*tp_getset*/ nullptr,
/*tp_base*/ &BinaryPredicate1D_Type,
/*tp_dict*/ nullptr,
/*tp_descr_get*/ nullptr,
/*tp_descr_set*/ nullptr,
/*tp_dictoffset*/ 0,
/*tp_init*/ (initproc)ViewMapGradientNormBP1D___init__,
/*tp_alloc*/ nullptr,
/*tp_new*/ nullptr,
};
///////////////////////////////////////////////////////////////////////////////////////////

View File

@@ -0,0 +1,25 @@
/* SPDX-FileCopyrightText: 2023 Blender Authors
*
* SPDX-License-Identifier: GPL-2.0-or-later */
/** \file
* \ingroup freestyle
*/
#pragma once
#include "../BPy_BinaryPredicate1D.h"
///////////////////////////////////////////////////////////////////////////////////////////
extern PyTypeObject ViewMapGradientNormBP1D_Type;
#define BPy_ViewMapGradientNormBP1D_Check(v) \
(PyObject_IsInstance((PyObject *)v, (PyObject *)&ViewMapGradientNormBP1D_Type))
/*---------------------------Python BPy_ViewMapGradientNormBP1D structure definition----------*/
struct BPy_ViewMapGradientNormBP1D {
BPy_BinaryPredicate1D py_bp1D;
};
///////////////////////////////////////////////////////////////////////////////////////////

View File

@@ -0,0 +1,346 @@
/* SPDX-FileCopyrightText: 2008-2022 Blender Authors
*
* SPDX-License-Identifier: GPL-2.0-or-later */
/** \file
* \ingroup freestyle
*/
#include "Director.h"
#include "BPy_Convert.h"
#include "BPy_BinaryPredicate0D.h"
#include "BPy_BinaryPredicate1D.h"
#include "BPy_FrsMaterial.h"
#include "BPy_Id.h"
#include "BPy_StrokeShader.h"
#include "BPy_UnaryFunction0D.h"
#include "BPy_UnaryFunction1D.h"
#include "BPy_UnaryPredicate0D.h"
#include "BPy_UnaryPredicate1D.h"
#include "BPy_ViewShape.h"
#include "Interface1D/BPy_Stroke.h"
#include "Interface1D/BPy_ViewEdge.h"
#include "Iterator/BPy_ChainingIterator.h"
#include "Iterator/BPy_Interface0DIterator.h"
#include "UnaryFunction0D/BPy_UnaryFunction0DDouble.h"
#include "UnaryFunction0D/BPy_UnaryFunction0DEdgeNature.h"
#include "UnaryFunction0D/BPy_UnaryFunction0DFloat.h"
#include "UnaryFunction0D/BPy_UnaryFunction0DId.h"
#include "UnaryFunction0D/BPy_UnaryFunction0DMaterial.h"
#include "UnaryFunction0D/BPy_UnaryFunction0DUnsigned.h"
#include "UnaryFunction0D/BPy_UnaryFunction0DVec2f.h"
#include "UnaryFunction0D/BPy_UnaryFunction0DVec3f.h"
#include "UnaryFunction0D/BPy_UnaryFunction0DVectorViewShape.h"
#include "UnaryFunction0D/BPy_UnaryFunction0DViewShape.h"
#include "UnaryFunction1D/BPy_UnaryFunction1DDouble.h"
#include "UnaryFunction1D/BPy_UnaryFunction1DEdgeNature.h"
#include "UnaryFunction1D/BPy_UnaryFunction1DFloat.h"
#include "UnaryFunction1D/BPy_UnaryFunction1DUnsigned.h"
#include "UnaryFunction1D/BPy_UnaryFunction1DVec2f.h"
#include "UnaryFunction1D/BPy_UnaryFunction1DVec3f.h"
#include "UnaryFunction1D/BPy_UnaryFunction1DVectorViewShape.h"
#include "BLI_sys_types.h"
using namespace Freestyle;
// BinaryPredicate0D: __call__
int Director_BPy_BinaryPredicate0D___call__(BinaryPredicate0D *bp0D,
Interface0D &i1,
Interface0D &i2)
{
if (!bp0D->py_bp0D) { // internal error
PyErr_SetString(PyExc_RuntimeError, "Reference to Python object (py_bp0D) not initialized");
return -1;
}
PyObject *arg1 = Any_BPy_Interface0D_from_Interface0D(i1);
PyObject *arg2 = Any_BPy_Interface0D_from_Interface0D(i2);
if (!arg1 || !arg2) {
Py_XDECREF(arg1);
Py_XDECREF(arg2);
return -1;
}
PyObject *result = PyObject_CallMethod((PyObject *)bp0D->py_bp0D, "__call__", "OO", arg1, arg2);
Py_DECREF(arg1);
Py_DECREF(arg2);
if (!result) {
return -1;
}
int ret = PyObject_IsTrue(result);
Py_DECREF(result);
if (ret < 0) {
return -1;
}
bp0D->result = ret;
return 0;
}
// BinaryPredicate1D: __call__
int Director_BPy_BinaryPredicate1D___call__(BinaryPredicate1D *bp1D,
Interface1D &i1,
Interface1D &i2)
{
if (!bp1D->py_bp1D) { // internal error
PyErr_SetString(PyExc_RuntimeError, "Reference to Python object (py_bp1D) not initialized");
return -1;
}
PyObject *arg1 = Any_BPy_Interface1D_from_Interface1D(i1);
PyObject *arg2 = Any_BPy_Interface1D_from_Interface1D(i2);
if (!arg1 || !arg2) {
Py_XDECREF(arg1);
Py_XDECREF(arg2);
return -1;
}
PyObject *result = PyObject_CallMethod((PyObject *)bp1D->py_bp1D, "__call__", "OO", arg1, arg2);
Py_DECREF(arg1);
Py_DECREF(arg2);
if (!result) {
return -1;
}
int ret = PyObject_IsTrue(result);
Py_DECREF(result);
if (ret < 0) {
return -1;
}
bp1D->result = ret;
return 0;
}
// UnaryPredicate0D: __call__
int Director_BPy_UnaryPredicate0D___call__(UnaryPredicate0D *up0D, Interface0DIterator &if0D_it)
{
if (!up0D->py_up0D) { // internal error
PyErr_SetString(PyExc_RuntimeError, "Reference to Python object (py_up0D) not initialized");
return -1;
}
PyObject *arg = BPy_Interface0DIterator_from_Interface0DIterator(if0D_it, false);
if (!arg) {
return -1;
}
PyObject *result = PyObject_CallMethod((PyObject *)up0D->py_up0D, "__call__", "O", arg);
Py_DECREF(arg);
if (!result) {
return -1;
}
int ret = PyObject_IsTrue(result);
Py_DECREF(result);
if (ret < 0) {
return -1;
}
up0D->result = ret;
return 0;
}
// UnaryPredicate1D: __call__
int Director_BPy_UnaryPredicate1D___call__(UnaryPredicate1D *up1D, Interface1D &if1D)
{
if (!up1D->py_up1D) { // internal error
PyErr_SetString(PyExc_RuntimeError, "Reference to Python object (py_up1D) not initialized");
return -1;
}
PyObject *arg = Any_BPy_Interface1D_from_Interface1D(if1D);
if (!arg) {
return -1;
}
PyObject *result = PyObject_CallMethod((PyObject *)up1D->py_up1D, "__call__", "O", arg);
Py_DECREF(arg);
if (!result) {
return -1;
}
int ret = PyObject_IsTrue(result);
Py_DECREF(result);
if (ret < 0) {
return -1;
}
up1D->result = ret;
return 0;
}
// StrokeShader: shade
int Director_BPy_StrokeShader_shade(StrokeShader *ss, Stroke &s)
{
if (!ss->py_ss) { // internal error
PyErr_SetString(PyExc_RuntimeError, "Reference to Python object (py_ss) not initialized");
return -1;
}
PyObject *arg = BPy_Stroke_from_Stroke(s);
if (!arg) {
return -1;
}
PyObject *result = PyObject_CallMethod((PyObject *)ss->py_ss, "shade", "O", arg);
Py_DECREF(arg);
if (!result) {
return -1;
}
Py_DECREF(result);
return 0;
}
// ChainingIterator: init, traverse
int Director_BPy_ChainingIterator_init(ChainingIterator *c_it)
{
if (!c_it->py_c_it) { // internal error
PyErr_SetString(PyExc_RuntimeError, "Reference to Python object (py_c_it) not initialized");
return -1;
}
PyObject *result = PyObject_CallMethod((PyObject *)c_it->py_c_it, "init", nullptr);
if (!result) {
return -1;
}
Py_DECREF(result);
return 0;
}
int Director_BPy_ChainingIterator_traverse(ChainingIterator *c_it, AdjacencyIterator &a_it)
{
if (!c_it->py_c_it) { // internal error
PyErr_SetString(PyExc_RuntimeError, "Reference to Python object (py_c_it) not initialized");
return -1;
}
PyObject *arg = BPy_AdjacencyIterator_from_AdjacencyIterator(a_it);
if (!arg) {
return -1;
}
PyObject *result = PyObject_CallMethod((PyObject *)c_it->py_c_it, "traverse", "O", arg);
Py_DECREF(arg);
if (!result) {
return -1;
}
if (BPy_ViewEdge_Check(result)) {
c_it->result = ((BPy_ViewEdge *)result)->ve;
}
else if (result == Py_None) {
c_it->result = nullptr;
}
else {
PyErr_SetString(PyExc_RuntimeError, "traverse method returned a wrong value");
Py_DECREF(result);
return -1;
}
Py_DECREF(result);
return 0;
}
// BPy_UnaryFunction{0D,1D}: __call__
int Director_BPy_UnaryFunction0D___call__(void *uf0D, void *py_uf0D, Interface0DIterator &if0D_it)
{
if (!py_uf0D) { // internal error
PyErr_SetString(PyExc_RuntimeError, "Reference to Python object (py_uf0D) not initialized");
return -1;
}
PyObject *obj = (PyObject *)py_uf0D;
PyObject *arg = BPy_Interface0DIterator_from_Interface0DIterator(if0D_it, false);
if (!arg) {
return -1;
}
PyObject *result = PyObject_CallMethod(obj, "__call__", "O", arg);
Py_DECREF(arg);
if (!result) {
return -1;
}
if (BPy_UnaryFunction0DDouble_Check(obj)) {
((UnaryFunction0D<double> *)uf0D)->result = PyFloat_AsDouble(result);
}
else if (BPy_UnaryFunction0DEdgeNature_Check(obj)) {
((UnaryFunction0D<Nature::EdgeNature> *)uf0D)->result = EdgeNature_from_BPy_Nature(result);
}
else if (BPy_UnaryFunction0DFloat_Check(obj)) {
((UnaryFunction0D<float> *)uf0D)->result = PyFloat_AsDouble(result);
}
else if (BPy_UnaryFunction0DId_Check(obj)) {
((UnaryFunction0D<Id> *)uf0D)->result = *(((BPy_Id *)result)->id);
}
else if (BPy_UnaryFunction0DMaterial_Check(obj)) {
((UnaryFunction0D<FrsMaterial> *)uf0D)->result = *(((BPy_FrsMaterial *)result)->m);
}
else if (BPy_UnaryFunction0DUnsigned_Check(obj)) {
((UnaryFunction0D<uint> *)uf0D)->result = PyLong_AsLong(result);
}
else if (BPy_UnaryFunction0DVec2f_Check(obj)) {
Vec2f vec;
if (!Vec2f_ptr_from_Vector(result, vec)) {
return -1;
}
((UnaryFunction0D<Vec2f> *)uf0D)->result = vec;
}
else if (BPy_UnaryFunction0DVec3f_Check(obj)) {
Vec3f vec;
if (!Vec3f_ptr_from_Vector(result, vec)) {
return -1;
}
((UnaryFunction0D<Vec3f> *)uf0D)->result = vec;
}
else if (BPy_UnaryFunction0DVectorViewShape_Check(obj)) {
vector<ViewShape *> vec;
vec.reserve(PyList_Size(result));
for (int i = 0; i < PyList_Size(result); i++) {
ViewShape *b = ((BPy_ViewShape *)PyList_GET_ITEM(result, i))->vs;
vec.push_back(b);
}
((UnaryFunction0D<vector<ViewShape *>> *)uf0D)->result = vec;
}
else if (BPy_UnaryFunction0DViewShape_Check(obj)) {
((UnaryFunction0D<ViewShape *> *)uf0D)->result = ((BPy_ViewShape *)result)->vs;
}
Py_DECREF(result);
return 0;
}
int Director_BPy_UnaryFunction1D___call__(void *uf1D, void *py_uf1D, Interface1D &if1D)
{
if (!py_uf1D) { // internal error
PyErr_SetString(PyExc_RuntimeError, "Reference to Python object (py_uf1D) not initialized");
return -1;
}
PyObject *obj = (PyObject *)py_uf1D;
PyObject *arg = Any_BPy_Interface1D_from_Interface1D(if1D);
if (!arg) {
return -1;
}
PyObject *result = PyObject_CallMethod(obj, "__call__", "O", arg);
Py_DECREF(arg);
if (!result) {
return -1;
}
if (BPy_UnaryFunction1DDouble_Check(obj)) {
((UnaryFunction1D<double> *)uf1D)->result = PyFloat_AsDouble(result);
}
else if (BPy_UnaryFunction1DEdgeNature_Check(obj)) {
((UnaryFunction1D<Nature::EdgeNature> *)uf1D)->result = EdgeNature_from_BPy_Nature(result);
}
else if (BPy_UnaryFunction1DFloat_Check(obj)) {
((UnaryFunction1D<float> *)uf1D)->result = PyFloat_AsDouble(result);
}
else if (BPy_UnaryFunction1DUnsigned_Check(obj)) {
((UnaryFunction1D<uint> *)uf1D)->result = PyLong_AsLong(result);
}
else if (BPy_UnaryFunction1DVec2f_Check(obj)) {
Vec2f vec;
if (!Vec2f_ptr_from_Vector(result, vec)) {
return -1;
}
((UnaryFunction1D<Vec2f> *)uf1D)->result = vec;
}
else if (BPy_UnaryFunction1DVec3f_Check(obj)) {
Vec3f vec;
if (!Vec3f_ptr_from_Vector(result, vec)) {
return -1;
}
((UnaryFunction1D<Vec3f> *)uf1D)->result = vec;
}
else if (BPy_UnaryFunction1DVectorViewShape_Check(obj)) {
vector<ViewShape *> vec;
vec.reserve(PyList_Size(result));
for (int i = 1; i < PyList_Size(result); i++) {
ViewShape *b = ((BPy_ViewShape *)PyList_GET_ITEM(result, i))->vs;
vec.push_back(b);
}
((UnaryFunction1D<vector<ViewShape *>> *)uf1D)->result = vec;
}
Py_DECREF(result);
return 0;
}

View File

@@ -0,0 +1,55 @@
/* SPDX-FileCopyrightText: 2023 Blender Authors
*
* SPDX-License-Identifier: GPL-2.0-or-later */
/** \file
* \ingroup freestyle
*/
#pragma once
namespace Freestyle {
class UnaryPredicate0D;
class UnaryPredicate1D;
class BinaryPredicate0D;
class BinaryPredicate1D;
class ChainingIterator;
class AdjacencyIterator;
class Interface0D;
class Interface1D;
class Interface0DIterator;
class Stroke;
class StrokeShader;
} // namespace Freestyle
// BinaryPredicate0D: __call__
int Director_BPy_BinaryPredicate0D___call__(Freestyle::BinaryPredicate0D *bp0D,
Freestyle::Interface0D &i1,
Freestyle::Interface0D &i2);
// BinaryPredicate1D: __call__
int Director_BPy_BinaryPredicate1D___call__(Freestyle::BinaryPredicate1D *bp1D,
Freestyle::Interface1D &i1,
Freestyle::Interface1D &i2);
// UnaryFunction{0D,1D}: __call__
int Director_BPy_UnaryFunction0D___call__(void *uf0D,
void *py_uf0D,
Freestyle::Interface0DIterator &if0D_it);
int Director_BPy_UnaryFunction1D___call__(void *uf1D, void *py_uf1D, Freestyle::Interface1D &if1D);
// UnaryPredicate0D: __call__
int Director_BPy_UnaryPredicate0D___call__(Freestyle::UnaryPredicate0D *up0D,
Freestyle::Interface0DIterator &if0D_it);
// UnaryPredicate1D: __call__
int Director_BPy_UnaryPredicate1D___call__(Freestyle::UnaryPredicate1D *up1D,
Freestyle::Interface1D &if1D);
// StrokeShader: shade
int Director_BPy_StrokeShader_shade(Freestyle::StrokeShader *ss, Freestyle::Stroke &s);
// ChainingIterator: init, traverse
int Director_BPy_ChainingIterator_init(Freestyle::ChainingIterator *c_it);
int Director_BPy_ChainingIterator_traverse(Freestyle::ChainingIterator *c_it,
Freestyle::AdjacencyIterator &a_it);

View File

@@ -0,0 +1,275 @@
/* SPDX-FileCopyrightText: 2004-2023 Blender Authors
*
* SPDX-License-Identifier: GPL-2.0-or-later */
/** \file
* \ingroup freestyle
*/
#include "BPy_CurvePoint.h"
#include "../BPy_Convert.h"
#include "../Interface0D/BPy_SVertex.h"
using namespace Freestyle;
///////////////////////////////////////////////////////////////////////////////////////////
/*----------------------CurvePoint methods----------------------------*/
PyDoc_STRVAR(
/* Wrap. */
CurvePoint_doc,
"Class hierarchy: :class:`Interface0D` > :class:`CurvePoint`\n"
"\n"
"Class to represent a point of a curve. A CurvePoint can be any point\n"
"of a 1D curve (it doesn't have to be a vertex of the curve). Any\n"
":class:`Interface1D` is built upon ViewEdges, themselves built upon\n"
"FEdges. Therefore, a curve is basically a polyline made of a list of\n"
":class:`SVertex` objects. Thus, a CurvePoint is built by linearly\n"
"interpolating two :class:`SVertex` instances. CurvePoint can be used\n"
"as virtual points while querying 0D information along a curve at a\n"
"given resolution.\n"
"\n"
".. method:: __init__(*args)\n"
"\n"
" Accepted call signatures:\n"
"\n"
" - ``__init__()``\n"
" - ``__init__(brother)``\n"
" - ``__init__(first_vertex, second_vertex, t2d)``\n"
" - ``__init__(first_point, second_point, t2d)``\n"
"\n"
" Builds a CurvePoint using the default constructor, copy constructor,\n"
" or one of the overloaded constructors. The over loaded constructors\n"
" can either take two :class:`SVertex` or two :class:`CurvePoint`\n"
" objects and an interpolation parameter\n"
"\n"
" :param brother: A CurvePoint object.\n"
" :type brother: :class:`CurvePoint`\n"
" :param first_vertex: The first SVertex.\n"
" :type first_vertex: :class:`SVertex`\n"
" :param second_vertex: The second SVertex.\n"
" :type second_vertex: :class:`SVertex`\n"
" :param first_point: The first CurvePoint.\n"
" :type first_point: :class:`CurvePoint`\n"
" :param second_point: The second CurvePoint.\n"
" :type second_point: :class:`CurvePoint`\n"
" :param t2d: A 2D interpolation parameter used to linearly interpolate\n"
" first_vertex and second_vertex or first_point and second_point.\n"
" :type t2d: float\n");
static int CurvePoint_init(BPy_CurvePoint *self, PyObject *args, PyObject *kwds)
{
static const char *kwlist_1[] = {"brother", nullptr};
static const char *kwlist_2[] = {"first_vertex", "second_vertex", "t2d", nullptr};
static const char *kwlist_3[] = {"first_point", "second_point", "t2d", nullptr};
PyObject *obj1 = nullptr, *obj2 = nullptr;
float t2d;
if (PyArg_ParseTupleAndKeywords(args, kwds, "|O!", (char **)kwlist_1, &CurvePoint_Type, &obj1)) {
if (!obj1) {
self->cp = new CurvePoint();
}
else {
self->cp = new CurvePoint(*(((BPy_CurvePoint *)obj1)->cp));
}
}
else if ((void)PyErr_Clear(),
PyArg_ParseTupleAndKeywords(args,
kwds,
"O!O!f",
(char **)kwlist_2,
&SVertex_Type,
&obj1,
&SVertex_Type,
&obj2,
&t2d))
{
self->cp = new CurvePoint(((BPy_SVertex *)obj1)->sv, ((BPy_SVertex *)obj2)->sv, t2d);
}
else if ((void)PyErr_Clear(),
PyArg_ParseTupleAndKeywords(args,
kwds,
"O!O!f",
(char **)kwlist_3,
&CurvePoint_Type,
&obj1,
&CurvePoint_Type,
&obj2,
&t2d))
{
CurvePoint *cp1 = ((BPy_CurvePoint *)obj1)->cp;
CurvePoint *cp2 = ((BPy_CurvePoint *)obj2)->cp;
if (!cp1 || cp1->A() == nullptr || cp1->B() == nullptr) {
PyErr_SetString(PyExc_TypeError, "argument 1 is an invalid CurvePoint object");
return -1;
}
if (!cp2 || cp2->A() == nullptr || cp2->B() == nullptr) {
PyErr_SetString(PyExc_TypeError, "argument 2 is an invalid CurvePoint object");
return -1;
}
self->cp = new CurvePoint(cp1, cp2, t2d);
}
else {
PyErr_SetString(PyExc_TypeError, "invalid argument(s)");
return -1;
}
self->py_if0D.if0D = self->cp;
self->py_if0D.borrowed = false;
return 0;
}
/// bool operator== (const CurvePoint &b)
/*----------------------CurvePoint get/setters ----------------------------*/
PyDoc_STRVAR(
/* Wrap. */
CurvePoint_first_svertex_doc,
"The first SVertex upon which the CurvePoint is built.\n"
"\n"
":type: :class:`SVertex`\n");
static PyObject *CurvePoint_first_svertex_get(BPy_CurvePoint *self, void * /*closure*/)
{
SVertex *A = self->cp->A();
if (A) {
return BPy_SVertex_from_SVertex(*A);
}
Py_RETURN_NONE;
}
static int CurvePoint_first_svertex_set(BPy_CurvePoint *self, PyObject *value, void * /*closure*/)
{
if (!BPy_SVertex_Check(value)) {
PyErr_SetString(PyExc_TypeError, "value must be an SVertex");
return -1;
}
self->cp->setA(((BPy_SVertex *)value)->sv);
return 0;
}
PyDoc_STRVAR(
/* Wrap. */
CurvePoint_second_svertex_doc,
"The second SVertex upon which the CurvePoint is built.\n"
"\n"
":type: :class:`SVertex`\n");
static PyObject *CurvePoint_second_svertex_get(BPy_CurvePoint *self, void * /*closure*/)
{
SVertex *B = self->cp->B();
if (B) {
return BPy_SVertex_from_SVertex(*B);
}
Py_RETURN_NONE;
}
static int CurvePoint_second_svertex_set(BPy_CurvePoint *self, PyObject *value, void * /*closure*/)
{
if (!BPy_SVertex_Check(value)) {
PyErr_SetString(PyExc_TypeError, "value must be an SVertex");
return -1;
}
self->cp->setB(((BPy_SVertex *)value)->sv);
return 0;
}
PyDoc_STRVAR(
/* Wrap. */
CurvePoint_fedge_doc,
"Gets the FEdge for the two SVertices that given CurvePoints consists out of.\n"
"A shortcut for CurvePoint.first_svertex.get_fedge(CurvePoint.second_svertex).\n"
"\n"
":type: :class:`FEdge`\n");
static PyObject *CurvePoint_fedge_get(BPy_CurvePoint *self, void * /*closure*/)
{
SVertex *A = self->cp->A();
Interface0D *B = (Interface0D *)self->cp->B();
// B can be nullptr under certain circumstances
if (B) {
return Any_BPy_Interface1D_from_Interface1D(*(A->getFEdge(*B)));
}
Py_RETURN_NONE;
}
PyDoc_STRVAR(
/* Wrap. */
CurvePoint_t2d_doc,
"The 2D interpolation parameter.\n"
"\n"
":type: float\n");
static PyObject *CurvePoint_t2d_get(BPy_CurvePoint *self, void * /*closure*/)
{
return PyFloat_FromDouble(self->cp->t2d());
}
static int CurvePoint_t2d_set(BPy_CurvePoint *self, PyObject *value, void * /*closure*/)
{
float scalar;
if ((scalar = PyFloat_AsDouble(value)) == -1.0f && PyErr_Occurred()) {
PyErr_SetString(PyExc_TypeError, "value must be a number");
return -1;
}
self->cp->setT2d(scalar);
return 0;
}
static PyGetSetDef BPy_CurvePoint_getseters[] = {
{"first_svertex",
(getter)CurvePoint_first_svertex_get,
(setter)CurvePoint_first_svertex_set,
CurvePoint_first_svertex_doc,
nullptr},
{"second_svertex",
(getter)CurvePoint_second_svertex_get,
(setter)CurvePoint_second_svertex_set,
CurvePoint_second_svertex_doc,
nullptr},
{"fedge", (getter)CurvePoint_fedge_get, nullptr, CurvePoint_fedge_doc, nullptr},
{"t2d", (getter)CurvePoint_t2d_get, (setter)CurvePoint_t2d_set, CurvePoint_t2d_doc, nullptr},
{nullptr, nullptr, nullptr, nullptr, nullptr} /* Sentinel */
};
/*-----------------------BPy_CurvePoint type definition ------------------------------*/
PyTypeObject CurvePoint_Type = {
/*ob_base*/ PyVarObject_HEAD_INIT(nullptr, 0)
/*tp_name*/ "CurvePoint",
/*tp_basicsize*/ sizeof(BPy_CurvePoint),
/*tp_itemsize*/ 0,
/*tp_dealloc*/ nullptr,
/*tp_vectorcall_offset*/ 0,
/*tp_getattr*/ nullptr,
/*tp_setattr*/ nullptr,
/*tp_as_async*/ nullptr,
/*tp_repr*/ nullptr,
/*tp_as_number*/ nullptr,
/*tp_as_sequence*/ nullptr,
/*tp_as_mapping*/ nullptr,
/*tp_hash*/ nullptr,
/*tp_call*/ nullptr,
/*tp_str*/ nullptr,
/*tp_getattro*/ nullptr,
/*tp_setattro*/ nullptr,
/*tp_as_buffer*/ nullptr,
/*tp_flags*/ Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE,
/*tp_doc*/ CurvePoint_doc,
/*tp_traverse*/ nullptr,
/*tp_clear*/ nullptr,
/*tp_richcompare*/ nullptr,
/*tp_weaklistoffset*/ 0,
/*tp_iter*/ nullptr,
/*tp_iternext*/ nullptr,
/*tp_methods*/ nullptr,
/*tp_members*/ nullptr,
/*tp_getset*/ BPy_CurvePoint_getseters,
/*tp_base*/ &Interface0D_Type,
/*tp_dict*/ nullptr,
/*tp_descr_get*/ nullptr,
/*tp_descr_set*/ nullptr,
/*tp_dictoffset*/ 0,
/*tp_init*/ (initproc)CurvePoint_init,
/*tp_alloc*/ nullptr,
/*tp_new*/ nullptr,
};
///////////////////////////////////////////////////////////////////////////////////////////

View File

@@ -0,0 +1,27 @@
/* SPDX-FileCopyrightText: 2023 Blender Authors
*
* SPDX-License-Identifier: GPL-2.0-or-later */
/** \file
* \ingroup freestyle
*/
#pragma once
#include "../BPy_Interface0D.h"
#include "../../stroke/Curve.h"
///////////////////////////////////////////////////////////////////////////////////////////
extern PyTypeObject CurvePoint_Type;
#define BPy_CurvePoint_Check(v) (PyObject_IsInstance((PyObject *)v, (PyObject *)&CurvePoint_Type))
/*---------------------------Python BPy_CurvePoint structure definition----------*/
struct BPy_CurvePoint {
BPy_Interface0D py_if0D;
Freestyle::CurvePoint *cp;
};
///////////////////////////////////////////////////////////////////////////////////////////

View File

@@ -0,0 +1,522 @@
/* SPDX-FileCopyrightText: 2004-2023 Blender Authors
*
* SPDX-License-Identifier: GPL-2.0-or-later */
/** \file
* \ingroup freestyle
*/
#include "BPy_SVertex.h"
#include "../BPy_Convert.h"
#include "../BPy_Id.h"
#include "../Interface1D/BPy_FEdge.h"
#include "BLI_sys_types.h"
using namespace Freestyle;
///////////////////////////////////////////////////////////////////////////////////////////
/*----------------------SVertex methods ----------------------------*/
PyDoc_STRVAR(
/* Wrap. */
SVertex_doc,
"Class hierarchy: :class:`Interface0D` > :class:`SVertex`\n"
"\n"
"Class to define a vertex of the embedding.\n"
"\n"
".. method:: __init__(*args)\n"
"\n"
" Accepted call signatures:\n"
"\n"
" - ``__init__()``\n"
" - ``__init__(brother)``\n"
" - ``__init__(point_3d, id)``\n"
"\n"
" Builds a :class:`SVertex` using the default constructor,\n"
" copy constructor or the overloaded constructor which builds"
" a :class:`SVertex` from 3D coordinates and an Id.\n"
"\n"
" :param brother: A SVertex object.\n"
" :type brother: :class:`SVertex`\n"
" :param point_3d: A three-dimensional vector.\n"
" :type point_3d: :class:`mathutils.Vector`\n"
" :param id: An Id object.\n"
" :type id: :class:`Id`\n");
static int SVertex_init(BPy_SVertex *self, PyObject *args, PyObject *kwds)
{
static const char *kwlist_1[] = {"brother", nullptr};
static const char *kwlist_2[] = {"point_3d", "id", nullptr};
PyObject *obj = nullptr;
float v[3];
if (PyArg_ParseTupleAndKeywords(args, kwds, "|O!", (char **)kwlist_1, &SVertex_Type, &obj)) {
if (!obj) {
self->sv = new SVertex();
}
else {
self->sv = new SVertex(*(((BPy_SVertex *)obj)->sv));
}
}
else if ((void)PyErr_Clear(),
PyArg_ParseTupleAndKeywords(
args, kwds, "O&O!", (char **)kwlist_2, convert_v3, v, &Id_Type, &obj))
{
Vec3r point_3d(v[0], v[1], v[2]);
self->sv = new SVertex(point_3d, *(((BPy_Id *)obj)->id));
}
else {
PyErr_SetString(PyExc_TypeError, "invalid argument(s)");
return -1;
}
self->py_if0D.if0D = self->sv;
self->py_if0D.borrowed = false;
return 0;
}
PyDoc_STRVAR(
/* Wrap. */
SVertex_add_normal_doc,
".. method:: add_normal(normal)\n"
"\n"
" Adds a normal to the SVertex's set of normals. If the same normal\n"
" is already in the set, nothing changes.\n"
"\n"
" :param normal: A three-dimensional vector.\n"
" :type normal: :class:`mathutils.Vector` | tuple[float, float, float] | list[float]\n");
static PyObject *SVertex_add_normal(BPy_SVertex *self, PyObject *args, PyObject *kwds)
{
static const char *kwlist[] = {"normal", nullptr};
PyObject *py_normal;
Vec3r n;
if (!PyArg_ParseTupleAndKeywords(args, kwds, "O", (char **)kwlist, &py_normal)) {
return nullptr;
}
if (!Vec3r_ptr_from_PyObject(py_normal, n)) {
PyErr_SetString(PyExc_TypeError,
"argument 1 must be a 3D vector (either a list of 3 elements or Vector)");
return nullptr;
}
self->sv->AddNormal(n);
Py_RETURN_NONE;
}
PyDoc_STRVAR(
/* Wrap. */
SVertex_add_fedge_doc,
".. method:: add_fedge(fedge)\n"
"\n"
" Add an FEdge to the list of edges emanating from this SVertex.\n"
"\n"
" :param fedge: An FEdge.\n"
" :type fedge: :class:`FEdge`\n");
static PyObject *SVertex_add_fedge(BPy_SVertex *self, PyObject *args, PyObject *kwds)
{
static const char *kwlist[] = {"fedge", nullptr};
PyObject *py_fe;
if (!PyArg_ParseTupleAndKeywords(args, kwds, "O!", (char **)kwlist, &FEdge_Type, &py_fe)) {
return nullptr;
}
self->sv->AddFEdge(((BPy_FEdge *)py_fe)->fe);
Py_RETURN_NONE;
}
// virtual bool operator== (const SVertex &brother)
#ifdef __GNUC__
# ifdef __clang__
# pragma clang diagnostic push
# pragma clang diagnostic ignored "-Wcast-function-type"
# else
# pragma GCC diagnostic push
# pragma GCC diagnostic ignored "-Wcast-function-type"
# endif
#endif
static PyMethodDef BPy_SVertex_methods[] = {
{"add_normal",
(PyCFunction)SVertex_add_normal,
METH_VARARGS | METH_KEYWORDS,
SVertex_add_normal_doc},
{"add_fedge",
(PyCFunction)SVertex_add_fedge,
METH_VARARGS | METH_KEYWORDS,
SVertex_add_fedge_doc},
{nullptr, nullptr, 0, nullptr},
};
#ifdef __GNUC__
# ifdef __clang__
# pragma clang diagnostic pop
# else
# pragma GCC diagnostic pop
# endif
#endif
/*----------------------mathutils callbacks ----------------------------*/
/* subtype */
#define MATHUTILS_SUBTYPE_POINT3D 1
#define MATHUTILS_SUBTYPE_POINT2D 2
static int SVertex_mathutils_check(blender::BaseMathObject *bmo)
{
if (!BPy_SVertex_Check(bmo->cb_user)) {
return -1;
}
return 0;
}
static int SVertex_mathutils_get(blender::BaseMathObject *bmo, int subtype)
{
BPy_SVertex *self = (BPy_SVertex *)bmo->cb_user;
switch (subtype) {
case MATHUTILS_SUBTYPE_POINT3D:
bmo->data[0] = self->sv->getX();
bmo->data[1] = self->sv->getY();
bmo->data[2] = self->sv->getZ();
break;
case MATHUTILS_SUBTYPE_POINT2D:
bmo->data[0] = self->sv->getProjectedX();
bmo->data[1] = self->sv->getProjectedY();
bmo->data[2] = self->sv->getProjectedZ();
break;
default:
return -1;
}
return 0;
}
static int SVertex_mathutils_set(blender::BaseMathObject *bmo, int subtype)
{
BPy_SVertex *self = (BPy_SVertex *)bmo->cb_user;
switch (subtype) {
case MATHUTILS_SUBTYPE_POINT3D: {
Vec3r p(bmo->data[0], bmo->data[1], bmo->data[2]);
self->sv->setPoint3D(p);
break;
}
case MATHUTILS_SUBTYPE_POINT2D: {
Vec3r p(bmo->data[0], bmo->data[1], bmo->data[2]);
self->sv->setPoint2D(p);
break;
}
default:
return -1;
}
return 0;
}
static int SVertex_mathutils_get_index(blender::BaseMathObject *bmo, int subtype, int index)
{
BPy_SVertex *self = (BPy_SVertex *)bmo->cb_user;
switch (subtype) {
case MATHUTILS_SUBTYPE_POINT3D:
switch (index) {
case 0:
bmo->data[0] = self->sv->getX();
break;
case 1:
bmo->data[1] = self->sv->getY();
break;
case 2:
bmo->data[2] = self->sv->getZ();
break;
default:
return -1;
}
break;
case MATHUTILS_SUBTYPE_POINT2D:
switch (index) {
case 0:
bmo->data[0] = self->sv->getProjectedX();
break;
case 1:
bmo->data[1] = self->sv->getProjectedY();
break;
case 2:
bmo->data[2] = self->sv->getProjectedZ();
break;
default:
return -1;
}
break;
default:
return -1;
}
return 0;
}
static int SVertex_mathutils_set_index(blender::BaseMathObject *bmo, int subtype, int index)
{
BPy_SVertex *self = (BPy_SVertex *)bmo->cb_user;
switch (subtype) {
case MATHUTILS_SUBTYPE_POINT3D: {
Vec3r p(self->sv->point3D());
p[index] = bmo->data[index];
self->sv->setPoint3D(p);
break;
}
case MATHUTILS_SUBTYPE_POINT2D: {
Vec3r p(self->sv->point2D());
p[index] = bmo->data[index];
self->sv->setPoint2D(p);
break;
}
default:
return -1;
}
return 0;
}
static blender::Mathutils_Callback SVertex_mathutils_cb = {
SVertex_mathutils_check,
SVertex_mathutils_get,
SVertex_mathutils_set,
SVertex_mathutils_get_index,
SVertex_mathutils_set_index,
};
static uchar SVertex_mathutils_cb_index = -1;
void SVertex_mathutils_register_callback()
{
SVertex_mathutils_cb_index = Mathutils_RegisterCallback(&SVertex_mathutils_cb);
}
/*----------------------SVertex get/setters ----------------------------*/
PyDoc_STRVAR(
/* Wrap. */
SVertex_point_3d_doc,
"The 3D coordinates of the SVertex.\n"
"\n"
":type: :class:`mathutils.Vector`\n");
static PyObject *SVertex_point_3d_get(BPy_SVertex *self, void * /*closure*/)
{
return blender::Vector_CreatePyObject_cb(
(PyObject *)self, 3, SVertex_mathutils_cb_index, MATHUTILS_SUBTYPE_POINT3D);
}
static int SVertex_point_3d_set(BPy_SVertex *self, PyObject *value, void * /*closure*/)
{
float v[3];
if (blender::mathutils_array_parse(v, 3, 3, value, "value must be a 3-dimensional vector") == -1)
{
return -1;
}
Vec3r p(v[0], v[1], v[2]);
self->sv->setPoint3D(p);
return 0;
}
PyDoc_STRVAR(
/* Wrap. */
SVertex_point_2d_doc,
"The projected 3D coordinates of the SVertex.\n"
"\n"
":type: :class:`mathutils.Vector`\n");
static PyObject *SVertex_point_2d_get(BPy_SVertex *self, void * /*closure*/)
{
return blender::Vector_CreatePyObject_cb(
(PyObject *)self, 3, SVertex_mathutils_cb_index, MATHUTILS_SUBTYPE_POINT2D);
}
static int SVertex_point_2d_set(BPy_SVertex *self, PyObject *value, void * /*closure*/)
{
float v[3];
if (blender::mathutils_array_parse(v, 3, 3, value, "value must be a 3-dimensional vector") == -1)
{
return -1;
}
Vec3r p(v[0], v[1], v[2]);
self->sv->setPoint2D(p);
return 0;
}
PyDoc_STRVAR(
/* Wrap. */
SVertex_id_doc,
"The Id of this SVertex.\n"
"\n"
":type: :class:`Id`\n");
static PyObject *SVertex_id_get(BPy_SVertex *self, void * /*closure*/)
{
Id id(self->sv->getId());
return BPy_Id_from_Id(id); // return a copy
}
static int SVertex_id_set(BPy_SVertex *self, PyObject *value, void * /*closure*/)
{
if (!BPy_Id_Check(value)) {
PyErr_SetString(PyExc_TypeError, "value must be an Id");
return -1;
}
self->sv->setId(*(((BPy_Id *)value)->id));
return 0;
}
PyDoc_STRVAR(
/* Wrap. */
SVertex_normals_doc,
"The normals for this Vertex as a list. In a sharp surface, an SVertex\n"
"has exactly one normal. In a smooth surface, an SVertex can have any\n"
"number of normals.\n"
"\n"
":type: list[:class:`mathutils.Vector`]\n");
static PyObject *SVertex_normals_get(BPy_SVertex *self, void * /*closure*/)
{
PyObject *py_normals;
set<Vec3r> normals = self->sv->normals();
set<Vec3r>::iterator it;
py_normals = PyList_New(normals.size());
uint i = 0;
for (it = normals.begin(); it != normals.end(); it++) {
Vec3r v(*it);
PyList_SET_ITEM(py_normals, i++, Vector_from_Vec3r(v));
}
return py_normals;
}
PyDoc_STRVAR(
/* Wrap. */
SVertex_normals_size_doc,
"The number of different normals for this SVertex.\n"
"\n"
":type: int\n");
static PyObject *SVertex_normals_size_get(BPy_SVertex *self, void * /*closure*/)
{
return PyLong_FromLong(self->sv->normalsSize());
}
PyDoc_STRVAR(
/* Wrap. */
SVertex_viewvertex_doc,
"If this SVertex is also a ViewVertex, this property refers to the\n"
"ViewVertex, and None otherwise.\n"
"\n"
":type: :class:`ViewVertex`\n");
static PyObject *SVertex_viewvertex_get(BPy_SVertex *self, void * /*closure*/)
{
ViewVertex *vv = self->sv->viewvertex();
if (vv) {
return Any_BPy_ViewVertex_from_ViewVertex(*vv);
}
Py_RETURN_NONE;
}
PyDoc_STRVAR(
/* Wrap. */
SVertex_curvatures_doc,
"Curvature information expressed in the form of a seven-element tuple\n"
"(K1, e1, K2, e2, Kr, er, dKr), where K1 and K2 are scalar values\n"
"representing the first (maximum) and second (minimum) principal\n"
"curvatures at this SVertex, respectively; e1 and e2 are\n"
"three-dimensional vectors representing the first and second principal\n"
"directions, i.e. the directions of the normal plane where the\n"
"curvature takes its maximum and minimum values, respectively; and Kr,\n"
"er and dKr are the radial curvature, radial direction, and the\n"
"derivative of the radial curvature at this SVertex, respectively.\n"
"\n"
":type: tuple\n");
static PyObject *SVertex_curvatures_get(BPy_SVertex *self, void * /*closure*/)
{
const CurvatureInfo *info = self->sv->getCurvatureInfo();
if (!info) {
Py_RETURN_NONE;
}
Vec3r e1(info->e1.x(), info->e1.y(), info->e1.z());
Vec3r e2(info->e2.x(), info->e2.y(), info->e2.z());
Vec3r er(info->er.x(), info->er.y(), info->er.z());
PyObject *retval = PyTuple_New(7);
PyTuple_SET_ITEMS(retval,
PyFloat_FromDouble(info->K1),
PyFloat_FromDouble(info->K2),
Vector_from_Vec3r(e1),
Vector_from_Vec3r(e2),
PyFloat_FromDouble(info->Kr),
Vector_from_Vec3r(er),
PyFloat_FromDouble(info->dKr));
return retval;
}
static PyGetSetDef BPy_SVertex_getseters[] = {
{"point_3d",
(getter)SVertex_point_3d_get,
(setter)SVertex_point_3d_set,
SVertex_point_3d_doc,
nullptr},
{"point_2d",
(getter)SVertex_point_2d_get,
(setter)SVertex_point_2d_set,
SVertex_point_2d_doc,
nullptr},
{"id", (getter)SVertex_id_get, (setter)SVertex_id_set, SVertex_id_doc, nullptr},
{"normals", (getter)SVertex_normals_get, (setter) nullptr, SVertex_normals_doc, nullptr},
{"normals_size",
(getter)SVertex_normals_size_get,
(setter) nullptr,
SVertex_normals_size_doc,
nullptr},
{"viewvertex",
(getter)SVertex_viewvertex_get,
(setter) nullptr,
SVertex_viewvertex_doc,
nullptr},
{"curvatures",
(getter)SVertex_curvatures_get,
(setter) nullptr,
SVertex_curvatures_doc,
nullptr},
{nullptr, nullptr, nullptr, nullptr, nullptr} /* Sentinel */
};
/*-----------------------BPy_SVertex type definition ------------------------------*/
PyTypeObject SVertex_Type = {
/*ob_base*/ PyVarObject_HEAD_INIT(nullptr, 0)
/*tp_name*/ "SVertex",
/*tp_basicsize*/ sizeof(BPy_SVertex),
/*tp_itemsize*/ 0,
/*tp_dealloc*/ nullptr,
/*tp_vectorcall_offset*/ 0,
/*tp_getattr*/ nullptr,
/*tp_setattr*/ nullptr,
/*tp_as_async*/ nullptr,
/*tp_repr*/ nullptr,
/*tp_as_number*/ nullptr,
/*tp_as_sequence*/ nullptr,
/*tp_as_mapping*/ nullptr,
/*tp_hash*/ nullptr,
/*tp_call*/ nullptr,
/*tp_str*/ nullptr,
/*tp_getattro*/ nullptr,
/*tp_setattro*/ nullptr,
/*tp_as_buffer*/ nullptr,
/*tp_flags*/ Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE,
/*tp_doc*/ SVertex_doc,
/*tp_traverse*/ nullptr,
/*tp_clear*/ nullptr,
/*tp_richcompare*/ nullptr,
/*tp_weaklistoffset*/ 0,
/*tp_iter*/ nullptr,
/*tp_iternext*/ nullptr,
/*tp_methods*/ BPy_SVertex_methods,
/*tp_members*/ nullptr,
/*tp_getset*/ BPy_SVertex_getseters,
/*tp_base*/ &Interface0D_Type,
/*tp_dict*/ nullptr,
/*tp_descr_get*/ nullptr,
/*tp_descr_set*/ nullptr,
/*tp_dictoffset*/ 0,
/*tp_init*/ (initproc)SVertex_init,
/*tp_alloc*/ nullptr,
/*tp_new*/ nullptr,
};
///////////////////////////////////////////////////////////////////////////////////////////

View File

@@ -0,0 +1,31 @@
/* SPDX-FileCopyrightText: 2023 Blender Authors
*
* SPDX-License-Identifier: GPL-2.0-or-later */
/** \file
* \ingroup freestyle
*/
#pragma once
#include "../BPy_Interface0D.h"
#include "../../view_map/Silhouette.h"
///////////////////////////////////////////////////////////////////////////////////////////
extern PyTypeObject SVertex_Type;
#define BPy_SVertex_Check(v) (PyObject_IsInstance((PyObject *)v, (PyObject *)&SVertex_Type))
/*---------------------------Python BPy_SVertex structure definition----------*/
struct BPy_SVertex {
BPy_Interface0D py_if0D;
Freestyle::SVertex *sv;
};
/*---------------------------Python BPy_SVertex visible prototypes-----------*/
void SVertex_mathutils_register_callback();
///////////////////////////////////////////////////////////////////////////////////////////

View File

@@ -0,0 +1,213 @@
/* SPDX-FileCopyrightText: 2004-2022 Blender Authors
*
* SPDX-License-Identifier: GPL-2.0-or-later */
/** \file
* \ingroup freestyle
*/
#include "BPy_ViewVertex.h"
#include "../BPy_Convert.h"
#include "../BPy_Nature.h"
#include "../Interface1D/BPy_ViewEdge.h"
using namespace Freestyle;
///////////////////////////////////////////////////////////////////////////////////////////
/*----------------------ViewVertex methods----------------------------*/
PyDoc_STRVAR(
/* Wrap. */
ViewVertex_doc,
"Class hierarchy: :class:`Interface0D` > :class:`ViewVertex`\n"
"\n"
"Class to define a view vertex. A view vertex is a feature vertex\n"
"corresponding to a point of the image graph, where the characteristics\n"
"of an edge (e.g., nature and visibility) might change. A\n"
":class:`ViewVertex` can be of two kinds: A :class:`TVertex` when it\n"
"corresponds to the intersection between two ViewEdges or a\n"
":class:`NonTVertex` when it corresponds to a vertex of the initial\n"
"input mesh (it is the case for vertices such as corners for example).\n"
"Thus, this class can be specialized into two classes, the\n"
":class:`TVertex` class and the :class:`NonTVertex` class.\n");
static int ViewVertex_init(BPy_ViewVertex * /*self*/, PyObject * /*args*/, PyObject * /*kwds*/)
{
PyErr_SetString(PyExc_TypeError, "cannot instantiate abstract class");
return -1;
}
PyDoc_STRVAR(
/* Wrap. */
ViewVertex_edges_begin_doc,
".. method:: edges_begin()\n"
"\n"
" Returns an iterator over the ViewEdges that goes to or comes from\n"
" this ViewVertex pointing to the first ViewEdge of the list. The\n"
" orientedViewEdgeIterator allows to iterate in CCW order over these\n"
" ViewEdges and to get the orientation for each ViewEdge\n"
" (incoming/outgoing).\n"
"\n"
" :return: An orientedViewEdgeIterator pointing to the first ViewEdge.\n"
" :rtype: :class:`orientedViewEdgeIterator`\n");
static PyObject *ViewVertex_edges_begin(BPy_ViewVertex *self)
{
ViewVertexInternal::orientedViewEdgeIterator ove_it(self->vv->edgesBegin());
return BPy_orientedViewEdgeIterator_from_orientedViewEdgeIterator(ove_it, false);
}
PyDoc_STRVAR(
/* Wrap. */
ViewVertex_edges_end_doc,
".. method:: edges_end()\n"
"\n"
" Returns an orientedViewEdgeIterator over the ViewEdges around this\n"
" ViewVertex, pointing after the last ViewEdge.\n"
"\n"
" :return: An orientedViewEdgeIterator pointing after the last ViewEdge.\n"
" :rtype: :class:`orientedViewEdgeIterator`\n");
static PyObject *ViewVertex_edges_end(BPy_ViewVertex * /*self*/)
{
#if 0
ViewVertexInternal::orientedViewEdgeIterator ove_it(self->vv->edgesEnd());
return BPy_orientedViewEdgeIterator_from_orientedViewEdgeIterator(ove_it, 1);
#else
PyErr_SetString(PyExc_NotImplementedError, "edges_end method currently disabled");
return nullptr;
#endif
}
PyDoc_STRVAR(
/* Wrap. */
ViewVertex_edges_iterator_doc,
".. method:: edges_iterator(edge)\n"
"\n"
" Returns an orientedViewEdgeIterator pointing to the ViewEdge given\n"
" as argument.\n"
"\n"
" :param edge: A ViewEdge object.\n"
" :type edge: :class:`ViewEdge`\n"
" :return: An orientedViewEdgeIterator pointing to the given ViewEdge.\n"
" :rtype: :class:`orientedViewEdgeIterator`\n");
static PyObject *ViewVertex_edges_iterator(BPy_ViewVertex *self, PyObject *args, PyObject *kwds)
{
static const char *kwlist[] = {"edge", nullptr};
PyObject *py_ve;
if (PyArg_ParseTupleAndKeywords(args, kwds, "O!", (char **)kwlist, &ViewEdge_Type, &py_ve)) {
return nullptr;
}
ViewEdge *ve = ((BPy_ViewEdge *)py_ve)->ve;
ViewVertexInternal::orientedViewEdgeIterator ove_it(self->vv->edgesIterator(ve));
return BPy_orientedViewEdgeIterator_from_orientedViewEdgeIterator(ove_it, false);
}
#ifdef __GNUC__
# ifdef __clang__
# pragma clang diagnostic push
# pragma clang diagnostic ignored "-Wcast-function-type"
# else
# pragma GCC diagnostic push
# pragma GCC diagnostic ignored "-Wcast-function-type"
# endif
#endif
static PyMethodDef BPy_ViewVertex_methods[] = {
{"edges_begin", (PyCFunction)ViewVertex_edges_begin, METH_NOARGS, ViewVertex_edges_begin_doc},
{"edges_end", (PyCFunction)ViewVertex_edges_end, METH_NOARGS, ViewVertex_edges_end_doc},
{"edges_iterator",
(PyCFunction)ViewVertex_edges_iterator,
METH_VARARGS | METH_KEYWORDS,
ViewVertex_edges_iterator_doc},
{nullptr, nullptr, 0, nullptr},
};
#ifdef __GNUC__
# ifdef __clang__
# pragma clang diagnostic pop
# else
# pragma GCC diagnostic pop
# endif
#endif
/*----------------------ViewVertex get/setters ----------------------------*/
PyDoc_STRVAR(
/* Wrap. */
ViewVertex_nature_doc,
"The nature of this ViewVertex.\n"
"\n"
":type: :class:`Nature`\n");
static PyObject *ViewVertex_nature_get(BPy_ViewVertex *self, void * /*closure*/)
{
Nature::VertexNature nature = self->vv->getNature();
if (PyErr_Occurred()) {
return nullptr;
}
return BPy_Nature_from_Nature(nature); // return a copy
}
static int ViewVertex_nature_set(BPy_ViewVertex *self, PyObject *value, void * /*closure*/)
{
if (!BPy_Nature_Check(value)) {
PyErr_SetString(PyExc_TypeError, "value must be a Nature");
return -1;
}
self->vv->setNature(PyLong_AsLong((PyObject *)&((BPy_Nature *)value)->i));
return 0;
}
static PyGetSetDef BPy_ViewVertex_getseters[] = {
{"nature",
(getter)ViewVertex_nature_get,
(setter)ViewVertex_nature_set,
ViewVertex_nature_doc,
nullptr},
{nullptr, nullptr, nullptr, nullptr, nullptr} /* Sentinel */
};
/*-----------------------BPy_ViewVertex type definition ------------------------------*/
PyTypeObject ViewVertex_Type = {
/*ob_base*/ PyVarObject_HEAD_INIT(nullptr, 0)
/*tp_name*/ "ViewVertex",
/*tp_basicsize*/ sizeof(BPy_ViewVertex),
/*tp_itemsize*/ 0,
/*tp_dealloc*/ nullptr,
/*tp_vectorcall_offset*/ 0,
/*tp_getattr*/ nullptr,
/*tp_setattr*/ nullptr,
/*tp_as_async*/ nullptr,
/*tp_repr*/ nullptr,
/*tp_as_number*/ nullptr,
/*tp_as_sequence*/ nullptr,
/*tp_as_mapping*/ nullptr,
/*tp_hash*/ nullptr,
/*tp_call*/ nullptr,
/*tp_str*/ nullptr,
/*tp_getattro*/ nullptr,
/*tp_setattro*/ nullptr,
/*tp_as_buffer*/ nullptr,
/*tp_flags*/ Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE,
/*tp_doc*/ ViewVertex_doc,
/*tp_traverse*/ nullptr,
/*tp_clear*/ nullptr,
/*tp_richcompare*/ nullptr,
/*tp_weaklistoffset*/ 0,
/*tp_iter*/ nullptr,
/*tp_iternext*/ nullptr,
/*tp_methods*/ BPy_ViewVertex_methods,
/*tp_members*/ nullptr,
/*tp_getset*/ BPy_ViewVertex_getseters,
/*tp_base*/ &Interface0D_Type,
/*tp_dict*/ nullptr,
/*tp_descr_get*/ nullptr,
/*tp_descr_set*/ nullptr,
/*tp_dictoffset*/ 0,
/*tp_init*/ (initproc)ViewVertex_init,
/*tp_alloc*/ nullptr,
/*tp_new*/ nullptr,
};
///////////////////////////////////////////////////////////////////////////////////////////

View File

@@ -0,0 +1,27 @@
/* SPDX-FileCopyrightText: 2023 Blender Authors
*
* SPDX-License-Identifier: GPL-2.0-or-later */
/** \file
* \ingroup freestyle
*/
#pragma once
#include "../BPy_Interface0D.h"
#include "../../view_map/ViewMap.h"
///////////////////////////////////////////////////////////////////////////////////////////
extern PyTypeObject ViewVertex_Type;
#define BPy_ViewVertex_Check(v) (PyObject_IsInstance((PyObject *)v, (PyObject *)&ViewVertex_Type))
/*---------------------------Python BPy_ViewVertex structure definition----------*/
struct BPy_ViewVertex {
BPy_Interface0D py_if0D;
Freestyle::ViewVertex *vv;
};
///////////////////////////////////////////////////////////////////////////////////////////

View File

@@ -0,0 +1,402 @@
/* SPDX-FileCopyrightText: 2004-2023 Blender Authors
*
* SPDX-License-Identifier: GPL-2.0-or-later */
/** \file
* \ingroup freestyle
*/
#include "BPy_StrokeVertex.h"
#include "../../BPy_Convert.h"
#include "../../BPy_Freestyle.h"
#include "../../BPy_StrokeAttribute.h"
#include "../../Interface0D/BPy_SVertex.h"
using namespace Freestyle;
///////////////////////////////////////////////////////////////////////////////////////////
//------------------------INSTANCE METHODS ----------------------------------
PyDoc_STRVAR(
/* Wrap. */
StrokeVertex_doc,
"Class hierarchy: :class:`Interface0D` > :class:`CurvePoint` > :class:`StrokeVertex`\n"
"\n"
"Class to define a stroke vertex.\n"
"\n"
".. method:: __init__(*args)\n"
"\n"
" Accepted call signatures:\n"
"\n"
" - ``__init__()``\n"
" - ``__init__(brother)``\n"
" - ``__init__(first_vertex, second_vertex, t3d)``\n"
" - ``__init__(point)``\n"
" - ``__init__(svertex)``\n"
" - ``__init__(svertex, attribute)``\n"
"\n"
" Builds a :class:`StrokeVertex` using the default constructor,\n"
" copy constructor, from 2 :class:`StrokeVertex` and an interpolation parameter,\n"
" from a CurvePoint, from a SVertex, or a :class:`SVertex`"
" and a :class:`StrokeAttribute` object.\n"
"\n"
" :param brother: A StrokeVertex object.\n"
" :type brother: :class:`StrokeVertex`\n"
" :param first_vertex: The first StrokeVertex.\n"
" :type first_vertex: :class:`StrokeVertex`\n"
" :param second_vertex: The second StrokeVertex.\n"
" :type second_vertex: :class:`StrokeVertex`\n"
" :param t3d: An interpolation parameter.\n"
" :type t3d: float\n"
" :param point: A CurvePoint object.\n"
" :type point: :class:`CurvePoint`\n"
" :param svertex: An SVertex object.\n"
" :type svertex: :class:`SVertex`\n"
" :param svertex: An SVertex object.\n"
" :type svertex: :class:`SVertex`\n"
" :param attribute: A StrokeAttribute object.\n"
" :type attribute: :class:`StrokeAttribute`\n");
static int StrokeVertex_init(BPy_StrokeVertex *self, PyObject *args, PyObject *kwds)
{
static const char *kwlist_1[] = {"brother", nullptr};
static const char *kwlist_2[] = {"first_vertex", "second_vertex", "t3d", nullptr};
static const char *kwlist_3[] = {"point", nullptr};
static const char *kwlist_4[] = {"svertex", "attribute", nullptr};
PyObject *obj1 = nullptr, *obj2 = nullptr;
float t3d;
if (PyArg_ParseTupleAndKeywords(args, kwds, "|O!", (char **)kwlist_1, &StrokeVertex_Type, &obj1))
{
if (!obj1) {
self->sv = new StrokeVertex();
}
else {
if (!((BPy_StrokeVertex *)obj1)->sv) {
PyErr_SetString(PyExc_TypeError, "argument 1 is an invalid StrokeVertex object");
return -1;
}
self->sv = new StrokeVertex(*(((BPy_StrokeVertex *)obj1)->sv));
}
}
else if ((void)PyErr_Clear(),
PyArg_ParseTupleAndKeywords(args,
kwds,
"O!O!f",
(char **)kwlist_2,
&StrokeVertex_Type,
&obj1,
&StrokeVertex_Type,
&obj2,
&t3d))
{
StrokeVertex *sv1 = ((BPy_StrokeVertex *)obj1)->sv;
StrokeVertex *sv2 = ((BPy_StrokeVertex *)obj2)->sv;
if (!sv1 || (sv1->A() == nullptr && sv1->B() == nullptr)) {
PyErr_SetString(PyExc_TypeError, "argument 1 is an invalid StrokeVertex object");
return -1;
}
if (!sv2 || (sv2->A() == nullptr && sv2->B() == nullptr)) {
PyErr_SetString(PyExc_TypeError, "argument 2 is an invalid StrokeVertex object");
return -1;
}
self->sv = new StrokeVertex(sv1, sv2, t3d);
}
else if ((void)PyErr_Clear(),
PyArg_ParseTupleAndKeywords(
args, kwds, "O!", (char **)kwlist_3, &CurvePoint_Type, &obj1))
{
CurvePoint *cp = ((BPy_CurvePoint *)obj1)->cp;
if (!cp || cp->A() == nullptr || cp->B() == nullptr) {
PyErr_SetString(PyExc_TypeError, "argument 1 is an invalid CurvePoint object");
return -1;
}
self->sv = new StrokeVertex(cp);
}
else if ((void)PyErr_Clear(),
(void)(obj2 = nullptr),
PyArg_ParseTupleAndKeywords(args,
kwds,
"O!|O!",
(char **)kwlist_4,
&SVertex_Type,
&obj1,
&StrokeAttribute_Type,
&obj2))
{
if (!obj2) {
self->sv = new StrokeVertex(((BPy_SVertex *)obj1)->sv);
}
else {
self->sv = new StrokeVertex(((BPy_SVertex *)obj1)->sv, *(((BPy_StrokeAttribute *)obj2)->sa));
}
}
else {
PyErr_SetString(PyExc_TypeError, "invalid argument(s)");
return -1;
}
self->py_cp.cp = self->sv;
self->py_cp.py_if0D.if0D = self->sv;
self->py_cp.py_if0D.borrowed = false;
return 0;
}
// real operator[] (const int i) const
// real & operator[] (const int i)
/*----------------------mathutils callbacks ----------------------------*/
static int StrokeVertex_mathutils_check(blender::BaseMathObject *bmo)
{
if (!BPy_StrokeVertex_Check(bmo->cb_user)) {
return -1;
}
return 0;
}
static int StrokeVertex_mathutils_get(blender::BaseMathObject *bmo, int /*subtype*/)
{
BPy_StrokeVertex *self = (BPy_StrokeVertex *)bmo->cb_user;
bmo->data[0] = float(self->sv->x());
bmo->data[1] = float(self->sv->y());
return 0;
}
static int StrokeVertex_mathutils_set(blender::BaseMathObject *bmo, int /*subtype*/)
{
BPy_StrokeVertex *self = (BPy_StrokeVertex *)bmo->cb_user;
self->sv->setX((real)bmo->data[0]);
self->sv->setY((real)bmo->data[1]);
return 0;
}
static int StrokeVertex_mathutils_get_index(blender::BaseMathObject *bmo,
int /*subtype*/,
int index)
{
BPy_StrokeVertex *self = (BPy_StrokeVertex *)bmo->cb_user;
switch (index) {
case 0:
bmo->data[0] = float(self->sv->x());
break;
case 1:
bmo->data[1] = float(self->sv->y());
break;
default:
return -1;
}
return 0;
}
static int StrokeVertex_mathutils_set_index(blender::BaseMathObject *bmo,
int /*subtype*/,
int index)
{
BPy_StrokeVertex *self = (BPy_StrokeVertex *)bmo->cb_user;
switch (index) {
case 0:
self->sv->setX((real)bmo->data[0]);
break;
case 1:
self->sv->setY((real)bmo->data[1]);
break;
default:
return -1;
}
return 0;
}
static blender::Mathutils_Callback StrokeVertex_mathutils_cb = {
StrokeVertex_mathutils_check,
StrokeVertex_mathutils_get,
StrokeVertex_mathutils_set,
StrokeVertex_mathutils_get_index,
StrokeVertex_mathutils_set_index,
};
static uchar StrokeVertex_mathutils_cb_index = -1;
void StrokeVertex_mathutils_register_callback()
{
StrokeVertex_mathutils_cb_index = Mathutils_RegisterCallback(&StrokeVertex_mathutils_cb);
}
/*----------------------StrokeVertex get/setters ----------------------------*/
PyDoc_STRVAR(
/* Wrap. */
StrokeVertex_attribute_doc,
"StrokeAttribute for this StrokeVertex.\n"
"\n"
":type: :class:`StrokeAttribute`\n");
static PyObject *StrokeVertex_attribute_get(BPy_StrokeVertex *self, void * /*closure*/)
{
return BPy_StrokeAttribute_from_StrokeAttribute(self->sv->attribute());
}
static int StrokeVertex_attribute_set(BPy_StrokeVertex *self, PyObject *value, void * /*closure*/)
{
if (!BPy_StrokeAttribute_Check(value)) {
PyErr_SetString(PyExc_TypeError, "value must be a StrokeAttribute object");
return -1;
}
self->sv->setAttribute(*(((BPy_StrokeAttribute *)value)->sa));
return 0;
}
PyDoc_STRVAR(
/* Wrap. */
StrokeVertex_curvilinear_abscissa_doc,
"Curvilinear abscissa of this StrokeVertex in the Stroke.\n"
"\n"
":type: float\n");
static PyObject *StrokeVertex_curvilinear_abscissa_get(BPy_StrokeVertex *self, void * /*closure*/)
{
return PyFloat_FromDouble(self->sv->curvilinearAbscissa());
}
static int StrokeVertex_curvilinear_abscissa_set(BPy_StrokeVertex *self,
PyObject *value,
void * /*closure*/)
{
float scalar;
if ((scalar = PyFloat_AsDouble(value)) == -1.0f && PyErr_Occurred()) {
/* parsed item not a number */
PyErr_SetString(PyExc_TypeError, "value must be a number");
return -1;
}
self->sv->setCurvilinearAbscissa(scalar);
return 0;
}
PyDoc_STRVAR(
/* Wrap. */
StrokeVertex_point_doc,
"2D point coordinates.\n"
"\n"
":type: :class:`mathutils.Vector`\n");
static PyObject *StrokeVertex_point_get(BPy_StrokeVertex *self, void * /*closure*/)
{
return blender::Vector_CreatePyObject_cb(
(PyObject *)self, 2, StrokeVertex_mathutils_cb_index, 0);
}
static int StrokeVertex_point_set(BPy_StrokeVertex *self, PyObject *value, void * /*closure*/)
{
float v[2];
if (blender::mathutils_array_parse(v, 2, 2, value, "value must be a 2-dimensional vector") == -1)
{
return -1;
}
self->sv->setX(v[0]);
self->sv->setY(v[1]);
return 0;
}
PyDoc_STRVAR(
/* Wrap. */
StrokeVertex_stroke_length_doc,
"Stroke length (it is only a value retained by the StrokeVertex,\n"
"and it won't change the real stroke length).\n"
"\n"
":type: float\n");
static PyObject *StrokeVertex_stroke_length_get(BPy_StrokeVertex *self, void * /*closure*/)
{
return PyFloat_FromDouble(self->sv->strokeLength());
}
static int StrokeVertex_stroke_length_set(BPy_StrokeVertex *self,
PyObject *value,
void * /*closure*/)
{
float scalar;
if ((scalar = PyFloat_AsDouble(value)) == -1.0f && PyErr_Occurred()) {
/* parsed item not a number */
PyErr_SetString(PyExc_TypeError, "value must be a number");
return -1;
}
self->sv->setStrokeLength(scalar);
return 0;
}
PyDoc_STRVAR(
/* Wrap. */
StrokeVertex_u_doc,
"Curvilinear abscissa of this StrokeVertex in the Stroke.\n"
"\n"
":type: float\n");
static PyObject *StrokeVertex_u_get(BPy_StrokeVertex *self, void * /*closure*/)
{
return PyFloat_FromDouble(self->sv->u());
}
static PyGetSetDef BPy_StrokeVertex_getseters[] = {
{"attribute",
(getter)StrokeVertex_attribute_get,
(setter)StrokeVertex_attribute_set,
StrokeVertex_attribute_doc,
nullptr},
{"curvilinear_abscissa",
(getter)StrokeVertex_curvilinear_abscissa_get,
(setter)StrokeVertex_curvilinear_abscissa_set,
StrokeVertex_curvilinear_abscissa_doc,
nullptr},
{"point",
(getter)StrokeVertex_point_get,
(setter)StrokeVertex_point_set,
StrokeVertex_point_doc,
nullptr},
{"stroke_length",
(getter)StrokeVertex_stroke_length_get,
(setter)StrokeVertex_stroke_length_set,
StrokeVertex_stroke_length_doc,
nullptr},
{"u", (getter)StrokeVertex_u_get, (setter) nullptr, StrokeVertex_u_doc, nullptr},
{nullptr, nullptr, nullptr, nullptr, nullptr} /* Sentinel */
};
/*-----------------------BPy_StrokeVertex type definition ------------------------------*/
PyTypeObject StrokeVertex_Type = {
/*ob_base*/ PyVarObject_HEAD_INIT(nullptr, 0)
/*tp_name*/ "StrokeVertex",
/*tp_basicsize*/ sizeof(BPy_StrokeVertex),
/*tp_itemsize*/ 0,
/*tp_dealloc*/ nullptr,
/*tp_vectorcall_offset*/ 0,
/*tp_getattr*/ nullptr,
/*tp_setattr*/ nullptr,
/*tp_as_async*/ nullptr,
/*tp_repr*/ nullptr,
/*tp_as_number*/ nullptr,
/*tp_as_sequence*/ nullptr,
/*tp_as_mapping*/ nullptr,
/*tp_hash*/ nullptr,
/*tp_call*/ nullptr,
/*tp_str*/ nullptr,
/*tp_getattro*/ nullptr,
/*tp_setattro*/ nullptr,
/*tp_as_buffer*/ nullptr,
/*tp_flags*/ Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE,
/*tp_doc*/ StrokeVertex_doc,
/*tp_traverse*/ nullptr,
/*tp_clear*/ nullptr,
/*tp_richcompare*/ nullptr,
/*tp_weaklistoffset*/ 0,
/*tp_iter*/ nullptr,
/*tp_iternext*/ nullptr,
/*tp_methods*/ nullptr,
/*tp_members*/ nullptr,
/*tp_getset*/ BPy_StrokeVertex_getseters,
/*tp_base*/ &CurvePoint_Type,
/*tp_dict*/ nullptr,
/*tp_descr_get*/ nullptr,
/*tp_descr_set*/ nullptr,
/*tp_dictoffset*/ 0,
/*tp_init*/ (initproc)StrokeVertex_init,
/*tp_alloc*/ nullptr,
/*tp_new*/ nullptr,
};
///////////////////////////////////////////////////////////////////////////////////////////

View File

@@ -0,0 +1,32 @@
/* SPDX-FileCopyrightText: 2023 Blender Authors
*
* SPDX-License-Identifier: GPL-2.0-or-later */
/** \file
* \ingroup freestyle
*/
#pragma once
#include "../BPy_CurvePoint.h"
#include "../../../stroke/Stroke.h"
///////////////////////////////////////////////////////////////////////////////////////////
extern PyTypeObject StrokeVertex_Type;
#define BPy_StrokeVertex_Check(v) \
(PyObject_IsInstance((PyObject *)v, (PyObject *)&StrokeVertex_Type))
/*---------------------------Python BPy_StrokeVertex structure definition----------*/
struct BPy_StrokeVertex {
BPy_CurvePoint py_cp;
Freestyle::StrokeVertex *sv;
};
/*---------------------------Python BPy_StrokeVertex visible prototypes-----------*/
void StrokeVertex_mathutils_register_callback();
///////////////////////////////////////////////////////////////////////////////////////////

View File

@@ -0,0 +1,141 @@
/* SPDX-FileCopyrightText: 2004-2022 Blender Authors
*
* SPDX-License-Identifier: GPL-2.0-or-later */
/** \file
* \ingroup freestyle
*/
#include "BPy_NonTVertex.h"
#include "../../BPy_Convert.h"
#include "../BPy_SVertex.h"
using namespace Freestyle;
///////////////////////////////////////////////////////////////////////////////////////////
/*----------------------NonTVertex methods ----------------------------*/
PyDoc_STRVAR(
/* Wrap. */
NonTVertex_doc,
"Class hierarchy: :class:`Interface0D` > :class:`ViewVertex` > :class:`NonTVertex`\n"
"\n"
"View vertex for corners, cusps, etc. associated to a single SVertex.\n"
"Can be associated to 2 or more view edges.\n"
"\n"
".. method:: __init__(*args)\n"
"\n"
" Accepted call signatures:\n"
"\n"
" - ``__init__()``\n"
" - ``__init__(svertex)``\n"
"\n"
" Builds a :class:`NonTVertex` using the default constructor or a :class:`SVertex`.\n"
"\n"
" :param svertex: An SVertex object.\n"
" :type svertex: :class:`SVertex`\n");
/* NOTE: No copy constructor in Python because the C++ copy constructor is 'protected'. */
static int NonTVertex_init(BPy_NonTVertex *self, PyObject *args, PyObject *kwds)
{
static const char *kwlist[] = {"svertex", nullptr};
PyObject *obj = nullptr;
if (!PyArg_ParseTupleAndKeywords(args, kwds, "|O!", (char **)kwlist, &SVertex_Type, &obj)) {
return -1;
}
if (!obj) {
self->ntv = new NonTVertex();
}
else {
self->ntv = new NonTVertex(((BPy_SVertex *)obj)->sv);
}
self->py_vv.vv = self->ntv;
self->py_vv.py_if0D.if0D = self->ntv;
self->py_vv.py_if0D.borrowed = false;
return 0;
}
/*----------------------NonTVertex get/setters ----------------------------*/
PyDoc_STRVAR(
/* Wrap. */
NonTVertex_svertex_doc,
"The SVertex on top of which this NonTVertex is built.\n"
"\n"
":type: :class:`SVertex`\n");
static PyObject *NonTVertex_svertex_get(BPy_NonTVertex *self, void * /*closure*/)
{
SVertex *v = self->ntv->svertex();
if (v) {
return BPy_SVertex_from_SVertex(*v);
}
Py_RETURN_NONE;
}
static int NonTVertex_svertex_set(BPy_NonTVertex *self, PyObject *value, void * /*closure*/)
{
if (!BPy_SVertex_Check(value)) {
PyErr_SetString(PyExc_TypeError, "value must be an SVertex");
return -1;
}
self->ntv->setSVertex(((BPy_SVertex *)value)->sv);
return 0;
}
static PyGetSetDef BPy_NonTVertex_getseters[] = {
{"svertex",
(getter)NonTVertex_svertex_get,
(setter)NonTVertex_svertex_set,
NonTVertex_svertex_doc,
nullptr},
{nullptr, nullptr, nullptr, nullptr, nullptr} /* Sentinel */
};
/*-----------------------BPy_NonTVertex type definition ------------------------------*/
PyTypeObject NonTVertex_Type = {
/*ob_base*/ PyVarObject_HEAD_INIT(nullptr, 0)
/*tp_name*/ "NonTVertex",
/*tp_basicsize*/ sizeof(BPy_NonTVertex),
/*tp_itemsize*/ 0,
/*tp_dealloc*/ nullptr,
/*tp_vectorcall_offset*/ 0,
/*tp_getattr*/ nullptr,
/*tp_setattr*/ nullptr,
/*tp_as_async*/ nullptr,
/*tp_repr*/ nullptr,
/*tp_as_number*/ nullptr,
/*tp_as_sequence*/ nullptr,
/*tp_as_mapping*/ nullptr,
/*tp_hash*/ nullptr,
/*tp_call*/ nullptr,
/*tp_str*/ nullptr,
/*tp_getattro*/ nullptr,
/*tp_setattro*/ nullptr,
/*tp_as_buffer*/ nullptr,
/*tp_flags*/ Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE,
/*tp_doc*/ NonTVertex_doc,
/*tp_traverse*/ nullptr,
/*tp_clear*/ nullptr,
/*tp_richcompare*/ nullptr,
/*tp_weaklistoffset*/ 0,
/*tp_iter*/ nullptr,
/*tp_iternext*/ nullptr,
/*tp_methods*/ nullptr,
/*tp_members*/ nullptr,
/*tp_getset*/ BPy_NonTVertex_getseters,
/*tp_base*/ &ViewVertex_Type,
/*tp_dict*/ nullptr,
/*tp_descr_get*/ nullptr,
/*tp_descr_set*/ nullptr,
/*tp_dictoffset*/ 0,
/*tp_init*/ (initproc)NonTVertex_init,
/*tp_alloc*/ nullptr,
/*tp_new*/ nullptr,
};
///////////////////////////////////////////////////////////////////////////////////////////

View File

@@ -0,0 +1,27 @@
/* SPDX-FileCopyrightText: 2023 Blender Authors
*
* SPDX-License-Identifier: GPL-2.0-or-later */
/** \file
* \ingroup freestyle
*/
#pragma once
#include "../BPy_ViewVertex.h"
#include "../../../view_map/ViewMap.h"
///////////////////////////////////////////////////////////////////////////////////////////
extern PyTypeObject NonTVertex_Type;
#define BPy_NonTVertex_Check(v) (PyObject_IsInstance((PyObject *)v, (PyObject *)&NonTVertex_Type))
/*---------------------------Python BPy_NonTVertex structure definition----------*/
struct BPy_NonTVertex {
BPy_ViewVertex py_vv;
Freestyle::NonTVertex *ntv;
};
///////////////////////////////////////////////////////////////////////////////////////////

View File

@@ -0,0 +1,270 @@
/* SPDX-FileCopyrightText: 2004-2022 Blender Authors
*
* SPDX-License-Identifier: GPL-2.0-or-later */
/** \file
* \ingroup freestyle
*/
#include "BPy_TVertex.h"
#include "../../BPy_Convert.h"
#include "../../BPy_Id.h"
#include "../../Interface1D/BPy_FEdge.h"
#include "../../Interface1D/BPy_ViewEdge.h"
#include "../BPy_SVertex.h"
using namespace Freestyle;
///////////////////////////////////////////////////////////////////////////////////////////
/*----------------------TVertex methods ----------------------------*/
PyDoc_STRVAR(
/* Wrap. */
TVertex_doc,
"Class hierarchy: :class:`Interface0D` > :class:`ViewVertex` > :class:`TVertex`\n"
"\n"
"Class to define a T vertex, i.e. an intersection between two edges.\n"
"It points towards two SVertex and four ViewEdges. Among the\n"
"ViewEdges, two are front and the other two are back. Basically a\n"
"front edge hides part of a back edge. So, among the back edges, one\n"
"is of invisibility N and the other of invisibility N+1.\n"
"\n"
".. method:: __init__()\n"
"\n"
" Default constructor.\n");
/* NOTE: No copy constructor in Python because the C++ copy constructor is 'protected'. */
static int TVertex_init(BPy_TVertex *self, PyObject *args, PyObject *kwds)
{
static const char *kwlist[] = {nullptr};
if (!PyArg_ParseTupleAndKeywords(args, kwds, "", (char **)kwlist)) {
return -1;
}
self->tv = new TVertex();
self->py_vv.vv = self->tv;
self->py_vv.py_if0D.if0D = self->tv;
self->py_vv.py_if0D.borrowed = false;
return 0;
}
PyDoc_STRVAR(
/* Wrap. */
TVertex_get_svertex_doc,
".. method:: get_svertex(fedge)\n"
"\n"
" Returns the SVertex (among the 2) belonging to the given FEdge.\n"
"\n"
" :param fedge: An FEdge object.\n"
" :type fedge: :class:`FEdge`\n"
" :return: The SVertex belonging to the given FEdge.\n"
" :rtype: :class:`SVertex`\n");
static PyObject *TVertex_get_svertex(BPy_TVertex *self, PyObject *args, PyObject *kwds)
{
static const char *kwlist[] = {"fedge", nullptr};
PyObject *py_fe;
if (!PyArg_ParseTupleAndKeywords(args, kwds, "O!", (char **)kwlist, &FEdge_Type, &py_fe)) {
return nullptr;
}
SVertex *sv = self->tv->getSVertex(((BPy_FEdge *)py_fe)->fe);
if (sv) {
return BPy_SVertex_from_SVertex(*sv);
}
Py_RETURN_NONE;
}
PyDoc_STRVAR(
/* Wrap. */
TVertex_get_mate_doc,
".. method:: get_mate(viewedge)\n"
"\n"
" Returns the mate edge of the ViewEdge given as argument. If the\n"
" ViewEdge is frontEdgeA, frontEdgeB is returned. If the ViewEdge is\n"
" frontEdgeB, frontEdgeA is returned. Same for back edges.\n"
"\n"
" :param viewedge: A ViewEdge object.\n"
" :type viewedge: :class:`ViewEdge`\n"
" :return: The mate edge of the given ViewEdge.\n"
" :rtype: :class:`ViewEdge`\n");
static PyObject *TVertex_get_mate(BPy_TVertex *self, PyObject *args, PyObject *kwds)
{
static const char *kwlist[] = {"viewedge", nullptr};
PyObject *py_ve;
if (!PyArg_ParseTupleAndKeywords(args, kwds, "O!", (char **)kwlist, &ViewEdge_Type, &py_ve)) {
return nullptr;
}
ViewEdge *ve = self->tv->mate(((BPy_ViewEdge *)py_ve)->ve);
if (ve) {
return BPy_ViewEdge_from_ViewEdge(*ve);
}
Py_RETURN_NONE;
}
#ifdef __GNUC__
# ifdef __clang__
# pragma clang diagnostic push
# pragma clang diagnostic ignored "-Wcast-function-type"
# else
# pragma GCC diagnostic push
# pragma GCC diagnostic ignored "-Wcast-function-type"
# endif
#endif
static PyMethodDef BPy_TVertex_methods[] = {
{"get_svertex",
(PyCFunction)TVertex_get_svertex,
METH_VARARGS | METH_KEYWORDS,
TVertex_get_svertex_doc},
{"get_mate",
(PyCFunction)TVertex_get_mate,
METH_VARARGS | METH_KEYWORDS,
TVertex_get_mate_doc},
{nullptr, nullptr, 0, nullptr},
};
#ifdef __GNUC__
# ifdef __clang__
# pragma clang diagnostic pop
# else
# pragma GCC diagnostic pop
# endif
#endif
/*----------------------TVertex get/setters ----------------------------*/
PyDoc_STRVAR(
/* Wrap. */
TVertex_front_svertex_doc,
"The SVertex that is closer to the viewpoint.\n"
"\n"
":type: :class:`SVertex`\n");
static PyObject *TVertex_front_svertex_get(BPy_TVertex *self, void * /*closure*/)
{
SVertex *v = self->tv->frontSVertex();
if (v) {
return BPy_SVertex_from_SVertex(*v);
}
Py_RETURN_NONE;
}
static int TVertex_front_svertex_set(BPy_TVertex *self, PyObject *value, void * /*closure*/)
{
if (!BPy_SVertex_Check(value)) {
PyErr_SetString(PyExc_TypeError, "value must be an SVertex");
return -1;
}
self->tv->setFrontSVertex(((BPy_SVertex *)value)->sv);
return 0;
}
PyDoc_STRVAR(
/* Wrap. */
TVertex_back_svertex_doc,
"The SVertex that is further away from the viewpoint.\n"
"\n"
":type: :class:`SVertex`\n");
static PyObject *TVertex_back_svertex_get(BPy_TVertex *self, void * /*closure*/)
{
SVertex *v = self->tv->backSVertex();
if (v) {
return BPy_SVertex_from_SVertex(*v);
}
Py_RETURN_NONE;
}
static int TVertex_back_svertex_set(BPy_TVertex *self, PyObject *value, void * /*closure*/)
{
if (!BPy_SVertex_Check(value)) {
PyErr_SetString(PyExc_TypeError, "value must be an SVertex");
return -1;
}
self->tv->setBackSVertex(((BPy_SVertex *)value)->sv);
return 0;
}
PyDoc_STRVAR(
/* Wrap. */
TVertex_id_doc,
"The Id of this TVertex.\n"
"\n"
":type: :class:`Id`\n");
static PyObject *TVertex_id_get(BPy_TVertex *self, void * /*closure*/)
{
Id id(self->tv->getId());
return BPy_Id_from_Id(id); // return a copy
}
static int TVertex_id_set(BPy_TVertex *self, PyObject *value, void * /*closure*/)
{
if (!BPy_Id_Check(value)) {
PyErr_SetString(PyExc_TypeError, "value must be an Id");
return -1;
}
self->tv->setId(*(((BPy_Id *)value)->id));
return 0;
}
static PyGetSetDef BPy_TVertex_getseters[] = {
{"front_svertex",
(getter)TVertex_front_svertex_get,
(setter)TVertex_front_svertex_set,
TVertex_front_svertex_doc,
nullptr},
{"back_svertex",
(getter)TVertex_back_svertex_get,
(setter)TVertex_back_svertex_set,
TVertex_back_svertex_doc,
nullptr},
{"id", (getter)TVertex_id_get, (setter)TVertex_id_set, TVertex_id_doc, nullptr},
{nullptr, nullptr, nullptr, nullptr, nullptr} /* Sentinel */
};
/*-----------------------BPy_TVertex type definition ------------------------------*/
PyTypeObject TVertex_Type = {
/*ob_base*/ PyVarObject_HEAD_INIT(nullptr, 0)
/*tp_name*/ "TVertex",
/*tp_basicsize*/ sizeof(BPy_TVertex),
/*tp_itemsize*/ 0,
/*tp_dealloc*/ nullptr,
/*tp_vectorcall_offset*/ 0,
/*tp_getattr*/ nullptr,
/*tp_setattr*/ nullptr,
/*tp_as_async*/ nullptr,
/*tp_repr*/ nullptr,
/*tp_as_number*/ nullptr,
/*tp_as_sequence*/ nullptr,
/*tp_as_mapping*/ nullptr,
/*tp_hash*/ nullptr,
/*tp_call*/ nullptr,
/*tp_str*/ nullptr,
/*tp_getattro*/ nullptr,
/*tp_setattro*/ nullptr,
/*tp_as_buffer*/ nullptr,
/*tp_flags*/ Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE,
/*tp_doc*/ TVertex_doc,
/*tp_traverse*/ nullptr,
/*tp_clear*/ nullptr,
/*tp_richcompare*/ nullptr,
/*tp_weaklistoffset*/ 0,
/*tp_iter*/ nullptr,
/*tp_iternext*/ nullptr,
/*tp_methods*/ BPy_TVertex_methods,
/*tp_members*/ nullptr,
/*tp_getset*/ BPy_TVertex_getseters,
/*tp_base*/ &ViewVertex_Type,
/*tp_dict*/ nullptr,
/*tp_descr_get*/ nullptr,
/*tp_descr_set*/ nullptr,
/*tp_dictoffset*/ 0,
/*tp_init*/ (initproc)TVertex_init,
/*tp_alloc*/ nullptr,
/*tp_new*/ nullptr,
};
///////////////////////////////////////////////////////////////////////////////////////////

View File

@@ -0,0 +1,27 @@
/* SPDX-FileCopyrightText: 2023 Blender Authors
*
* SPDX-License-Identifier: GPL-2.0-or-later */
/** \file
* \ingroup freestyle
*/
#pragma once
#include "../BPy_ViewVertex.h"
#include "../../../view_map/ViewMap.h"
///////////////////////////////////////////////////////////////////////////////////////////
extern PyTypeObject TVertex_Type;
#define BPy_TVertex_Check(v) (PyObject_IsInstance((PyObject *)v, (PyObject *)&TVertex_Type))
/*---------------------------Python BPy_TVertex structure definition----------*/
struct BPy_TVertex {
BPy_ViewVertex py_vv;
Freestyle::TVertex *tv;
};
///////////////////////////////////////////////////////////////////////////////////////////

View File

@@ -0,0 +1,391 @@
/* SPDX-FileCopyrightText: 2004-2023 Blender Authors
*
* SPDX-License-Identifier: GPL-2.0-or-later */
/** \file
* \ingroup freestyle
*/
#include "BPy_FEdge.h"
#include "../BPy_Convert.h"
#include "../BPy_Id.h"
#include "../BPy_Nature.h"
#include "../Interface0D/BPy_SVertex.h"
#include "../Interface1D/BPy_ViewEdge.h"
using namespace Freestyle;
///////////////////////////////////////////////////////////////////////////////////////////
/*----------------------FEdge methods ----------------------------*/
PyDoc_STRVAR(
/* Wrap. */
FEdge_doc,
"Class hierarchy: :class:`Interface1D` > :class:`FEdge`\n"
"\n"
"Base Class for feature edges. This FEdge can represent a silhouette,\n"
"a crease, a ridge/valley, a border or a suggestive contour. For\n"
"silhouettes, the FEdge is oriented so that the visible face lies on\n"
"the left of the edge. For borders, the FEdge is oriented so that the\n"
"face lies on the left of the edge. An FEdge can represent an initial\n"
"edge of the mesh or runs across a face of the initial mesh depending\n"
"on the smoothness or sharpness of the mesh. This class is specialized\n"
"into a smooth and a sharp version since their properties slightly vary\n"
"from one to the other.\n"
"\n"
".. method:: FEdge(*args)\n"
"\n"
" Accepted call signatures:\n"
"\n"
" - ``FEdge()``\n"
" - ``FEdge(brother)``\n"
"\n"
" Builds an :class:`FEdge` using the default constructor,\n"
" copy constructor, or between two :class:`SVertex` objects.\n"
"\n"
" :param brother: An FEdge object.\n"
" :type brother: :class:`FEdge`\n"
" :param first_vertex: The first SVertex.\n"
" :type first_vertex: :class:`SVertex`\n"
" :param second_vertex: The second SVertex.\n"
" :type second_vertex: :class:`SVertex`\n");
static int FEdge_init(BPy_FEdge *self, PyObject *args, PyObject *kwds)
{
static const char *kwlist_1[] = {"brother", nullptr};
static const char *kwlist_2[] = {"first_vertex", "second_vertex", nullptr};
PyObject *obj1 = nullptr, *obj2 = nullptr;
if (PyArg_ParseTupleAndKeywords(args, kwds, "|O!", (char **)kwlist_1, &FEdge_Type, &obj1)) {
if (!obj1) {
self->fe = new FEdge();
}
else {
self->fe = new FEdge(*(((BPy_FEdge *)obj1)->fe));
}
}
else if ((void)PyErr_Clear(),
PyArg_ParseTupleAndKeywords(
args, kwds, "O!O!", (char **)kwlist_2, &SVertex_Type, &obj1, &SVertex_Type, &obj2))
{
self->fe = new FEdge(((BPy_SVertex *)obj1)->sv, ((BPy_SVertex *)obj2)->sv);
}
else {
PyErr_SetString(PyExc_TypeError, "invalid argument(s)");
return -1;
}
self->py_if1D.if1D = self->fe;
self->py_if1D.borrowed = false;
return 0;
}
/*----------------------FEdge sequence protocol ----------------------------*/
static Py_ssize_t FEdge_sq_length(BPy_FEdge * /*self*/)
{
return 2;
}
static PyObject *FEdge_sq_item(BPy_FEdge *self, Py_ssize_t keynum)
{
if (keynum < 0) {
keynum += FEdge_sq_length(self);
}
if (ELEM(keynum, 0, 1)) {
SVertex *v = self->fe->operator[](keynum);
if (v) {
return BPy_SVertex_from_SVertex(*v);
}
Py_RETURN_NONE;
}
PyErr_Format(PyExc_IndexError, "FEdge[index]: index %d out of range", keynum);
return nullptr;
}
static PySequenceMethods BPy_FEdge_as_sequence = {
/*sq_length*/ (lenfunc)FEdge_sq_length,
/*sq_concat*/ nullptr,
/*sq_repeat*/ nullptr,
/*sq_item*/ (ssizeargfunc)FEdge_sq_item,
/*was_sq_slice*/ nullptr, /* DEPRECATED. */
/*sq_ass_item*/ nullptr,
/*was_sq_ass_slice*/ nullptr, /* DEPRECATED. */
/*sq_contains*/ nullptr,
/*sq_inplace_concat*/ nullptr,
/*sq_inplace_repeat*/ nullptr,
};
/*----------------------FEdge get/setters ----------------------------*/
PyDoc_STRVAR(
/* Wrap. */
FEdge_first_svertex_doc,
"The first SVertex constituting this FEdge.\n"
"\n"
":type: :class:`SVertex`\n");
static PyObject *FEdge_first_svertex_get(BPy_FEdge *self, void * /*closure*/)
{
SVertex *A = self->fe->vertexA();
if (A) {
return BPy_SVertex_from_SVertex(*A);
}
Py_RETURN_NONE;
}
static int FEdge_first_svertex_set(BPy_FEdge *self, PyObject *value, void * /*closure*/)
{
if (!BPy_SVertex_Check(value)) {
PyErr_SetString(PyExc_TypeError, "value must be an SVertex");
return -1;
}
self->fe->setVertexA(((BPy_SVertex *)value)->sv);
return 0;
}
PyDoc_STRVAR(
/* Wrap. */
FEdge_second_svertex_doc,
"The second SVertex constituting this FEdge.\n"
"\n"
":type: :class:`SVertex`\n");
static PyObject *FEdge_second_svertex_get(BPy_FEdge *self, void * /*closure*/)
{
SVertex *B = self->fe->vertexB();
if (B) {
return BPy_SVertex_from_SVertex(*B);
}
Py_RETURN_NONE;
}
static int FEdge_second_svertex_set(BPy_FEdge *self, PyObject *value, void * /*closure*/)
{
if (!BPy_SVertex_Check(value)) {
PyErr_SetString(PyExc_TypeError, "value must be an SVertex");
return -1;
}
self->fe->setVertexB(((BPy_SVertex *)value)->sv);
return 0;
}
PyDoc_STRVAR(
/* Wrap. */
FEdge_next_fedge_doc,
"The FEdge following this one in the ViewEdge. The value is None if\n"
"this FEdge is the last of the ViewEdge.\n"
"\n"
":type: :class:`FEdge`\n");
static PyObject *FEdge_next_fedge_get(BPy_FEdge *self, void * /*closure*/)
{
FEdge *fe = self->fe->nextEdge();
if (fe) {
return Any_BPy_FEdge_from_FEdge(*fe);
}
Py_RETURN_NONE;
}
static int FEdge_next_fedge_set(BPy_FEdge *self, PyObject *value, void * /*closure*/)
{
if (!BPy_FEdge_Check(value)) {
PyErr_SetString(PyExc_TypeError, "value must be an FEdge");
return -1;
}
self->fe->setNextEdge(((BPy_FEdge *)value)->fe);
return 0;
}
PyDoc_STRVAR(
/* Wrap. */
FEdge_previous_fedge_doc,
"The FEdge preceding this one in the ViewEdge. The value is None if\n"
"this FEdge is the first one of the ViewEdge.\n"
"\n"
":type: :class:`FEdge`\n");
static PyObject *FEdge_previous_fedge_get(BPy_FEdge *self, void * /*closure*/)
{
FEdge *fe = self->fe->previousEdge();
if (fe) {
return Any_BPy_FEdge_from_FEdge(*fe);
}
Py_RETURN_NONE;
}
static int FEdge_previous_fedge_set(BPy_FEdge *self, PyObject *value, void * /*closure*/)
{
if (!BPy_FEdge_Check(value)) {
PyErr_SetString(PyExc_TypeError, "value must be an FEdge");
return -1;
}
self->fe->setPreviousEdge(((BPy_FEdge *)value)->fe);
return 0;
}
PyDoc_STRVAR(
/* Wrap. */
FEdge_viewedge_doc,
"The ViewEdge to which this FEdge belongs to.\n"
"\n"
":type: :class:`ViewEdge`\n");
static PyObject *FEdge_viewedge_get(BPy_FEdge *self, void * /*closure*/)
{
ViewEdge *ve = self->fe->viewedge();
if (ve) {
return BPy_ViewEdge_from_ViewEdge(*ve);
}
Py_RETURN_NONE;
}
static int FEdge_viewedge_set(BPy_FEdge *self, PyObject *value, void * /*closure*/)
{
if (!BPy_ViewEdge_Check(value)) {
PyErr_SetString(PyExc_TypeError, "value must be an ViewEdge");
return -1;
}
self->fe->setViewEdge(((BPy_ViewEdge *)value)->ve);
return 0;
}
PyDoc_STRVAR(
/* Wrap. */
FEdge_is_smooth_doc,
"True if this FEdge is a smooth FEdge.\n"
"\n"
":type: bool\n");
static PyObject *FEdge_is_smooth_get(BPy_FEdge *self, void * /*closure*/)
{
return PyBool_from_bool(self->fe->isSmooth());
}
static int FEdge_is_smooth_set(BPy_FEdge *self, PyObject *value, void * /*closure*/)
{
if (!PyBool_Check(value)) {
PyErr_SetString(PyExc_TypeError, "value must be boolean");
return -1;
}
self->fe->setSmooth(bool_from_PyBool(value));
return 0;
}
PyDoc_STRVAR(
/* Wrap. */
FEdge_id_doc,
"The Id of this FEdge.\n"
"\n"
":type: :class:`Id`\n");
static PyObject *FEdge_id_get(BPy_FEdge *self, void * /*closure*/)
{
Id id(self->fe->getId());
return BPy_Id_from_Id(id); // return a copy
}
static int FEdge_id_set(BPy_FEdge *self, PyObject *value, void * /*closure*/)
{
if (!BPy_Id_Check(value)) {
PyErr_SetString(PyExc_TypeError, "value must be an Id");
return -1;
}
self->fe->setId(*(((BPy_Id *)value)->id));
return 0;
}
PyDoc_STRVAR(
/* Wrap. */
FEdge_nature_doc,
"The nature of this FEdge.\n"
"\n"
":type: :class:`Nature`\n");
static PyObject *FEdge_nature_get(BPy_FEdge *self, void * /*closure*/)
{
return BPy_Nature_from_Nature(self->fe->getNature());
}
static int FEdge_nature_set(BPy_FEdge *self, PyObject *value, void * /*closure*/)
{
if (!BPy_Nature_Check(value)) {
PyErr_SetString(PyExc_TypeError, "value must be a Nature");
return -1;
}
self->fe->setNature(PyLong_AsLong((PyObject *)&((BPy_Nature *)value)->i));
return 0;
}
static PyGetSetDef BPy_FEdge_getseters[] = {
{"first_svertex",
(getter)FEdge_first_svertex_get,
(setter)FEdge_first_svertex_set,
FEdge_first_svertex_doc,
nullptr},
{"second_svertex",
(getter)FEdge_second_svertex_get,
(setter)FEdge_second_svertex_set,
FEdge_second_svertex_doc,
nullptr},
{"next_fedge",
(getter)FEdge_next_fedge_get,
(setter)FEdge_next_fedge_set,
FEdge_next_fedge_doc,
nullptr},
{"previous_fedge",
(getter)FEdge_previous_fedge_get,
(setter)FEdge_previous_fedge_set,
FEdge_previous_fedge_doc,
nullptr},
{"viewedge",
(getter)FEdge_viewedge_get,
(setter)FEdge_viewedge_set,
FEdge_viewedge_doc,
nullptr},
{"is_smooth",
(getter)FEdge_is_smooth_get,
(setter)FEdge_is_smooth_set,
FEdge_is_smooth_doc,
nullptr},
{"id", (getter)FEdge_id_get, (setter)FEdge_id_set, FEdge_id_doc, nullptr},
{"nature", (getter)FEdge_nature_get, (setter)FEdge_nature_set, FEdge_nature_doc, nullptr},
{nullptr, nullptr, nullptr, nullptr, nullptr} /* Sentinel */
};
/*-----------------------BPy_FEdge type definition ------------------------------*/
PyTypeObject FEdge_Type = {
/*ob_base*/ PyVarObject_HEAD_INIT(nullptr, 0)
/*tp_name*/ "FEdge",
/*tp_basicsize*/ sizeof(BPy_FEdge),
/*tp_itemsize*/ 0,
/*tp_dealloc*/ nullptr,
/*tp_vectorcall_offset*/ 0,
/*tp_getattr*/ nullptr,
/*tp_setattr*/ nullptr,
/*tp_as_async*/ nullptr,
/*tp_repr*/ nullptr,
/*tp_as_number*/ nullptr,
/*tp_as_sequence*/ &BPy_FEdge_as_sequence,
/*tp_as_mapping*/ nullptr,
/*tp_hash*/ nullptr,
/*tp_call*/ nullptr,
/*tp_str*/ nullptr,
/*tp_getattro*/ nullptr,
/*tp_setattro*/ nullptr,
/*tp_as_buffer*/ nullptr,
/*tp_flags*/ Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE,
/*tp_doc*/ FEdge_doc,
/*tp_traverse*/ nullptr,
/*tp_clear*/ nullptr,
/*tp_richcompare*/ nullptr,
/*tp_weaklistoffset*/ 0,
/*tp_iter*/ nullptr,
/*tp_iternext*/ nullptr,
/*tp_methods*/ nullptr,
/*tp_members*/ nullptr,
/*tp_getset*/ BPy_FEdge_getseters,
/*tp_base*/ &Interface1D_Type,
/*tp_dict*/ nullptr,
/*tp_descr_get*/ nullptr,
/*tp_descr_set*/ nullptr,
/*tp_dictoffset*/ 0,
/*tp_init*/ (initproc)FEdge_init,
/*tp_alloc*/ nullptr,
/*tp_new*/ nullptr,
};
///////////////////////////////////////////////////////////////////////////////////////////

View File

@@ -0,0 +1,27 @@
/* SPDX-FileCopyrightText: 2023 Blender Authors
*
* SPDX-License-Identifier: GPL-2.0-or-later */
/** \file
* \ingroup freestyle
*/
#pragma once
#include "../BPy_Interface1D.h"
#include "../../view_map/Silhouette.h"
///////////////////////////////////////////////////////////////////////////////////////////
extern PyTypeObject FEdge_Type;
#define BPy_FEdge_Check(v) (PyObject_IsInstance((PyObject *)v, (PyObject *)&FEdge_Type))
/*---------------------------Python BPy_FEdge structure definition----------*/
struct BPy_FEdge {
BPy_Interface1D py_if1D;
Freestyle::FEdge *fe;
};
///////////////////////////////////////////////////////////////////////////////////////////

View File

@@ -0,0 +1,243 @@
/* SPDX-FileCopyrightText: 2004-2023 Blender Authors
*
* SPDX-License-Identifier: GPL-2.0-or-later */
/** \file
* \ingroup freestyle
*/
#include "BPy_FrsCurve.h"
#include "../BPy_Convert.h"
#include "../BPy_Id.h"
#include "../Interface0D/BPy_CurvePoint.h"
#include "../Interface0D/BPy_SVertex.h"
using namespace Freestyle;
///////////////////////////////////////////////////////////////////////////////////////////
/*----------------------CurvePoint methods ----------------------------*/
PyDoc_STRVAR(
/* Wrap. */
FrsCurve_doc,
"Class hierarchy: :class:`Interface1D` > :class:`Curve`\n"
"\n"
"Base class for curves made of CurvePoints. :class:`SVertex` is the\n"
"type of the initial curve vertices. A :class:`Chain` is a\n"
"specialization of a Curve.\n"
"\n"
".. method:: __init__(*args)\n"
"\n"
" Accepted call signatures:\n"
"\n"
" - ``__init__()``\n"
" - ``__init__(brother)``\n"
" - ``__init__(id)``\n"
"\n"
" Builds a :class:`FrsCurve` using a default constructor,\n"
" copy constructor or from an :class:`Id`.\n"
"\n"
" :param brother: A Curve object.\n"
" :type brother: :class:`Curve`\n"
" :param id: An Id object.\n"
" :type id: :class:`Id`\n");
static int FrsCurve_init(BPy_FrsCurve *self, PyObject *args, PyObject *kwds)
{
static const char *kwlist_1[] = {"brother", nullptr};
static const char *kwlist_2[] = {"id", nullptr};
PyObject *obj = nullptr;
if (PyArg_ParseTupleAndKeywords(args, kwds, "|O!", (char **)kwlist_1, &FrsCurve_Type, &obj)) {
if (!obj) {
self->c = new Curve();
}
else {
self->c = new Curve(*(((BPy_FrsCurve *)obj)->c));
}
}
else if ((void)PyErr_Clear(),
PyArg_ParseTupleAndKeywords(args, kwds, "O!", (char **)kwlist_2, &Id_Type, &obj))
{
self->c = new Curve(*(((BPy_Id *)obj)->id));
}
else {
PyErr_SetString(PyExc_TypeError, "invalid argument(s)");
return -1;
}
self->py_if1D.if1D = self->c;
self->py_if1D.borrowed = false;
return 0;
}
PyDoc_STRVAR(
/* Wrap. */
FrsCurve_push_vertex_back_doc,
".. method:: push_vertex_back(vertex)\n"
"\n"
" Adds a single vertex at the end of the Curve.\n"
"\n"
" :param vertex: A vertex object.\n"
" :type vertex: :class:`SVertex` | :class:`CurvePoint`\n");
static PyObject *FrsCurve_push_vertex_back(BPy_FrsCurve *self, PyObject *args, PyObject *kwds)
{
static const char *kwlist[] = {"vertex", nullptr};
PyObject *obj = nullptr;
if (!PyArg_ParseTupleAndKeywords(args, kwds, "O", (char **)kwlist, &obj)) {
return nullptr;
}
if (BPy_CurvePoint_Check(obj)) {
self->c->push_vertex_back(((BPy_CurvePoint *)obj)->cp);
}
else if (BPy_SVertex_Check(obj)) {
self->c->push_vertex_back(((BPy_SVertex *)obj)->sv);
}
else {
PyErr_SetString(PyExc_TypeError, "invalid argument");
return nullptr;
}
Py_RETURN_NONE;
}
PyDoc_STRVAR(
/* Wrap. */
FrsCurve_push_vertex_front_doc,
".. method:: push_vertex_front(vertex)\n"
"\n"
" Adds a single vertex at the front of the Curve.\n"
"\n"
" :param vertex: A vertex object.\n"
" :type vertex: :class:`SVertex` | :class:`CurvePoint`\n");
static PyObject *FrsCurve_push_vertex_front(BPy_FrsCurve *self, PyObject *args, PyObject *kwds)
{
static const char *kwlist[] = {"vertex", nullptr};
PyObject *obj = nullptr;
if (!PyArg_ParseTupleAndKeywords(args, kwds, "O", (char **)kwlist, &obj)) {
return nullptr;
}
if (BPy_CurvePoint_Check(obj)) {
self->c->push_vertex_front(((BPy_CurvePoint *)obj)->cp);
}
else if (BPy_SVertex_Check(obj)) {
self->c->push_vertex_front(((BPy_SVertex *)obj)->sv);
}
else {
PyErr_SetString(PyExc_TypeError, "invalid argument");
return nullptr;
}
Py_RETURN_NONE;
}
#ifdef __GNUC__
# ifdef __clang__
# pragma clang diagnostic push
# pragma clang diagnostic ignored "-Wcast-function-type"
# else
# pragma GCC diagnostic push
# pragma GCC diagnostic ignored "-Wcast-function-type"
# endif
#endif
static PyMethodDef BPy_FrsCurve_methods[] = {
{"push_vertex_back",
(PyCFunction)FrsCurve_push_vertex_back,
METH_VARARGS | METH_KEYWORDS,
FrsCurve_push_vertex_back_doc},
{"push_vertex_front",
(PyCFunction)FrsCurve_push_vertex_front,
METH_VARARGS | METH_KEYWORDS,
FrsCurve_push_vertex_front_doc},
{nullptr, nullptr, 0, nullptr},
};
#ifdef __GNUC__
# ifdef __clang__
# pragma clang diagnostic pop
# else
# pragma GCC diagnostic pop
# endif
#endif
/*----------------------CurvePoint get/setters ----------------------------*/
PyDoc_STRVAR(
/* Wrap. */
FrsCurve_is_empty_doc,
"True if the Curve doesn't have any Vertex yet.\n"
"\n"
":type: bool\n");
static PyObject *FrsCurve_is_empty_get(BPy_FrsCurve *self, void * /*closure*/)
{
return PyBool_from_bool(self->c->empty());
}
PyDoc_STRVAR(
/* Wrap. */
FrsCurve_segments_size_doc,
"The number of segments in the polyline constituting the Curve.\n"
"\n"
":type: int\n");
static PyObject *FrsCurve_segments_size_get(BPy_FrsCurve *self, void * /*closure*/)
{
return PyLong_FromLong(self->c->nSegments());
}
static PyGetSetDef BPy_FrsCurve_getseters[] = {
{"is_empty", (getter)FrsCurve_is_empty_get, (setter) nullptr, FrsCurve_is_empty_doc, nullptr},
{"segments_size",
(getter)FrsCurve_segments_size_get,
(setter) nullptr,
FrsCurve_segments_size_doc,
nullptr},
{nullptr, nullptr, nullptr, nullptr, nullptr} /* Sentinel */
};
/*-----------------------BPy_FrsCurve type definition ------------------------------*/
PyTypeObject FrsCurve_Type = {
/*ob_base*/ PyVarObject_HEAD_INIT(nullptr, 0)
/*tp_name*/ "Curve",
/*tp_basicsize*/ sizeof(BPy_FrsCurve),
/*tp_itemsize*/ 0,
/*tp_dealloc*/ nullptr,
/*tp_vectorcall_offset*/ 0,
/*tp_getattr*/ nullptr,
/*tp_setattr*/ nullptr,
/*tp_as_async*/ nullptr,
/*tp_repr*/ nullptr,
/*tp_as_number*/ nullptr,
/*tp_as_sequence*/ nullptr,
/*tp_as_mapping*/ nullptr,
/*tp_hash*/ nullptr,
/*tp_call*/ nullptr,
/*tp_str*/ nullptr,
/*tp_getattro*/ nullptr,
/*tp_setattro*/ nullptr,
/*tp_as_buffer*/ nullptr,
/*tp_flags*/ Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE,
/*tp_doc*/ FrsCurve_doc,
/*tp_traverse*/ nullptr,
/*tp_clear*/ nullptr,
/*tp_richcompare*/ nullptr,
/*tp_weaklistoffset*/ 0,
/*tp_iter*/ nullptr,
/*tp_iternext*/ nullptr,
/*tp_methods*/ BPy_FrsCurve_methods,
/*tp_members*/ nullptr,
/*tp_getset*/ BPy_FrsCurve_getseters,
/*tp_base*/ &Interface1D_Type,
/*tp_dict*/ nullptr,
/*tp_descr_get*/ nullptr,
/*tp_descr_set*/ nullptr,
/*tp_dictoffset*/ 0,
/*tp_init*/ (initproc)FrsCurve_init,
/*tp_alloc*/ nullptr,
/*tp_new*/ nullptr,
};
///////////////////////////////////////////////////////////////////////////////////////////

View File

@@ -0,0 +1,27 @@
/* SPDX-FileCopyrightText: 2023 Blender Authors
*
* SPDX-License-Identifier: GPL-2.0-or-later */
/** \file
* \ingroup freestyle
*/
#pragma once
#include "../BPy_Interface1D.h"
#include "../../stroke/Curve.h"
///////////////////////////////////////////////////////////////////////////////////////////
extern PyTypeObject FrsCurve_Type;
#define BPy_FrsCurve_Check(v) (PyObject_IsInstance((PyObject *)v, (PyObject *)&FrsCurve_Type))
/*---------------------------Python BPy_FrsCurve structure definition----------*/
struct BPy_FrsCurve {
BPy_Interface1D py_if1D;
Freestyle::Curve *c;
};
///////////////////////////////////////////////////////////////////////////////////////////

View File

@@ -0,0 +1,572 @@
/* SPDX-FileCopyrightText: 2004-2023 Blender Authors
*
* SPDX-License-Identifier: GPL-2.0-or-later */
/** \file
* \ingroup freestyle
*/
#include "BPy_Stroke.h"
#include "../BPy_Convert.h"
#include "../BPy_Id.h"
#include "../BPy_MediumType.h"
#include "../Interface0D/BPy_SVertex.h"
#include "../Interface0D/CurvePoint/BPy_StrokeVertex.h"
#include "../Iterator/BPy_StrokeVertexIterator.h"
#include "BLI_sys_types.h"
using namespace Freestyle;
///////////////////////////////////////////////////////////////////////////////////////////
/*----------------------Stroke methods ----------------------------*/
// Stroke ()
// template<class InputVertexIterator> Stroke (InputVertexIterator begin, InputVertexIterator end)
//
// pb: - need to be able to switch representation: InputVertexIterator <=> position
// - is it even used ? not even in SWIG version
PyDoc_STRVAR(
/* Wrap. */
Stroke_doc,
"Class hierarchy: :class:`Interface1D` > :class:`Stroke`\n"
"\n"
"Class to define a stroke. A stroke is made of a set of 2D vertices\n"
"(:class:`StrokeVertex`), regularly spaced out. This set of vertices\n"
"defines the stroke's backbone geometry. Each of these stroke vertices\n"
"defines the stroke's shape and appearance at this vertex position.\n"
"\n"
".. method:: Stroke(*args)\n"
"\n"
" Accepted call signatures:\n"
"\n"
" - ``Stroke()``\n"
" - ``Stroke(brother)``\n"
"\n"
" Creates a :class:`Stroke` using the default constructor or copy constructor\n");
static int Stroke_init(BPy_Stroke *self, PyObject *args, PyObject *kwds)
{
static const char *kwlist[] = {"brother", nullptr};
PyObject *brother = nullptr;
if (!PyArg_ParseTupleAndKeywords(args, kwds, "|O!", (char **)kwlist, &Stroke_Type, &brother)) {
return -1;
}
if (!brother) {
self->s = new Stroke();
}
else {
self->s = new Stroke(*(((BPy_Stroke *)brother)->s));
}
self->py_if1D.if1D = self->s;
self->py_if1D.borrowed = false;
return 0;
}
static PyObject *Stroke_iter(PyObject *self)
{
StrokeInternal::StrokeVertexIterator sv_it(((BPy_Stroke *)self)->s->strokeVerticesBegin());
return BPy_StrokeVertexIterator_from_StrokeVertexIterator(sv_it, false);
}
static Py_ssize_t Stroke_sq_length(BPy_Stroke *self)
{
return self->s->strokeVerticesSize();
}
static PyObject *Stroke_sq_item(BPy_Stroke *self, Py_ssize_t keynum)
{
if (keynum < 0) {
keynum += Stroke_sq_length(self);
}
if (keynum < 0 || keynum >= Stroke_sq_length(self)) {
PyErr_Format(PyExc_IndexError, "Stroke[index]: index %d out of range", keynum);
return nullptr;
}
return BPy_StrokeVertex_from_StrokeVertex(self->s->strokeVerticeAt(keynum));
}
PyDoc_STRVAR(
/* Wrap. */
Stroke_compute_sampling_doc,
".. method:: compute_sampling(n)\n"
"\n"
" Compute the sampling needed to get N vertices. If the\n"
" specified number of vertices is less than the actual number of\n"
" vertices, the actual sampling value is returned. (To remove Vertices,\n"
" use the RemoveVertex() method of this class.)\n"
"\n"
" :param n: The number of stroke vertices we eventually want\n"
" in our Stroke.\n"
" :type n: int\n"
" :return: The sampling that must be used in the Resample(float)\n"
" method.\n"
" :rtype: float\n");
static PyObject *Stroke_compute_sampling(BPy_Stroke *self, PyObject *args, PyObject *kwds)
{
static const char *kwlist[] = {"n", nullptr};
int i;
if (!PyArg_ParseTupleAndKeywords(args, kwds, "i", (char **)kwlist, &i)) {
return nullptr;
}
return PyFloat_FromDouble(self->s->ComputeSampling(i));
}
PyDoc_STRVAR(
/* Wrap. */
Stroke_resample_doc,
".. method:: resample(*args)\n"
"\n"
" Accepted call signatures:\n"
"\n"
" - ``resample(n)``\n"
" - ``resample(sampling)``\n"
"\n"
" Resamples the stroke so using one of two methods with the goal\n"
" of creating a stroke with fewer points and the same shape.\n"
"\n"
" :param n: Resamples the stroke so that it eventually has N points. That means\n"
" it is going to add N-vertices_size, where vertices_size is the\n"
" number of points we already have. If vertices_size >= N, no\n"
" resampling is done.\n"
" :type n: int\n"
" :param sampling: Resamples the stroke with a given sampling value. If the\n"
" sampling is smaller than the actual sampling value, no resampling is done.\n"
" :type sampling: float\n");
static PyObject *Stroke_resample(BPy_Stroke *self, PyObject *args, PyObject *kwds)
{
static const char *kwlist_1[] = {"n", nullptr};
static const char *kwlist_2[] = {"sampling", nullptr};
int i;
float f;
if (PyArg_ParseTupleAndKeywords(args, kwds, "i", (char **)kwlist_1, &i)) {
if (self->s->Resample(i) < 0) {
PyErr_SetString(PyExc_RuntimeError, "Stroke resampling (by vertex count) failed");
return nullptr;
}
}
else if ((void)PyErr_Clear(),
PyArg_ParseTupleAndKeywords(args, kwds, "f", (char **)kwlist_2, &f))
{
if (self->s->Resample(f) < 0) {
PyErr_SetString(PyExc_RuntimeError, "Stroke resampling (by vertex interval) failed");
return nullptr;
}
}
else {
PyErr_SetString(PyExc_TypeError, "invalid argument");
return nullptr;
}
Py_RETURN_NONE;
}
PyDoc_STRVAR(
/* Wrap. */
Stroke_insert_vertex_doc,
".. method:: insert_vertex(vertex, next)\n"
"\n"
" Inserts the StrokeVertex given as argument into the Stroke before the\n"
" point specified by next. The length and curvilinear abscissa are\n"
" updated consequently.\n"
"\n"
" :param vertex: The StrokeVertex to insert in the Stroke.\n"
" :type vertex: :class:`StrokeVertex`\n"
" :param next: A StrokeVertexIterator pointing to the StrokeVertex\n"
" before which vertex must be inserted.\n"
" :type next: :class:`StrokeVertexIterator`\n");
static PyObject *Stroke_insert_vertex(BPy_Stroke *self, PyObject *args, PyObject *kwds)
{
static const char *kwlist[] = {"vertex", "next", nullptr};
PyObject *py_sv = nullptr, *py_sv_it = nullptr;
if (!PyArg_ParseTupleAndKeywords(args,
kwds,
"O!O!",
(char **)kwlist,
&StrokeVertex_Type,
&py_sv,
&StrokeVertexIterator_Type,
&py_sv_it))
{
return nullptr;
}
/* Make the wrapped StrokeVertex internal. */
((BPy_StrokeVertex *)py_sv)->py_cp.py_if0D.borrowed = true;
StrokeVertex *sv = ((BPy_StrokeVertex *)py_sv)->sv;
StrokeInternal::StrokeVertexIterator sv_it(*(((BPy_StrokeVertexIterator *)py_sv_it)->sv_it));
self->s->InsertVertex(sv, sv_it);
Py_RETURN_NONE;
}
PyDoc_STRVAR(
/* Wrap. */
Stroke_remove_vertex_doc,
".. method:: remove_vertex(vertex)\n"
"\n"
" Removes the StrokeVertex given as argument from the Stroke. The length\n"
" and curvilinear abscissa are updated consequently.\n"
"\n"
" :param vertex: the StrokeVertex to remove from the Stroke.\n"
" :type vertex: :class:`StrokeVertex`\n");
static PyObject *Stroke_remove_vertex(BPy_Stroke *self, PyObject *args, PyObject *kwds)
{
static const char *kwlist[] = {"vertex", nullptr};
PyObject *py_sv = nullptr;
if (!PyArg_ParseTupleAndKeywords(args, kwds, "O!", (char **)kwlist, &StrokeVertex_Type, &py_sv))
{
return nullptr;
}
if (((BPy_StrokeVertex *)py_sv)->sv) {
self->s->RemoveVertex(((BPy_StrokeVertex *)py_sv)->sv);
}
else {
PyErr_SetString(PyExc_TypeError, "invalid argument");
return nullptr;
}
Py_RETURN_NONE;
}
PyDoc_STRVAR(
/* Wrap. */
Stroke_remove_all_vertices_doc,
".. method:: remove_all_vertices()\n"
"\n"
" Removes all vertices from the Stroke.\n");
static PyObject *Stroke_remove_all_vertices(BPy_Stroke *self)
{
self->s->RemoveAllVertices();
Py_RETURN_NONE;
}
PyDoc_STRVAR(
/* Wrap. */
Stroke_update_length_doc,
".. method:: update_length()\n"
"\n"
" Updates the 2D length of the Stroke.\n");
static PyObject *Stroke_update_length(BPy_Stroke *self)
{
self->s->UpdateLength();
Py_RETURN_NONE;
}
PyDoc_STRVAR(
/* Wrap. */
Stroke_stroke_vertices_begin_doc,
".. method:: stroke_vertices_begin(t=0.0)\n"
"\n"
" Returns a StrokeVertexIterator pointing on the first StrokeVertex of\n"
" the Stroke. One can specify a sampling value to re-sample the Stroke\n"
" on the fly if needed.\n"
"\n"
" :param t: The resampling value with which we want our Stroke to be\n"
" resampled. If 0 is specified, no resampling is done.\n"
" :type t: float\n"
" :return: A StrokeVertexIterator pointing on the first StrokeVertex.\n"
" :rtype: :class:`StrokeVertexIterator`\n");
static PyObject *Stroke_stroke_vertices_begin(BPy_Stroke *self, PyObject *args, PyObject *kwds)
{
static const char *kwlist[] = {"t", nullptr};
float f = 0.0f;
if (!PyArg_ParseTupleAndKeywords(args, kwds, "|f", (char **)kwlist, &f)) {
return nullptr;
}
StrokeInternal::StrokeVertexIterator sv_it(self->s->strokeVerticesBegin(f));
return BPy_StrokeVertexIterator_from_StrokeVertexIterator(sv_it, false);
}
PyDoc_STRVAR(
/* Wrap. */
Stroke_stroke_vertices_end_doc,
".. method:: stroke_vertices_end()\n"
"\n"
" Returns a StrokeVertexIterator pointing after the last StrokeVertex\n"
" of the Stroke.\n"
"\n"
" :return: A StrokeVertexIterator pointing after the last StrokeVertex.\n"
" :rtype: :class:`StrokeVertexIterator`\n");
static PyObject *Stroke_stroke_vertices_end(BPy_Stroke *self)
{
StrokeInternal::StrokeVertexIterator sv_it(self->s->strokeVerticesEnd());
return BPy_StrokeVertexIterator_from_StrokeVertexIterator(sv_it, true);
}
PyDoc_STRVAR(
/* Wrap. */
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`\n");
static PyObject *Stroke_reversed(BPy_Stroke *self)
{
StrokeInternal::StrokeVertexIterator sv_it(self->s->strokeVerticesEnd());
return BPy_StrokeVertexIterator_from_StrokeVertexIterator(sv_it, true);
}
PyDoc_STRVAR(
/* Wrap. */
Stroke_stroke_vertices_size_doc,
".. method:: stroke_vertices_size()\n"
"\n"
" Returns the number of StrokeVertex constituting the Stroke.\n"
"\n"
" :return: The number of stroke vertices.\n"
" :rtype: int\n");
static PyObject *Stroke_stroke_vertices_size(BPy_Stroke *self)
{
return PyLong_FromLong(self->s->strokeVerticesSize());
}
#ifdef __GNUC__
# ifdef __clang__
# pragma clang diagnostic push
# pragma clang diagnostic ignored "-Wcast-function-type"
# else
# pragma GCC diagnostic push
# pragma GCC diagnostic ignored "-Wcast-function-type"
# endif
#endif
static PyMethodDef BPy_Stroke_methods[] = {
{"compute_sampling",
(PyCFunction)Stroke_compute_sampling,
METH_VARARGS | METH_KEYWORDS,
Stroke_compute_sampling_doc},
{"resample", (PyCFunction)Stroke_resample, METH_VARARGS | METH_KEYWORDS, Stroke_resample_doc},
{"remove_all_vertices",
(PyCFunction)Stroke_remove_all_vertices,
METH_NOARGS,
Stroke_remove_all_vertices_doc},
{"remove_vertex",
(PyCFunction)Stroke_remove_vertex,
METH_VARARGS | METH_KEYWORDS,
Stroke_remove_vertex_doc},
{"insert_vertex",
(PyCFunction)Stroke_insert_vertex,
METH_VARARGS | METH_KEYWORDS,
Stroke_insert_vertex_doc},
{"update_length", (PyCFunction)Stroke_update_length, METH_NOARGS, Stroke_update_length_doc},
{"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},
{nullptr, nullptr, 0, nullptr},
};
#ifdef __GNUC__
# ifdef __clang__
# pragma clang diagnostic pop
# else
# pragma GCC diagnostic pop
# endif
#endif
/*----------------------Stroke get/setters ----------------------------*/
PyDoc_STRVAR(
/* Wrap. */
Stroke_medium_type_doc,
"The MediumType used for this Stroke.\n"
"\n"
":type: :class:`MediumType`\n");
static PyObject *Stroke_medium_type_get(BPy_Stroke *self, void * /*closure*/)
{
return BPy_MediumType_from_MediumType(self->s->getMediumType());
}
static int Stroke_medium_type_set(BPy_Stroke *self, PyObject *value, void * /*closure*/)
{
if (!BPy_MediumType_Check(value)) {
PyErr_SetString(PyExc_TypeError, "value must be a MediumType");
return -1;
}
self->s->setMediumType(MediumType_from_BPy_MediumType(value));
return 0;
}
PyDoc_STRVAR(
/* Wrap. */
Stroke_texture_id_doc,
"The ID of the texture used to simulate th marks system for this Stroke.\n"
"\n"
":type: int\n");
static PyObject *Stroke_texture_id_get(BPy_Stroke *self, void * /*closure*/)
{
return PyLong_FromLong(self->s->getTextureId());
}
static int Stroke_texture_id_set(BPy_Stroke *self, PyObject *value, void * /*closure*/)
{
uint i = PyLong_AsUnsignedLong(value);
if (PyErr_Occurred()) {
return -1;
}
self->s->setTextureId(i);
return 0;
}
PyDoc_STRVAR(
/* Wrap. */
Stroke_tips_doc,
"True if this Stroke uses a texture with tips, and false otherwise.\n"
"\n"
":type: bool\n");
static PyObject *Stroke_tips_get(BPy_Stroke *self, void * /*closure*/)
{
return PyBool_from_bool(self->s->hasTips());
}
static int Stroke_tips_set(BPy_Stroke *self, PyObject *value, void * /*closure*/)
{
if (!PyBool_Check(value)) {
return -1;
}
self->s->setTips(bool_from_PyBool(value));
return 0;
}
PyDoc_STRVAR(
/* Wrap. */
Stroke_length_2d_doc,
"The 2D length of the Stroke.\n"
"\n"
":type: float\n");
static PyObject *Stroke_length_2d_get(BPy_Stroke *self, void * /*closure*/)
{
return PyFloat_FromDouble(self->s->getLength2D());
}
static int Stroke_length_2d_set(BPy_Stroke *self, PyObject *value, void * /*closure*/)
{
float scalar;
if ((scalar = PyFloat_AsDouble(value)) == -1.0f && PyErr_Occurred()) {
/* parsed item not a number */
PyErr_SetString(PyExc_TypeError, "value must be a number");
return -1;
}
self->s->setLength(scalar);
return 0;
}
PyDoc_STRVAR(
/* Wrap. */
Stroke_id_doc,
"The Id of this Stroke.\n"
"\n"
":type: :class:`Id`\n");
static PyObject *Stroke_id_get(BPy_Stroke *self, void * /*closure*/)
{
Id id(self->s->getId());
return BPy_Id_from_Id(id); // return a copy
}
static int Stroke_id_set(BPy_Stroke *self, PyObject *value, void * /*closure*/)
{
if (!BPy_Id_Check(value)) {
PyErr_SetString(PyExc_TypeError, "value must be an Id");
return -1;
}
self->s->setId(*(((BPy_Id *)value)->id));
return 0;
}
static PyGetSetDef BPy_Stroke_getseters[] = {
{"medium_type",
(getter)Stroke_medium_type_get,
(setter)Stroke_medium_type_set,
Stroke_medium_type_doc,
nullptr},
{"texture_id",
(getter)Stroke_texture_id_get,
(setter)Stroke_texture_id_set,
Stroke_texture_id_doc,
nullptr},
{"tips", (getter)Stroke_tips_get, (setter)Stroke_tips_set, Stroke_tips_doc, nullptr},
{"length_2d",
(getter)Stroke_length_2d_get,
(setter)Stroke_length_2d_set,
Stroke_length_2d_doc,
nullptr},
{"id", (getter)Stroke_id_get, (setter)Stroke_id_set, Stroke_id_doc, nullptr},
{nullptr, nullptr, nullptr, nullptr, nullptr} /* Sentinel */
};
/*-----------------------BPy_Stroke type definition ------------------------------*/
static PySequenceMethods BPy_Stroke_as_sequence = {
/*sq_length*/ (lenfunc)Stroke_sq_length,
/*sq_concat*/ nullptr,
/*sq_repeat*/ nullptr,
/*sq_item*/ (ssizeargfunc)Stroke_sq_item,
/*was_sq_slice*/ nullptr, /* DEPRECATED. */
/*sq_ass_item*/ nullptr,
/*was_sq_ass_slice*/ nullptr, /* DEPRECATED. */
/*sq_contains*/ nullptr,
/*sq_inplace_concat*/ nullptr,
/*sq_inplace_repeat*/ nullptr,
};
PyTypeObject Stroke_Type = {
/*ob_base*/ PyVarObject_HEAD_INIT(nullptr, 0)
/*tp_name*/ "Stroke",
/*tp_basicsize*/ sizeof(BPy_Stroke),
/*tp_itemsize*/ 0,
/*tp_dealloc*/ nullptr,
/*tp_vectorcall_offset*/ 0,
/*tp_getattr*/ nullptr,
/*tp_setattr*/ nullptr,
/*tp_as_async*/ nullptr,
/*tp_repr*/ nullptr,
/*tp_as_number*/ nullptr,
/*tp_as_sequence*/ &BPy_Stroke_as_sequence,
/*tp_as_mapping*/ nullptr,
/*tp_hash*/ nullptr,
/*tp_call*/ nullptr,
/*tp_str*/ nullptr,
/*tp_getattro*/ nullptr,
/*tp_setattro*/ nullptr,
/*tp_as_buffer*/ nullptr,
/*tp_flags*/ Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE,
/*tp_doc*/ Stroke_doc,
/*tp_traverse*/ nullptr,
/*tp_clear*/ nullptr,
/*tp_richcompare*/ nullptr,
/*tp_weaklistoffset*/ 0,
/*tp_iter*/ (getiterfunc)Stroke_iter,
/*tp_iternext*/ nullptr,
/*tp_methods*/ BPy_Stroke_methods,
/*tp_members*/ nullptr,
/*tp_getset*/ BPy_Stroke_getseters,
/*tp_base*/ &Interface1D_Type,
/*tp_dict*/ nullptr,
/*tp_descr_get*/ nullptr,
/*tp_descr_set*/ nullptr,
/*tp_dictoffset*/ 0,
/*tp_init*/ (initproc)Stroke_init,
/*tp_alloc*/ nullptr,
/*tp_new*/ nullptr,
};
///////////////////////////////////////////////////////////////////////////////////////////

View File

@@ -0,0 +1,27 @@
/* SPDX-FileCopyrightText: 2023 Blender Authors
*
* SPDX-License-Identifier: GPL-2.0-or-later */
/** \file
* \ingroup freestyle
*/
#pragma once
#include "../BPy_Interface1D.h"
#include "../../stroke/Stroke.h"
///////////////////////////////////////////////////////////////////////////////////////////
extern PyTypeObject Stroke_Type;
#define BPy_Stroke_Check(v) (((PyObject *)v)->ob_type == &Stroke_Type)
/*---------------------------Python BPy_Stroke structure definition----------*/
struct BPy_Stroke {
BPy_Interface1D py_if1D;
Freestyle::Stroke *s;
};
///////////////////////////////////////////////////////////////////////////////////////////

View File

@@ -0,0 +1,443 @@
/* SPDX-FileCopyrightText: 2004-2022 Blender Authors
*
* SPDX-License-Identifier: GPL-2.0-or-later */
/** \file
* \ingroup freestyle
*/
#include "BPy_ViewEdge.h"
#include "../BPy_Convert.h"
#include "../BPy_Id.h"
#include "../BPy_Nature.h"
#include "../BPy_ViewShape.h"
#include "../Interface0D/BPy_ViewVertex.h"
#include "../Interface1D/BPy_FEdge.h"
#include "../Interface1D/BPy_ViewEdge.h"
using namespace Freestyle;
///////////////////////////////////////////////////////////////////////////////////////////
/*----------------------ViewEdge methods ----------------------------*/
PyDoc_STRVAR(
/* Wrap. */
ViewEdge_doc,
"Class hierarchy: :class:`Interface1D` > :class:`ViewEdge`\n"
"\n"
"Class defining a ViewEdge. A ViewEdge in an edge of the image graph.\n"
"it connects two :class:`ViewVertex` objects. It is made by connecting\n"
"a set of FEdges.\n"
"\n"
".. method:: __init__(*args)\n"
"\n"
" Accepted call signatures:\n"
"\n"
" - ``__init__()``\n"
" - ``__init__(brother)``\n"
"\n"
" Builds a :class:`ViewEdge` using the default constructor or the copy constructor.\n"
"\n"
" :param brother: A ViewEdge object.\n"
" :type brother: :class:`ViewEdge`\n");
static int ViewEdge_init(BPy_ViewEdge *self, PyObject *args, PyObject *kwds)
{
static const char *kwlist[] = {"brother", nullptr};
PyObject *brother = nullptr;
if (!PyArg_ParseTupleAndKeywords(args, kwds, "|O!", (char **)kwlist, &ViewEdge_Type, &brother)) {
return -1;
}
if (!brother) {
self->ve = new ViewEdge();
}
else {
self->ve = new ViewEdge(*(((BPy_ViewEdge *)brother)->ve));
}
self->py_if1D.if1D = self->ve;
self->py_if1D.borrowed = false;
return 0;
}
PyDoc_STRVAR(
/* Wrap. */
ViewEdge_update_fedges_doc,
".. method:: update_fedges()\n"
"\n"
" Sets Viewedge to this for all embedded fedges.\n");
static PyObject *ViewEdge_update_fedges(BPy_ViewEdge *self)
{
self->ve->UpdateFEdges();
Py_RETURN_NONE;
}
#ifdef __GNUC__
# ifdef __clang__
# pragma clang diagnostic push
# pragma clang diagnostic ignored "-Wcast-function-type"
# else
# pragma GCC diagnostic push
# pragma GCC diagnostic ignored "-Wcast-function-type"
# endif
#endif
static PyMethodDef BPy_ViewEdge_methods[] = {
{"update_fedges",
(PyCFunction)ViewEdge_update_fedges,
METH_NOARGS,
ViewEdge_update_fedges_doc},
{nullptr, nullptr, 0, nullptr},
};
#ifdef __GNUC__
# ifdef __clang__
# pragma clang diagnostic pop
# else
# pragma GCC diagnostic pop
# endif
#endif
/*----------------------ViewEdge get/setters ----------------------------*/
PyDoc_STRVAR(
/* Wrap. */
ViewEdge_first_viewvertex_doc,
"The first ViewVertex.\n"
"\n"
":type: :class:`ViewVertex`\n");
static PyObject *ViewEdge_first_viewvertex_get(BPy_ViewEdge *self, void * /*closure*/)
{
ViewVertex *v = self->ve->A();
if (v) {
return Any_BPy_ViewVertex_from_ViewVertex(*v);
}
Py_RETURN_NONE;
}
static int ViewEdge_first_viewvertex_set(BPy_ViewEdge *self, PyObject *value, void * /*closure*/)
{
if (!BPy_ViewVertex_Check(value)) {
return -1;
}
self->ve->setA(((BPy_ViewVertex *)value)->vv);
return 0;
}
PyDoc_STRVAR(
/* Wrap. */
ViewEdge_last_viewvertex_doc,
"The second ViewVertex.\n"
"\n"
":type: :class:`ViewVertex`\n");
static PyObject *ViewEdge_last_viewvertex_get(BPy_ViewEdge *self, void * /*closure*/)
{
ViewVertex *v = self->ve->B();
if (v) {
return Any_BPy_ViewVertex_from_ViewVertex(*v);
}
Py_RETURN_NONE;
}
static int ViewEdge_last_viewvertex_set(BPy_ViewEdge *self, PyObject *value, void * /*closure*/)
{
if (!BPy_ViewVertex_Check(value)) {
return -1;
}
self->ve->setB(((BPy_ViewVertex *)value)->vv);
return 0;
}
PyDoc_STRVAR(
/* Wrap. */
ViewEdge_first_fedge_doc,
"The first FEdge that constitutes this ViewEdge.\n"
"\n"
":type: :class:`FEdge`\n");
static PyObject *ViewEdge_first_fedge_get(BPy_ViewEdge *self, void * /*closure*/)
{
FEdge *fe = self->ve->fedgeA();
if (fe) {
return Any_BPy_FEdge_from_FEdge(*fe);
}
Py_RETURN_NONE;
}
static int ViewEdge_first_fedge_set(BPy_ViewEdge *self, PyObject *value, void * /*closure*/)
{
if (!BPy_FEdge_Check(value)) {
return -1;
}
self->ve->setFEdgeA(((BPy_FEdge *)value)->fe);
return 0;
}
PyDoc_STRVAR(
/* Wrap. */
ViewEdge_last_fedge_doc,
"The last FEdge that constitutes this ViewEdge.\n"
"\n"
":type: :class:`FEdge`\n");
static PyObject *ViewEdge_last_fedge_get(BPy_ViewEdge *self, void * /*closure*/)
{
FEdge *fe = self->ve->fedgeB();
if (fe) {
return Any_BPy_FEdge_from_FEdge(*fe);
}
Py_RETURN_NONE;
}
static int ViewEdge_last_fedge_set(BPy_ViewEdge *self, PyObject *value, void * /*closure*/)
{
if (!BPy_FEdge_Check(value)) {
return -1;
}
self->ve->setFEdgeB(((BPy_FEdge *)value)->fe);
return 0;
}
PyDoc_STRVAR(
/* Wrap. */
ViewEdge_viewshape_doc,
"The ViewShape to which this ViewEdge belongs to.\n"
"\n"
":type: :class:`ViewShape`\n");
static PyObject *ViewEdge_viewshape_get(BPy_ViewEdge *self, void * /*closure*/)
{
ViewShape *vs = self->ve->viewShape();
if (vs) {
return BPy_ViewShape_from_ViewShape(*vs);
}
Py_RETURN_NONE;
}
static int ViewEdge_viewshape_set(BPy_ViewEdge *self, PyObject *value, void * /*closure*/)
{
if (!BPy_ViewShape_Check(value)) {
return -1;
}
self->ve->setShape(((BPy_ViewShape *)value)->vs);
return 0;
}
PyDoc_STRVAR(
/* Wrap. */
ViewEdge_occludee_doc,
"The shape that is occluded by the ViewShape to which this ViewEdge\n"
"belongs to. If no object is occluded, this property is set to None.\n"
"\n"
":type: :class:`ViewShape`\n");
static PyObject *ViewEdge_occludee_get(BPy_ViewEdge *self, void * /*closure*/)
{
ViewShape *vs = self->ve->aShape();
if (vs) {
return BPy_ViewShape_from_ViewShape(*vs);
}
Py_RETURN_NONE;
}
static int ViewEdge_occludee_set(BPy_ViewEdge *self, PyObject *value, void * /*closure*/)
{
if (!BPy_ViewShape_Check(value)) {
return -1;
}
self->ve->setaShape(((BPy_ViewShape *)value)->vs);
return 0;
}
PyDoc_STRVAR(
/* Wrap. */
ViewEdge_is_closed_doc,
"True if this ViewEdge forms a closed loop.\n"
"\n"
":type: bool\n");
static PyObject *ViewEdge_is_closed_get(BPy_ViewEdge *self, void * /*closure*/)
{
return PyBool_from_bool(self->ve->isClosed());
}
PyDoc_STRVAR(
/* Wrap. */
ViewEdge_id_doc,
"The Id of this ViewEdge.\n"
"\n"
":type: :class:`Id`\n");
static PyObject *ViewEdge_id_get(BPy_ViewEdge *self, void * /*closure*/)
{
Id id(self->ve->getId());
return BPy_Id_from_Id(id); // return a copy
}
static int ViewEdge_id_set(BPy_ViewEdge *self, PyObject *value, void * /*closure*/)
{
if (!BPy_Id_Check(value)) {
PyErr_SetString(PyExc_TypeError, "value must be an Id");
return -1;
}
self->ve->setId(*(((BPy_Id *)value)->id));
return 0;
}
PyDoc_STRVAR(
/* Wrap. */
ViewEdge_nature_doc,
"The nature of this ViewEdge.\n"
"\n"
":type: :class:`Nature`\n");
static PyObject *ViewEdge_nature_get(BPy_ViewEdge *self, void * /*closure*/)
{
return BPy_Nature_from_Nature(self->ve->getNature());
}
static int ViewEdge_nature_set(BPy_ViewEdge *self, PyObject *value, void * /*closure*/)
{
if (!BPy_Nature_Check(value)) {
PyErr_SetString(PyExc_TypeError, "value must be a Nature");
return -1;
}
self->ve->setNature(PyLong_AsLong((PyObject *)&((BPy_Nature *)value)->i));
return 0;
}
PyDoc_STRVAR(
/* Wrap. */
ViewEdge_qi_doc,
"The quantitative invisibility.\n"
"\n"
":type: int\n");
static PyObject *ViewEdge_qi_get(BPy_ViewEdge *self, void * /*closure*/)
{
return PyLong_FromLong(self->ve->qi());
}
static int ViewEdge_qi_set(BPy_ViewEdge *self, PyObject *value, void * /*closure*/)
{
int qi;
if ((qi = PyLong_AsLong(value)) == -1 && PyErr_Occurred()) {
return -1;
}
self->ve->setQI(qi);
return 0;
}
PyDoc_STRVAR(
/* Wrap. */
ViewEdge_chaining_time_stamp_doc,
"The time stamp of this ViewEdge.\n"
"\n"
":type: int\n");
static PyObject *ViewEdge_chaining_time_stamp_get(BPy_ViewEdge *self, void * /*closure*/)
{
return PyLong_FromLong(self->ve->getChainingTimeStamp());
}
static int ViewEdge_chaining_time_stamp_set(BPy_ViewEdge *self,
PyObject *value,
void * /*closure*/)
{
int timestamp;
if ((timestamp = PyLong_AsLong(value)) == -1 && PyErr_Occurred()) {
return -1;
}
self->ve->setChainingTimeStamp(timestamp);
return 0;
}
static PyGetSetDef BPy_ViewEdge_getseters[] = {
{"first_viewvertex",
(getter)ViewEdge_first_viewvertex_get,
(setter)ViewEdge_first_viewvertex_set,
ViewEdge_first_viewvertex_doc,
nullptr},
{"last_viewvertex",
(getter)ViewEdge_last_viewvertex_get,
(setter)ViewEdge_last_viewvertex_set,
ViewEdge_last_viewvertex_doc,
nullptr},
{"first_fedge",
(getter)ViewEdge_first_fedge_get,
(setter)ViewEdge_first_fedge_set,
ViewEdge_first_fedge_doc,
nullptr},
{"last_fedge",
(getter)ViewEdge_last_fedge_get,
(setter)ViewEdge_last_fedge_set,
ViewEdge_last_fedge_doc,
nullptr},
{"viewshape",
(getter)ViewEdge_viewshape_get,
(setter)ViewEdge_viewshape_set,
ViewEdge_viewshape_doc,
nullptr},
{"occludee",
(getter)ViewEdge_occludee_get,
(setter)ViewEdge_occludee_set,
ViewEdge_occludee_doc,
nullptr},
{"is_closed",
(getter)ViewEdge_is_closed_get,
(setter) nullptr,
ViewEdge_is_closed_doc,
nullptr},
{"id", (getter)ViewEdge_id_get, (setter)ViewEdge_id_set, ViewEdge_id_doc, nullptr},
{"nature",
(getter)ViewEdge_nature_get,
(setter)ViewEdge_nature_set,
ViewEdge_nature_doc,
nullptr},
{"qi", (getter)ViewEdge_qi_get, (setter)ViewEdge_qi_set, ViewEdge_qi_doc, nullptr},
{"chaining_time_stamp",
(getter)ViewEdge_chaining_time_stamp_get,
(setter)ViewEdge_chaining_time_stamp_set,
ViewEdge_chaining_time_stamp_doc,
nullptr},
{nullptr, nullptr, nullptr, nullptr, nullptr} /* Sentinel */
};
/*-----------------------BPy_ViewEdge type definition ------------------------------*/
PyTypeObject ViewEdge_Type = {
/*ob_base*/ PyVarObject_HEAD_INIT(nullptr, 0)
/*tp_name*/ "ViewEdge",
/*tp_basicsize*/ sizeof(BPy_ViewEdge),
/*tp_itemsize*/ 0,
/*tp_dealloc*/ nullptr,
/*tp_vectorcall_offset*/ 0,
/*tp_getattr*/ nullptr,
/*tp_setattr*/ nullptr,
/*tp_as_async*/ nullptr,
/*tp_repr*/ nullptr,
/*tp_as_number*/ nullptr,
/*tp_as_sequence*/ nullptr,
/*tp_as_mapping*/ nullptr,
/*tp_hash*/ nullptr,
/*tp_call*/ nullptr,
/*tp_str*/ nullptr,
/*tp_getattro*/ nullptr,
/*tp_setattro*/ nullptr,
/*tp_as_buffer*/ nullptr,
/*tp_flags*/ Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE,
/*tp_doc*/ ViewEdge_doc,
/*tp_traverse*/ nullptr,
/*tp_clear*/ nullptr,
/*tp_richcompare*/ nullptr,
/*tp_weaklistoffset*/ 0,
/*tp_iter*/ nullptr,
/*tp_iternext*/ nullptr,
/*tp_methods*/ BPy_ViewEdge_methods,
/*tp_members*/ nullptr,
/*tp_getset*/ BPy_ViewEdge_getseters,
/*tp_base*/ &Interface1D_Type,
/*tp_dict*/ nullptr,
/*tp_descr_get*/ nullptr,
/*tp_descr_set*/ nullptr,
/*tp_dictoffset*/ 0,
/*tp_init*/ (initproc)ViewEdge_init,
/*tp_alloc*/ nullptr,
/*tp_new*/ nullptr,
};
///////////////////////////////////////////////////////////////////////////////////////////

View File

@@ -0,0 +1,27 @@
/* SPDX-FileCopyrightText: 2023 Blender Authors
*
* SPDX-License-Identifier: GPL-2.0-or-later */
/** \file
* \ingroup freestyle
*/
#pragma once
#include "../BPy_Interface1D.h"
#include "../../view_map/ViewMap.h"
///////////////////////////////////////////////////////////////////////////////////////////
extern PyTypeObject ViewEdge_Type;
#define BPy_ViewEdge_Check(v) (PyObject_IsInstance((PyObject *)v, (PyObject *)&ViewEdge_Type))
/*---------------------------Python BPy_ViewEdge structure definition----------*/
struct BPy_ViewEdge {
BPy_Interface1D py_if1D;
Freestyle::ViewEdge *ve;
};
///////////////////////////////////////////////////////////////////////////////////////////

View File

@@ -0,0 +1,202 @@
/* SPDX-FileCopyrightText: 2004-2023 Blender Authors
*
* SPDX-License-Identifier: GPL-2.0-or-later */
/** \file
* \ingroup freestyle
*/
#include "BPy_Chain.h"
#include "../../BPy_Convert.h"
#include "../../BPy_Id.h"
#include "../BPy_ViewEdge.h"
using namespace Freestyle;
///////////////////////////////////////////////////////////////////////////////////////////
/*----------------------Chain methods ----------------------------*/
PyDoc_STRVAR(
/* Wrap. */
Chain_doc,
"Class hierarchy: :class:`Interface1D` > :class:`Curve` > :class:`Chain`\n"
"\n"
"Class to represent a 1D elements issued from the chaining process. A\n"
"Chain is the last step before the :class:`Stroke` and is used in the\n"
"Splitting and Creation processes.\n"
"\n"
".. method:: __init__(*args)\n"
"\n"
" Accepted call signatures:\n"
"\n"
" - ``__init__()``\n"
" - ``__init__(brother)``\n"
" - ``__init__(id)``\n"
"\n"
" Builds a :class:`Chain` using the default constructor,\n"
" copy constructor or from an :class:`Id`.\n"
"\n"
" :param brother: A Chain object.\n"
" :type brother: :class:`Chain`\n"
" :param id: An Id object.\n"
" :type id: :class:`Id`\n");
static int Chain_init(BPy_Chain *self, PyObject *args, PyObject *kwds)
{
static const char *kwlist_1[] = {"brother", nullptr};
static const char *kwlist_2[] = {"id", nullptr};
PyObject *obj = nullptr;
if (PyArg_ParseTupleAndKeywords(args, kwds, "|O!", (char **)kwlist_1, &Chain_Type, &obj)) {
if (!obj) {
self->c = new Chain();
}
else {
self->c = new Chain(*(((BPy_Chain *)obj)->c));
}
}
else if ((void)PyErr_Clear(),
PyArg_ParseTupleAndKeywords(args, kwds, "O!", (char **)kwlist_2, &Id_Type, &obj))
{
self->c = new Chain(*(((BPy_Id *)obj)->id));
}
else {
PyErr_SetString(PyExc_TypeError, "invalid argument(s)");
return -1;
}
self->py_c.c = self->c;
self->py_c.py_if1D.if1D = self->c;
self->py_c.py_if1D.borrowed = false;
return 0;
}
PyDoc_STRVAR(
/* Wrap. */
Chain_push_viewedge_back_doc,
".. method:: push_viewedge_back(viewedge, orientation)\n"
"\n"
" Adds a ViewEdge at the end of the Chain.\n"
"\n"
" :param viewedge: The ViewEdge that must be added.\n"
" :type viewedge: :class:`ViewEdge`\n"
" :param orientation: The orientation with which the ViewEdge must be processed.\n"
" :type orientation: bool\n");
static PyObject *Chain_push_viewedge_back(BPy_Chain *self, PyObject *args, PyObject *kwds)
{
static const char *kwlist[] = {"viewedge", "orientation", nullptr};
PyObject *obj1 = nullptr, *obj2 = nullptr;
if (!PyArg_ParseTupleAndKeywords(
args, kwds, "O!O!", (char **)kwlist, &ViewEdge_Type, &obj1, &PyBool_Type, &obj2))
{
return nullptr;
}
ViewEdge *ve = ((BPy_ViewEdge *)obj1)->ve;
bool orientation = bool_from_PyBool(obj2);
self->c->push_viewedge_back(ve, orientation);
Py_RETURN_NONE;
}
PyDoc_STRVAR(
/* Wrap. */
Chain_push_viewedge_front_doc,
".. method:: push_viewedge_front(viewedge, orientation)\n"
"\n"
" Adds a ViewEdge at the beginning of the Chain.\n"
"\n"
" :param viewedge: The ViewEdge that must be added.\n"
" :type viewedge: :class:`ViewEdge`\n"
" :param orientation: The orientation with which the ViewEdge must be\n"
" processed.\n"
" :type orientation: bool\n");
static PyObject *Chain_push_viewedge_front(BPy_Chain *self, PyObject *args, PyObject *kwds)
{
static const char *kwlist[] = {"viewedge", "orientation", nullptr};
PyObject *obj1 = nullptr, *obj2 = nullptr;
if (!PyArg_ParseTupleAndKeywords(
args, kwds, "O!O!", (char **)kwlist, &ViewEdge_Type, &obj1, &PyBool_Type, &obj2))
{
return nullptr;
}
ViewEdge *ve = ((BPy_ViewEdge *)obj1)->ve;
bool orientation = bool_from_PyBool(obj2);
self->c->push_viewedge_front(ve, orientation);
Py_RETURN_NONE;
}
#ifdef __GNUC__
# ifdef __clang__
# pragma clang diagnostic push
# pragma clang diagnostic ignored "-Wcast-function-type"
# else
# pragma GCC diagnostic push
# pragma GCC diagnostic ignored "-Wcast-function-type"
# endif
#endif
static PyMethodDef BPy_Chain_methods[] = {
{"push_viewedge_back",
(PyCFunction)Chain_push_viewedge_back,
METH_VARARGS | METH_KEYWORDS,
Chain_push_viewedge_back_doc},
{"push_viewedge_front",
(PyCFunction)Chain_push_viewedge_front,
METH_VARARGS | METH_KEYWORDS,
Chain_push_viewedge_front_doc},
{nullptr, nullptr, 0, nullptr},
};
#ifdef __GNUC__
# ifdef __clang__
# pragma clang diagnostic pop
# else
# pragma GCC diagnostic pop
# endif
#endif
/*-----------------------BPy_Chain type definition ------------------------------*/
PyTypeObject Chain_Type = {
/*ob_base*/ PyVarObject_HEAD_INIT(nullptr, 0)
/*tp_name*/ "Chain",
/*tp_basicsize*/ sizeof(BPy_Chain),
/*tp_itemsize*/ 0,
/*tp_dealloc*/ nullptr,
/*tp_vectorcall_offset*/ 0,
/*tp_getattr*/ nullptr,
/*tp_setattr*/ nullptr,
/*tp_as_async*/ nullptr,
/*tp_repr*/ nullptr,
/*tp_as_number*/ nullptr,
/*tp_as_sequence*/ nullptr,
/*tp_as_mapping*/ nullptr,
/*tp_hash*/ nullptr,
/*tp_call*/ nullptr,
/*tp_str*/ nullptr,
/*tp_getattro*/ nullptr,
/*tp_setattro*/ nullptr,
/*tp_as_buffer*/ nullptr,
/*tp_flags*/ Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE,
/*tp_doc*/ Chain_doc,
/*tp_traverse*/ nullptr,
/*tp_clear*/ nullptr,
/*tp_richcompare*/ nullptr,
/*tp_weaklistoffset*/ 0,
/*tp_iter*/ nullptr,
/*tp_iternext*/ nullptr,
/*tp_methods*/ BPy_Chain_methods,
/*tp_members*/ nullptr,
/*tp_getset*/ nullptr,
/*tp_base*/ &FrsCurve_Type,
/*tp_dict*/ nullptr,
/*tp_descr_get*/ nullptr,
/*tp_descr_set*/ nullptr,
/*tp_dictoffset*/ 0,
/*tp_init*/ (initproc)Chain_init,
/*tp_alloc*/ nullptr,
/*tp_new*/ nullptr,
};
///////////////////////////////////////////////////////////////////////////////////////////

View File

@@ -0,0 +1,27 @@
/* SPDX-FileCopyrightText: 2023 Blender Authors
*
* SPDX-License-Identifier: GPL-2.0-or-later */
/** \file
* \ingroup freestyle
*/
#pragma once
#include "../BPy_FrsCurve.h"
#include "../../../stroke/Chain.h"
///////////////////////////////////////////////////////////////////////////////////////////
extern PyTypeObject Chain_Type;
#define BPy_Chain_Check(v) (PyObject_IsInstance((PyObject *)v, (PyObject *)&Chain_Type))
/*---------------------------Python BPy_Chain structure definition----------*/
struct BPy_Chain {
BPy_FrsCurve py_c;
Freestyle::Chain *c;
};
///////////////////////////////////////////////////////////////////////////////////////////

View File

@@ -0,0 +1,449 @@
/* SPDX-FileCopyrightText: 2004-2023 Blender Authors
*
* SPDX-License-Identifier: GPL-2.0-or-later */
/** \file
* \ingroup freestyle
*/
#include "BPy_FEdgeSharp.h"
#include "../../BPy_Convert.h"
#include "../../Interface0D/BPy_SVertex.h"
#include "BLI_sys_types.h"
using namespace Freestyle;
///////////////////////////////////////////////////////////////////////////////////////////
/*----------------------FEdgeSharp methods ----------------------------*/
PyDoc_STRVAR(
/* Wrap. */
FEdgeSharp_doc,
"Class hierarchy: :class:`Interface1D` > :class:`FEdge` > :class:`FEdgeSharp`\n"
"\n"
"Class defining a sharp FEdge. A Sharp FEdge corresponds to an initial\n"
"edge of the input mesh. It can be a silhouette, a crease or a border.\n"
"If it is a crease edge, then it is bordered by two faces of the mesh.\n"
"Face a lies on its right whereas Face b lies on its left. If it is a\n"
"border edge, then it doesn't have any face on its right, and thus Face\n"
"a is None.\n"
"\n"
".. method:: __init__(*args)\n"
"\n"
" Accepted call signatures:\n"
"\n"
" - ``__init__()``\n"
" - ``__init__(brother)``\n"
" - ``__init__(first_vertex, second_vertex)``\n"
"\n"
" Builds an :class:`FEdgeSharp` using the default constructor,\n"
" copy constructor, or between two :class:`SVertex` objects.\n"
"\n"
" :param brother: An FEdgeSharp object.\n"
" :type brother: :class:`FEdgeSharp`\n"
" :param first_vertex: The first SVertex object.\n"
" :type first_vertex: :class:`SVertex`\n"
" :param second_vertex: The second SVertex object.\n"
" :type second_vertex: :class:`SVertex`\n");
static int FEdgeSharp_init(BPy_FEdgeSharp *self, PyObject *args, PyObject *kwds)
{
static const char *kwlist_1[] = {"brother", nullptr};
static const char *kwlist_2[] = {"first_vertex", "second_vertex", nullptr};
PyObject *obj1 = nullptr, *obj2 = nullptr;
if (PyArg_ParseTupleAndKeywords(args, kwds, "|O!", (char **)kwlist_1, &FEdgeSharp_Type, &obj1)) {
if (!obj1) {
self->fes = new FEdgeSharp();
}
else {
self->fes = new FEdgeSharp(*(((BPy_FEdgeSharp *)obj1)->fes));
}
}
else if ((void)PyErr_Clear(),
PyArg_ParseTupleAndKeywords(
args, kwds, "O!O!", (char **)kwlist_2, &SVertex_Type, &obj1, &SVertex_Type, &obj2))
{
self->fes = new FEdgeSharp(((BPy_SVertex *)obj1)->sv, ((BPy_SVertex *)obj2)->sv);
}
else {
PyErr_SetString(PyExc_TypeError, "invalid argument(s)");
return -1;
}
self->py_fe.fe = self->fes;
self->py_fe.py_if1D.if1D = self->fes;
self->py_fe.py_if1D.borrowed = false;
return 0;
}
/*----------------------mathutils callbacks ----------------------------*/
/* subtype */
#define MATHUTILS_SUBTYPE_NORMAL_A 1
#define MATHUTILS_SUBTYPE_NORMAL_B 2
static int FEdgeSharp_mathutils_check(blender::BaseMathObject *bmo)
{
if (!BPy_FEdgeSharp_Check(bmo->cb_user)) {
return -1;
}
return 0;
}
static int FEdgeSharp_mathutils_get(blender::BaseMathObject *bmo, int subtype)
{
BPy_FEdgeSharp *self = (BPy_FEdgeSharp *)bmo->cb_user;
switch (subtype) {
case MATHUTILS_SUBTYPE_NORMAL_A: {
Vec3r p(self->fes->normalA());
bmo->data[0] = p[0];
bmo->data[1] = p[1];
bmo->data[2] = p[2];
break;
}
case MATHUTILS_SUBTYPE_NORMAL_B: {
Vec3r p(self->fes->normalB());
bmo->data[0] = p[0];
bmo->data[1] = p[1];
bmo->data[2] = p[2];
break;
}
default:
return -1;
}
return 0;
}
static int FEdgeSharp_mathutils_set(blender::BaseMathObject *bmo, int subtype)
{
BPy_FEdgeSharp *self = (BPy_FEdgeSharp *)bmo->cb_user;
switch (subtype) {
case MATHUTILS_SUBTYPE_NORMAL_A: {
Vec3r p(bmo->data[0], bmo->data[1], bmo->data[2]);
self->fes->setNormalA(p);
break;
}
case MATHUTILS_SUBTYPE_NORMAL_B: {
Vec3r p(bmo->data[0], bmo->data[1], bmo->data[2]);
self->fes->setNormalB(p);
break;
}
default:
return -1;
}
return 0;
}
static int FEdgeSharp_mathutils_get_index(blender::BaseMathObject *bmo, int subtype, int index)
{
BPy_FEdgeSharp *self = (BPy_FEdgeSharp *)bmo->cb_user;
switch (subtype) {
case MATHUTILS_SUBTYPE_NORMAL_A: {
Vec3r p(self->fes->normalA());
bmo->data[index] = p[index];
break;
}
case MATHUTILS_SUBTYPE_NORMAL_B: {
Vec3r p(self->fes->normalB());
bmo->data[index] = p[index];
break;
}
default:
return -1;
}
return 0;
}
static int FEdgeSharp_mathutils_set_index(blender::BaseMathObject *bmo, int subtype, int index)
{
BPy_FEdgeSharp *self = (BPy_FEdgeSharp *)bmo->cb_user;
switch (subtype) {
case MATHUTILS_SUBTYPE_NORMAL_A: {
Vec3r p(self->fes->normalA());
p[index] = bmo->data[index];
self->fes->setNormalA(p);
break;
}
case MATHUTILS_SUBTYPE_NORMAL_B: {
Vec3r p(self->fes->normalB());
p[index] = bmo->data[index];
self->fes->setNormalB(p);
break;
}
default:
return -1;
}
return 0;
}
static blender::Mathutils_Callback FEdgeSharp_mathutils_cb = {
FEdgeSharp_mathutils_check,
FEdgeSharp_mathutils_get,
FEdgeSharp_mathutils_set,
FEdgeSharp_mathutils_get_index,
FEdgeSharp_mathutils_set_index,
};
static uchar FEdgeSharp_mathutils_cb_index = -1;
void FEdgeSharp_mathutils_register_callback()
{
FEdgeSharp_mathutils_cb_index = Mathutils_RegisterCallback(&FEdgeSharp_mathutils_cb);
}
/*----------------------FEdgeSharp get/setters ----------------------------*/
PyDoc_STRVAR(
/* Wrap. */
FEdgeSharp_normal_right_doc,
"The normal to the face lying on the right of the FEdge. If this FEdge\n"
"is a border, it has no Face on its right and therefore no normal.\n"
"\n"
":type: :class:`mathutils.Vector`\n");
static PyObject *FEdgeSharp_normal_right_get(BPy_FEdgeSharp *self, void * /*closure*/)
{
return blender::Vector_CreatePyObject_cb(
(PyObject *)self, 3, FEdgeSharp_mathutils_cb_index, MATHUTILS_SUBTYPE_NORMAL_A);
}
static int FEdgeSharp_normal_right_set(BPy_FEdgeSharp *self, PyObject *value, void * /*closure*/)
{
float v[3];
if (blender::mathutils_array_parse(v, 3, 3, value, "value must be a 3-dimensional vector") == -1)
{
return -1;
}
Vec3r p(v[0], v[1], v[2]);
self->fes->setNormalA(p);
return 0;
}
PyDoc_STRVAR(
/* Wrap. */
FEdgeSharp_normal_left_doc,
"The normal to the face lying on the left of the FEdge.\n"
"\n"
":type: :class:`mathutils.Vector`\n");
static PyObject *FEdgeSharp_normal_left_get(BPy_FEdgeSharp *self, void * /*closure*/)
{
return blender::Vector_CreatePyObject_cb(
(PyObject *)self, 3, FEdgeSharp_mathutils_cb_index, MATHUTILS_SUBTYPE_NORMAL_B);
}
static int FEdgeSharp_normal_left_set(BPy_FEdgeSharp *self, PyObject *value, void * /*closure*/)
{
float v[3];
if (blender::mathutils_array_parse(v, 3, 3, value, "value must be a 3-dimensional vector") == -1)
{
return -1;
}
Vec3r p(v[0], v[1], v[2]);
self->fes->setNormalB(p);
return 0;
}
PyDoc_STRVAR(
/* Wrap. */
FEdgeSharp_material_index_right_doc,
"The index of the material of the face lying on the right of the FEdge.\n"
"If this FEdge is a border, it has no Face on its right and therefore\n"
"no material.\n"
"\n"
":type: int\n");
static PyObject *FEdgeSharp_material_index_right_get(BPy_FEdgeSharp *self, void * /*closure*/)
{
return PyLong_FromLong(self->fes->aFrsMaterialIndex());
}
static int FEdgeSharp_material_index_right_set(BPy_FEdgeSharp *self,
PyObject *value,
void * /*closure*/)
{
uint i = PyLong_AsUnsignedLong(value);
if (PyErr_Occurred()) {
return -1;
}
self->fes->setaFrsMaterialIndex(i);
return 0;
}
PyDoc_STRVAR(
/* Wrap. */
FEdgeSharp_material_index_left_doc,
"The index of the material of the face lying on the left of the FEdge.\n"
"\n"
":type: int\n");
static PyObject *FEdgeSharp_material_index_left_get(BPy_FEdgeSharp *self, void * /*closure*/)
{
return PyLong_FromLong(self->fes->bFrsMaterialIndex());
}
static int FEdgeSharp_material_index_left_set(BPy_FEdgeSharp *self,
PyObject *value,
void * /*closure*/)
{
uint i = PyLong_AsUnsignedLong(value);
if (PyErr_Occurred()) {
return -1;
}
self->fes->setbFrsMaterialIndex(i);
return 0;
}
PyDoc_STRVAR(
/* Wrap. */
FEdgeSharp_material_right_doc,
"The material of the face lying on the right of the FEdge. If this FEdge\n"
"is a border, it has no Face on its right and therefore no material.\n"
"\n"
":type: :class:`Material`\n");
static PyObject *FEdgeSharp_material_right_get(BPy_FEdgeSharp *self, void * /*closure*/)
{
return BPy_FrsMaterial_from_FrsMaterial(self->fes->aFrsMaterial());
}
PyDoc_STRVAR(
/* Wrap. */
FEdgeSharp_material_left_doc,
"The material of the face lying on the left of the FEdge.\n"
"\n"
":type: :class:`Material`\n");
static PyObject *FEdgeSharp_material_left_get(BPy_FEdgeSharp *self, void * /*closure*/)
{
return BPy_FrsMaterial_from_FrsMaterial(self->fes->bFrsMaterial());
}
PyDoc_STRVAR(
/* Wrap. */
FEdgeSharp_face_mark_right_doc,
"The face mark of the face lying on the right of the FEdge. If this FEdge\n"
"is a border, it has no face on the right and thus this property is set to\n"
"false.\n"
"\n"
":type: bool\n");
static PyObject *FEdgeSharp_face_mark_right_get(BPy_FEdgeSharp *self, void * /*closure*/)
{
return PyBool_from_bool(self->fes->aFaceMark());
}
static int FEdgeSharp_face_mark_right_set(BPy_FEdgeSharp *self,
PyObject *value,
void * /*closure*/)
{
if (!PyBool_Check(value)) {
return -1;
}
self->fes->setaFaceMark(bool_from_PyBool(value));
return 0;
}
PyDoc_STRVAR(
/* Wrap. */
FEdgeSharp_face_mark_left_doc,
"The face mark of the face lying on the left of the FEdge.\n"
"\n"
":type: bool\n");
static PyObject *FEdgeSharp_face_mark_left_get(BPy_FEdgeSharp *self, void * /*closure*/)
{
return PyBool_from_bool(self->fes->bFaceMark());
}
static int FEdgeSharp_face_mark_left_set(BPy_FEdgeSharp *self, PyObject *value, void * /*closure*/)
{
if (!PyBool_Check(value)) {
return -1;
}
self->fes->setbFaceMark(bool_from_PyBool(value));
return 0;
}
static PyGetSetDef BPy_FEdgeSharp_getseters[] = {
{"normal_right",
(getter)FEdgeSharp_normal_right_get,
(setter)FEdgeSharp_normal_right_set,
FEdgeSharp_normal_right_doc,
nullptr},
{"normal_left",
(getter)FEdgeSharp_normal_left_get,
(setter)FEdgeSharp_normal_left_set,
FEdgeSharp_normal_left_doc,
nullptr},
{"material_index_right",
(getter)FEdgeSharp_material_index_right_get,
(setter)FEdgeSharp_material_index_right_set,
FEdgeSharp_material_index_right_doc,
nullptr},
{"material_index_left",
(getter)FEdgeSharp_material_index_left_get,
(setter)FEdgeSharp_material_index_left_set,
FEdgeSharp_material_index_left_doc,
nullptr},
{"material_right",
(getter)FEdgeSharp_material_right_get,
(setter) nullptr,
FEdgeSharp_material_right_doc,
nullptr},
{"material_left",
(getter)FEdgeSharp_material_left_get,
(setter) nullptr,
FEdgeSharp_material_left_doc,
nullptr},
{"face_mark_right",
(getter)FEdgeSharp_face_mark_right_get,
(setter)FEdgeSharp_face_mark_right_set,
FEdgeSharp_face_mark_right_doc,
nullptr},
{"face_mark_left",
(getter)FEdgeSharp_face_mark_left_get,
(setter)FEdgeSharp_face_mark_left_set,
FEdgeSharp_face_mark_left_doc,
nullptr},
{nullptr, nullptr, nullptr, nullptr, nullptr} /* Sentinel */
};
/*-----------------------BPy_FEdgeSharp type definition ------------------------------*/
PyTypeObject FEdgeSharp_Type = {
/*ob_base*/ PyVarObject_HEAD_INIT(nullptr, 0)
/*tp_name*/ "FEdgeSharp",
/*tp_basicsize*/ sizeof(BPy_FEdgeSharp),
/*tp_itemsize*/ 0,
/*tp_dealloc*/ nullptr,
/*tp_vectorcall_offset*/ 0,
/*tp_getattr*/ nullptr,
/*tp_setattr*/ nullptr,
/*tp_as_async*/ nullptr,
/*tp_repr*/ nullptr,
/*tp_as_number*/ nullptr,
/*tp_as_sequence*/ nullptr,
/*tp_as_mapping*/ nullptr,
/*tp_hash*/ nullptr,
/*tp_call*/ nullptr,
/*tp_str*/ nullptr,
/*tp_getattro*/ nullptr,
/*tp_setattro*/ nullptr,
/*tp_as_buffer*/ nullptr,
/*tp_flags*/ Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE,
/*tp_doc*/ FEdgeSharp_doc,
/*tp_traverse*/ nullptr,
/*tp_clear*/ nullptr,
/*tp_richcompare*/ nullptr,
/*tp_weaklistoffset*/ 0,
/*tp_iter*/ nullptr,
/*tp_iternext*/ nullptr,
/*tp_methods*/ nullptr,
/*tp_members*/ nullptr,
/*tp_getset*/ BPy_FEdgeSharp_getseters,
/*tp_base*/ &FEdge_Type,
/*tp_dict*/ nullptr,
/*tp_descr_get*/ nullptr,
/*tp_descr_set*/ nullptr,
/*tp_dictoffset*/ 0,
/*tp_init*/ (initproc)FEdgeSharp_init,
/*tp_alloc*/ nullptr,
/*tp_new*/ nullptr,
};
///////////////////////////////////////////////////////////////////////////////////////////

View File

@@ -0,0 +1,31 @@
/* SPDX-FileCopyrightText: 2023 Blender Authors
*
* SPDX-License-Identifier: GPL-2.0-or-later */
/** \file
* \ingroup freestyle
*/
#pragma once
#include "../BPy_FEdge.h"
#include "../../../view_map/Silhouette.h"
///////////////////////////////////////////////////////////////////////////////////////////
extern PyTypeObject FEdgeSharp_Type;
#define BPy_FEdgeSharp_Check(v) (PyObject_IsInstance((PyObject *)v, (PyObject *)&FEdgeSharp_Type))
/*---------------------------Python BPy_FEdgeSharp structure definition----------*/
struct BPy_FEdgeSharp {
BPy_FEdge py_fe;
Freestyle::FEdgeSharp *fes;
};
/*---------------------------Python BPy_FEdgeSharp visible prototypes-----------*/
void FEdgeSharp_mathutils_register_callback();
///////////////////////////////////////////////////////////////////////////////////////////

View File

@@ -0,0 +1,289 @@
/* SPDX-FileCopyrightText: 2004-2023 Blender Authors
*
* SPDX-License-Identifier: GPL-2.0-or-later */
/** \file
* \ingroup freestyle
*/
#include "BPy_FEdgeSmooth.h"
#include "../../BPy_Convert.h"
#include "../../Interface0D/BPy_SVertex.h"
#include "BLI_sys_types.h"
using namespace Freestyle;
///////////////////////////////////////////////////////////////////////////////////////////
/*----------------------FEdgeSmooth methods ----------------------------*/
PyDoc_STRVAR(
/* Wrap. */
FEdgeSmooth_doc,
"Class hierarchy: :class:`Interface1D` > :class:`FEdge` > :class:`FEdgeSmooth`\n"
"\n"
"Class defining a smooth edge. This kind of edge typically runs across\n"
"a face of the input mesh. It can be a silhouette, a ridge or valley,\n"
"a suggestive contour.\n"
"\n"
".. method:: __init__(*args)\n"
"\n"
" Accepted call signatures:\n"
"\n"
" - ``__init__()``\n"
" - ``__init__(brother)``\n"
" - ``__init__(first_vertex, second_vertex)``\n"
"\n"
" Builds an :class:`FEdgeSmooth` using the default constructor,\n"
" copy constructor, or between two :class:`SVertex`.\n"
"\n"
" :param brother: An FEdgeSmooth object.\n"
" :type brother: :class:`FEdgeSmooth`\n"
" :param first_vertex: The first SVertex object.\n"
" :type first_vertex: :class:`SVertex`\n"
" :param second_vertex: The second SVertex object.\n"
" :type second_vertex: :class:`SVertex`\n");
static int FEdgeSmooth_init(BPy_FEdgeSmooth *self, PyObject *args, PyObject *kwds)
{
static const char *kwlist_1[] = {"brother", nullptr};
static const char *kwlist_2[] = {"first_vertex", "second_vertex", nullptr};
PyObject *obj1 = nullptr, *obj2 = nullptr;
if (PyArg_ParseTupleAndKeywords(args, kwds, "|O!", (char **)kwlist_1, &FEdgeSmooth_Type, &obj1))
{
if (!obj1) {
self->fes = new FEdgeSmooth();
}
else {
self->fes = new FEdgeSmooth(*(((BPy_FEdgeSmooth *)obj1)->fes));
}
}
else if ((void)PyErr_Clear(),
PyArg_ParseTupleAndKeywords(
args, kwds, "O!O!", (char **)kwlist_2, &SVertex_Type, &obj1, &SVertex_Type, &obj2))
{
self->fes = new FEdgeSmooth(((BPy_SVertex *)obj1)->sv, ((BPy_SVertex *)obj2)->sv);
}
else {
PyErr_SetString(PyExc_TypeError, "invalid argument(s)");
return -1;
}
self->py_fe.fe = self->fes;
self->py_fe.py_if1D.if1D = self->fes;
self->py_fe.py_if1D.borrowed = false;
return 0;
}
/*----------------------mathutils callbacks ----------------------------*/
static int FEdgeSmooth_mathutils_check(blender::BaseMathObject *bmo)
{
if (!BPy_FEdgeSmooth_Check(bmo->cb_user)) {
return -1;
}
return 0;
}
static int FEdgeSmooth_mathutils_get(blender::BaseMathObject *bmo, int /*subtype*/)
{
BPy_FEdgeSmooth *self = (BPy_FEdgeSmooth *)bmo->cb_user;
Vec3r p(self->fes->normal());
bmo->data[0] = p[0];
bmo->data[1] = p[1];
bmo->data[2] = p[2];
return 0;
}
static int FEdgeSmooth_mathutils_set(blender::BaseMathObject *bmo, int /*subtype*/)
{
BPy_FEdgeSmooth *self = (BPy_FEdgeSmooth *)bmo->cb_user;
Vec3r p(bmo->data[0], bmo->data[1], bmo->data[2]);
self->fes->setNormal(p);
return 0;
}
static int FEdgeSmooth_mathutils_get_index(blender::BaseMathObject *bmo,
int /*subtype*/,
int index)
{
BPy_FEdgeSmooth *self = (BPy_FEdgeSmooth *)bmo->cb_user;
Vec3r p(self->fes->normal());
bmo->data[index] = p[index];
return 0;
}
static int FEdgeSmooth_mathutils_set_index(blender::BaseMathObject *bmo,
int /*subtype*/,
int index)
{
BPy_FEdgeSmooth *self = (BPy_FEdgeSmooth *)bmo->cb_user;
Vec3r p(self->fes->normal());
p[index] = bmo->data[index];
self->fes->setNormal(p);
return 0;
}
static blender::Mathutils_Callback FEdgeSmooth_mathutils_cb = {
FEdgeSmooth_mathutils_check,
FEdgeSmooth_mathutils_get,
FEdgeSmooth_mathutils_set,
FEdgeSmooth_mathutils_get_index,
FEdgeSmooth_mathutils_set_index,
};
static uchar FEdgeSmooth_mathutils_cb_index = -1;
void FEdgeSmooth_mathutils_register_callback()
{
FEdgeSmooth_mathutils_cb_index = Mathutils_RegisterCallback(&FEdgeSmooth_mathutils_cb);
}
/*----------------------FEdgeSmooth get/setters ----------------------------*/
PyDoc_STRVAR(
/* Wrap. */
FEdgeSmooth_normal_doc,
"The normal of the face that this FEdge is running across.\n"
"\n"
":type: :class:`mathutils.Vector`\n");
static PyObject *FEdgeSmooth_normal_get(BPy_FEdgeSmooth *self, void * /*closure*/)
{
return blender::Vector_CreatePyObject_cb((PyObject *)self, 3, FEdgeSmooth_mathutils_cb_index, 0);
}
static int FEdgeSmooth_normal_set(BPy_FEdgeSmooth *self, PyObject *value, void * /*closure*/)
{
float v[3];
if (blender::mathutils_array_parse(v, 3, 3, value, "value must be a 3-dimensional vector") == -1)
{
return -1;
}
Vec3r p(v[0], v[1], v[2]);
self->fes->setNormal(p);
return 0;
}
PyDoc_STRVAR(
/* Wrap. */
FEdgeSmooth_material_index_doc,
"The index of the material of the face that this FEdge is running across.\n"
"\n"
":type: int\n");
static PyObject *FEdgeSmooth_material_index_get(BPy_FEdgeSmooth *self, void * /*closure*/)
{
return PyLong_FromLong(self->fes->frs_materialIndex());
}
static int FEdgeSmooth_material_index_set(BPy_FEdgeSmooth *self,
PyObject *value,
void * /*closure*/)
{
uint i = PyLong_AsUnsignedLong(value);
if (PyErr_Occurred()) {
return -1;
}
self->fes->setFrsMaterialIndex(i);
return 0;
}
PyDoc_STRVAR(
/* Wrap. */
FEdgeSmooth_material_doc,
"The material of the face that this FEdge is running across.\n"
"\n"
":type: :class:`Material`\n");
static PyObject *FEdgeSmooth_material_get(BPy_FEdgeSmooth *self, void * /*closure*/)
{
return BPy_FrsMaterial_from_FrsMaterial(self->fes->frs_material());
}
PyDoc_STRVAR(
/* Wrap. */
FEdgeSmooth_face_mark_doc,
"The face mark of the face that this FEdge is running across.\n"
"\n"
":type: bool\n");
static PyObject *FEdgeSmooth_face_mark_get(BPy_FEdgeSmooth *self, void * /*closure*/)
{
return PyBool_from_bool(self->fes->faceMark());
}
static int FEdgeSmooth_face_mark_set(BPy_FEdgeSmooth *self, PyObject *value, void * /*closure*/)
{
if (!PyBool_Check(value)) {
return -1;
}
self->fes->setFaceMark(bool_from_PyBool(value));
return 0;
}
static PyGetSetDef BPy_FEdgeSmooth_getseters[] = {
{"normal",
(getter)FEdgeSmooth_normal_get,
(setter)FEdgeSmooth_normal_set,
FEdgeSmooth_normal_doc,
nullptr},
{"material_index",
(getter)FEdgeSmooth_material_index_get,
(setter)FEdgeSmooth_material_index_set,
FEdgeSmooth_material_index_doc,
nullptr},
{"material",
(getter)FEdgeSmooth_material_get,
(setter) nullptr,
FEdgeSmooth_material_doc,
nullptr},
{"face_mark",
(getter)FEdgeSmooth_face_mark_get,
(setter)FEdgeSmooth_face_mark_set,
FEdgeSmooth_face_mark_doc,
nullptr},
{nullptr, nullptr, nullptr, nullptr, nullptr} /* Sentinel */
};
/*-----------------------BPy_FEdgeSmooth type definition ------------------------------*/
PyTypeObject FEdgeSmooth_Type = {
/*ob_base*/ PyVarObject_HEAD_INIT(nullptr, 0)
/*tp_name*/ "FEdgeSmooth",
/*tp_basicsize*/ sizeof(BPy_FEdgeSmooth),
/*tp_itemsize*/ 0,
/*tp_dealloc*/ nullptr,
/*tp_vectorcall_offset*/ 0,
/*tp_getattr*/ nullptr,
/*tp_setattr*/ nullptr,
/*tp_as_async*/ nullptr,
/*tp_repr*/ nullptr,
/*tp_as_number*/ nullptr,
/*tp_as_sequence*/ nullptr,
/*tp_as_mapping*/ nullptr,
/*tp_hash*/ nullptr,
/*tp_call*/ nullptr,
/*tp_str*/ nullptr,
/*tp_getattro*/ nullptr,
/*tp_setattro*/ nullptr,
/*tp_as_buffer*/ nullptr,
/*tp_flags*/ Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE,
/*tp_doc*/ FEdgeSmooth_doc,
/*tp_traverse*/ nullptr,
/*tp_clear*/ nullptr,
/*tp_richcompare*/ nullptr,
/*tp_weaklistoffset*/ 0,
/*tp_iter*/ nullptr,
/*tp_iternext*/ nullptr,
/*tp_methods*/ nullptr,
/*tp_members*/ nullptr,
/*tp_getset*/ BPy_FEdgeSmooth_getseters,
/*tp_base*/ &FEdge_Type,
/*tp_dict*/ nullptr,
/*tp_descr_get*/ nullptr,
/*tp_descr_set*/ nullptr,
/*tp_dictoffset*/ 0,
/*tp_init*/ (initproc)FEdgeSmooth_init,
/*tp_alloc*/ nullptr,
/*tp_new*/ nullptr,
};
///////////////////////////////////////////////////////////////////////////////////////////

View File

@@ -0,0 +1,32 @@
/* SPDX-FileCopyrightText: 2023 Blender Authors
*
* SPDX-License-Identifier: GPL-2.0-or-later */
/** \file
* \ingroup freestyle
*/
#pragma once
#include "../BPy_FEdge.h"
#include "../../../view_map/Silhouette.h"
///////////////////////////////////////////////////////////////////////////////////////////
extern PyTypeObject FEdgeSmooth_Type;
#define BPy_FEdgeSmooth_Check(v) \
(PyObject_IsInstance((PyObject *)v, (PyObject *)&FEdgeSmooth_Type))
/*---------------------------Python BPy_FEdgeSmooth structure definition----------*/
struct BPy_FEdgeSmooth {
BPy_FEdge py_fe;
Freestyle::FEdgeSmooth *fes;
};
/*---------------------------Python BPy_FEdgeSmooth visible prototypes-----------*/
void FEdgeSmooth_mathutils_register_callback();
///////////////////////////////////////////////////////////////////////////////////////////

View File

@@ -0,0 +1,218 @@
/* SPDX-FileCopyrightText: 2004-2023 Blender Authors
*
* SPDX-License-Identifier: GPL-2.0-or-later */
/** \file
* \ingroup freestyle
*/
#include "BPy_AdjacencyIterator.h"
#include "../BPy_Convert.h"
#include "../Interface0D/BPy_ViewVertex.h"
using namespace Freestyle;
///////////////////////////////////////////////////////////////////////////////////////////
//------------------------INSTANCE METHODS ----------------------------------
PyDoc_STRVAR(
/* Wrap. */
AdjacencyIterator_doc,
"Class hierarchy: :class:`Iterator` > :class:`AdjacencyIterator`\n"
"\n"
"Class for representing adjacency iterators used in the chaining\n"
"process. An AdjacencyIterator is created in the increment() and\n"
"decrement() methods of a :class:`ChainingIterator` and passed to the\n"
"traverse() method of the ChainingIterator.\n"
"\n"
".. method:: __init__(*args, **kwargs)\n"
"\n"
" Accepted call signatures:\n"
"\n"
" - ``__init__()``\n"
" - ``__init__(brother)``\n"
" - ``__init__(vertex, restrict_to_selection=True, restrict_to_unvisited=True)``\n"
"\n"
" Builds an :class:`AdjacencyIterator` using the default constructor,\n"
" copy constructor or the overloaded constructor.\n"
"\n"
" :param brother: An AdjacencyIterator object.\n"
" :type brother: :class:`AdjacencyIterator`\n"
" :param vertex: The vertex which is the next crossing.\n"
" :type vertex: :class:`ViewVertex`\n"
" :param 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"
" :param 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");
static int AdjacencyIterator_init(BPy_AdjacencyIterator *self, PyObject *args, PyObject *kwds)
{
static const char *kwlist_1[] = {"brother", nullptr};
static const char *kwlist_2[] = {
"vertex", "restrict_to_selection", "restrict_to_unvisited", nullptr};
PyObject *obj1 = nullptr, *obj2 = nullptr, *obj3 = nullptr;
if (PyArg_ParseTupleAndKeywords(
args, kwds, "|O!", (char **)kwlist_1, &AdjacencyIterator_Type, &obj1))
{
if (!obj1) {
self->a_it = new AdjacencyIterator();
self->at_start = true;
}
else {
self->a_it = new AdjacencyIterator(*(((BPy_AdjacencyIterator *)obj1)->a_it));
self->at_start = ((BPy_AdjacencyIterator *)obj1)->at_start;
}
}
else if ((void)PyErr_Clear(),
(void)(obj2 = obj3 = nullptr),
PyArg_ParseTupleAndKeywords(args,
kwds,
"O!|O!O!",
(char **)kwlist_2,
&ViewVertex_Type,
&obj1,
&PyBool_Type,
&obj2,
&PyBool_Type,
&obj3))
{
bool restrictToSelection = (!obj2) ? true : bool_from_PyBool(obj2);
bool restrictToUnvisited = (!obj3) ? true : bool_from_PyBool(obj3);
self->a_it = new AdjacencyIterator(
((BPy_ViewVertex *)obj1)->vv, restrictToSelection, restrictToUnvisited);
self->at_start = ((BPy_AdjacencyIterator *)obj1)->at_start;
}
else {
PyErr_SetString(PyExc_TypeError, "invalid argument(s)");
return -1;
}
self->py_it.it = self->a_it;
return 0;
}
static PyObject *AdjacencyIterator_iter(BPy_AdjacencyIterator *self)
{
Py_INCREF(self);
self->at_start = true;
return (PyObject *)self;
}
static PyObject *AdjacencyIterator_iternext(BPy_AdjacencyIterator *self)
{
if (self->a_it->isEnd()) {
PyErr_SetNone(PyExc_StopIteration);
return nullptr;
}
if (self->at_start) {
self->at_start = false;
}
else {
self->a_it->increment();
if (self->a_it->isEnd()) {
PyErr_SetNone(PyExc_StopIteration);
return nullptr;
}
}
ViewEdge *ve = self->a_it->operator->();
return BPy_ViewEdge_from_ViewEdge(*ve);
}
/*----------------------AdjacencyIterator get/setters ----------------------------*/
PyDoc_STRVAR(
/* Wrap. */
AdjacencyIterator_object_doc,
"The ViewEdge object currently pointed to by this iterator.\n"
"\n"
":type: :class:`ViewEdge`\n");
static PyObject *AdjacencyIterator_object_get(BPy_AdjacencyIterator *self, void * /*closure*/)
{
if (self->a_it->isEnd()) {
PyErr_SetString(PyExc_RuntimeError, "iteration has stopped");
return nullptr;
}
ViewEdge *ve = self->a_it->operator*();
if (ve) {
return BPy_ViewEdge_from_ViewEdge(*ve);
}
Py_RETURN_NONE;
}
PyDoc_STRVAR(
/* Wrap. */
AdjacencyIterator_is_incoming_doc,
"True if the current ViewEdge is coming towards the iteration vertex, and\n"
"False otherwise.\n"
"\n"
":type: bool\n");
static PyObject *AdjacencyIterator_is_incoming_get(BPy_AdjacencyIterator *self, void * /*closure*/)
{
if (self->a_it->isEnd()) {
PyErr_SetString(PyExc_RuntimeError, "iteration has stopped");
return nullptr;
}
return PyBool_from_bool(self->a_it->isIncoming());
}
static PyGetSetDef BPy_AdjacencyIterator_getseters[] = {
{"is_incoming",
(getter)AdjacencyIterator_is_incoming_get,
(setter) nullptr,
AdjacencyIterator_is_incoming_doc,
nullptr},
{"object",
(getter)AdjacencyIterator_object_get,
(setter) nullptr,
AdjacencyIterator_object_doc,
nullptr},
{nullptr, nullptr, nullptr, nullptr, nullptr} /* Sentinel */
};
/*-----------------------BPy_AdjacencyIterator type definition ------------------------------*/
PyTypeObject AdjacencyIterator_Type = {
/*ob_base*/ PyVarObject_HEAD_INIT(nullptr, 0)
/*tp_name*/ "AdjacencyIterator",
/*tp_basicsize*/ sizeof(BPy_AdjacencyIterator),
/*tp_itemsize*/ 0,
/*tp_dealloc*/ nullptr,
/*tp_vectorcall_offset*/ 0,
/*tp_getattr*/ nullptr,
/*tp_setattr*/ nullptr,
/*tp_as_async*/ nullptr,
/*tp_repr*/ nullptr,
/*tp_as_number*/ nullptr,
/*tp_as_sequence*/ nullptr,
/*tp_as_mapping*/ nullptr,
/*tp_hash*/ nullptr,
/*tp_call*/ nullptr,
/*tp_str*/ nullptr,
/*tp_getattro*/ nullptr,
/*tp_setattro*/ nullptr,
/*tp_as_buffer*/ nullptr,
/*tp_flags*/ Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE,
/*tp_doc*/ AdjacencyIterator_doc,
/*tp_traverse*/ nullptr,
/*tp_clear*/ nullptr,
/*tp_richcompare*/ nullptr,
/*tp_weaklistoffset*/ 0,
/*tp_iter*/ (getiterfunc)AdjacencyIterator_iter,
/*tp_iternext*/ (iternextfunc)AdjacencyIterator_iternext,
/*tp_methods*/ nullptr,
/*tp_members*/ nullptr,
/*tp_getset*/ BPy_AdjacencyIterator_getseters,
/*tp_base*/ &Iterator_Type,
/*tp_dict*/ nullptr,
/*tp_descr_get*/ nullptr,
/*tp_descr_set*/ nullptr,
/*tp_dictoffset*/ 0,
/*tp_init*/ (initproc)AdjacencyIterator_init,
/*tp_alloc*/ nullptr,
/*tp_new*/ nullptr,
};
///////////////////////////////////////////////////////////////////////////////////////////

View File

@@ -0,0 +1,29 @@
/* SPDX-FileCopyrightText: 2023 Blender Authors
*
* SPDX-License-Identifier: GPL-2.0-or-later */
/** \file
* \ingroup freestyle
*/
#pragma once
#include "../BPy_Iterator.h"
#include "../../stroke/ChainingIterators.h"
///////////////////////////////////////////////////////////////////////////////////////////
extern PyTypeObject AdjacencyIterator_Type;
#define BPy_AdjacencyIterator_Check(v) \
(PyObject_IsInstance((PyObject *)v, (PyObject *)&AdjacencyIterator_Type))
/*---------------------------Python BPy_AdjacencyIterator structure definition----------*/
struct BPy_AdjacencyIterator {
BPy_Iterator py_it;
Freestyle::AdjacencyIterator *a_it;
bool at_start;
};
///////////////////////////////////////////////////////////////////////////////////////////

View File

@@ -0,0 +1,197 @@
/* SPDX-FileCopyrightText: 2004-2023 Blender Authors
*
* SPDX-License-Identifier: GPL-2.0-or-later */
/** \file
* \ingroup freestyle
*/
#include "BPy_ChainPredicateIterator.h"
#include "../BPy_BinaryPredicate1D.h"
#include "../BPy_Convert.h"
#include "../BPy_UnaryPredicate1D.h"
#include "../Interface1D/BPy_ViewEdge.h"
using namespace Freestyle;
///////////////////////////////////////////////////////////////////////////////////////////
//------------------------INSTANCE METHODS ----------------------------------
PyDoc_STRVAR(
/* Wrap. */
ChainPredicateIterator_doc,
"Class hierarchy: :class:`freestyle.types.Iterator` >\n"
":class:`freestyle.types.ViewEdgeIterator` >\n"
":class:`freestyle.types.ChainingIterator` >\n"
":class:`ChainPredicateIterator`\n"
"\n"
"A \"generic\" user-controlled ViewEdge iterator. This iterator is in\n"
"particular built from a unary predicate and a binary predicate.\n"
"First, the unary predicate is evaluated for all potential next\n"
"ViewEdges in order to only keep the ones respecting a certain\n"
"constraint. Then, the binary predicate is evaluated on the current\n"
"ViewEdge together with each ViewEdge of the previous selection. The\n"
"first ViewEdge respecting both the unary predicate and the binary\n"
"predicate is kept as the next one. If none of the potential next\n"
"ViewEdge respects these two predicates, None is returned.\n"
"\n"
".. method:: __init__(*args)\n"
"\n"
" Accepted call signatures:\n"
"\n"
" - ``__init__(upred, bpred, restrict_to_selection=True, restrict_to_unvisited=True, "
"begin=None, orientation=True)``\n"
" - ``__init__(brother)``\n"
"\n"
" Builds a ChainPredicateIterator from a unary predicate, a binary\n"
" predicate, a starting ViewEdge and its orientation or using the copy constructor.\n"
"\n"
" :param upred: The unary predicate that the next ViewEdge must satisfy.\n"
" :type upred: :class:`freestyle.types.UnaryPredicate1D`\n"
" :param bpred: The binary predicate that the next ViewEdge must\n"
" satisfy together with the actual pointed ViewEdge.\n"
" :type bpred: :class:`freestyle.types.BinaryPredicate1D`\n"
" :param 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"
" :param 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"
" :param begin: The ViewEdge from where to start the iteration.\n"
" :type begin: :class:`freestyle.types.ViewEdge` | None\n"
" :param orientation: If true, we'll look for the next ViewEdge among\n"
" the ViewEdges that surround the ending ViewVertex of begin. If\n"
" false, we'll search over the ViewEdges surrounding the ending\n"
" ViewVertex of begin.\n"
" :type orientation: bool\n"
" :param brother: A ChainPredicateIterator object.\n"
" :type brother: :class:`ChainPredicateIterator`\n");
static int check_begin(PyObject *obj, void *v)
{
if (obj != nullptr && obj != Py_None && !BPy_ViewEdge_Check(obj)) {
return 0;
}
*((PyObject **)v) = obj;
return 1;
}
static int ChainPredicateIterator_init(BPy_ChainPredicateIterator *self,
PyObject *args,
PyObject *kwds)
{
static const char *kwlist_1[] = {"brother", nullptr};
static const char *kwlist_2[] = {"upred",
"bpred",
"restrict_to_selection",
"restrict_to_unvisited",
"begin",
"orientation",
nullptr};
PyObject *obj1 = nullptr, *obj2 = nullptr, *obj3 = nullptr, *obj4 = nullptr, *obj5 = nullptr,
*obj6 = nullptr;
if (PyArg_ParseTupleAndKeywords(
args, kwds, "O!", (char **)kwlist_1, &ChainPredicateIterator_Type, &obj1))
{
self->cp_it = new ChainPredicateIterator(*(((BPy_ChainPredicateIterator *)obj1)->cp_it));
self->upred = ((BPy_ChainPredicateIterator *)obj1)->upred;
self->bpred = ((BPy_ChainPredicateIterator *)obj1)->bpred;
Py_INCREF(self->upred);
Py_INCREF(self->bpred);
}
else if ((void)PyErr_Clear(),
(void)(obj3 = obj4 = obj5 = obj6 = nullptr),
PyArg_ParseTupleAndKeywords(args,
kwds,
"O!O!|O!O!O&O!",
(char **)kwlist_2,
&UnaryPredicate1D_Type,
&obj1,
&BinaryPredicate1D_Type,
&obj2,
&PyBool_Type,
&obj3,
&PyBool_Type,
&obj4,
check_begin,
&obj5,
&PyBool_Type,
&obj6))
{
UnaryPredicate1D *up1D = ((BPy_UnaryPredicate1D *)obj1)->up1D;
BinaryPredicate1D *bp1D = ((BPy_BinaryPredicate1D *)obj2)->bp1D;
bool restrict_to_selection = (!obj3) ? true : bool_from_PyBool(obj3);
bool restrict_to_unvisited = (!obj4) ? true : bool_from_PyBool(obj4);
ViewEdge *begin = (!obj5 || obj5 == Py_None) ? nullptr : ((BPy_ViewEdge *)obj5)->ve;
bool orientation = (!obj6) ? true : bool_from_PyBool(obj6);
self->cp_it = new ChainPredicateIterator(
*up1D, *bp1D, restrict_to_selection, restrict_to_unvisited, begin, orientation);
self->upred = obj1;
self->bpred = obj2;
Py_INCREF(self->upred);
Py_INCREF(self->bpred);
}
else {
PyErr_SetString(PyExc_TypeError, "invalid argument(s)");
return -1;
}
self->py_c_it.c_it = self->cp_it;
self->py_c_it.py_ve_it.ve_it = self->cp_it;
self->py_c_it.py_ve_it.py_it.it = self->cp_it;
return 0;
}
static void ChainPredicateIterator_dealloc(BPy_ChainPredicateIterator *self)
{
Py_XDECREF(self->upred);
Py_XDECREF(self->bpred);
ChainingIterator_Type.tp_dealloc((PyObject *)self);
}
/*-----------------------BPy_ChainPredicateIterator type definition ----------------------------*/
PyTypeObject ChainPredicateIterator_Type = {
/*ob_base*/ PyVarObject_HEAD_INIT(nullptr, 0)
/*tp_name*/ "ChainPredicateIterator",
/*tp_basicsize*/ sizeof(BPy_ChainPredicateIterator),
/*tp_itemsize*/ 0,
/*tp_dealloc*/ (destructor)ChainPredicateIterator_dealloc,
/*tp_vectorcall_offset*/ 0,
/*tp_getattr*/ nullptr,
/*tp_setattr*/ nullptr,
/*tp_as_async*/ nullptr,
/*tp_repr*/ nullptr,
/*tp_as_number*/ nullptr,
/*tp_as_sequence*/ nullptr,
/*tp_as_mapping*/ nullptr,
/*tp_hash*/ nullptr,
/*tp_call*/ nullptr,
/*tp_str*/ nullptr,
/*tp_getattro*/ nullptr,
/*tp_setattro*/ nullptr,
/*tp_as_buffer*/ nullptr,
/*tp_flags*/ Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE,
/*tp_doc*/ ChainPredicateIterator_doc,
/*tp_traverse*/ nullptr,
/*tp_clear*/ nullptr,
/*tp_richcompare*/ nullptr,
/*tp_weaklistoffset*/ 0,
/*tp_iter*/ nullptr,
/*tp_iternext*/ nullptr,
/*tp_methods*/ nullptr,
/*tp_members*/ nullptr,
/*tp_getset*/ nullptr,
/*tp_base*/ &ChainingIterator_Type,
/*tp_dict*/ nullptr,
/*tp_descr_get*/ nullptr,
/*tp_descr_set*/ nullptr,
/*tp_dictoffset*/ 0,
/*tp_init*/ (initproc)ChainPredicateIterator_init,
/*tp_alloc*/ nullptr,
/*tp_new*/ nullptr,
};
///////////////////////////////////////////////////////////////////////////////////////////

View File

@@ -0,0 +1,30 @@
/* SPDX-FileCopyrightText: 2023 Blender Authors
*
* SPDX-License-Identifier: GPL-2.0-or-later */
/** \file
* \ingroup freestyle
*/
#pragma once
#include "BPy_ChainingIterator.h"
#include "../../stroke/ChainingIterators.h"
///////////////////////////////////////////////////////////////////////////////////////////
extern PyTypeObject ChainPredicateIterator_Type;
#define BPy_ChainPredicateIterator_Check(v) \
(PyObject_IsInstance((PyObject *)v, (PyObject *)&ChainPredicateIterator_Type))
/*---------------------------Python BPy_ChainPredicateIterator structure definition----------*/
struct BPy_ChainPredicateIterator {
BPy_ChainingIterator py_c_it;
Freestyle::ChainPredicateIterator *cp_it;
PyObject *upred;
PyObject *bpred;
};
///////////////////////////////////////////////////////////////////////////////////////////

View File

@@ -0,0 +1,153 @@
/* SPDX-FileCopyrightText: 2004-2023 Blender Authors
*
* SPDX-License-Identifier: GPL-2.0-or-later */
/** \file
* \ingroup freestyle
*/
#include "BPy_ChainSilhouetteIterator.h"
#include "../BPy_Convert.h"
#include "../Interface1D/BPy_ViewEdge.h"
using namespace Freestyle;
///////////////////////////////////////////////////////////////////////////////////////////
//------------------------INSTANCE METHODS ----------------------------------
// ChainSilhouetteIterator (bool restrict_to_selection=true, ViewEdge *begin=nullptr, bool
// orientation=true) ChainSilhouetteIterator (const ChainSilhouetteIterator &brother)
PyDoc_STRVAR(
/* Wrap. */
ChainSilhouetteIterator_doc,
"Class hierarchy: :class:`freestyle.types.Iterator` >\n"
":class:`freestyle.types.ViewEdgeIterator` >\n"
":class:`freestyle.types.ChainingIterator` >\n"
":class:`ChainSilhouetteIterator`\n"
"\n"
"A ViewEdge Iterator used to follow ViewEdges the most naturally. For\n"
"example, it will follow visible ViewEdges of same nature. As soon, as\n"
"the nature or the visibility changes, the iteration stops (by setting\n"
"the pointed ViewEdge to 0). In the case of an iteration over a set of\n"
"ViewEdge that are both Silhouette and Crease, there will be a\n"
"precedence of the silhouette over the crease criterion.\n"
"\n"
".. method:: __init__(*args)\n"
"\n"
" Accepted call signatures:\n"
"\n"
" - ``__init__(restrict_to_selection=True, begin=None, orientation=True)``\n"
" - ``__init__(brother)``\n"
"\n"
" Builds a ChainSilhouetteIterator from the first ViewEdge used for\n"
" iteration and its orientation or the copy constructor.\n"
"\n"
" :param 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"
" :param begin: The ViewEdge from where to start the iteration.\n"
" :type begin: :class:`freestyle.types.ViewEdge` | None\n"
" :param orientation: If true, we'll look for the next ViewEdge among\n"
" the ViewEdges that surround the ending ViewVertex of begin. If\n"
" false, we'll search over the ViewEdges surrounding the ending\n"
" ViewVertex of begin.\n"
" :type orientation: bool\n"
" :param brother: A ChainSilhouetteIterator object.\n"
" :type brother: :class:`ChainSilhouetteIterator`\n");
static int check_begin(PyObject *obj, void *v)
{
if (obj != nullptr && obj != Py_None && !BPy_ViewEdge_Check(obj)) {
return 0;
}
*((PyObject **)v) = obj;
return 1;
}
static int ChainSilhouetteIterator_init(BPy_ChainSilhouetteIterator *self,
PyObject *args,
PyObject *kwds)
{
static const char *kwlist_1[] = {"brother", nullptr};
static const char *kwlist_2[] = {"restrict_to_selection", "begin", "orientation", nullptr};
PyObject *obj1 = nullptr, *obj2 = nullptr, *obj3 = nullptr;
if (PyArg_ParseTupleAndKeywords(
args, kwds, "O!", (char **)kwlist_1, &ChainSilhouetteIterator_Type, &obj1))
{
self->cs_it = new ChainSilhouetteIterator(*(((BPy_ChainSilhouetteIterator *)obj1)->cs_it));
}
else if ((void)PyErr_Clear(),
(void)(obj1 = obj2 = obj3 = nullptr),
PyArg_ParseTupleAndKeywords(args,
kwds,
"|O!O&O!",
(char **)kwlist_2,
&PyBool_Type,
&obj1,
check_begin,
&obj2,
&PyBool_Type,
&obj3))
{
bool restrict_to_selection = (!obj1) ? true : bool_from_PyBool(obj1);
ViewEdge *begin = (!obj2 || obj2 == Py_None) ? nullptr : ((BPy_ViewEdge *)obj2)->ve;
bool orientation = (!obj3) ? true : bool_from_PyBool(obj3);
self->cs_it = new ChainSilhouetteIterator(restrict_to_selection, begin, orientation);
}
else {
PyErr_SetString(PyExc_TypeError, "invalid argument(s)");
return -1;
}
self->py_c_it.c_it = self->cs_it;
self->py_c_it.py_ve_it.ve_it = self->cs_it;
self->py_c_it.py_ve_it.py_it.it = self->cs_it;
return 0;
}
/*-----------------------BPy_ChainSilhouetteIterator type definition ----------------------------*/
PyTypeObject ChainSilhouetteIterator_Type = {
/*ob_base*/ PyVarObject_HEAD_INIT(nullptr, 0)
/*tp_name*/ "ChainSilhouetteIterator",
/*tp_basicsize*/ sizeof(BPy_ChainSilhouetteIterator),
/*tp_itemsize*/ 0,
/*tp_dealloc*/ nullptr,
/*tp_vectorcall_offset*/ 0,
/*tp_getattr*/ nullptr,
/*tp_setattr*/ nullptr,
/*tp_as_async*/ nullptr,
/*tp_repr*/ nullptr,
/*tp_as_number*/ nullptr,
/*tp_as_sequence*/ nullptr,
/*tp_as_mapping*/ nullptr,
/*tp_hash*/ nullptr,
/*tp_call*/ nullptr,
/*tp_str*/ nullptr,
/*tp_getattro*/ nullptr,
/*tp_setattro*/ nullptr,
/*tp_as_buffer*/ nullptr,
/*tp_flags*/ Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE,
/*tp_doc*/ ChainSilhouetteIterator_doc,
/*tp_traverse*/ nullptr,
/*tp_clear*/ nullptr,
/*tp_richcompare*/ nullptr,
/*tp_weaklistoffset*/ 0,
/*tp_iter*/ nullptr,
/*tp_iternext*/ nullptr,
/*tp_methods*/ nullptr,
/*tp_members*/ nullptr,
/*tp_getset*/ nullptr,
/*tp_base*/ &ChainingIterator_Type,
/*tp_dict*/ nullptr,
/*tp_descr_get*/ nullptr,
/*tp_descr_set*/ nullptr,
/*tp_dictoffset*/ 0,
/*tp_init*/ (initproc)ChainSilhouetteIterator_init,
/*tp_alloc*/ nullptr,
/*tp_new*/ nullptr,
};
///////////////////////////////////////////////////////////////////////////////////////////

View File

@@ -0,0 +1,28 @@
/* SPDX-FileCopyrightText: 2023 Blender Authors
*
* SPDX-License-Identifier: GPL-2.0-or-later */
/** \file
* \ingroup freestyle
*/
#pragma once
#include "BPy_ChainingIterator.h"
#include "../../stroke/ChainingIterators.h"
///////////////////////////////////////////////////////////////////////////////////////////
extern PyTypeObject ChainSilhouetteIterator_Type;
#define BPy_ChainSilhouetteIterator_Check(v) \
(PyObject_IsInstance((PyObject *)v, (PyObject *)&ChainSilhouetteIterator_Type))
/*---------------------------Python BPy_ChainSilhouetteIterator structure definition----------*/
struct BPy_ChainSilhouetteIterator {
BPy_ChainingIterator py_c_it;
Freestyle::ChainSilhouetteIterator *cs_it;
};
///////////////////////////////////////////////////////////////////////////////////////////

View File

@@ -0,0 +1,309 @@
/* SPDX-FileCopyrightText: 2004-2023 Blender Authors
*
* SPDX-License-Identifier: GPL-2.0-or-later */
/** \file
* \ingroup freestyle
*/
#include "BPy_ChainingIterator.h"
#include "../BPy_Convert.h"
#include "../Interface0D/BPy_ViewVertex.h"
#include "../Interface1D/BPy_ViewEdge.h"
#include "BPy_AdjacencyIterator.h"
using namespace Freestyle;
///////////////////////////////////////////////////////////////////////////////////////////
//------------------------INSTANCE METHODS ----------------------------------
PyDoc_STRVAR(
/* Wrap. */
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__(*args)\n"
"\n"
" Accepted call signatures:\n"
"\n"
" - ``__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"
" :param 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"
" :param 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"
" :param begin: The ViewEdge from which to start the chain.\n"
" :type begin: :class:`ViewEdge` | None\n"
" :param 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"
" :param brother: \n"
" :type brother: ChainingIterator\n");
static int check_begin(PyObject *obj, void *v)
{
if (obj != nullptr && obj != Py_None && !BPy_ViewEdge_Check(obj)) {
return 0;
}
*((PyObject **)v) = obj;
return 1;
}
static int ChainingIterator___init__(BPy_ChainingIterator *self, PyObject *args, PyObject *kwds)
{
static const char *kwlist_1[] = {"brother", nullptr};
static const char *kwlist_2[] = {
"restrict_to_selection", "restrict_to_unvisited", "begin", "orientation", nullptr};
PyObject *obj1 = nullptr, *obj2 = nullptr, *obj3 = nullptr, *obj4 = nullptr;
if (PyArg_ParseTupleAndKeywords(
args, kwds, "O!", (char **)kwlist_1, &ChainingIterator_Type, &obj1))
{
self->c_it = new ChainingIterator(*(((BPy_ChainingIterator *)obj1)->c_it));
}
else if ((void)PyErr_Clear(),
(void)(obj1 = obj2 = obj3 = obj4 = nullptr),
PyArg_ParseTupleAndKeywords(args,
kwds,
"|O!O!O&O!",
(char **)kwlist_2,
&PyBool_Type,
&obj1,
&PyBool_Type,
&obj2,
check_begin,
&obj3,
&PyBool_Type,
&obj4))
{
bool restrict_to_selection = (!obj1) ? true : bool_from_PyBool(obj1);
bool restrict_to_unvisited = (!obj2) ? true : bool_from_PyBool(obj2);
ViewEdge *begin = (!obj3 || obj3 == Py_None) ? nullptr : ((BPy_ViewEdge *)obj3)->ve;
bool orientation = (!obj4) ? true : bool_from_PyBool(obj4);
self->c_it = new ChainingIterator(
restrict_to_selection, restrict_to_unvisited, begin, orientation);
}
else {
PyErr_SetString(PyExc_TypeError, "invalid argument(s)");
return -1;
}
self->py_ve_it.ve_it = self->c_it;
self->py_ve_it.py_it.it = self->c_it;
self->c_it->py_c_it = (PyObject *)self;
return 0;
}
PyDoc_STRVAR(
/* Wrap. */
ChainingIterator_init_doc,
".. method:: init()\n"
"\n"
" Initializes the iterator context. This method is called each\n"
" time a new chain is started. It can be used to reset some\n"
" history information that you might want to keep.\n");
static PyObject *ChainingIterator_init(BPy_ChainingIterator *self)
{
if (typeid(*(self->c_it)) == typeid(ChainingIterator)) {
PyErr_SetString(PyExc_TypeError, "init() method not properly overridden");
return nullptr;
}
self->c_it->init();
Py_RETURN_NONE;
}
PyDoc_STRVAR(
/* Wrap. */
ChainingIterator_traverse_doc,
".. method:: traverse(it)\n"
"\n"
" This method iterates over the potential next ViewEdges and returns\n"
" the one that will be followed next. Returns the next ViewEdge to\n"
" follow or None when the end of the chain is reached.\n"
"\n"
" :param it: The iterator over the ViewEdges adjacent to the end vertex\n"
" of the current ViewEdge. The adjacency iterator reflects the\n"
" restriction rules by only iterating over the valid ViewEdges.\n"
" :type it: :class:`AdjacencyIterator`\n"
" :return: Returns the next ViewEdge to follow, or None if chaining ends.\n"
" :rtype: :class:`ViewEdge` | None\n");
static PyObject *ChainingIterator_traverse(BPy_ChainingIterator *self,
PyObject *args,
PyObject *kwds)
{
static const char *kwlist[] = {"it", nullptr};
PyObject *py_a_it;
if (typeid(*(self->c_it)) == typeid(ChainingIterator)) {
PyErr_SetString(PyExc_TypeError, "traverse() method not properly overridden");
return nullptr;
}
if (!PyArg_ParseTupleAndKeywords(
args, kwds, "O!", (char **)kwlist, &AdjacencyIterator_Type, &py_a_it))
{
return nullptr;
}
if (((BPy_AdjacencyIterator *)py_a_it)->a_it) {
self->c_it->traverse(*(((BPy_AdjacencyIterator *)py_a_it)->a_it));
}
Py_RETURN_NONE;
}
#ifdef __GNUC__
# ifdef __clang__
# pragma clang diagnostic push
# pragma clang diagnostic ignored "-Wcast-function-type"
# else
# pragma GCC diagnostic push
# pragma GCC diagnostic ignored "-Wcast-function-type"
# endif
#endif
static PyMethodDef BPy_ChainingIterator_methods[] = {
{"init", (PyCFunction)ChainingIterator_init, METH_NOARGS, ChainingIterator_init_doc},
{"traverse",
(PyCFunction)ChainingIterator_traverse,
METH_VARARGS | METH_KEYWORDS,
ChainingIterator_traverse_doc},
{nullptr, nullptr, 0, nullptr},
};
#ifdef __GNUC__
# ifdef __clang__
# pragma clang diagnostic pop
# else
# pragma GCC diagnostic pop
# endif
#endif
/*----------------------ChainingIterator get/setters ----------------------------*/
PyDoc_STRVAR(
/* Wrap. */
ChainingIterator_object_doc,
"The ViewEdge object currently pointed by this iterator.\n"
"\n"
":type: :class:`ViewEdge`\n");
static PyObject *ChainingIterator_object_get(BPy_ChainingIterator *self, void * /*closure*/)
{
if (self->c_it->isEnd()) {
PyErr_SetString(PyExc_RuntimeError, "iteration has stopped");
return nullptr;
}
ViewEdge *ve = self->c_it->operator*();
if (ve) {
return BPy_ViewEdge_from_ViewEdge(*ve);
}
Py_RETURN_NONE;
}
PyDoc_STRVAR(
/* Wrap. */
ChainingIterator_next_vertex_doc,
"The ViewVertex that is the next crossing.\n"
"\n"
":type: :class:`ViewVertex`\n");
static PyObject *ChainingIterator_next_vertex_get(BPy_ChainingIterator *self, void * /*closure*/)
{
ViewVertex *v = self->c_it->getVertex();
if (v) {
return Any_BPy_ViewVertex_from_ViewVertex(*v);
}
Py_RETURN_NONE;
}
PyDoc_STRVAR(
/* Wrap. */
ChainingIterator_is_incrementing_doc,
"True if the current iteration is an incrementation.\n"
"\n"
":type: bool\n");
static PyObject *ChainingIterator_is_incrementing_get(BPy_ChainingIterator *self,
void * /*closure*/)
{
return PyBool_from_bool(self->c_it->isIncrementing());
}
static PyGetSetDef BPy_ChainingIterator_getseters[] = {
{"object",
(getter)ChainingIterator_object_get,
(setter) nullptr,
ChainingIterator_object_doc,
nullptr},
{"next_vertex",
(getter)ChainingIterator_next_vertex_get,
(setter) nullptr,
ChainingIterator_next_vertex_doc,
nullptr},
{"is_incrementing",
(getter)ChainingIterator_is_incrementing_get,
(setter) nullptr,
ChainingIterator_is_incrementing_doc,
nullptr},
{nullptr, nullptr, nullptr, nullptr, nullptr} /* Sentinel */
};
/*-----------------------BPy_ChainingIterator type definition ------------------------------*/
PyTypeObject ChainingIterator_Type = {
/*ob_base*/ PyVarObject_HEAD_INIT(nullptr, 0)
/*tp_name*/ "ChainingIterator",
/*tp_basicsize*/ sizeof(BPy_ChainingIterator),
/*tp_itemsize*/ 0,
/*tp_dealloc*/ nullptr,
/*tp_vectorcall_offset*/ 0,
/*tp_getattr*/ nullptr,
/*tp_setattr*/ nullptr,
/*tp_as_async*/ nullptr,
/*tp_repr*/ nullptr,
/*tp_as_number*/ nullptr,
/*tp_as_sequence*/ nullptr,
/*tp_as_mapping*/ nullptr,
/*tp_hash*/ nullptr,
/*tp_call*/ nullptr,
/*tp_str*/ nullptr,
/*tp_getattro*/ nullptr,
/*tp_setattro*/ nullptr,
/*tp_as_buffer*/ nullptr,
/*tp_flags*/ Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE,
/*tp_doc*/ ChainingIterator_doc,
/*tp_traverse*/ nullptr,
/*tp_clear*/ nullptr,
/*tp_richcompare*/ nullptr,
/*tp_weaklistoffset*/ 0,
/*tp_iter*/ nullptr,
/*tp_iternext*/ nullptr,
/*tp_methods*/ BPy_ChainingIterator_methods,
/*tp_members*/ nullptr,
/*tp_getset*/ BPy_ChainingIterator_getseters,
/*tp_base*/ &ViewEdgeIterator_Type,
/*tp_dict*/ nullptr,
/*tp_descr_get*/ nullptr,
/*tp_descr_set*/ nullptr,
/*tp_dictoffset*/ 0,
/*tp_init*/ (initproc)ChainingIterator___init__,
/*tp_alloc*/ nullptr,
/*tp_new*/ nullptr,
};
///////////////////////////////////////////////////////////////////////////////////////////

View File

@@ -0,0 +1,28 @@
/* SPDX-FileCopyrightText: 2023 Blender Authors
*
* SPDX-License-Identifier: GPL-2.0-or-later */
/** \file
* \ingroup freestyle
*/
#pragma once
#include "BPy_ViewEdgeIterator.h"
#include "../../stroke/ChainingIterators.h"
///////////////////////////////////////////////////////////////////////////////////////////
extern PyTypeObject ChainingIterator_Type;
#define BPy_ChainingIterator_Check(v) \
(PyObject_IsInstance((PyObject *)v, (PyObject *)&ChainingIterator_Type))
/*---------------------------Python BPy_ChainingIterator structure definition----------*/
struct BPy_ChainingIterator {
BPy_ViewEdgeIterator py_ve_it;
Freestyle::ChainingIterator *c_it;
};
///////////////////////////////////////////////////////////////////////////////////////////

View File

@@ -0,0 +1,170 @@
/* SPDX-FileCopyrightText: 2004-2023 Blender Authors
*
* SPDX-License-Identifier: GPL-2.0-or-later */
/** \file
* \ingroup freestyle
*/
#include "BPy_CurvePointIterator.h"
#include "../BPy_Convert.h"
#include "BPy_Interface0DIterator.h"
using namespace Freestyle;
///////////////////////////////////////////////////////////////////////////////////////////
//------------------------INSTANCE METHODS ----------------------------------
PyDoc_STRVAR(
/* Wrap. */
CurvePointIterator_doc,
"Class hierarchy: :class:`Iterator` > :class:`CurvePointIterator`\n"
"\n"
"Class representing an iterator on a curve. Allows an iterating\n"
"outside initial vertices. A CurvePoint is instantiated and returned\n"
"through the .object attribute.\n"
"\n"
".. method:: __init__(*args, **kwargs)\n"
"\n"
" Accepted call signatures:\n"
"\n"
" - ``__init__()``\n"
" - ``__init__(brother)``\n"
" - ``__init__(step=0.0)``\n"
"\n"
" Builds a CurvePointIterator object using either the default constructor,\n"
" copy constructor, or the overloaded constructor.\n"
"\n"
" :param brother: A CurvePointIterator object.\n"
" :type brother: :class:`CurvePointIterator`\n"
" :param step: A resampling resolution with which the curve is resampled.\n"
" If zero, no resampling is done (i.e., the iterator iterates over\n"
" initial vertices).\n"
" :type step: float\n");
static int CurvePointIterator_init(BPy_CurvePointIterator *self, PyObject *args, PyObject *kwds)
{
static const char *kwlist_1[] = {"brother", nullptr};
static const char *kwlist_2[] = {"step", nullptr};
PyObject *brother = nullptr;
float step;
if (PyArg_ParseTupleAndKeywords(
args, kwds, "|O!", (char **)kwlist_1, &CurvePointIterator_Type, &brother))
{
if (!brother) {
self->cp_it = new CurveInternal::CurvePointIterator();
}
else {
self->cp_it = new CurveInternal::CurvePointIterator(
*(((BPy_CurvePointIterator *)brother)->cp_it));
}
}
else if ((void)PyErr_Clear(),
PyArg_ParseTupleAndKeywords(args, kwds, "f", (char **)kwlist_2, &step))
{
self->cp_it = new CurveInternal::CurvePointIterator(step);
}
else {
PyErr_SetString(PyExc_TypeError, "invalid argument(s)");
return -1;
}
self->py_it.it = self->cp_it;
return 0;
}
/*----------------------CurvePointIterator get/setters ----------------------------*/
PyDoc_STRVAR(
/* Wrap. */
CurvePointIterator_object_doc,
"The CurvePoint object currently pointed by this iterator.\n"
"\n"
":type: :class:`CurvePoint`\n");
static PyObject *CurvePointIterator_object_get(BPy_CurvePointIterator *self, void * /*closure*/)
{
if (self->cp_it->isEnd()) {
PyErr_SetString(PyExc_RuntimeError, "iteration has stopped");
return nullptr;
}
return BPy_CurvePoint_from_CurvePoint(self->cp_it->operator*());
}
PyDoc_STRVAR(
/* Wrap. */
CurvePointIterator_t_doc,
"The curvilinear abscissa of the current point.\n"
"\n"
":type: float\n");
static PyObject *CurvePointIterator_t_get(BPy_CurvePointIterator *self, void * /*closure*/)
{
return PyFloat_FromDouble(self->cp_it->t());
}
PyDoc_STRVAR(
/* Wrap. */
CurvePointIterator_u_doc,
"The point parameter at the current point in the stroke (0 <= u <= 1).\n"
"\n"
":type: float\n");
static PyObject *CurvePointIterator_u_get(BPy_CurvePointIterator *self, void * /*closure*/)
{
return PyFloat_FromDouble(self->cp_it->u());
}
static PyGetSetDef BPy_CurvePointIterator_getseters[] = {
{"object",
(getter)CurvePointIterator_object_get,
(setter) nullptr,
CurvePointIterator_object_doc,
nullptr},
{"t", (getter)CurvePointIterator_t_get, (setter) nullptr, CurvePointIterator_t_doc, nullptr},
{"u", (getter)CurvePointIterator_u_get, (setter) nullptr, CurvePointIterator_u_doc, nullptr},
{nullptr, nullptr, nullptr, nullptr, nullptr} /* Sentinel */
};
/*-----------------------BPy_CurvePointIterator type definition ------------------------------*/
PyTypeObject CurvePointIterator_Type = {
/*ob_base*/ PyVarObject_HEAD_INIT(nullptr, 0)
/*tp_name*/ "CurvePointIterator",
/*tp_basicsize*/ sizeof(BPy_CurvePointIterator),
/*tp_itemsize*/ 0,
/*tp_dealloc*/ nullptr,
/*tp_vectorcall_offset*/ 0,
/*tp_getattr*/ nullptr,
/*tp_setattr*/ nullptr,
/*tp_as_async*/ nullptr,
/*tp_repr*/ nullptr,
/*tp_as_number*/ nullptr,
/*tp_as_sequence*/ nullptr,
/*tp_as_mapping*/ nullptr,
/*tp_hash*/ nullptr,
/*tp_call*/ nullptr,
/*tp_str*/ nullptr,
/*tp_getattro*/ nullptr,
/*tp_setattro*/ nullptr,
/*tp_as_buffer*/ nullptr,
/*tp_flags*/ Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE,
/*tp_doc*/ CurvePointIterator_doc,
/*tp_traverse*/ nullptr,
/*tp_clear*/ nullptr,
/*tp_richcompare*/ nullptr,
/*tp_weaklistoffset*/ 0,
/*tp_iter*/ nullptr,
/*tp_iternext*/ nullptr,
/*tp_methods*/ nullptr,
/*tp_members*/ nullptr,
/*tp_getset*/ BPy_CurvePointIterator_getseters,
/*tp_base*/ &Iterator_Type,
/*tp_dict*/ nullptr,
/*tp_descr_get*/ nullptr,
/*tp_descr_set*/ nullptr,
/*tp_dictoffset*/ 0,
/*tp_init*/ (initproc)CurvePointIterator_init,
/*tp_alloc*/ nullptr,
/*tp_new*/ nullptr,
};
///////////////////////////////////////////////////////////////////////////////////////////

View File

@@ -0,0 +1,28 @@
/* SPDX-FileCopyrightText: 2023 Blender Authors
*
* SPDX-License-Identifier: GPL-2.0-or-later */
/** \file
* \ingroup freestyle
*/
#pragma once
#include "../BPy_Iterator.h"
#include "../../stroke/CurveIterators.h"
///////////////////////////////////////////////////////////////////////////////////////////
extern PyTypeObject CurvePointIterator_Type;
#define BPy_CurvePointIterator_Check(v) \
(PyObject_IsInstance((PyObject *)v, (PyObject *)&CurvePointIterator_Type))
/*---------------------------Python BPy_CurvePointIterator structure definition----------*/
struct BPy_CurvePointIterator {
BPy_Iterator py_it;
Freestyle::CurveInternal::CurvePointIterator *cp_it;
};
///////////////////////////////////////////////////////////////////////////////////////////

View File

@@ -0,0 +1,246 @@
/* SPDX-FileCopyrightText: 2004-2023 Blender Authors
*
* SPDX-License-Identifier: GPL-2.0-or-later */
/** \file
* \ingroup freestyle
*/
#include "BPy_Interface0DIterator.h"
#include "../BPy_Convert.h"
#include "../BPy_Interface1D.h"
using namespace Freestyle;
///////////////////////////////////////////////////////////////////////////////////////////
//------------------------INSTANCE METHODS ----------------------------------
PyDoc_STRVAR(
/* Wrap. */
Interface0DIterator_doc,
"Class hierarchy: :class:`Iterator` > :class:`Interface0DIterator`\n"
"\n"
"Class defining an iterator over Interface0D elements. An instance of\n"
"this iterator is always obtained from a 1D element.\n"
"\n"
".. method:: __init__(*args)\n"
"\n"
" Accepted call signatures:\n"
"\n"
" - ``__init__(brother)``\n"
" - ``__init__(it)``\n"
"\n"
" Construct a nested Interface0DIterator using either the copy constructor\n"
" or the constructor that takes an argument of a Function0D.\n"
"\n"
" :param brother: An Interface0DIterator object.\n"
" :type brother: :class:`Interface0DIterator`\n"
" :param it: An iterator object to be nested.\n"
" :type it: :class:`SVertexIterator` | :class:`CurvePointIterator` | "
":class:`StrokeVertexIterator`\n");
static int convert_nested_it(PyObject *obj, void *v)
{
if (!obj || !BPy_Iterator_Check(obj)) {
return 0;
}
Interface0DIteratorNested *nested_it = dynamic_cast<Interface0DIteratorNested *>(
((BPy_Iterator *)obj)->it);
if (!nested_it) {
return 0;
}
*((Interface0DIteratorNested **)v) = nested_it;
return 1;
}
static int Interface0DIterator_init(BPy_Interface0DIterator *self, PyObject *args, PyObject *kwds)
{
static const char *kwlist_1[] = {"it", nullptr};
static const char *kwlist_2[] = {"inter", nullptr};
static const char *kwlist_3[] = {"brother", nullptr};
Interface0DIteratorNested *nested_it;
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());
self->at_start = true;
self->reversed = false;
}
else if ((void)PyErr_Clear(),
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 ((void)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;
self->reversed = ((BPy_Interface0DIterator *)brother)->reversed;
}
else {
PyErr_SetString(PyExc_TypeError, "invalid argument(s)");
return -1;
}
self->py_it.it = self->if0D_it;
return 0;
}
static PyObject *Interface0DIterator_iter(BPy_Interface0DIterator *self)
{
Py_INCREF(self);
self->at_start = true;
return (PyObject *)self;
}
static PyObject *Interface0DIterator_iternext(BPy_Interface0DIterator *self)
{
if (self->reversed) {
if (self->if0D_it->isBegin()) {
PyErr_SetNone(PyExc_StopIteration);
return nullptr;
}
self->if0D_it->decrement();
}
else {
if (self->if0D_it->isEnd()) {
PyErr_SetNone(PyExc_StopIteration);
return nullptr;
}
if (self->at_start) {
self->at_start = false;
}
else if (self->if0D_it->atLast()) {
PyErr_SetNone(PyExc_StopIteration);
return nullptr;
}
else {
self->if0D_it->increment();
}
}
Interface0D *if0D = self->if0D_it->operator->();
return Any_BPy_Interface0D_from_Interface0D(*if0D);
}
/*----------------------Interface0DIterator get/setters ----------------------------*/
PyDoc_STRVAR(
/* Wrap. */
Interface0DIterator_object_doc,
"The 0D object currently pointed to by this iterator. The object may be an\n"
"instance of :class:`Interface0D` or one of its subclasses. For example if\n"
"the iterator has been created from the `vertices_begin()` method of the\n"
":class:`Stroke` class, the .object property refers to a :class:`StrokeVertex`\n"
"object.\n"
"\n"
":type: :class:`Interface0D`\n");
static PyObject *Interface0DIterator_object_get(BPy_Interface0DIterator *self, void * /*closure*/)
{
if (self->if0D_it->isEnd()) {
PyErr_SetString(PyExc_RuntimeError, "iteration has stopped");
return nullptr;
}
return Any_BPy_Interface0D_from_Interface0D(self->if0D_it->operator*());
}
PyDoc_STRVAR(
/* Wrap. */
Interface0DIterator_t_doc,
"The curvilinear abscissa of the current point.\n"
"\n"
":type: float\n");
static PyObject *Interface0DIterator_t_get(BPy_Interface0DIterator *self, void * /*closure*/)
{
return PyFloat_FromDouble(self->if0D_it->t());
}
PyDoc_STRVAR(
/* Wrap. */
Interface0DIterator_u_doc,
"The point parameter at the current point in the 1D element (0 <= u <= 1).\n"
"\n"
":type: float\n");
static PyObject *Interface0DIterator_u_get(BPy_Interface0DIterator *self, void * /*closure*/)
{
return PyFloat_FromDouble(self->if0D_it->u());
}
PyDoc_STRVAR(
/* Wrap. */
Interface0DIterator_at_last_doc,
"True if the iterator points to the last valid element.\n"
"For its counterpart (pointing to the first valid element), use it.is_begin.\n"
"\n"
":type: bool\n");
static PyObject *Interface0DIterator_at_last_get(BPy_Interface0DIterator *self, void * /*closure*/)
{
return PyBool_from_bool(self->if0D_it->atLast());
}
static PyGetSetDef BPy_Interface0DIterator_getseters[] = {
{"object",
(getter)Interface0DIterator_object_get,
(setter) nullptr,
Interface0DIterator_object_doc,
nullptr},
{"t", (getter)Interface0DIterator_t_get, (setter) nullptr, Interface0DIterator_t_doc, nullptr},
{"u", (getter)Interface0DIterator_u_get, (setter) nullptr, Interface0DIterator_u_doc, nullptr},
{"at_last",
(getter)Interface0DIterator_at_last_get,
(setter) nullptr,
Interface0DIterator_at_last_doc,
nullptr},
{nullptr, nullptr, nullptr, nullptr, nullptr} /* Sentinel */
};
/*-----------------------BPy_Interface0DIterator type definition ------------------------------*/
PyTypeObject Interface0DIterator_Type = {
/*ob_base*/ PyVarObject_HEAD_INIT(nullptr, 0)
/*tp_name*/ "Interface0DIterator",
/*tp_basicsize*/ sizeof(BPy_Interface0DIterator),
/*tp_itemsize*/ 0,
/*tp_dealloc*/ nullptr,
/*tp_vectorcall_offset*/ 0,
/*tp_getattr*/ nullptr,
/*tp_setattr*/ nullptr,
/*tp_as_async*/ nullptr,
/*tp_repr*/ nullptr,
/*tp_as_number*/ nullptr,
/*tp_as_sequence*/ nullptr,
/*tp_as_mapping*/ nullptr,
/*tp_hash*/ nullptr,
/*tp_call*/ nullptr,
/*tp_str*/ nullptr,
/*tp_getattro*/ nullptr,
/*tp_setattro*/ nullptr,
/*tp_as_buffer*/ nullptr,
/*tp_flags*/ Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE,
/*tp_doc*/ Interface0DIterator_doc,
/*tp_traverse*/ nullptr,
/*tp_clear*/ nullptr,
/*tp_richcompare*/ nullptr,
/*tp_weaklistoffset*/ 0,
/*tp_iter*/ (getiterfunc)Interface0DIterator_iter,
/*tp_iternext*/ (iternextfunc)Interface0DIterator_iternext,
/*tp_methods*/ nullptr,
/*tp_members*/ nullptr,
/*tp_getset*/ BPy_Interface0DIterator_getseters,
/*tp_base*/ &Iterator_Type,
/*tp_dict*/ nullptr,
/*tp_descr_get*/ nullptr,
/*tp_descr_set*/ nullptr,
/*tp_dictoffset*/ 0,
/*tp_init*/ (initproc)Interface0DIterator_init,
/*tp_alloc*/ nullptr,
/*tp_new*/ nullptr,
};
///////////////////////////////////////////////////////////////////////////////////////////

View File

@@ -0,0 +1,30 @@
/* SPDX-FileCopyrightText: 2023 Blender Authors
*
* SPDX-License-Identifier: GPL-2.0-or-later */
/** \file
* \ingroup freestyle
*/
#pragma once
#include "../BPy_Iterator.h"
#include "../../view_map/Interface0D.h"
///////////////////////////////////////////////////////////////////////////////////////////
extern PyTypeObject Interface0DIterator_Type;
#define BPy_Interface0DIterator_Check(v) \
(PyObject_IsInstance((PyObject *)v, (PyObject *)&Interface0DIterator_Type))
/*---------------------------Python BPy_Interface0DIterator structure definition----------*/
struct BPy_Interface0DIterator {
BPy_Iterator py_it;
Freestyle::Interface0DIterator *if0D_it;
bool reversed;
bool at_start;
};
///////////////////////////////////////////////////////////////////////////////////////////

Some files were not shown because too many files have changed in this diff Show More