ClangFormat: apply to source, most of intern

Apply clang format as proposed in T53211.

For details on usage and instructions for migrating branches
without conflicts, see:

https://wiki.blender.org/wiki/Tools/ClangFormat
This commit is contained in:
2019-04-17 06:17:24 +02:00
parent b3dabc200a
commit e12c08e8d1
4481 changed files with 1230080 additions and 1155401 deletions

View File

@@ -18,20 +18,18 @@
* \ingroup python
*/
#ifndef __BPY_EXTERN_H__
#define __BPY_EXTERN_H__
struct ChannelDriver; /* DNA_anim_types.h */
struct ID; /* DNA_ID.h */
struct ListBase; /* DNA_listBase.h */
struct Object; /* DNA_object_types.h */
struct ID; /* DNA_ID.h */
struct ListBase; /* DNA_listBase.h */
struct Object; /* DNA_object_types.h */
struct PathResolvedRNA;
struct ReportList;
struct Text; /* defined in DNA_text_types.h */
struct bConstraint; /* DNA_constraint_types.h */
struct bConstraintOb; /* DNA_constraint_types.h */
struct Text; /* defined in DNA_text_types.h */
struct bConstraint; /* DNA_constraint_types.h */
struct bConstraintOb; /* DNA_constraint_types.h */
struct bConstraintTarget; /* DNA_constraint_types.h*/
struct bContext;
struct bContextDataResult;
@@ -41,18 +39,19 @@ struct bPythonConstraint; /* DNA_constraint_types.h */
extern "C" {
#endif
void BPY_pyconstraint_exec(struct bPythonConstraint *con, struct bConstraintOb *cob, struct ListBase *targets);
// void BPY_pyconstraint_settings(void *arg1, void *arg2);
void BPY_pyconstraint_exec(struct bPythonConstraint *con,
struct bConstraintOb *cob,
struct ListBase *targets);
// void BPY_pyconstraint_settings(void *arg1, void *arg2);
void BPY_pyconstraint_target(struct bPythonConstraint *con, struct bConstraintTarget *ct);
void BPY_pyconstraint_update(struct Object *owner, struct bConstraint *con);
int BPY_is_pyconstraint(struct Text *text);
// void BPY_free_pyconstraint_links(struct Text *text);
// void BPY_free_pyconstraint_links(struct Text *text);
void BPY_python_start(int argc, const char **argv);
void BPY_python_end(void);
void BPY_python_reset(struct bContext *C);
/* global interpreter lock */
typedef void *BPy_ThreadStatePtr;
@@ -61,38 +60,67 @@ BPy_ThreadStatePtr BPY_thread_save(void);
void BPY_thread_restore(BPy_ThreadStatePtr tstate);
/* our own wrappers to Py_BEGIN_ALLOW_THREADS/Py_END_ALLOW_THREADS */
#define BPy_BEGIN_ALLOW_THREADS { BPy_ThreadStatePtr _bpy_saved_tstate = BPY_thread_save(); (void)0
#define BPy_END_ALLOW_THREADS BPY_thread_restore(_bpy_saved_tstate); } (void)0
#define BPy_BEGIN_ALLOW_THREADS \
{ \
BPy_ThreadStatePtr _bpy_saved_tstate = BPY_thread_save(); \
(void)0
#define BPy_END_ALLOW_THREADS \
BPY_thread_restore(_bpy_saved_tstate); \
} \
(void)0
bool BPY_execute_filepath(struct bContext *C, const char *filepath, struct ReportList *reports);
bool BPY_execute_text(struct bContext *C, struct Text *text, struct ReportList *reports, const bool do_jump);
bool BPY_execute_filepath(struct bContext *C, const char *filepath, struct ReportList *reports);
bool BPY_execute_text(struct bContext *C,
struct Text *text,
struct ReportList *reports,
const bool do_jump);
bool BPY_execute_string_as_number(struct bContext *C, const char *imports[], const char *expr, const bool verbose, double *r_value);
bool BPY_execute_string_as_intptr(struct bContext *C, const char *imports[], const char *expr, const bool verbose, intptr_t *r_value);
bool BPY_execute_string_as_string(struct bContext *C, const char *imports[], const char *expr, const bool verbose, char **r_value);
bool BPY_execute_string_as_number(struct bContext *C,
const char *imports[],
const char *expr,
const bool verbose,
double *r_value);
bool BPY_execute_string_as_intptr(struct bContext *C,
const char *imports[],
const char *expr,
const bool verbose,
intptr_t *r_value);
bool BPY_execute_string_as_string(struct bContext *C,
const char *imports[],
const char *expr,
const bool verbose,
char **r_value);
bool BPY_execute_string_ex(struct bContext *C, const char *imports[], const char *expr, bool use_eval);
bool BPY_execute_string(struct bContext *C, const char *imports[], const char *expr);
bool BPY_execute_string_ex(struct bContext *C,
const char *imports[],
const char *expr,
bool use_eval);
bool BPY_execute_string(struct bContext *C, const char *imports[], const char *expr);
void BPY_text_free_code(struct Text *text);
void BPY_modules_update(struct bContext *C); // XXX - annoying, need this for pointers that get out of date
void BPY_modules_load_user(struct bContext *C);
void BPY_text_free_code(struct Text *text);
void BPY_modules_update(
struct bContext *C); // XXX - annoying, need this for pointers that get out of date
void BPY_modules_load_user(struct bContext *C);
void BPY_app_handlers_reset(const short do_all);
void BPY_app_handlers_reset(const short do_all);
void BPY_driver_reset(void);
float BPY_driver_exec(struct PathResolvedRNA *anim_rna, struct ChannelDriver *driver,
struct ChannelDriver *driver_orig, const float evaltime);
void BPY_driver_reset(void);
float BPY_driver_exec(struct PathResolvedRNA *anim_rna,
struct ChannelDriver *driver,
struct ChannelDriver *driver_orig,
const float evaltime);
void BPY_DECREF(void *pyob_ptr); /* Py_DECREF() */
void BPY_DECREF_RNA_INVALIDATE(void *pyob_ptr);
int BPY_context_member_get(struct bContext *C, const char *member, struct bContextDataResult *result);
void BPY_context_set(struct bContext *C);
void BPY_context_update(struct bContext *C);
void BPY_DECREF(void *pyob_ptr); /* Py_DECREF() */
void BPY_DECREF_RNA_INVALIDATE(void *pyob_ptr);
int BPY_context_member_get(struct bContext *C,
const char *member,
struct bContextDataResult *result);
void BPY_context_set(struct bContext *C);
void BPY_context_update(struct bContext *C);
void BPY_id_release(struct ID *id);
void BPY_id_release(struct ID *id);
bool BPY_string_is_keyword(const char *str);
bool BPY_string_is_keyword(const char *str);
/* I18n for addons */
#ifdef WITH_INTERNATIONAL
@@ -100,7 +128,7 @@ const char *BPY_app_translations_py_pgettext(const char *msgctxt, const char *ms
#endif
#ifdef __cplusplus
} /* extern "C" */
} /* extern "C" */
#endif
#endif /* __BPY_EXTERN_H__ */
#endif /* __BPY_EXTERN_H__ */

View File

@@ -23,9 +23,8 @@
#ifndef __BPY_EXTERN_CLOG_H__
#define __BPY_EXTERN_CLOG_H__
/* bpy_interface.c */
extern struct CLG_LogRef *BPY_LOG_RNA;
extern struct CLG_LogRef *BPY_LOG_CONTEXT;
#endif /* __BPY_EXTERN_CLOG_H__ */
#endif /* __BPY_EXTERN_CLOG_H__ */

View File

@@ -16,49 +16,49 @@
# ***** END GPL LICENSE BLOCK *****
set(INC
.
../../bmesh
../../blenkernel
../../blenlib
../../depsgraph
../../makesdna
../../../../intern/guardedalloc
.
../../bmesh
../../blenkernel
../../blenlib
../../depsgraph
../../makesdna
../../../../intern/guardedalloc
)
set(INC_SYS
${PYTHON_INCLUDE_DIRS}
${PYTHON_INCLUDE_DIRS}
)
set(SRC
bmesh_py_api.c
bmesh_py_geometry.c
bmesh_py_ops.c
bmesh_py_ops_call.c
bmesh_py_types.c
bmesh_py_types_customdata.c
bmesh_py_types_meshdata.c
bmesh_py_types_select.c
bmesh_py_utils.c
bmesh_py_api.c
bmesh_py_geometry.c
bmesh_py_ops.c
bmesh_py_ops_call.c
bmesh_py_types.c
bmesh_py_types_customdata.c
bmesh_py_types_meshdata.c
bmesh_py_types_select.c
bmesh_py_utils.c
bmesh_py_api.h
bmesh_py_geometry.h
bmesh_py_ops.h
bmesh_py_ops_call.h
bmesh_py_types.h
bmesh_py_types_customdata.h
bmesh_py_types_meshdata.h
bmesh_py_types_select.h
bmesh_py_utils.h
bmesh_py_api.h
bmesh_py_geometry.h
bmesh_py_ops.h
bmesh_py_ops_call.h
bmesh_py_types.h
bmesh_py_types_customdata.h
bmesh_py_types_meshdata.h
bmesh_py_types_select.h
bmesh_py_utils.h
)
set(LIB
bf_blenkernel
bf_blenlib
bf_python_mathutils
bf_blenkernel
bf_blenlib
bf_python_mathutils
)
if(WITH_FREESTYLE)
add_definitions(-DWITH_FREESTYLE)
add_definitions(-DWITH_FREESTYLE)
endif()
blender_add_lib(bf_python_bmesh "${SRC}" "${INC}" "${INC_SYS}" "${LIB}")

View File

@@ -47,167 +47,168 @@
#include "bmesh_py_api.h" /* own include */
PyDoc_STRVAR(bpy_bm_new_doc,
".. method:: new(use_operators=True)\n"
"\n"
" :arg use_operators: Support calling operators in :mod:`bmesh.ops` (uses some extra memory per vert/edge/face).\n"
" :type use_operators: bool\n"
" :return: Return a new, empty BMesh.\n"
" :rtype: :class:`bmesh.types.BMesh`\n"
);
".. method:: new(use_operators=True)\n"
"\n"
" :arg use_operators: Support calling operators in :mod:`bmesh.ops` (uses some "
"extra memory per vert/edge/face).\n"
" :type use_operators: bool\n"
" :return: Return a new, empty BMesh.\n"
" :rtype: :class:`bmesh.types.BMesh`\n");
static PyObject *bpy_bm_new(PyObject *UNUSED(self), PyObject *args, PyObject *kw)
{
static const char *kwlist[] = {"use_operators", NULL};
BMesh *bm;
static const char *kwlist[] = {"use_operators", NULL};
BMesh *bm;
bool use_operators = true;
bool use_operators = true;
if (!PyArg_ParseTupleAndKeywords(
args, kw, "|$O&:new", (char **)kwlist,
PyC_ParseBool, &use_operators))
{
return NULL;
}
if (!PyArg_ParseTupleAndKeywords(
args, kw, "|$O&:new", (char **)kwlist, PyC_ParseBool, &use_operators)) {
return NULL;
}
bm = BM_mesh_create(
&bm_mesh_allocsize_default,
&((struct BMeshCreateParams){.use_toolflags = use_operators,}));
bm = BM_mesh_create(&bm_mesh_allocsize_default,
&((struct BMeshCreateParams){
.use_toolflags = use_operators,
}));
return BPy_BMesh_CreatePyObject(bm, BPY_BMFLAG_NOP);
return BPy_BMesh_CreatePyObject(bm, BPY_BMFLAG_NOP);
}
PyDoc_STRVAR(bpy_bm_from_edit_mesh_doc,
".. method:: from_edit_mesh(mesh)\n"
"\n"
" Return a BMesh from this mesh, currently the mesh must already be in editmode.\n"
"\n"
" :arg mesh: The editmode mesh.\n"
" :type mesh: :class:`bpy.types.Mesh`\n"
" :return: the BMesh associated with this mesh.\n"
" :rtype: :class:`bmesh.types.BMesh`\n"
);
".. method:: from_edit_mesh(mesh)\n"
"\n"
" Return a BMesh from this mesh, currently the mesh must already be in editmode.\n"
"\n"
" :arg mesh: The editmode mesh.\n"
" :type mesh: :class:`bpy.types.Mesh`\n"
" :return: the BMesh associated with this mesh.\n"
" :rtype: :class:`bmesh.types.BMesh`\n");
static PyObject *bpy_bm_from_edit_mesh(PyObject *UNUSED(self), PyObject *value)
{
BMesh *bm;
Mesh *me = PyC_RNA_AsPointer(value, "Mesh");
BMesh *bm;
Mesh *me = PyC_RNA_AsPointer(value, "Mesh");
if (me == NULL) {
return NULL;
}
if (me == NULL) {
return NULL;
}
if (me->edit_mesh == NULL) {
PyErr_SetString(PyExc_ValueError,
"The mesh must be in editmode");
return NULL;
}
if (me->edit_mesh == NULL) {
PyErr_SetString(PyExc_ValueError, "The mesh must be in editmode");
return NULL;
}
bm = me->edit_mesh->bm;
bm = me->edit_mesh->bm;
return BPy_BMesh_CreatePyObject(bm, BPY_BMFLAG_IS_WRAPPED);
return BPy_BMesh_CreatePyObject(bm, BPY_BMFLAG_IS_WRAPPED);
}
PyDoc_STRVAR(bpy_bm_update_edit_mesh_doc,
".. method:: update_edit_mesh(mesh, loop_triangles=True, destructive=True)\n"
"\n"
" Update the mesh after changes to the BMesh in editmode,\n"
" optionally recalculating n-gon tessellation.\n"
"\n"
" :arg mesh: The editmode mesh.\n"
" :type mesh: :class:`bpy.types.Mesh`\n"
" :arg loop_triangles: Option to recalculate n-gon tessellation.\n"
" :type loop_triangles: boolean\n"
" :arg destructive: Use when geometry has been added or removed.\n"
" :type destructive: boolean\n"
);
".. method:: update_edit_mesh(mesh, loop_triangles=True, destructive=True)\n"
"\n"
" Update the mesh after changes to the BMesh in editmode,\n"
" optionally recalculating n-gon tessellation.\n"
"\n"
" :arg mesh: The editmode mesh.\n"
" :type mesh: :class:`bpy.types.Mesh`\n"
" :arg loop_triangles: Option to recalculate n-gon tessellation.\n"
" :type loop_triangles: boolean\n"
" :arg destructive: Use when geometry has been added or removed.\n"
" :type destructive: boolean\n");
static PyObject *bpy_bm_update_edit_mesh(PyObject *UNUSED(self), PyObject *args, PyObject *kw)
{
static const char *kwlist[] = {"mesh", "loop_triangles", "destructive", NULL};
PyObject *py_me;
Mesh *me;
bool do_loop_triangles = true;
bool is_destructive = true;
static const char *kwlist[] = {"mesh", "loop_triangles", "destructive", NULL};
PyObject *py_me;
Mesh *me;
bool do_loop_triangles = true;
bool is_destructive = true;
if (!PyArg_ParseTupleAndKeywords(
args, kw, "O|O&O&:update_edit_mesh", (char **)kwlist,
&py_me,
PyC_ParseBool, &do_loop_triangles,
PyC_ParseBool, &is_destructive))
{
return NULL;
}
if (!PyArg_ParseTupleAndKeywords(args,
kw,
"O|O&O&:update_edit_mesh",
(char **)kwlist,
&py_me,
PyC_ParseBool,
&do_loop_triangles,
PyC_ParseBool,
&is_destructive)) {
return NULL;
}
me = PyC_RNA_AsPointer(py_me, "Mesh");
me = PyC_RNA_AsPointer(py_me, "Mesh");
if (me == NULL) {
return NULL;
}
if (me == NULL) {
return NULL;
}
if (me->edit_mesh == NULL) {
PyErr_SetString(PyExc_ValueError,
"The mesh must be in editmode");
return NULL;
}
if (me->edit_mesh == NULL) {
PyErr_SetString(PyExc_ValueError, "The mesh must be in editmode");
return NULL;
}
{
extern void EDBM_update_generic(BMEditMesh *em, const bool do_tessface, const bool is_destructive);
{
extern void EDBM_update_generic(
BMEditMesh * em, const bool do_tessface, const bool is_destructive);
EDBM_update_generic(me->edit_mesh, do_loop_triangles, is_destructive);
}
EDBM_update_generic(me->edit_mesh, do_loop_triangles, is_destructive);
}
Py_RETURN_NONE;
Py_RETURN_NONE;
}
static struct PyMethodDef BPy_BM_methods[] = {
{"new", (PyCFunction)bpy_bm_new, METH_VARARGS | METH_KEYWORDS, bpy_bm_new_doc},
{"from_edit_mesh", (PyCFunction)bpy_bm_from_edit_mesh, METH_O, bpy_bm_from_edit_mesh_doc},
{"update_edit_mesh", (PyCFunction)bpy_bm_update_edit_mesh, METH_VARARGS | METH_KEYWORDS, bpy_bm_update_edit_mesh_doc},
{NULL, NULL, 0, NULL},
{"new", (PyCFunction)bpy_bm_new, METH_VARARGS | METH_KEYWORDS, bpy_bm_new_doc},
{"from_edit_mesh", (PyCFunction)bpy_bm_from_edit_mesh, METH_O, bpy_bm_from_edit_mesh_doc},
{"update_edit_mesh",
(PyCFunction)bpy_bm_update_edit_mesh,
METH_VARARGS | METH_KEYWORDS,
bpy_bm_update_edit_mesh_doc},
{NULL, NULL, 0, NULL},
};
PyDoc_STRVAR(BPy_BM_doc,
"This module provides access to blenders bmesh data structures.\n"
"\n"
".. include:: include__bmesh.rst\n"
);
"This module provides access to blenders bmesh data structures.\n"
"\n"
".. include:: include__bmesh.rst\n");
static struct PyModuleDef BPy_BM_module_def = {
PyModuleDef_HEAD_INIT,
"bmesh", /* m_name */
BPy_BM_doc, /* m_doc */
0, /* m_size */
BPy_BM_methods, /* m_methods */
NULL, /* m_reload */
NULL, /* m_traverse */
NULL, /* m_clear */
NULL, /* m_free */
PyModuleDef_HEAD_INIT,
"bmesh", /* m_name */
BPy_BM_doc, /* m_doc */
0, /* m_size */
BPy_BM_methods, /* m_methods */
NULL, /* m_reload */
NULL, /* m_traverse */
NULL, /* m_clear */
NULL, /* m_free */
};
PyObject *BPyInit_bmesh(void)
{
PyObject *mod;
PyObject *submodule;
PyObject *sys_modules = PyImport_GetModuleDict();
PyObject *mod;
PyObject *submodule;
PyObject *sys_modules = PyImport_GetModuleDict();
BPy_BM_init_types();
BPy_BM_init_types_select();
BPy_BM_init_types_customdata();
BPy_BM_init_types_meshdata();
BPy_BM_init_types();
BPy_BM_init_types_select();
BPy_BM_init_types_customdata();
BPy_BM_init_types_meshdata();
mod = PyModule_Create(&BPy_BM_module_def);
mod = PyModule_Create(&BPy_BM_module_def);
/* bmesh.types */
PyModule_AddObject(mod, "types", (submodule = BPyInit_bmesh_types()));
PyDict_SetItem(sys_modules, PyModule_GetNameObject(submodule), submodule);
/* bmesh.types */
PyModule_AddObject(mod, "types", (submodule = BPyInit_bmesh_types()));
PyDict_SetItem(sys_modules, PyModule_GetNameObject(submodule), submodule);
/* bmesh.ops (not a real module, exposes module like access). */
PyModule_AddObject(mod, "ops", (submodule = BPyInit_bmesh_ops()));
/* PyDict_SetItemString(sys_modules, PyModule_GetNameObject(submodule), submodule); */
PyDict_SetItemString(sys_modules, "bmesh.ops", submodule); /* fake module */
/* bmesh.ops (not a real module, exposes module like access). */
PyModule_AddObject(mod, "ops", (submodule = BPyInit_bmesh_ops()));
/* PyDict_SetItemString(sys_modules, PyModule_GetNameObject(submodule), submodule); */
PyDict_SetItemString(sys_modules, "bmesh.ops", submodule); /* fake module */
PyModule_AddObject(mod, "utils", (submodule = BPyInit_bmesh_utils()));
PyDict_SetItem(sys_modules, PyModule_GetNameObject(submodule), submodule);
PyModule_AddObject(mod, "utils", (submodule = BPyInit_bmesh_utils()));
PyDict_SetItem(sys_modules, PyModule_GetNameObject(submodule), submodule);
PyModule_AddObject(mod, "geometry", (submodule = BPyInit_bmesh_geometry()));
PyDict_SetItem(sys_modules, PyModule_GetNameObject(submodule), submodule);
PyModule_AddObject(mod, "geometry", (submodule = BPyInit_bmesh_geometry()));
PyDict_SetItem(sys_modules, PyModule_GetNameObject(submodule), submodule);
return mod;
return mod;
}

View File

@@ -35,70 +35,64 @@
#include "bmesh_py_geometry.h" /* own include */
PyDoc_STRVAR(bpy_bm_geometry_intersect_face_point_doc,
".. method:: intersect_face_point(face, point)\n"
"\n"
" Tests if the projection of a point is inside a face (using the face's normal).\n"
"\n"
" :arg face: The face to test.\n"
" :type face: :class:`bmesh.types.BMFace`\n"
" :arg point: The point to test.\n"
" :type point: float triplet\n"
" :return: True when the projection of the point is in the face.\n"
" :rtype: bool\n"
);
".. method:: intersect_face_point(face, point)\n"
"\n"
" Tests if the projection of a point is inside a face (using the face's normal).\n"
"\n"
" :arg face: The face to test.\n"
" :type face: :class:`bmesh.types.BMFace`\n"
" :arg point: The point to test.\n"
" :type point: float triplet\n"
" :return: True when the projection of the point is in the face.\n"
" :rtype: bool\n");
static PyObject *bpy_bm_geometry_intersect_face_point(BPy_BMFace *UNUSED(self), PyObject *args)
{
BPy_BMFace *py_face;
PyObject *py_point;
float point[3];
bool ret;
BPy_BMFace *py_face;
PyObject *py_point;
float point[3];
bool ret;
if (!PyArg_ParseTuple(args,
"O!O:intersect_face_point",
&BPy_BMFace_Type, &py_face,
&py_point))
{
return NULL;
}
if (!PyArg_ParseTuple(args, "O!O:intersect_face_point", &BPy_BMFace_Type, &py_face, &py_point)) {
return NULL;
}
BPY_BM_CHECK_OBJ(py_face);
if (mathutils_array_parse(point, 3, 3, py_point, "intersect_face_point") == -1) {
return NULL;
}
BPY_BM_CHECK_OBJ(py_face);
if (mathutils_array_parse(point, 3, 3, py_point, "intersect_face_point") == -1) {
return NULL;
}
ret = BM_face_point_inside_test(py_face->f, point);
ret = BM_face_point_inside_test(py_face->f, point);
return PyBool_FromLong(ret);
return PyBool_FromLong(ret);
}
static struct PyMethodDef BPy_BM_geometry_methods[] = {
{"intersect_face_point", (PyCFunction)bpy_bm_geometry_intersect_face_point, METH_VARARGS, bpy_bm_geometry_intersect_face_point_doc},
{NULL, NULL, 0, NULL},
{"intersect_face_point",
(PyCFunction)bpy_bm_geometry_intersect_face_point,
METH_VARARGS,
bpy_bm_geometry_intersect_face_point_doc},
{NULL, NULL, 0, NULL},
};
PyDoc_STRVAR(BPy_BM_utils_doc,
"This module provides access to bmesh geometry evaluation functions."
);
"This module provides access to bmesh geometry evaluation functions.");
static struct PyModuleDef BPy_BM_geometry_module_def = {
PyModuleDef_HEAD_INIT,
"bmesh.geometry", /* m_name */
BPy_BM_utils_doc, /* m_doc */
0, /* m_size */
BPy_BM_geometry_methods, /* m_methods */
NULL, /* m_reload */
NULL, /* m_traverse */
NULL, /* m_clear */
NULL, /* m_free */
PyModuleDef_HEAD_INIT,
"bmesh.geometry", /* m_name */
BPy_BM_utils_doc, /* m_doc */
0, /* m_size */
BPy_BM_geometry_methods, /* m_methods */
NULL, /* m_reload */
NULL, /* m_traverse */
NULL, /* m_clear */
NULL, /* m_free */
};
PyObject *BPyInit_bmesh_geometry(void)
{
PyObject *submodule;
PyObject *submodule;
submodule = PyModule_Create(&BPy_BM_geometry_module_def);
submodule = PyModule_Create(&BPy_BM_geometry_module_def);
return submodule;
return submodule;
}

View File

@@ -31,11 +31,10 @@
#include "MEM_guardedalloc.h"
#include "bmesh.h"
#include "bmesh_py_ops_call.h"
#include "bmesh_py_ops.h" /* own include */
#include "bmesh_py_ops.h" /* own include */
/* bmesh operator 'bmesh.ops.*' callable types
* ******************************************* */
@@ -43,327 +42,337 @@ static PyTypeObject bmesh_op_Type;
static PyObject *bpy_bmesh_op_CreatePyObject(const char *opname)
{
BPy_BMeshOpFunc *self = PyObject_New(BPy_BMeshOpFunc, &bmesh_op_Type);
BPy_BMeshOpFunc *self = PyObject_New(BPy_BMeshOpFunc, &bmesh_op_Type);
self->opname = opname;
self->opname = opname;
return (PyObject *)self;
return (PyObject *)self;
}
static PyObject *bpy_bmesh_op_repr(BPy_BMeshOpFunc *self)
{
return PyUnicode_FromFormat("<%.200s bmesh.ops.%.200s()>",
Py_TYPE(self)->tp_name,
self->opname);
return PyUnicode_FromFormat("<%.200s bmesh.ops.%.200s()>", Py_TYPE(self)->tp_name, self->opname);
}
/* methods
* ======= */
/* __doc__
* ------- */
static char *bmp_slots_as_args(const BMOSlotType slot_types[BMO_OP_MAX_SLOTS], const bool is_out)
{
DynStr *dyn_str = BLI_dynstr_new();
char *ret;
bool quoted;
bool set;
DynStr *dyn_str = BLI_dynstr_new();
char *ret;
bool quoted;
bool set;
int i = 0;
int i = 0;
while (*slot_types[i].name) {
quoted = false;
set = false;
/* cut off '.out' by using a string size arg */
const int name_len = is_out ?
(strchr(slot_types[i].name, '.') - slot_types[i].name) :
sizeof(slot_types[i].name);
const char *value = "<Unknown>";
switch (slot_types[i].type) {
case BMO_OP_SLOT_BOOL: value = "False"; break;
case BMO_OP_SLOT_INT:
if (slot_types[i].subtype.intg == BMO_OP_SLOT_SUBTYPE_INT_ENUM) {
value = slot_types[i].enum_flags[0].identifier;
quoted = true;
}
else if (slot_types[i].subtype.intg == BMO_OP_SLOT_SUBTYPE_INT_FLAG) {
value = "";
set = true;
}
else {
value = "0";
}
break;
case BMO_OP_SLOT_FLT: value = "0.0"; break;
case BMO_OP_SLOT_PTR: value = "None"; break;
case BMO_OP_SLOT_MAT: value = "Matrix()"; break;
case BMO_OP_SLOT_VEC: value = "Vector()"; break;
case BMO_OP_SLOT_ELEMENT_BUF: value =
(slot_types[i].subtype.elem & BMO_OP_SLOT_SUBTYPE_ELEM_IS_SINGLE) ? "None" : "[]"; break;
case BMO_OP_SLOT_MAPPING: value = "{}"; break;
}
BLI_dynstr_appendf(
dyn_str, i ? ", %.*s=%s%s%s%s%s" : "%.*s=%s%s%s%s%s",
name_len, slot_types[i].name,
set ? "{" : "", quoted ? "'" : "",
value,
quoted ? "'" : "", set ? "}" : "");
i++;
}
while (*slot_types[i].name) {
quoted = false;
set = false;
/* cut off '.out' by using a string size arg */
const int name_len = is_out ? (strchr(slot_types[i].name, '.') - slot_types[i].name) :
sizeof(slot_types[i].name);
const char *value = "<Unknown>";
switch (slot_types[i].type) {
case BMO_OP_SLOT_BOOL:
value = "False";
break;
case BMO_OP_SLOT_INT:
if (slot_types[i].subtype.intg == BMO_OP_SLOT_SUBTYPE_INT_ENUM) {
value = slot_types[i].enum_flags[0].identifier;
quoted = true;
}
else if (slot_types[i].subtype.intg == BMO_OP_SLOT_SUBTYPE_INT_FLAG) {
value = "";
set = true;
}
else {
value = "0";
}
break;
case BMO_OP_SLOT_FLT:
value = "0.0";
break;
case BMO_OP_SLOT_PTR:
value = "None";
break;
case BMO_OP_SLOT_MAT:
value = "Matrix()";
break;
case BMO_OP_SLOT_VEC:
value = "Vector()";
break;
case BMO_OP_SLOT_ELEMENT_BUF:
value = (slot_types[i].subtype.elem & BMO_OP_SLOT_SUBTYPE_ELEM_IS_SINGLE) ? "None" : "[]";
break;
case BMO_OP_SLOT_MAPPING:
value = "{}";
break;
}
BLI_dynstr_appendf(dyn_str,
i ? ", %.*s=%s%s%s%s%s" : "%.*s=%s%s%s%s%s",
name_len,
slot_types[i].name,
set ? "{" : "",
quoted ? "'" : "",
value,
quoted ? "'" : "",
set ? "}" : "");
i++;
}
ret = BLI_dynstr_get_cstring(dyn_str);
BLI_dynstr_free(dyn_str);
return ret;
ret = BLI_dynstr_get_cstring(dyn_str);
BLI_dynstr_free(dyn_str);
return ret;
}
static PyObject *bpy_bmesh_op_doc_get(BPy_BMeshOpFunc *self, void *UNUSED(closure))
{
PyObject *ret;
char *slot_in;
char *slot_out;
int i;
PyObject *ret;
char *slot_in;
char *slot_out;
int i;
i = BMO_opcode_from_opname(self->opname);
i = BMO_opcode_from_opname(self->opname);
slot_in = bmp_slots_as_args(bmo_opdefines[i]->slot_types_in, false);
slot_out = bmp_slots_as_args(bmo_opdefines[i]->slot_types_out, true);
slot_in = bmp_slots_as_args(bmo_opdefines[i]->slot_types_in, false);
slot_out = bmp_slots_as_args(bmo_opdefines[i]->slot_types_out, true);
ret = PyUnicode_FromFormat("%.200s bmesh.ops.%.200s(bmesh, %s)\n -> dict(%s)",
Py_TYPE(self)->tp_name,
self->opname, slot_in, slot_out);
ret = PyUnicode_FromFormat("%.200s bmesh.ops.%.200s(bmesh, %s)\n -> dict(%s)",
Py_TYPE(self)->tp_name,
self->opname,
slot_in,
slot_out);
MEM_freeN(slot_in);
MEM_freeN(slot_out);
MEM_freeN(slot_in);
MEM_freeN(slot_out);
return ret;
return ret;
}
static PyGetSetDef bpy_bmesh_op_getseters[] = {
{(char *)"__doc__", (getter)bpy_bmesh_op_doc_get, (setter)NULL, NULL, NULL},
{NULL, NULL, NULL, NULL, NULL} /* Sentinel */
{(char *)"__doc__", (getter)bpy_bmesh_op_doc_get, (setter)NULL, NULL, NULL},
{NULL, NULL, NULL, NULL, NULL} /* Sentinel */
};
/* Types
* ===== */
static PyTypeObject bmesh_op_Type = {
PyVarObject_HEAD_INIT(NULL, 0)
"BMeshOpFunc", /* tp_name */
sizeof(BPy_BMeshOpFunc), /* tp_basicsize */
0, /* tp_itemsize */
/* methods */
NULL, /* tp_dealloc */
NULL, /* printfunc tp_print; */
NULL, /* getattrfunc tp_getattr; */
NULL, /* setattrfunc tp_setattr; */
NULL, /* tp_compare */ /* DEPRECATED in python 3.0! */
(reprfunc) bpy_bmesh_op_repr, /* tp_repr */
PyVarObject_HEAD_INIT(NULL, 0) "BMeshOpFunc", /* tp_name */
sizeof(BPy_BMeshOpFunc), /* tp_basicsize */
0, /* tp_itemsize */
/* methods */
NULL, /* tp_dealloc */
NULL, /* printfunc tp_print; */
NULL, /* getattrfunc tp_getattr; */
NULL, /* setattrfunc tp_setattr; */
NULL,
/* tp_compare */ /* DEPRECATED in python 3.0! */
(reprfunc)bpy_bmesh_op_repr, /* tp_repr */
/* Method suites for standard classes */
/* Method suites for standard classes */
NULL, /* PyNumberMethods *tp_as_number; */
NULL, /* PySequenceMethods *tp_as_sequence; */
NULL, /* PyMappingMethods *tp_as_mapping; */
NULL, /* PyNumberMethods *tp_as_number; */
NULL, /* PySequenceMethods *tp_as_sequence; */
NULL, /* PyMappingMethods *tp_as_mapping; */
/* More standard operations (here for binary compatibility) */
/* More standard operations (here for binary compatibility) */
NULL, /* hashfunc tp_hash; */
(ternaryfunc)BPy_BMO_call, /* ternaryfunc tp_call; */
NULL, /* reprfunc tp_str; */
NULL, /* hashfunc tp_hash; */
(ternaryfunc)BPy_BMO_call, /* ternaryfunc tp_call; */
NULL, /* reprfunc tp_str; */
/* will only use these if this is a subtype of a py class */
NULL, /* getattrofunc tp_getattro; */
NULL, /* setattrofunc tp_setattro; */
/* will only use these if this is a subtype of a py class */
NULL, /* getattrofunc tp_getattro; */
NULL, /* setattrofunc tp_setattro; */
/* Functions to access object as input/output buffer */
NULL, /* PyBufferProcs *tp_as_buffer; */
/* Functions to access object as input/output buffer */
NULL, /* PyBufferProcs *tp_as_buffer; */
/*** Flags to define presence of optional/expanded features ***/
Py_TPFLAGS_DEFAULT, /* long tp_flags; */
/*** Flags to define presence of optional/expanded features ***/
Py_TPFLAGS_DEFAULT, /* long tp_flags; */
NULL, /* char *tp_doc; Documentation string */
/*** Assigned meaning in release 2.0 ***/
/* call function for all accessible objects */
NULL, /* traverseproc tp_traverse; */
NULL, /* char *tp_doc; Documentation string */
/*** Assigned meaning in release 2.0 ***/
/* call function for all accessible objects */
NULL, /* traverseproc tp_traverse; */
/* delete references to contained objects */
NULL, /* inquiry tp_clear; */
/* delete references to contained objects */
NULL, /* inquiry tp_clear; */
/*** Assigned meaning in release 2.1 ***/
/*** rich comparisons ***/
NULL, /* richcmpfunc tp_richcompare; */
/*** Assigned meaning in release 2.1 ***/
/*** rich comparisons ***/
NULL, /* richcmpfunc tp_richcompare; */
/*** weak reference enabler ***/
0,
/*** Added in release 2.2 ***/
/* Iterators */
NULL, /* getiterfunc tp_iter; */
NULL, /* iternextfunc tp_iternext; */
/*** weak reference enabler ***/
0,
/*** Added in release 2.2 ***/
/* Iterators */
NULL, /* getiterfunc tp_iter; */
NULL, /* iternextfunc tp_iternext; */
/*** Attribute descriptor and subclassing stuff ***/
NULL, /* struct PyMethodDef *tp_methods; */
NULL, /* struct PyMemberDef *tp_members; */
bpy_bmesh_op_getseters, /* struct PyGetSetDef *tp_getset; */
NULL, /* struct _typeobject *tp_base; */
NULL, /* PyObject *tp_dict; */
NULL, /* descrgetfunc tp_descr_get; */
NULL, /* descrsetfunc tp_descr_set; */
0, /* long tp_dictoffset; */
NULL, /* initproc tp_init; */
NULL, /* allocfunc tp_alloc; */
NULL, /* newfunc tp_new; */
/* Low-level free-memory routine */
NULL, /* freefunc tp_free; */
/* For PyObject_IS_GC */
NULL, /* inquiry tp_is_gc; */
NULL, /* PyObject *tp_bases; */
/* method resolution order */
NULL, /* PyObject *tp_mro; */
NULL, /* PyObject *tp_cache; */
NULL, /* PyObject *tp_subclasses; */
NULL, /* PyObject *tp_weaklist; */
NULL,
/*** Attribute descriptor and subclassing stuff ***/
NULL, /* struct PyMethodDef *tp_methods; */
NULL, /* struct PyMemberDef *tp_members; */
bpy_bmesh_op_getseters, /* struct PyGetSetDef *tp_getset; */
NULL, /* struct _typeobject *tp_base; */
NULL, /* PyObject *tp_dict; */
NULL, /* descrgetfunc tp_descr_get; */
NULL, /* descrsetfunc tp_descr_set; */
0, /* long tp_dictoffset; */
NULL, /* initproc tp_init; */
NULL, /* allocfunc tp_alloc; */
NULL, /* newfunc tp_new; */
/* Low-level free-memory routine */
NULL, /* freefunc tp_free; */
/* For PyObject_IS_GC */
NULL, /* inquiry tp_is_gc; */
NULL, /* PyObject *tp_bases; */
/* method resolution order */
NULL, /* PyObject *tp_mro; */
NULL, /* PyObject *tp_cache; */
NULL, /* PyObject *tp_subclasses; */
NULL, /* PyObject *tp_weaklist; */
NULL,
};
/* bmesh fake module 'bmesh.ops'
* ***************************** */
static PyObject *bpy_bmesh_ops_fakemod_getattro(PyObject *UNUSED(self), PyObject *pyname)
{
const char *opname = _PyUnicode_AsString(pyname);
const char *opname = _PyUnicode_AsString(pyname);
if (BMO_opcode_from_opname(opname) != -1) {
return bpy_bmesh_op_CreatePyObject(opname);
}
else {
PyErr_Format(PyExc_AttributeError,
"BMeshOpsModule: operator \"%.200s\" doesn't exist",
opname);
return NULL;
}
if (BMO_opcode_from_opname(opname) != -1) {
return bpy_bmesh_op_CreatePyObject(opname);
}
else {
PyErr_Format(
PyExc_AttributeError, "BMeshOpsModule: operator \"%.200s\" doesn't exist", opname);
return NULL;
}
}
static PyObject *bpy_bmesh_ops_fakemod_dir(PyObject *UNUSED(self))
{
const unsigned int tot = bmo_opdefines_total;
unsigned int i;
PyObject *ret;
const unsigned int tot = bmo_opdefines_total;
unsigned int i;
PyObject *ret;
ret = PyList_New(bmo_opdefines_total);
ret = PyList_New(bmo_opdefines_total);
for (i = 0; i < tot; i++) {
PyList_SET_ITEM(ret, i, PyUnicode_FromString(bmo_opdefines[i]->opname));
}
for (i = 0; i < tot; i++) {
PyList_SET_ITEM(ret, i, PyUnicode_FromString(bmo_opdefines[i]->opname));
}
return ret;
return ret;
}
static struct PyMethodDef bpy_bmesh_ops_fakemod_methods[] = {
{"__dir__", (PyCFunction)bpy_bmesh_ops_fakemod_dir, METH_NOARGS, NULL},
{NULL, NULL, 0, NULL},
{"__dir__", (PyCFunction)bpy_bmesh_ops_fakemod_dir, METH_NOARGS, NULL},
{NULL, NULL, 0, NULL},
};
static PyTypeObject bmesh_ops_fakemod_Type = {
PyVarObject_HEAD_INIT(NULL, 0)
"BMeshOpsModule", /* tp_name */
0, /* tp_basicsize */
0, /* tp_itemsize */
/* methods */
NULL, /* tp_dealloc */
NULL, /* printfunc tp_print; */
NULL, /* getattrfunc tp_getattr; */
NULL, /* setattrfunc tp_setattr; */
NULL, /* tp_compare */ /* DEPRECATED in python 3.0! */
NULL, /* tp_repr */
PyVarObject_HEAD_INIT(NULL, 0) "BMeshOpsModule", /* tp_name */
0, /* tp_basicsize */
0, /* tp_itemsize */
/* methods */
NULL, /* tp_dealloc */
NULL, /* printfunc tp_print; */
NULL, /* getattrfunc tp_getattr; */
NULL, /* setattrfunc tp_setattr; */
NULL,
/* tp_compare */ /* DEPRECATED in python 3.0! */
NULL, /* tp_repr */
/* Method suites for standard classes */
/* Method suites for standard classes */
NULL, /* PyNumberMethods *tp_as_number; */
NULL, /* PySequenceMethods *tp_as_sequence; */
NULL, /* PyMappingMethods *tp_as_mapping; */
NULL, /* PyNumberMethods *tp_as_number; */
NULL, /* PySequenceMethods *tp_as_sequence; */
NULL, /* PyMappingMethods *tp_as_mapping; */
/* More standard operations (here for binary compatibility) */
/* More standard operations (here for binary compatibility) */
NULL, /* hashfunc tp_hash; */
NULL, /* ternaryfunc tp_call; */
NULL, /* reprfunc tp_str; */
NULL, /* hashfunc tp_hash; */
NULL, /* ternaryfunc tp_call; */
NULL, /* reprfunc tp_str; */
/* will only use these if this is a subtype of a py class */
bpy_bmesh_ops_fakemod_getattro, /* getattrofunc tp_getattro; */
NULL, /* setattrofunc tp_setattro; */
/* will only use these if this is a subtype of a py class */
bpy_bmesh_ops_fakemod_getattro, /* getattrofunc tp_getattro; */
NULL, /* setattrofunc tp_setattro; */
/* Functions to access object as input/output buffer */
NULL, /* PyBufferProcs *tp_as_buffer; */
/* Functions to access object as input/output buffer */
NULL, /* PyBufferProcs *tp_as_buffer; */
/*** Flags to define presence of optional/expanded features ***/
Py_TPFLAGS_DEFAULT, /* long tp_flags; */
/*** Flags to define presence of optional/expanded features ***/
Py_TPFLAGS_DEFAULT, /* long tp_flags; */
NULL, /* char *tp_doc; Documentation string */
/*** Assigned meaning in release 2.0 ***/
/* call function for all accessible objects */
NULL, /* traverseproc tp_traverse; */
NULL, /* char *tp_doc; Documentation string */
/*** Assigned meaning in release 2.0 ***/
/* call function for all accessible objects */
NULL, /* traverseproc tp_traverse; */
/* delete references to contained objects */
NULL, /* inquiry tp_clear; */
/* delete references to contained objects */
NULL, /* inquiry tp_clear; */
/*** Assigned meaning in release 2.1 ***/
/*** rich comparisons (subclassed) ***/
NULL, /* richcmpfunc tp_richcompare; */
/*** Assigned meaning in release 2.1 ***/
/*** rich comparisons (subclassed) ***/
NULL, /* richcmpfunc tp_richcompare; */
/*** weak reference enabler ***/
0,
/*** Added in release 2.2 ***/
/* Iterators */
NULL, /* getiterfunc tp_iter; */
NULL, /* iternextfunc tp_iternext; */
/*** weak reference enabler ***/
0,
/*** Added in release 2.2 ***/
/* Iterators */
NULL, /* getiterfunc tp_iter; */
NULL, /* iternextfunc tp_iternext; */
/*** Attribute descriptor and subclassing stuff ***/
bpy_bmesh_ops_fakemod_methods, /* struct PyMethodDef *tp_methods; */
NULL, /* struct PyMemberDef *tp_members; */
NULL, /* struct PyGetSetDef *tp_getset; */
NULL, /* struct _typeobject *tp_base; */
NULL, /* PyObject *tp_dict; */
NULL, /* descrgetfunc tp_descr_get; */
NULL, /* descrsetfunc tp_descr_set; */
0, /* long tp_dictoffset; */
NULL, /* initproc tp_init; */
NULL, /* allocfunc tp_alloc; */
NULL, /* newfunc tp_new; */
/* Low-level free-memory routine */
NULL, /* freefunc tp_free; */
/* For PyObject_IS_GC */
NULL, /* inquiry tp_is_gc; */
NULL, /* PyObject *tp_bases; */
/* method resolution order */
NULL, /* PyObject *tp_mro; */
NULL, /* PyObject *tp_cache; */
NULL, /* PyObject *tp_subclasses; */
NULL, /* PyObject *tp_weaklist; */
NULL,
/*** Attribute descriptor and subclassing stuff ***/
bpy_bmesh_ops_fakemod_methods, /* struct PyMethodDef *tp_methods; */
NULL, /* struct PyMemberDef *tp_members; */
NULL, /* struct PyGetSetDef *tp_getset; */
NULL, /* struct _typeobject *tp_base; */
NULL, /* PyObject *tp_dict; */
NULL, /* descrgetfunc tp_descr_get; */
NULL, /* descrsetfunc tp_descr_set; */
0, /* long tp_dictoffset; */
NULL, /* initproc tp_init; */
NULL, /* allocfunc tp_alloc; */
NULL, /* newfunc tp_new; */
/* Low-level free-memory routine */
NULL, /* freefunc tp_free; */
/* For PyObject_IS_GC */
NULL, /* inquiry tp_is_gc; */
NULL, /* PyObject *tp_bases; */
/* method resolution order */
NULL, /* PyObject *tp_mro; */
NULL, /* PyObject *tp_cache; */
NULL, /* PyObject *tp_subclasses; */
NULL, /* PyObject *tp_weaklist; */
NULL,
};
PyObject *BPyInit_bmesh_ops(void)
{
PyObject *submodule;
PyObject *submodule;
if (PyType_Ready(&bmesh_ops_fakemod_Type) < 0) {
return NULL;
}
if (PyType_Ready(&bmesh_ops_fakemod_Type) < 0) {
return NULL;
}
if (PyType_Ready(&bmesh_op_Type) < 0) {
return NULL;
}
if (PyType_Ready(&bmesh_op_Type) < 0) {
return NULL;
}
submodule = PyObject_New(PyObject, &bmesh_ops_fakemod_Type);
submodule = PyObject_New(PyObject, &bmesh_ops_fakemod_Type);
/* prevent further creation of instances */
bmesh_ops_fakemod_Type.tp_init = NULL;
bmesh_ops_fakemod_Type.tp_new = NULL;
/* prevent further creation of instances */
bmesh_ops_fakemod_Type.tp_init = NULL;
bmesh_ops_fakemod_Type.tp_new = NULL;
return submodule;
return submodule;
}

File diff suppressed because it is too large Load Diff

View File

@@ -25,11 +25,10 @@
#define __BMESH_PY_OPS_CALL_H__
typedef struct {
PyObject_HEAD /* required python macro */
const char *opname;
PyObject_HEAD /* required python macro */
const char *opname;
} BPy_BMeshOpFunc;
PyObject *BPy_BMO_call(BPy_BMeshOpFunc *self, PyObject *args, PyObject *kw);
#endif /* __BMESH_PY_OPS_CALL_H__ */

File diff suppressed because it is too large Load Diff

View File

@@ -38,65 +38,57 @@ extern PyTypeObject BPy_BMLoopSeq_Type;
extern PyTypeObject BPy_BMIter_Type;
#define BPy_BMesh_Check(v) (Py_TYPE(v) == &BPy_BMesh_Type)
#define BPy_BMVert_Check(v) (Py_TYPE(v) == &BPy_BMVert_Type)
#define BPy_BMEdge_Check(v) (Py_TYPE(v) == &BPy_BMEdge_Type)
#define BPy_BMFace_Check(v) (Py_TYPE(v) == &BPy_BMFace_Type)
#define BPy_BMLoop_Check(v) (Py_TYPE(v) == &BPy_BMLoop_Type)
#define BPy_BMElemSeq_Check(v) (Py_TYPE(v) == &BPy_BMElemSeq_Type)
#define BPy_BMVertSeq_Check(v) (Py_TYPE(v) == &BPy_BMVertSeq_Type)
#define BPy_BMEdgeSeq_Check(v) (Py_TYPE(v) == &BPy_BMEdgeSeq_Type)
#define BPy_BMFaceSeq_Check(v) (Py_TYPE(v) == &BPy_BMFaceSeq_Type)
#define BPy_BMLoopSeq_Check(v) (Py_TYPE(v) == &BPy_BMLoopSeq_Type)
#define BPy_BMIter_Check(v) (Py_TYPE(v) == &BPy_BMIter_Type)
#define BPy_BMesh_Check(v) (Py_TYPE(v) == &BPy_BMesh_Type)
#define BPy_BMVert_Check(v) (Py_TYPE(v) == &BPy_BMVert_Type)
#define BPy_BMEdge_Check(v) (Py_TYPE(v) == &BPy_BMEdge_Type)
#define BPy_BMFace_Check(v) (Py_TYPE(v) == &BPy_BMFace_Type)
#define BPy_BMLoop_Check(v) (Py_TYPE(v) == &BPy_BMLoop_Type)
#define BPy_BMElemSeq_Check(v) (Py_TYPE(v) == &BPy_BMElemSeq_Type)
#define BPy_BMVertSeq_Check(v) (Py_TYPE(v) == &BPy_BMVertSeq_Type)
#define BPy_BMEdgeSeq_Check(v) (Py_TYPE(v) == &BPy_BMEdgeSeq_Type)
#define BPy_BMFaceSeq_Check(v) (Py_TYPE(v) == &BPy_BMFaceSeq_Type)
#define BPy_BMLoopSeq_Check(v) (Py_TYPE(v) == &BPy_BMLoopSeq_Type)
#define BPy_BMIter_Check(v) (Py_TYPE(v) == &BPy_BMIter_Type)
/* trick since we know they share a hash function */
#define BPy_BMElem_Check(v) (Py_TYPE(v)->tp_hash == BPy_BMVert_Type.tp_hash)
#define BPy_BMElem_Check(v) (Py_TYPE(v)->tp_hash == BPy_BMVert_Type.tp_hash)
/* cast from _any_ bmesh type - they all have BMesh first */
typedef struct BPy_BMGeneric {
PyObject_VAR_HEAD
struct BMesh *bm; /* keep first */
PyObject_VAR_HEAD struct BMesh *bm; /* keep first */
} BPy_BMGeneric;
/* BPy_BMVert/BPy_BMEdge/BPy_BMFace/BPy_BMLoop can cast to this */
typedef struct BPy_BMElem {
PyObject_VAR_HEAD
struct BMesh *bm; /* keep first */
struct BMElem *ele;
PyObject_VAR_HEAD struct BMesh *bm; /* keep first */
struct BMElem *ele;
} BPy_BMElem;
typedef struct BPy_BMesh {
PyObject_VAR_HEAD
struct BMesh *bm; /* keep first */
int flag;
PyObject_VAR_HEAD struct BMesh *bm; /* keep first */
int flag;
} BPy_BMesh;
/* element types */
typedef struct BPy_BMVert {
PyObject_VAR_HEAD
struct BMesh *bm; /* keep first */
struct BMVert *v;
PyObject_VAR_HEAD struct BMesh *bm; /* keep first */
struct BMVert *v;
} BPy_BMVert;
typedef struct BPy_BMEdge {
PyObject_VAR_HEAD
struct BMesh *bm; /* keep first */
struct BMEdge *e;
PyObject_VAR_HEAD struct BMesh *bm; /* keep first */
struct BMEdge *e;
} BPy_BMEdge;
typedef struct BPy_BMFace {
PyObject_VAR_HEAD
struct BMesh *bm; /* keep first */
struct BMFace *f;
PyObject_VAR_HEAD struct BMesh *bm; /* keep first */
struct BMFace *f;
} BPy_BMFace;
typedef struct BPy_BMLoop {
PyObject_VAR_HEAD
struct BMesh *bm; /* keep first */
struct BMLoop *l;
PyObject_VAR_HEAD struct BMesh *bm; /* keep first */
struct BMLoop *l;
} BPy_BMLoop;
/* iterators */
/* used for ...
@@ -107,26 +99,24 @@ typedef struct BPy_BMLoop {
* - BPy_BMLoopSeq_Type
*/
typedef struct BPy_BMElemSeq {
PyObject_VAR_HEAD
struct BMesh *bm; /* keep first */
PyObject_VAR_HEAD struct BMesh *bm; /* keep first */
/* if this is a sequence on an existing element,
* loops of faces for eg.
* If this variable is set, it will be used */
/* if this is a sequence on an existing element,
* loops of faces for eg.
* If this variable is set, it will be used */
/* we hold a reference to this.
* check in case the owner becomes invalid on access */
/* TODO - make this a GC'd object!, will function OK without this though */
BPy_BMElem *py_ele;
/* we hold a reference to this.
* check in case the owner becomes invalid on access */
/* TODO - make this a GC'd object!, will function OK without this though */
BPy_BMElem *py_ele;
/* iterator type */
short itype;
/* iterator type */
short itype;
} BPy_BMElemSeq;
typedef struct BPy_BMIter {
PyObject_VAR_HEAD
struct BMesh *bm; /* keep first */
BMIter iter;
PyObject_VAR_HEAD struct BMesh *bm; /* keep first */
BMIter iter;
} BPy_BMIter;
void BPy_BM_init_types(void);
@@ -134,8 +124,8 @@ void BPy_BM_init_types(void);
PyObject *BPyInit_bmesh_types(void);
enum {
BPY_BMFLAG_NOP = 0, /* do nothing */
BPY_BMFLAG_IS_WRAPPED = 1, /* the mesh is owned by editmode */
BPY_BMFLAG_NOP = 0, /* do nothing */
BPY_BMFLAG_IS_WRAPPED = 1, /* the mesh is owned by editmode */
};
PyObject *BPy_BMesh_CreatePyObject(BMesh *bm, int flag);
@@ -150,18 +140,27 @@ PyObject *BPy_BMFaceSeq_CreatePyObject(BMesh *bm);
PyObject *BPy_BMLoopSeq_CreatePyObject(BMesh *bm);
PyObject *BPy_BMIter_CreatePyObject(BMesh *bm);
PyObject *BPy_BMElem_CreatePyObject(BMesh *bm, BMHeader *ele); /* just checks type and creates v/e/f/l */
PyObject *BPy_BMElem_CreatePyObject(BMesh *bm,
BMHeader *ele); /* just checks type and creates v/e/f/l */
void *BPy_BMElem_PySeq_As_Array_FAST(
BMesh **r_bm, PyObject *seq_fast, Py_ssize_t min, Py_ssize_t max, Py_ssize_t *r_size,
const char htype,
const bool do_unique_check, const bool do_bm_check,
const char *error_prefix);
void *BPy_BMElem_PySeq_As_Array(
BMesh **r_bm, PyObject *seq, Py_ssize_t min, Py_ssize_t max, Py_ssize_t *r_size,
const char htype,
const bool do_unique_check, const bool do_bm_check,
const char *error_prefix);
void *BPy_BMElem_PySeq_As_Array_FAST(BMesh **r_bm,
PyObject *seq_fast,
Py_ssize_t min,
Py_ssize_t max,
Py_ssize_t *r_size,
const char htype,
const bool do_unique_check,
const bool do_bm_check,
const char *error_prefix);
void *BPy_BMElem_PySeq_As_Array(BMesh **r_bm,
PyObject *seq,
Py_ssize_t min,
Py_ssize_t max,
Py_ssize_t *r_size,
const char htype,
const bool do_unique_check,
const bool do_bm_check,
const char *error_prefix);
PyObject *BPy_BMElem_Array_As_Tuple(BMesh *bm, BMHeader **elem, Py_ssize_t elem_len);
PyObject *BPy_BMVert_Array_As_Tuple(BMesh *bm, BMVert **elem, Py_ssize_t elem_len);
@@ -169,47 +168,58 @@ PyObject *BPy_BMEdge_Array_As_Tuple(BMesh *bm, BMEdge **elem, Py_ssize_t elem_le
PyObject *BPy_BMFace_Array_As_Tuple(BMesh *bm, BMFace **elem, Py_ssize_t elem_len);
PyObject *BPy_BMLoop_Array_As_Tuple(BMesh *bm, BMLoop **elem, Py_ssize_t elem_len);
int BPy_BMElem_CheckHType(PyTypeObject *type, const char htype);
char *BPy_BMElem_StringFromHType_ex(const char htype, char ret[32]);
char *BPy_BMElem_StringFromHType(const char htype);
int BPy_BMElem_CheckHType(PyTypeObject *type, const char htype);
char *BPy_BMElem_StringFromHType_ex(const char htype, char ret[32]);
char *BPy_BMElem_StringFromHType(const char htype);
// void bpy_bm_generic_invalidate(BPy_BMGeneric *self);
int bpy_bm_generic_valid_check(BPy_BMGeneric *self);
int bpy_bm_generic_valid_check_source(BMesh *bm_source, const char *error_prefix, void **args, unsigned int args_n) ATTR_NONNULL(1, 2);
int bpy_bm_generic_valid_check(BPy_BMGeneric *self);
int bpy_bm_generic_valid_check_source(BMesh *bm_source,
const char *error_prefix,
void **args,
unsigned int args_n) ATTR_NONNULL(1, 2);
#define BPY_BM_CHECK_OBJ(obj) \
if (UNLIKELY(bpy_bm_generic_valid_check((BPy_BMGeneric *)obj) == -1)) { return NULL; } (void)0
if (UNLIKELY(bpy_bm_generic_valid_check((BPy_BMGeneric *)obj) == -1)) { \
return NULL; \
} \
(void)0
#define BPY_BM_CHECK_INT(obj) \
if (UNLIKELY(bpy_bm_generic_valid_check((BPy_BMGeneric *)obj) == -1)) { return -1; } (void)0
if (UNLIKELY(bpy_bm_generic_valid_check((BPy_BMGeneric *)obj) == -1)) { \
return -1; \
} \
(void)0
/* macros like BPY_BM_CHECK_OBJ/BPY_BM_CHECK_INT that ensure we're from the right BMesh */
#define BPY_BM_CHECK_SOURCE_OBJ(bm, errmsg, ...) { \
void *_args[] = {__VA_ARGS__}; \
if (UNLIKELY(bpy_bm_generic_valid_check_source(bm, errmsg, _args, ARRAY_SIZE(_args)) == -1)) { \
return NULL; \
} \
} (void)0
#define BPY_BM_CHECK_SOURCE_INT(bm, errmsg, ...) { \
void *_args[] = {__VA_ARGS__}; \
if (UNLIKELY(bpy_bm_generic_valid_check_source(bm, errmsg, _args, ARRAY_SIZE(_args)) == -1)) { \
return -1; \
} \
} (void)0
#define BPY_BM_CHECK_SOURCE_OBJ(bm, errmsg, ...) \
{ \
void *_args[] = {__VA_ARGS__}; \
if (UNLIKELY(bpy_bm_generic_valid_check_source(bm, errmsg, _args, ARRAY_SIZE(_args)) == \
-1)) { \
return NULL; \
} \
} \
(void)0
#define BPY_BM_CHECK_SOURCE_INT(bm, errmsg, ...) \
{ \
void *_args[] = {__VA_ARGS__}; \
if (UNLIKELY(bpy_bm_generic_valid_check_source(bm, errmsg, _args, ARRAY_SIZE(_args)) == \
-1)) { \
return -1; \
} \
} \
(void)0
#define BPY_BM_IS_VALID(obj) (LIKELY((obj)->bm != NULL))
#define BM_ITER_BPY_BM_SEQ(ele, iter, bpy_bmelemseq) \
for (BM_CHECK_TYPE_ELEM_ASSIGN(ele) = BM_iter_new( \
iter, \
(bpy_bmelemseq)->bm, \
(bpy_bmelemseq)->itype, \
(bpy_bmelemseq)->py_ele ? \
((BPy_BMElem *)(bpy_bmelemseq)->py_ele)->ele : \
NULL \
); \
ele; \
BM_CHECK_TYPE_ELEM_ASSIGN(ele) = BM_iter_step(iter))
#define BM_ITER_BPY_BM_SEQ(ele, iter, bpy_bmelemseq) \
for (BM_CHECK_TYPE_ELEM_ASSIGN(ele) = BM_iter_new( \
iter, \
(bpy_bmelemseq)->bm, \
(bpy_bmelemseq)->itype, \
(bpy_bmelemseq)->py_ele ? ((BPy_BMElem *)(bpy_bmelemseq)->py_ele)->ele : NULL); \
ele; \
BM_CHECK_TYPE_ELEM_ASSIGN(ele) = BM_iter_step(iter))
#ifdef __PY_CAPI_UTILS_H__
struct PyC_FlagSet;

File diff suppressed because it is too large Load Diff

View File

@@ -33,32 +33,29 @@ extern PyTypeObject BPy_BMLayerAccessLoop_Type;
extern PyTypeObject BPy_BMLayerCollection_Type;
extern PyTypeObject BPy_BMLayerItem_Type;
#define BPy_BMLayerAccess_Check(v) (Py_TYPE(v) == &BPy_BMLayerAccess_Type)
#define BPy_BMLayerCollection_Check(v) (Py_TYPE(v) == &BPy_BMLayerCollection_Type)
#define BPy_BMLayerItem_Check(v) (Py_TYPE(v) == &BPy_BMLayerItem_Type)
#define BPy_BMLayerAccess_Check(v) (Py_TYPE(v) == &BPy_BMLayerAccess_Type)
#define BPy_BMLayerCollection_Check(v) (Py_TYPE(v) == &BPy_BMLayerCollection_Type)
#define BPy_BMLayerItem_Check(v) (Py_TYPE(v) == &BPy_BMLayerItem_Type)
/* all layers for vert/edge/face/loop */
typedef struct BPy_BMLayerAccess {
PyObject_VAR_HEAD
struct BMesh *bm; /* keep first */
char htype;
PyObject_VAR_HEAD struct BMesh *bm; /* keep first */
char htype;
} BPy_BMLayerAccess;
/* access different layer types deform/uv/vertexcolor */
typedef struct BPy_BMLayerCollection {
PyObject_VAR_HEAD
struct BMesh *bm; /* keep first */
char htype;
int type; /* customdata type - CD_XXX */
PyObject_VAR_HEAD struct BMesh *bm; /* keep first */
char htype;
int type; /* customdata type - CD_XXX */
} BPy_BMLayerCollection;
/* access a specific layer directly */
typedef struct BPy_BMLayerItem {
PyObject_VAR_HEAD
struct BMesh *bm; /* keep first */
char htype;
int type; /* customdata type - CD_XXX */
int index; /* index of this layer type */
PyObject_VAR_HEAD struct BMesh *bm; /* keep first */
char htype;
int type; /* customdata type - CD_XXX */
int index; /* index of this layer type */
} BPy_BMLayerItem;
PyObject *BPy_BMLayerAccess_CreatePyObject(BMesh *bm, const char htype);
@@ -69,7 +66,6 @@ void BPy_BM_init_types_customdata(void);
/* __getitem__ / __setitem__ */
PyObject *BPy_BMLayerItem_GetItem(BPy_BMElem *py_ele, BPy_BMLayerItem *py_layer);
int BPy_BMLayerItem_SetItem(BPy_BMElem *py_ele, BPy_BMLayerItem *py_layer, PyObject *value);
int BPy_BMLayerItem_SetItem(BPy_BMElem *py_ele, BPy_BMLayerItem *py_layer, PyObject *value);
#endif /* __BMESH_PY_TYPES_CUSTOMDATA_H__ */

File diff suppressed because it is too large Load Diff

View File

@@ -27,11 +27,10 @@
extern PyTypeObject BPy_BMLoopUV_Type;
extern PyTypeObject BPy_BMDeformVert_Type;
#define BPy_BMLoopUV_Check(v) (Py_TYPE(v) == &BPy_BMLoopUV_Type)
#define BPy_BMLoopUV_Check(v) (Py_TYPE(v) == &BPy_BMLoopUV_Type)
typedef struct BPy_BMGenericMeshData {
PyObject_VAR_HEAD
void *data;
PyObject_VAR_HEAD void *data;
} BPy_BMGenericMeshData;
struct MDeformVert;
@@ -39,19 +38,18 @@ struct MLoopCol;
struct MLoopUV;
struct MVertSkin;
int BPy_BMLoopUV_AssignPyObject(struct MLoopUV *data, PyObject *value);
int BPy_BMLoopUV_AssignPyObject(struct MLoopUV *data, PyObject *value);
PyObject *BPy_BMLoopUV_CreatePyObject(struct MLoopUV *data);
int BPy_BMVertSkin_AssignPyObject(struct MVertSkin *data, PyObject *value);
int BPy_BMVertSkin_AssignPyObject(struct MVertSkin *data, PyObject *value);
PyObject *BPy_BMVertSkin_CreatePyObject(struct MVertSkin *data);
int BPy_BMLoopColor_AssignPyObject(struct MLoopCol *data, PyObject *value);
int BPy_BMLoopColor_AssignPyObject(struct MLoopCol *data, PyObject *value);
PyObject *BPy_BMLoopColor_CreatePyObject(struct MLoopCol *data);
int BPy_BMDeformVert_AssignPyObject(struct MDeformVert *dvert, PyObject *value);
int BPy_BMDeformVert_AssignPyObject(struct MDeformVert *dvert, PyObject *value);
PyObject *BPy_BMDeformVert_CreatePyObject(struct MDeformVert *dvert);
void BPy_BM_init_types_meshdata(void);
#endif /* __BMESH_PY_TYPES_MESHDATA_H__ */

View File

@@ -41,397 +41,387 @@
#include "../generic/python_utildefines.h"
PyDoc_STRVAR(bpy_bmeditselseq_active_doc,
"The last selected element or None (read-only).\n\n:type: :class:`BMVert`, :class:`BMEdge` or :class:`BMFace`"
);
"The last selected element or None (read-only).\n\n:type: :class:`BMVert`, "
":class:`BMEdge` or :class:`BMFace`");
static PyObject *bpy_bmeditselseq_active_get(BPy_BMEditSelSeq *self, void *UNUSED(closure))
{
BMEditSelection *ese;
BPY_BM_CHECK_OBJ(self);
BMEditSelection *ese;
BPY_BM_CHECK_OBJ(self);
if ((ese = self->bm->selected.last)) {
return BPy_BMElem_CreatePyObject(self->bm, &ese->ele->head);
}
else {
Py_RETURN_NONE;
}
if ((ese = self->bm->selected.last)) {
return BPy_BMElem_CreatePyObject(self->bm, &ese->ele->head);
}
else {
Py_RETURN_NONE;
}
}
static PyGetSetDef bpy_bmeditselseq_getseters[] = {
{(char *)"active", (getter)bpy_bmeditselseq_active_get, (setter)NULL, (char *)bpy_bmeditselseq_active_doc, NULL},
{NULL, NULL, NULL, NULL, NULL} /* Sentinel */
{(char *)"active",
(getter)bpy_bmeditselseq_active_get,
(setter)NULL,
(char *)bpy_bmeditselseq_active_doc,
NULL},
{NULL, NULL, NULL, NULL, NULL} /* Sentinel */
};
PyDoc_STRVAR(bpy_bmeditselseq_validate_doc,
".. method:: validate()\n"
"\n"
" Ensures all elements in the selection history are selected.\n"
);
".. method:: validate()\n"
"\n"
" Ensures all elements in the selection history are selected.\n");
static PyObject *bpy_bmeditselseq_validate(BPy_BMEditSelSeq *self)
{
BPY_BM_CHECK_OBJ(self);
BM_select_history_validate(self->bm);
Py_RETURN_NONE;
BPY_BM_CHECK_OBJ(self);
BM_select_history_validate(self->bm);
Py_RETURN_NONE;
}
PyDoc_STRVAR(bpy_bmeditselseq_clear_doc,
".. method:: clear()\n"
"\n"
" Empties the selection history.\n"
);
".. method:: clear()\n"
"\n"
" Empties the selection history.\n");
static PyObject *bpy_bmeditselseq_clear(BPy_BMEditSelSeq *self)
{
BPY_BM_CHECK_OBJ(self);
BM_select_history_clear(self->bm);
Py_RETURN_NONE;
BPY_BM_CHECK_OBJ(self);
BM_select_history_clear(self->bm);
Py_RETURN_NONE;
}
PyDoc_STRVAR(bpy_bmeditselseq_add_doc,
".. method:: add(element)\n"
"\n"
" Add an element to the selection history (no action taken if its already added).\n"
);
PyDoc_STRVAR(
bpy_bmeditselseq_add_doc,
".. method:: add(element)\n"
"\n"
" Add an element to the selection history (no action taken if its already added).\n");
static PyObject *bpy_bmeditselseq_add(BPy_BMEditSelSeq *self, BPy_BMElem *value)
{
BPY_BM_CHECK_OBJ(self);
BPY_BM_CHECK_OBJ(self);
if ((BPy_BMVert_Check(value) ||
BPy_BMEdge_Check(value) ||
BPy_BMFace_Check(value)) == false)
{
PyErr_Format(PyExc_TypeError,
"Expected a BMVert/BMedge/BMFace not a %.200s", Py_TYPE(value)->tp_name);
return NULL;
}
if ((BPy_BMVert_Check(value) || BPy_BMEdge_Check(value) || BPy_BMFace_Check(value)) == false) {
PyErr_Format(
PyExc_TypeError, "Expected a BMVert/BMedge/BMFace not a %.200s", Py_TYPE(value)->tp_name);
return NULL;
}
BPY_BM_CHECK_SOURCE_OBJ(self->bm, "select_history.add()", value);
BPY_BM_CHECK_SOURCE_OBJ(self->bm, "select_history.add()", value);
BM_select_history_store(self->bm, value->ele);
BM_select_history_store(self->bm, value->ele);
Py_RETURN_NONE;
Py_RETURN_NONE;
}
PyDoc_STRVAR(bpy_bmeditselseq_remove_doc,
".. method:: remove(element)\n"
"\n"
" Remove an element from the selection history.\n"
);
".. method:: remove(element)\n"
"\n"
" Remove an element from the selection history.\n");
static PyObject *bpy_bmeditselseq_remove(BPy_BMEditSelSeq *self, BPy_BMElem *value)
{
BPY_BM_CHECK_OBJ(self);
BPY_BM_CHECK_OBJ(self);
if ((BPy_BMVert_Check(value) ||
BPy_BMEdge_Check(value) ||
BPy_BMFace_Check(value)) == false)
{
PyErr_Format(PyExc_TypeError,
"Expected a BMVert/BMedge/BMFace not a %.200s", Py_TYPE(value)->tp_name);
return NULL;
}
if ((BPy_BMVert_Check(value) || BPy_BMEdge_Check(value) || BPy_BMFace_Check(value)) == false) {
PyErr_Format(
PyExc_TypeError, "Expected a BMVert/BMedge/BMFace not a %.200s", Py_TYPE(value)->tp_name);
return NULL;
}
BPY_BM_CHECK_SOURCE_OBJ(self->bm, "select_history.remove()", value);
BPY_BM_CHECK_SOURCE_OBJ(self->bm, "select_history.remove()", value);
if (BM_select_history_remove(self->bm, value->ele) == false) {
PyErr_SetString(PyExc_ValueError,
"Element not found in selection history");
return NULL;
}
if (BM_select_history_remove(self->bm, value->ele) == false) {
PyErr_SetString(PyExc_ValueError, "Element not found in selection history");
return NULL;
}
Py_RETURN_NONE;
Py_RETURN_NONE;
}
PyDoc_STRVAR(bpy_bmeditselseq_discard_doc,
".. method:: discard(element)\n"
"\n"
" Discard an element from the selection history.\n"
"\n"
" Like remove but doesn't raise an error when the elements not in the selection list.\n"
);
PyDoc_STRVAR(
bpy_bmeditselseq_discard_doc,
".. method:: discard(element)\n"
"\n"
" Discard an element from the selection history.\n"
"\n"
" Like remove but doesn't raise an error when the elements not in the selection list.\n");
static PyObject *bpy_bmeditselseq_discard(BPy_BMEditSelSeq *self, BPy_BMElem *value)
{
BPY_BM_CHECK_OBJ(self);
BPY_BM_CHECK_OBJ(self);
if ((BPy_BMVert_Check(value) ||
BPy_BMEdge_Check(value) ||
BPy_BMFace_Check(value)) == false)
{
PyErr_Format(PyExc_TypeError,
"Expected a BMVert/BMedge/BMFace not a %.200s", Py_TYPE(value)->tp_name);
return NULL;
}
if ((BPy_BMVert_Check(value) || BPy_BMEdge_Check(value) || BPy_BMFace_Check(value)) == false) {
PyErr_Format(
PyExc_TypeError, "Expected a BMVert/BMedge/BMFace not a %.200s", Py_TYPE(value)->tp_name);
return NULL;
}
BPY_BM_CHECK_SOURCE_OBJ(self->bm, "select_history.discard()", value);
BPY_BM_CHECK_SOURCE_OBJ(self->bm, "select_history.discard()", value);
BM_select_history_remove(self->bm, value->ele);
BM_select_history_remove(self->bm, value->ele);
Py_RETURN_NONE;
Py_RETURN_NONE;
}
static struct PyMethodDef bpy_bmeditselseq_methods[] = {
{"validate", (PyCFunction)bpy_bmeditselseq_validate, METH_NOARGS, bpy_bmeditselseq_validate_doc},
{"clear", (PyCFunction)bpy_bmeditselseq_clear, METH_NOARGS, bpy_bmeditselseq_clear_doc},
{"validate",
(PyCFunction)bpy_bmeditselseq_validate,
METH_NOARGS,
bpy_bmeditselseq_validate_doc},
{"clear", (PyCFunction)bpy_bmeditselseq_clear, METH_NOARGS, bpy_bmeditselseq_clear_doc},
{"add", (PyCFunction)bpy_bmeditselseq_add, METH_O, bpy_bmeditselseq_add_doc},
{"remove", (PyCFunction)bpy_bmeditselseq_remove, METH_O, bpy_bmeditselseq_remove_doc},
{"discard", (PyCFunction)bpy_bmeditselseq_discard, METH_O, bpy_bmeditselseq_discard_doc},
{NULL, NULL, 0, NULL},
{"add", (PyCFunction)bpy_bmeditselseq_add, METH_O, bpy_bmeditselseq_add_doc},
{"remove", (PyCFunction)bpy_bmeditselseq_remove, METH_O, bpy_bmeditselseq_remove_doc},
{"discard", (PyCFunction)bpy_bmeditselseq_discard, METH_O, bpy_bmeditselseq_discard_doc},
{NULL, NULL, 0, NULL},
};
/* Sequences
* ========= */
static Py_ssize_t bpy_bmeditselseq_length(BPy_BMEditSelSeq *self)
{
BPY_BM_CHECK_INT(self);
BPY_BM_CHECK_INT(self);
return BLI_listbase_count(&self->bm->selected);
return BLI_listbase_count(&self->bm->selected);
}
static PyObject *bpy_bmeditselseq_subscript_int(BPy_BMEditSelSeq *self, int keynum)
{
BMEditSelection *ese;
BMEditSelection *ese;
BPY_BM_CHECK_OBJ(self);
BPY_BM_CHECK_OBJ(self);
if (keynum < 0) {
ese = BLI_rfindlink(&self->bm->selected, -1 - keynum);
}
else {
ese = BLI_findlink(&self->bm->selected, keynum);
}
if (keynum < 0) {
ese = BLI_rfindlink(&self->bm->selected, -1 - keynum);
}
else {
ese = BLI_findlink(&self->bm->selected, keynum);
}
if (ese) {
return BPy_BMElem_CreatePyObject(self->bm, &ese->ele->head);
}
else {
PyErr_Format(PyExc_IndexError,
"BMElemSeq[index]: index %d out of range", keynum);
return NULL;
}
if (ese) {
return BPy_BMElem_CreatePyObject(self->bm, &ese->ele->head);
}
else {
PyErr_Format(PyExc_IndexError, "BMElemSeq[index]: index %d out of range", keynum);
return NULL;
}
}
static PyObject *bpy_bmeditselseq_subscript_slice(BPy_BMEditSelSeq *self, Py_ssize_t start, Py_ssize_t stop)
static PyObject *bpy_bmeditselseq_subscript_slice(BPy_BMEditSelSeq *self,
Py_ssize_t start,
Py_ssize_t stop)
{
int count = 0;
bool ok;
int count = 0;
bool ok;
PyObject *list;
BMEditSelection *ese;
PyObject *list;
BMEditSelection *ese;
BPY_BM_CHECK_OBJ(self);
BPY_BM_CHECK_OBJ(self);
list = PyList_New(0);
list = PyList_New(0);
ese = self->bm->selected.first;
ese = self->bm->selected.first;
ok = (ese != NULL);
ok = (ese != NULL);
if (UNLIKELY(ok == false)) {
return list;
}
if (UNLIKELY(ok == false)) {
return list;
}
/* first loop up-until the start */
for (ok = true; ok; ok = ((ese = ese->next) != NULL)) {
if (count == start) {
break;
}
count++;
}
/* first loop up-until the start */
for (ok = true; ok; ok = ((ese = ese->next) != NULL)) {
if (count == start) {
break;
}
count++;
}
/* add items until stop */
do {
PyList_APPEND(list, BPy_BMElem_CreatePyObject(self->bm, &ese->ele->head));
count++;
if (count == stop) {
break;
}
} while ((ese = ese->next));
/* add items until stop */
do {
PyList_APPEND(list, BPy_BMElem_CreatePyObject(self->bm, &ese->ele->head));
count++;
if (count == stop) {
break;
}
} while ((ese = ese->next));
return list;
return list;
}
static PyObject *bpy_bmeditselseq_subscript(BPy_BMEditSelSeq *self, PyObject *key)
{
/* don't need error check here */
if (PyIndex_Check(key)) {
Py_ssize_t i = PyNumber_AsSsize_t(key, PyExc_IndexError);
if (i == -1 && PyErr_Occurred()) {
return NULL;
}
return bpy_bmeditselseq_subscript_int(self, i);
}
else if (PySlice_Check(key)) {
PySliceObject *key_slice = (PySliceObject *)key;
Py_ssize_t step = 1;
/* don't need error check here */
if (PyIndex_Check(key)) {
Py_ssize_t i = PyNumber_AsSsize_t(key, PyExc_IndexError);
if (i == -1 && PyErr_Occurred()) {
return NULL;
}
return bpy_bmeditselseq_subscript_int(self, i);
}
else if (PySlice_Check(key)) {
PySliceObject *key_slice = (PySliceObject *)key;
Py_ssize_t step = 1;
if (key_slice->step != Py_None && !_PyEval_SliceIndex(key, &step)) {
return NULL;
}
else if (step != 1) {
PyErr_SetString(PyExc_TypeError,
"BMElemSeq[slice]: slice steps not supported");
return NULL;
}
else if (key_slice->start == Py_None && key_slice->stop == Py_None) {
return bpy_bmeditselseq_subscript_slice(self, 0, PY_SSIZE_T_MAX);
}
else {
Py_ssize_t start = 0, stop = PY_SSIZE_T_MAX;
if (key_slice->step != Py_None && !_PyEval_SliceIndex(key, &step)) {
return NULL;
}
else if (step != 1) {
PyErr_SetString(PyExc_TypeError, "BMElemSeq[slice]: slice steps not supported");
return NULL;
}
else if (key_slice->start == Py_None && key_slice->stop == Py_None) {
return bpy_bmeditselseq_subscript_slice(self, 0, PY_SSIZE_T_MAX);
}
else {
Py_ssize_t start = 0, stop = PY_SSIZE_T_MAX;
/* avoid PySlice_GetIndicesEx because it needs to know the length ahead of time. */
if (key_slice->start != Py_None && !_PyEval_SliceIndex(key_slice->start, &start)) {
return NULL;
}
if (key_slice->stop != Py_None && !_PyEval_SliceIndex(key_slice->stop, &stop)) {
return NULL;
}
/* avoid PySlice_GetIndicesEx because it needs to know the length ahead of time. */
if (key_slice->start != Py_None && !_PyEval_SliceIndex(key_slice->start, &start)) {
return NULL;
}
if (key_slice->stop != Py_None && !_PyEval_SliceIndex(key_slice->stop, &stop)) {
return NULL;
}
if (start < 0 || stop < 0) {
/* only get the length for negative values */
Py_ssize_t len = bpy_bmeditselseq_length(self);
if (start < 0) {
start += len;
}
if (stop < 0) {
stop += len;
}
}
if (start < 0 || stop < 0) {
/* only get the length for negative values */
Py_ssize_t len = bpy_bmeditselseq_length(self);
if (start < 0) {
start += len;
}
if (stop < 0) {
stop += len;
}
}
if (stop - start <= 0) {
return PyList_New(0);
}
else {
return bpy_bmeditselseq_subscript_slice(self, start, stop);
}
}
}
else {
PyErr_SetString(PyExc_AttributeError,
"BMElemSeq[key]: invalid key, key must be an int");
return NULL;
}
if (stop - start <= 0) {
return PyList_New(0);
}
else {
return bpy_bmeditselseq_subscript_slice(self, start, stop);
}
}
}
else {
PyErr_SetString(PyExc_AttributeError, "BMElemSeq[key]: invalid key, key must be an int");
return NULL;
}
}
static int bpy_bmeditselseq_contains(BPy_BMEditSelSeq *self, PyObject *value)
{
BPy_BMElem *value_bm_ele;
BPy_BMElem *value_bm_ele;
BPY_BM_CHECK_INT(self);
BPY_BM_CHECK_INT(self);
value_bm_ele = (BPy_BMElem *)value;
if (value_bm_ele->bm == self->bm) {
return BM_select_history_check(self->bm, value_bm_ele->ele);
}
value_bm_ele = (BPy_BMElem *)value;
if (value_bm_ele->bm == self->bm) {
return BM_select_history_check(self->bm, value_bm_ele->ele);
}
return 0;
return 0;
}
static PySequenceMethods bpy_bmeditselseq_as_sequence = {
(lenfunc)bpy_bmeditselseq_length, /* sq_length */
NULL, /* sq_concat */
NULL, /* sq_repeat */
(ssizeargfunc)bpy_bmeditselseq_subscript_int,/* sq_item */ /* Only set this so PySequence_Check() returns True */
NULL, /* sq_slice */
(ssizeobjargproc)NULL, /* sq_ass_item */
NULL, /* *was* sq_ass_slice */
(objobjproc)bpy_bmeditselseq_contains, /* sq_contains */
(binaryfunc) NULL, /* sq_inplace_concat */
(ssizeargfunc) NULL, /* sq_inplace_repeat */
(lenfunc)bpy_bmeditselseq_length, /* sq_length */
NULL, /* sq_concat */
NULL, /* sq_repeat */
(ssizeargfunc)bpy_bmeditselseq_subscript_int,
/* sq_item */ /* Only set this so PySequence_Check() returns True */
NULL, /* sq_slice */
(ssizeobjargproc)NULL, /* sq_ass_item */
NULL, /* *was* sq_ass_slice */
(objobjproc)bpy_bmeditselseq_contains, /* sq_contains */
(binaryfunc)NULL, /* sq_inplace_concat */
(ssizeargfunc)NULL, /* sq_inplace_repeat */
};
static PyMappingMethods bpy_bmeditselseq_as_mapping = {
(lenfunc)bpy_bmeditselseq_length, /* mp_length */
(binaryfunc)bpy_bmeditselseq_subscript, /* mp_subscript */
(objobjargproc)NULL, /* mp_ass_subscript */
(lenfunc)bpy_bmeditselseq_length, /* mp_length */
(binaryfunc)bpy_bmeditselseq_subscript, /* mp_subscript */
(objobjargproc)NULL, /* mp_ass_subscript */
};
/* Iterator
* -------- */
static PyObject *bpy_bmeditselseq_iter(BPy_BMEditSelSeq *self)
{
BPy_BMEditSelIter *py_iter;
BPy_BMEditSelIter *py_iter;
BPY_BM_CHECK_OBJ(self);
py_iter = (BPy_BMEditSelIter *)BPy_BMEditSelIter_CreatePyObject(self->bm);
py_iter->ese = self->bm->selected.first;
return (PyObject *)py_iter;
BPY_BM_CHECK_OBJ(self);
py_iter = (BPy_BMEditSelIter *)BPy_BMEditSelIter_CreatePyObject(self->bm);
py_iter->ese = self->bm->selected.first;
return (PyObject *)py_iter;
}
static PyObject *bpy_bmeditseliter_next(BPy_BMEditSelIter *self)
{
BMEditSelection *ese = self->ese;
if (ese == NULL) {
PyErr_SetNone(PyExc_StopIteration);
return NULL;
}
else {
self->ese = ese->next;
return (PyObject *)BPy_BMElem_CreatePyObject(self->bm, &ese->ele->head);
}
BMEditSelection *ese = self->ese;
if (ese == NULL) {
PyErr_SetNone(PyExc_StopIteration);
return NULL;
}
else {
self->ese = ese->next;
return (PyObject *)BPy_BMElem_CreatePyObject(self->bm, &ese->ele->head);
}
}
PyTypeObject BPy_BMEditSelSeq_Type;
PyTypeObject BPy_BMEditSelIter_Type;
PyObject *BPy_BMEditSel_CreatePyObject(BMesh *bm)
{
BPy_BMEditSelSeq *self = PyObject_New(BPy_BMEditSelSeq, &BPy_BMEditSelSeq_Type);
self->bm = bm;
/* caller must initialize 'iter' member */
return (PyObject *)self;
BPy_BMEditSelSeq *self = PyObject_New(BPy_BMEditSelSeq, &BPy_BMEditSelSeq_Type);
self->bm = bm;
/* caller must initialize 'iter' member */
return (PyObject *)self;
}
PyObject *BPy_BMEditSelIter_CreatePyObject(BMesh *bm)
{
BPy_BMEditSelIter *self = PyObject_New(BPy_BMEditSelIter, &BPy_BMEditSelIter_Type);
self->bm = bm;
/* caller must initialize 'iter' member */
return (PyObject *)self;
BPy_BMEditSelIter *self = PyObject_New(BPy_BMEditSelIter, &BPy_BMEditSelIter_Type);
self->bm = bm;
/* caller must initialize 'iter' member */
return (PyObject *)self;
}
void BPy_BM_init_types_select(void)
{
BPy_BMEditSelSeq_Type.tp_basicsize = sizeof(BPy_BMEditSelSeq);
BPy_BMEditSelIter_Type.tp_basicsize = sizeof(BPy_BMEditSelIter);
BPy_BMEditSelSeq_Type.tp_basicsize = sizeof(BPy_BMEditSelSeq);
BPy_BMEditSelIter_Type.tp_basicsize = sizeof(BPy_BMEditSelIter);
BPy_BMEditSelSeq_Type.tp_name = "BMEditSelSeq";
BPy_BMEditSelIter_Type.tp_name = "BMEditSelIter";
BPy_BMEditSelSeq_Type.tp_name = "BMEditSelSeq";
BPy_BMEditSelIter_Type.tp_name = "BMEditSelIter";
BPy_BMEditSelSeq_Type.tp_doc = NULL; /* todo */
BPy_BMEditSelIter_Type.tp_doc = NULL;
BPy_BMEditSelSeq_Type.tp_doc = NULL; /* todo */
BPy_BMEditSelIter_Type.tp_doc = NULL;
BPy_BMEditSelSeq_Type.tp_repr = (reprfunc)NULL;
BPy_BMEditSelIter_Type.tp_repr = (reprfunc)NULL;
BPy_BMEditSelSeq_Type.tp_repr = (reprfunc)NULL;
BPy_BMEditSelIter_Type.tp_repr = (reprfunc)NULL;
BPy_BMEditSelSeq_Type.tp_getset = bpy_bmeditselseq_getseters;
BPy_BMEditSelIter_Type.tp_getset = NULL;
BPy_BMEditSelSeq_Type.tp_getset = bpy_bmeditselseq_getseters;
BPy_BMEditSelIter_Type.tp_getset = NULL;
BPy_BMEditSelSeq_Type.tp_methods = bpy_bmeditselseq_methods;
BPy_BMEditSelIter_Type.tp_methods = NULL;
BPy_BMEditSelSeq_Type.tp_methods = bpy_bmeditselseq_methods;
BPy_BMEditSelIter_Type.tp_methods = NULL;
BPy_BMEditSelSeq_Type.tp_as_sequence = &bpy_bmeditselseq_as_sequence;
BPy_BMEditSelSeq_Type.tp_as_sequence = &bpy_bmeditselseq_as_sequence;
BPy_BMEditSelSeq_Type.tp_as_mapping = &bpy_bmeditselseq_as_mapping;
BPy_BMEditSelSeq_Type.tp_as_mapping = &bpy_bmeditselseq_as_mapping;
BPy_BMEditSelSeq_Type.tp_iter = (getiterfunc)bpy_bmeditselseq_iter;
BPy_BMEditSelSeq_Type.tp_iter = (getiterfunc)bpy_bmeditselseq_iter;
/* only 1 iteratir so far */
BPy_BMEditSelIter_Type.tp_iternext = (iternextfunc)bpy_bmeditseliter_next;
/* only 1 iteratir so far */
BPy_BMEditSelIter_Type.tp_iternext = (iternextfunc)bpy_bmeditseliter_next;
BPy_BMEditSelSeq_Type.tp_dealloc = NULL; //(destructor)bpy_bmeditselseq_dealloc;
BPy_BMEditSelIter_Type.tp_dealloc = NULL; //(destructor)bpy_bmvert_dealloc;
BPy_BMEditSelSeq_Type.tp_dealloc = NULL; //(destructor)bpy_bmeditselseq_dealloc;
BPy_BMEditSelIter_Type.tp_dealloc = NULL; //(destructor)bpy_bmvert_dealloc;
BPy_BMEditSelSeq_Type.tp_flags = Py_TPFLAGS_DEFAULT;
BPy_BMEditSelIter_Type.tp_flags = Py_TPFLAGS_DEFAULT;
BPy_BMEditSelSeq_Type.tp_flags = Py_TPFLAGS_DEFAULT;
BPy_BMEditSelIter_Type.tp_flags = Py_TPFLAGS_DEFAULT;
PyType_Ready(&BPy_BMEditSelSeq_Type);
PyType_Ready(&BPy_BMEditSelIter_Type);
PyType_Ready(&BPy_BMEditSelSeq_Type);
PyType_Ready(&BPy_BMEditSelIter_Type);
}
/* utility function */
/**
@@ -439,29 +429,35 @@ void BPy_BM_init_types_select(void)
*/
int BPy_BMEditSel_Assign(BPy_BMesh *self, PyObject *value)
{
BMesh *bm;
Py_ssize_t value_len;
Py_ssize_t i;
BMElem **value_array = NULL;
BMesh *bm;
Py_ssize_t value_len;
Py_ssize_t i;
BMElem **value_array = NULL;
BPY_BM_CHECK_INT(self);
BPY_BM_CHECK_INT(self);
bm = self->bm;
bm = self->bm;
value_array = BPy_BMElem_PySeq_As_Array(&bm, value, 0, PY_SSIZE_T_MAX,
&value_len, BM_VERT | BM_EDGE | BM_FACE,
true, true, "BMesh.select_history = value");
value_array = BPy_BMElem_PySeq_As_Array(&bm,
value,
0,
PY_SSIZE_T_MAX,
&value_len,
BM_VERT | BM_EDGE | BM_FACE,
true,
true,
"BMesh.select_history = value");
if (value_array == NULL) {
return -1;
}
if (value_array == NULL) {
return -1;
}
BM_select_history_clear(bm);
BM_select_history_clear(bm);
for (i = 0; i < value_len; i++) {
BM_select_history_store_notest(bm, value_array[i]);
}
for (i = 0; i < value_len; i++) {
BM_select_history_store_notest(bm, value_array[i]);
}
PyMem_FREE(value_array);
return 0;
PyMem_FREE(value_array);
return 0;
}

View File

@@ -29,24 +29,22 @@ struct BPy_BMesh;
extern PyTypeObject BPy_BMEditSelSeq_Type;
extern PyTypeObject BPy_BMEditSelIter_Type;
#define BPy_BMSelectHistory_Check(v) (Py_TYPE(v) == &BPy_BMEditSelSeq_Type)
#define BPy_BMSelectHistoryIter_Check(v) (Py_TYPE(v) == &BPy_BMEditSelIter_Type)
#define BPy_BMSelectHistory_Check(v) (Py_TYPE(v) == &BPy_BMEditSelSeq_Type)
#define BPy_BMSelectHistoryIter_Check(v) (Py_TYPE(v) == &BPy_BMEditSelIter_Type)
typedef struct BPy_BMEditSelSeq {
PyObject_VAR_HEAD
struct BMesh *bm; /* keep first */
PyObject_VAR_HEAD struct BMesh *bm; /* keep first */
} BPy_BMEditSelSeq;
typedef struct BPy_BMEditSelIter {
PyObject_VAR_HEAD
struct BMesh *bm; /* keep first */
struct BMEditSelection *ese;
PyObject_VAR_HEAD struct BMesh *bm; /* keep first */
struct BMEditSelection *ese;
} BPy_BMEditSelIter;
void BPy_BM_init_types_select(void);
PyObject *BPy_BMEditSel_CreatePyObject(BMesh *bm);
PyObject *BPy_BMEditSelIter_CreatePyObject(BMesh *bm);
int BPy_BMEditSel_Assign(struct BPy_BMesh *self, PyObject *value);
int BPy_BMEditSel_Assign(struct BPy_BMesh *self, PyObject *value);
#endif /* __BMESH_PY_SELECT_H__ */

File diff suppressed because it is too large Load Diff

View File

@@ -16,42 +16,42 @@
# ***** END GPL LICENSE BLOCK *****
set(INC
.
../../blenkernel
../../blenlib
../../gpu
../../makesdna
../../../../intern/guardedalloc
../../../../intern/glew-mx
.
../../blenkernel
../../blenlib
../../gpu
../../makesdna
../../../../intern/guardedalloc
../../../../intern/glew-mx
)
set(INC_SYS
${GLEW_INCLUDE_PATH}
${PYTHON_INCLUDE_DIRS}
${GLEW_INCLUDE_PATH}
${PYTHON_INCLUDE_DIRS}
)
set(SRC
bgl.c
blf_py_api.c
bpy_internal_import.c
bpy_threads.c
idprop_py_api.c
imbuf_py_api.c
py_capi_utils.c
bgl.c
blf_py_api.c
bpy_internal_import.c
bpy_threads.c
idprop_py_api.c
imbuf_py_api.c
py_capi_utils.c
bgl.h
blf_py_api.h
bpy_internal_import.h
idprop_py_api.h
imbuf_py_api.h
py_capi_utils.h
bgl.h
blf_py_api.h
bpy_internal_import.h
idprop_py_api.h
imbuf_py_api.h
py_capi_utils.h
# header-only
python_utildefines.h
# header-only
python_utildefines.h
)
set(LIB
${GLEW_LIBRARY}
${GLEW_LIBRARY}
)
add_definitions(${GL_DEFINITIONS})

File diff suppressed because it is too large Load Diff

View File

@@ -33,22 +33,21 @@ int BGL_typeSize(int type);
* For Python access to OpenGL functions requiring a pointer.
*/
typedef struct _Buffer {
PyObject_VAR_HEAD
PyObject *parent;
PyObject_VAR_HEAD PyObject *parent;
int type; /* GL_BYTE, GL_SHORT, GL_INT, GL_FLOAT */
int ndimensions;
int *dimensions;
int type; /* GL_BYTE, GL_SHORT, GL_INT, GL_FLOAT */
int ndimensions;
int *dimensions;
union {
char *asbyte;
short *asshort;
int *asint;
float *asfloat;
double *asdouble;
union {
char *asbyte;
short *asshort;
int *asint;
float *asfloat;
double *asdouble;
void *asvoid;
} buf;
void *asvoid;
} buf;
} Buffer;
/** The type object */

View File

@@ -29,486 +29,470 @@
#include "python_utildefines.h"
PyDoc_STRVAR(py_blf_position_doc,
".. function:: position(fontid, x, y, z)\n"
"\n"
" Set the position for drawing text.\n"
"\n"
" :arg fontid: The id of the typeface as returned by :func:`blf.load`, for default font use 0.\n"
" :type fontid: int\n"
" :arg x: X axis position to draw the text.\n"
" :type x: float\n"
" :arg y: Y axis position to draw the text.\n"
" :type y: float\n"
" :arg z: Z axis position to draw the text.\n"
" :type z: float\n"
);
".. function:: position(fontid, x, y, z)\n"
"\n"
" Set the position for drawing text.\n"
"\n"
" :arg fontid: The id of the typeface as returned by :func:`blf.load`, for default "
"font use 0.\n"
" :type fontid: int\n"
" :arg x: X axis position to draw the text.\n"
" :type x: float\n"
" :arg y: Y axis position to draw the text.\n"
" :type y: float\n"
" :arg z: Z axis position to draw the text.\n"
" :type z: float\n");
static PyObject *py_blf_position(PyObject *UNUSED(self), PyObject *args)
{
int fontid;
float x, y, z;
int fontid;
float x, y, z;
if (!PyArg_ParseTuple(args, "ifff:blf.position", &fontid, &x, &y, &z)) {
return NULL;
}
if (!PyArg_ParseTuple(args, "ifff:blf.position", &fontid, &x, &y, &z)) {
return NULL;
}
BLF_position(fontid, x, y, z);
BLF_position(fontid, x, y, z);
Py_RETURN_NONE;
Py_RETURN_NONE;
}
PyDoc_STRVAR(py_blf_size_doc,
".. function:: size(fontid, size, dpi)\n"
"\n"
" Set the size and dpi for drawing text.\n"
"\n"
" :arg fontid: The id of the typeface as returned by :func:`blf.load`, for default font use 0.\n"
" :type fontid: int\n"
" :arg size: Point size of the font.\n"
" :type size: int\n"
" :arg dpi: dots per inch value to use for drawing.\n"
" :type dpi: int\n"
);
".. function:: size(fontid, size, dpi)\n"
"\n"
" Set the size and dpi for drawing text.\n"
"\n"
" :arg fontid: The id of the typeface as returned by :func:`blf.load`, for default "
"font use 0.\n"
" :type fontid: int\n"
" :arg size: Point size of the font.\n"
" :type size: int\n"
" :arg dpi: dots per inch value to use for drawing.\n"
" :type dpi: int\n");
static PyObject *py_blf_size(PyObject *UNUSED(self), PyObject *args)
{
int fontid, size, dpi;
int fontid, size, dpi;
if (!PyArg_ParseTuple(args, "iii:blf.size", &fontid, &size, &dpi)) {
return NULL;
}
if (!PyArg_ParseTuple(args, "iii:blf.size", &fontid, &size, &dpi)) {
return NULL;
}
BLF_size(fontid, size, dpi);
BLF_size(fontid, size, dpi);
Py_RETURN_NONE;
Py_RETURN_NONE;
}
PyDoc_STRVAR(py_blf_aspect_doc,
".. function:: aspect(fontid, aspect)\n"
"\n"
" Set the aspect for drawing text.\n"
"\n"
" :arg fontid: The id of the typeface as returned by :func:`blf.load`, for default font use 0.\n"
" :type fontid: int\n"
" :arg aspect: The aspect ratio for text drawing to use.\n"
" :type aspect: float\n"
);
".. function:: aspect(fontid, aspect)\n"
"\n"
" Set the aspect for drawing text.\n"
"\n"
" :arg fontid: The id of the typeface as returned by :func:`blf.load`, for default "
"font use 0.\n"
" :type fontid: int\n"
" :arg aspect: The aspect ratio for text drawing to use.\n"
" :type aspect: float\n");
static PyObject *py_blf_aspect(PyObject *UNUSED(self), PyObject *args)
{
float aspect;
int fontid;
float aspect;
int fontid;
if (!PyArg_ParseTuple(args, "if:blf.aspect", &fontid, &aspect)) {
return NULL;
}
if (!PyArg_ParseTuple(args, "if:blf.aspect", &fontid, &aspect)) {
return NULL;
}
BLF_aspect(fontid, aspect, aspect, 1.0);
BLF_aspect(fontid, aspect, aspect, 1.0);
Py_RETURN_NONE;
Py_RETURN_NONE;
}
PyDoc_STRVAR(py_blf_color_doc,
".. function:: color(fontid, r, g, b, a)\n"
"\n"
" Set the color for drawing text.\n"
"\n"
" :arg fontid: The id of the typeface as returned by :func:`blf.load`, for default font use 0.\n"
" :type fontid: int\n"
" :arg r: red channel 0.0 - 1.0.\n"
" :type r: float\n"
" :arg g: green channel 0.0 - 1.0.\n"
" :type g: float\n"
" :arg b: blue channel 0.0 - 1.0.\n"
" :type b: float\n"
" :arg a: alpha channel 0.0 - 1.0.\n"
" :type a: float\n"
);
".. function:: color(fontid, r, g, b, a)\n"
"\n"
" Set the color for drawing text.\n"
"\n"
" :arg fontid: The id of the typeface as returned by :func:`blf.load`, for default "
"font use 0.\n"
" :type fontid: int\n"
" :arg r: red channel 0.0 - 1.0.\n"
" :type r: float\n"
" :arg g: green channel 0.0 - 1.0.\n"
" :type g: float\n"
" :arg b: blue channel 0.0 - 1.0.\n"
" :type b: float\n"
" :arg a: alpha channel 0.0 - 1.0.\n"
" :type a: float\n");
static PyObject *py_blf_color(PyObject *UNUSED(self), PyObject *args)
{
int fontid;
float rgba[4];
int fontid;
float rgba[4];
if (!PyArg_ParseTuple(
args, "iffff:blf.color",
&fontid, &rgba[0], &rgba[1], &rgba[2], &rgba[3]))
{
return NULL;
}
if (!PyArg_ParseTuple(
args, "iffff:blf.color", &fontid, &rgba[0], &rgba[1], &rgba[2], &rgba[3])) {
return NULL;
}
BLF_color4fv(fontid, rgba);
BLF_color4fv(fontid, rgba);
Py_RETURN_NONE;
Py_RETURN_NONE;
}
#if BLF_BLUR_ENABLE
PyDoc_STRVAR(py_blf_blur_doc,
".. function:: blur(fontid, radius)\n"
"\n"
" Set the blur radius for drawing text.\n"
"\n"
" :arg fontid: The id of the typeface as returned by :func:`blf.load`, for default font use 0.\n"
" :type fontid: int\n"
" :arg radius: The radius for blurring text (in pixels).\n"
" :type radius: int\n"
);
".. function:: blur(fontid, radius)\n"
"\n"
" Set the blur radius for drawing text.\n"
"\n"
" :arg fontid: The id of the typeface as returned by :func:`blf.load`, for default "
"font use 0.\n"
" :type fontid: int\n"
" :arg radius: The radius for blurring text (in pixels).\n"
" :type radius: int\n");
static PyObject *py_blf_blur(PyObject *UNUSED(self), PyObject *args)
{
int blur, fontid;
int blur, fontid;
if (!PyArg_ParseTuple(args, "ii:blf.blur", &fontid, &blur)) {
return NULL;
}
if (!PyArg_ParseTuple(args, "ii:blf.blur", &fontid, &blur)) {
return NULL;
}
BLF_blur(fontid, blur);
BLF_blur(fontid, blur);
Py_RETURN_NONE;
Py_RETURN_NONE;
}
#endif
PyDoc_STRVAR(py_blf_draw_doc,
".. function:: draw(fontid, text)\n"
"\n"
" Draw text in the current context.\n"
"\n"
" :arg fontid: The id of the typeface as returned by :func:`blf.load`, for default font use 0.\n"
" :type fontid: int\n"
" :arg text: the text to draw.\n"
" :type text: string\n"
);
".. function:: draw(fontid, text)\n"
"\n"
" Draw text in the current context.\n"
"\n"
" :arg fontid: The id of the typeface as returned by :func:`blf.load`, for default "
"font use 0.\n"
" :type fontid: int\n"
" :arg text: the text to draw.\n"
" :type text: string\n");
static PyObject *py_blf_draw(PyObject *UNUSED(self), PyObject *args)
{
const char *text;
int text_length;
int fontid;
const char *text;
int text_length;
int fontid;
if (!PyArg_ParseTuple(args, "is#:blf.draw", &fontid, &text, &text_length)) {
return NULL;
}
if (!PyArg_ParseTuple(args, "is#:blf.draw", &fontid, &text, &text_length)) {
return NULL;
}
BLF_draw(fontid, text, (unsigned int)text_length);
BLF_draw(fontid, text, (unsigned int)text_length);
Py_RETURN_NONE;
Py_RETURN_NONE;
}
PyDoc_STRVAR(py_blf_dimensions_doc,
".. function:: dimensions(fontid, text)\n"
"\n"
" Return the width and height of the text.\n"
"\n"
" :arg fontid: The id of the typeface as returned by :func:`blf.load`, for default font use 0.\n"
" :type fontid: int\n"
" :arg text: the text to draw.\n"
" :type text: string\n"
" :return: the width and height of the text.\n"
" :rtype: tuple of 2 floats\n"
);
".. function:: dimensions(fontid, text)\n"
"\n"
" Return the width and height of the text.\n"
"\n"
" :arg fontid: The id of the typeface as returned by :func:`blf.load`, for default "
"font use 0.\n"
" :type fontid: int\n"
" :arg text: the text to draw.\n"
" :type text: string\n"
" :return: the width and height of the text.\n"
" :rtype: tuple of 2 floats\n");
static PyObject *py_blf_dimensions(PyObject *UNUSED(self), PyObject *args)
{
const char *text;
float r_width, r_height;
PyObject *ret;
int fontid;
const char *text;
float r_width, r_height;
PyObject *ret;
int fontid;
if (!PyArg_ParseTuple(args, "is:blf.dimensions", &fontid, &text)) {
return NULL;
}
if (!PyArg_ParseTuple(args, "is:blf.dimensions", &fontid, &text)) {
return NULL;
}
BLF_width_and_height(fontid, text, INT_MAX, &r_width, &r_height);
BLF_width_and_height(fontid, text, INT_MAX, &r_width, &r_height);
ret = PyTuple_New(2);
PyTuple_SET_ITEMS(ret,
PyFloat_FromDouble(r_width),
PyFloat_FromDouble(r_height));
return ret;
ret = PyTuple_New(2);
PyTuple_SET_ITEMS(ret, PyFloat_FromDouble(r_width), PyFloat_FromDouble(r_height));
return ret;
}
PyDoc_STRVAR(py_blf_clipping_doc,
".. function:: clipping(fontid, xmin, ymin, xmax, ymax)\n"
"\n"
" Set the clipping, enable/disable using CLIPPING.\n"
"\n"
" :arg fontid: The id of the typeface as returned by :func:`blf.load`, for default font use 0.\n"
" :type fontid: int\n"
" :arg xmin: Clip the drawing area by these bounds.\n"
" :type xmin: float\n"
" :arg ymin: Clip the drawing area by these bounds.\n"
" :type ymin: float\n"
" :arg xmax: Clip the drawing area by these bounds.\n"
" :type xmax: float\n"
" :arg ymax: Clip the drawing area by these bounds.\n"
" :type ymax: float\n"
);
".. function:: clipping(fontid, xmin, ymin, xmax, ymax)\n"
"\n"
" Set the clipping, enable/disable using CLIPPING.\n"
"\n"
" :arg fontid: The id of the typeface as returned by :func:`blf.load`, for default "
"font use 0.\n"
" :type fontid: int\n"
" :arg xmin: Clip the drawing area by these bounds.\n"
" :type xmin: float\n"
" :arg ymin: Clip the drawing area by these bounds.\n"
" :type ymin: float\n"
" :arg xmax: Clip the drawing area by these bounds.\n"
" :type xmax: float\n"
" :arg ymax: Clip the drawing area by these bounds.\n"
" :type ymax: float\n");
static PyObject *py_blf_clipping(PyObject *UNUSED(self), PyObject *args)
{
float xmin, ymin, xmax, ymax;
int fontid;
float xmin, ymin, xmax, ymax;
int fontid;
if (!PyArg_ParseTuple(args, "iffff:blf.clipping", &fontid, &xmin, &ymin, &xmax, &ymax)) {
return NULL;
}
if (!PyArg_ParseTuple(args, "iffff:blf.clipping", &fontid, &xmin, &ymin, &xmax, &ymax)) {
return NULL;
}
BLF_clipping(fontid, xmin, ymin, xmax, ymax);
BLF_clipping(fontid, xmin, ymin, xmax, ymax);
Py_RETURN_NONE;
Py_RETURN_NONE;
}
PyDoc_STRVAR(py_blf_word_wrap_doc,
".. function:: word_wrap(fontid, wrap_width)\n"
"\n"
" Set the wrap width, enable/disable using WORD_WRAP.\n"
"\n"
" :arg fontid: The id of the typeface as returned by :func:`blf.load`, for default font use 0.\n"
" :type fontid: int\n"
" :arg wrap_width: The width (in pixels) to wrap words at.\n"
" :type wrap_width: int\n"
);
".. function:: word_wrap(fontid, wrap_width)\n"
"\n"
" Set the wrap width, enable/disable using WORD_WRAP.\n"
"\n"
" :arg fontid: The id of the typeface as returned by :func:`blf.load`, for default "
"font use 0.\n"
" :type fontid: int\n"
" :arg wrap_width: The width (in pixels) to wrap words at.\n"
" :type wrap_width: int\n");
static PyObject *py_blf_word_wrap(PyObject *UNUSED(self), PyObject *args)
{
int wrap_width;
int fontid;
int wrap_width;
int fontid;
if (!PyArg_ParseTuple(args, "ii:blf.word_wrap", &fontid, &wrap_width)) {
return NULL;
}
if (!PyArg_ParseTuple(args, "ii:blf.word_wrap", &fontid, &wrap_width)) {
return NULL;
}
BLF_wordwrap(fontid, wrap_width);
BLF_wordwrap(fontid, wrap_width);
Py_RETURN_NONE;
Py_RETURN_NONE;
}
PyDoc_STRVAR(py_blf_disable_doc,
".. function:: disable(fontid, option)\n"
"\n"
" Disable option.\n"
"\n"
" :arg fontid: The id of the typeface as returned by :func:`blf.load`, for default font use 0.\n"
" :type fontid: int\n"
" :arg option: One of ROTATION, CLIPPING, SHADOW or KERNING_DEFAULT.\n"
" :type option: int\n"
);
".. function:: disable(fontid, option)\n"
"\n"
" Disable option.\n"
"\n"
" :arg fontid: The id of the typeface as returned by :func:`blf.load`, for default "
"font use 0.\n"
" :type fontid: int\n"
" :arg option: One of ROTATION, CLIPPING, SHADOW or KERNING_DEFAULT.\n"
" :type option: int\n");
static PyObject *py_blf_disable(PyObject *UNUSED(self), PyObject *args)
{
int option, fontid;
int option, fontid;
if (!PyArg_ParseTuple(args, "ii:blf.disable", &fontid, &option)) {
return NULL;
}
if (!PyArg_ParseTuple(args, "ii:blf.disable", &fontid, &option)) {
return NULL;
}
BLF_disable(fontid, option);
BLF_disable(fontid, option);
Py_RETURN_NONE;
Py_RETURN_NONE;
}
PyDoc_STRVAR(py_blf_enable_doc,
".. function:: enable(fontid, option)\n"
"\n"
" Enable option.\n"
"\n"
" :arg fontid: The id of the typeface as returned by :func:`blf.load`, for default font use 0.\n"
" :type fontid: int\n"
" :arg option: One of ROTATION, CLIPPING, SHADOW or KERNING_DEFAULT.\n"
" :type option: int\n"
);
".. function:: enable(fontid, option)\n"
"\n"
" Enable option.\n"
"\n"
" :arg fontid: The id of the typeface as returned by :func:`blf.load`, for default "
"font use 0.\n"
" :type fontid: int\n"
" :arg option: One of ROTATION, CLIPPING, SHADOW or KERNING_DEFAULT.\n"
" :type option: int\n");
static PyObject *py_blf_enable(PyObject *UNUSED(self), PyObject *args)
{
int option, fontid;
int option, fontid;
if (!PyArg_ParseTuple(args, "ii:blf.enable", &fontid, &option)) {
return NULL;
}
if (!PyArg_ParseTuple(args, "ii:blf.enable", &fontid, &option)) {
return NULL;
}
BLF_enable(fontid, option);
BLF_enable(fontid, option);
Py_RETURN_NONE;
Py_RETURN_NONE;
}
PyDoc_STRVAR(py_blf_rotation_doc,
".. function:: rotation(fontid, angle)\n"
"\n"
" Set the text rotation angle, enable/disable using ROTATION.\n"
"\n"
" :arg fontid: The id of the typeface as returned by :func:`blf.load`, for default font use 0.\n"
" :type fontid: int\n"
" :arg angle: The angle for text drawing to use.\n"
" :type angle: float\n"
);
".. function:: rotation(fontid, angle)\n"
"\n"
" Set the text rotation angle, enable/disable using ROTATION.\n"
"\n"
" :arg fontid: The id of the typeface as returned by :func:`blf.load`, for default "
"font use 0.\n"
" :type fontid: int\n"
" :arg angle: The angle for text drawing to use.\n"
" :type angle: float\n");
static PyObject *py_blf_rotation(PyObject *UNUSED(self), PyObject *args)
{
float angle;
int fontid;
float angle;
int fontid;
if (!PyArg_ParseTuple(args, "if:blf.rotation", &fontid, &angle)) {
return NULL;
}
if (!PyArg_ParseTuple(args, "if:blf.rotation", &fontid, &angle)) {
return NULL;
}
BLF_rotation(fontid, angle);
BLF_rotation(fontid, angle);
Py_RETURN_NONE;
Py_RETURN_NONE;
}
PyDoc_STRVAR(py_blf_shadow_doc,
".. function:: shadow(fontid, level, r, g, b, a)\n"
"\n"
" Shadow options, enable/disable using SHADOW .\n"
"\n"
" :arg fontid: The id of the typeface as returned by :func:`blf.load`, for default font use 0.\n"
" :type fontid: int\n"
" :arg level: The blur level, can be 3, 5 or 0.\n"
" :type level: int\n"
" :arg r: Shadow color (red channel 0.0 - 1.0).\n"
" :type r: float\n"
" :arg g: Shadow color (green channel 0.0 - 1.0).\n"
" :type g: float\n"
" :arg b: Shadow color (blue channel 0.0 - 1.0).\n"
" :type b: float\n"
" :arg a: Shadow color (alpha channel 0.0 - 1.0).\n"
" :type a: float\n"
);
".. function:: shadow(fontid, level, r, g, b, a)\n"
"\n"
" Shadow options, enable/disable using SHADOW .\n"
"\n"
" :arg fontid: The id of the typeface as returned by :func:`blf.load`, for default "
"font use 0.\n"
" :type fontid: int\n"
" :arg level: The blur level, can be 3, 5 or 0.\n"
" :type level: int\n"
" :arg r: Shadow color (red channel 0.0 - 1.0).\n"
" :type r: float\n"
" :arg g: Shadow color (green channel 0.0 - 1.0).\n"
" :type g: float\n"
" :arg b: Shadow color (blue channel 0.0 - 1.0).\n"
" :type b: float\n"
" :arg a: Shadow color (alpha channel 0.0 - 1.0).\n"
" :type a: float\n");
static PyObject *py_blf_shadow(PyObject *UNUSED(self), PyObject *args)
{
int level, fontid;
float rgba[4];
int level, fontid;
float rgba[4];
if (!PyArg_ParseTuple(
args, "iiffff:blf.shadow",
&fontid, &level, &rgba[0], &rgba[1], &rgba[2], &rgba[3]))
{
return NULL;
}
if (!PyArg_ParseTuple(
args, "iiffff:blf.shadow", &fontid, &level, &rgba[0], &rgba[1], &rgba[2], &rgba[3])) {
return NULL;
}
if (level != 0 && level != 3 && level != 5) {
PyErr_SetString(PyExc_TypeError, "blf.shadow expected arg to be in (0, 3, 5)");
return NULL;
}
if (level != 0 && level != 3 && level != 5) {
PyErr_SetString(PyExc_TypeError, "blf.shadow expected arg to be in (0, 3, 5)");
return NULL;
}
BLF_shadow(fontid, level, rgba);
BLF_shadow(fontid, level, rgba);
Py_RETURN_NONE;
Py_RETURN_NONE;
}
PyDoc_STRVAR(py_blf_shadow_offset_doc,
".. function:: shadow_offset(fontid, x, y)\n"
"\n"
" Set the offset for shadow text.\n"
"\n"
" :arg fontid: The id of the typeface as returned by :func:`blf.load`, for default font use 0.\n"
" :type fontid: int\n"
" :arg x: Vertical shadow offset value in pixels.\n"
" :type x: float\n"
" :arg y: Horizontal shadow offset value in pixels.\n"
" :type y: float\n"
);
".. function:: shadow_offset(fontid, x, y)\n"
"\n"
" Set the offset for shadow text.\n"
"\n"
" :arg fontid: The id of the typeface as returned by :func:`blf.load`, for default "
"font use 0.\n"
" :type fontid: int\n"
" :arg x: Vertical shadow offset value in pixels.\n"
" :type x: float\n"
" :arg y: Horizontal shadow offset value in pixels.\n"
" :type y: float\n");
static PyObject *py_blf_shadow_offset(PyObject *UNUSED(self), PyObject *args)
{
int x, y, fontid;
int x, y, fontid;
if (!PyArg_ParseTuple(args, "iii:blf.shadow_offset", &fontid, &x, &y)) {
return NULL;
}
if (!PyArg_ParseTuple(args, "iii:blf.shadow_offset", &fontid, &x, &y)) {
return NULL;
}
BLF_shadow_offset(fontid, x, y);
BLF_shadow_offset(fontid, x, y);
Py_RETURN_NONE;
Py_RETURN_NONE;
}
PyDoc_STRVAR(py_blf_load_doc,
".. function:: load(filename)\n"
"\n"
" Load a new font.\n"
"\n"
" :arg filename: the filename of the font.\n"
" :type filename: string\n"
" :return: the new font's fontid or -1 if there was an error.\n"
" :rtype: integer\n"
);
".. function:: load(filename)\n"
"\n"
" Load a new font.\n"
"\n"
" :arg filename: the filename of the font.\n"
" :type filename: string\n"
" :return: the new font's fontid or -1 if there was an error.\n"
" :rtype: integer\n");
static PyObject *py_blf_load(PyObject *UNUSED(self), PyObject *args)
{
const char *filename;
const char *filename;
if (!PyArg_ParseTuple(args, "s:blf.load", &filename)) {
return NULL;
}
if (!PyArg_ParseTuple(args, "s:blf.load", &filename)) {
return NULL;
}
return PyLong_FromLong(BLF_load(filename));
return PyLong_FromLong(BLF_load(filename));
}
PyDoc_STRVAR(py_blf_unload_doc,
".. function:: unload(filename)\n"
"\n"
" Unload an existing font.\n"
"\n"
" :arg filename: the filename of the font.\n"
" :type filename: string\n"
);
".. function:: unload(filename)\n"
"\n"
" Unload an existing font.\n"
"\n"
" :arg filename: the filename of the font.\n"
" :type filename: string\n");
static PyObject *py_blf_unload(PyObject *UNUSED(self), PyObject *args)
{
const char *filename;
const char *filename;
if (!PyArg_ParseTuple(args, "s:blf.unload", &filename)) {
return NULL;
}
if (!PyArg_ParseTuple(args, "s:blf.unload", &filename)) {
return NULL;
}
BLF_unload(filename);
BLF_unload(filename);
Py_RETURN_NONE;
Py_RETURN_NONE;
}
/*----------------------------MODULE INIT-------------------------*/
static PyMethodDef BLF_methods[] = {
{"aspect", (PyCFunction) py_blf_aspect, METH_VARARGS, py_blf_aspect_doc},
{"aspect", (PyCFunction)py_blf_aspect, METH_VARARGS, py_blf_aspect_doc},
#if BLF_BLUR_ENABLE
{"blur", (PyCFunction) py_blf_blur, METH_VARARGS, py_blf_blur_doc},
{"blur", (PyCFunction)py_blf_blur, METH_VARARGS, py_blf_blur_doc},
#endif
{"clipping", (PyCFunction) py_blf_clipping, METH_VARARGS, py_blf_clipping_doc},
{"word_wrap", (PyCFunction) py_blf_word_wrap, METH_VARARGS, py_blf_word_wrap_doc},
{"disable", (PyCFunction) py_blf_disable, METH_VARARGS, py_blf_disable_doc},
{"dimensions", (PyCFunction) py_blf_dimensions, METH_VARARGS, py_blf_dimensions_doc},
{"draw", (PyCFunction) py_blf_draw, METH_VARARGS, py_blf_draw_doc},
{"enable", (PyCFunction) py_blf_enable, METH_VARARGS, py_blf_enable_doc},
{"position", (PyCFunction) py_blf_position, METH_VARARGS, py_blf_position_doc},
{"rotation", (PyCFunction) py_blf_rotation, METH_VARARGS, py_blf_rotation_doc},
{"shadow", (PyCFunction) py_blf_shadow, METH_VARARGS, py_blf_shadow_doc},
{"shadow_offset", (PyCFunction) py_blf_shadow_offset, METH_VARARGS, py_blf_shadow_offset_doc},
{"size", (PyCFunction) py_blf_size, METH_VARARGS, py_blf_size_doc},
{"color", (PyCFunction) py_blf_color, METH_VARARGS, py_blf_color_doc},
{"load", (PyCFunction) py_blf_load, METH_VARARGS, py_blf_load_doc},
{"unload", (PyCFunction) py_blf_unload, METH_VARARGS, py_blf_unload_doc},
{NULL, NULL, 0, NULL},
{"clipping", (PyCFunction)py_blf_clipping, METH_VARARGS, py_blf_clipping_doc},
{"word_wrap", (PyCFunction)py_blf_word_wrap, METH_VARARGS, py_blf_word_wrap_doc},
{"disable", (PyCFunction)py_blf_disable, METH_VARARGS, py_blf_disable_doc},
{"dimensions", (PyCFunction)py_blf_dimensions, METH_VARARGS, py_blf_dimensions_doc},
{"draw", (PyCFunction)py_blf_draw, METH_VARARGS, py_blf_draw_doc},
{"enable", (PyCFunction)py_blf_enable, METH_VARARGS, py_blf_enable_doc},
{"position", (PyCFunction)py_blf_position, METH_VARARGS, py_blf_position_doc},
{"rotation", (PyCFunction)py_blf_rotation, METH_VARARGS, py_blf_rotation_doc},
{"shadow", (PyCFunction)py_blf_shadow, METH_VARARGS, py_blf_shadow_doc},
{"shadow_offset", (PyCFunction)py_blf_shadow_offset, METH_VARARGS, py_blf_shadow_offset_doc},
{"size", (PyCFunction)py_blf_size, METH_VARARGS, py_blf_size_doc},
{"color", (PyCFunction)py_blf_color, METH_VARARGS, py_blf_color_doc},
{"load", (PyCFunction)py_blf_load, METH_VARARGS, py_blf_load_doc},
{"unload", (PyCFunction)py_blf_unload, METH_VARARGS, py_blf_unload_doc},
{NULL, NULL, 0, NULL},
};
PyDoc_STRVAR(BLF_doc,
"This module provides access to blenders text drawing functions."
);
PyDoc_STRVAR(BLF_doc, "This module provides access to blenders text drawing functions.");
static struct PyModuleDef BLF_module_def = {
PyModuleDef_HEAD_INIT,
"blf", /* m_name */
BLF_doc, /* m_doc */
0, /* m_size */
BLF_methods, /* m_methods */
NULL, /* m_reload */
NULL, /* m_traverse */
NULL, /* m_clear */
NULL, /* m_free */
PyModuleDef_HEAD_INIT,
"blf", /* m_name */
BLF_doc, /* m_doc */
0, /* m_size */
BLF_methods, /* m_methods */
NULL, /* m_reload */
NULL, /* m_traverse */
NULL, /* m_clear */
NULL, /* m_free */
};
PyObject *BPyInit_blf(void)
{
PyObject *submodule;
PyObject *submodule;
submodule = PyModule_Create(&BLF_module_def);
submodule = PyModule_Create(&BLF_module_def);
PyModule_AddIntConstant(submodule, "ROTATION", BLF_ROTATION);
PyModule_AddIntConstant(submodule, "CLIPPING", BLF_CLIPPING);
PyModule_AddIntConstant(submodule, "SHADOW", BLF_SHADOW);
PyModule_AddIntConstant(submodule, "KERNING_DEFAULT", BLF_KERNING_DEFAULT);
PyModule_AddIntConstant(submodule, "WORD_WRAP", BLF_WORD_WRAP);
PyModule_AddIntConstant(submodule, "MONOCHROME", BLF_MONOCHROME);
PyModule_AddIntConstant(submodule, "ROTATION", BLF_ROTATION);
PyModule_AddIntConstant(submodule, "CLIPPING", BLF_CLIPPING);
PyModule_AddIntConstant(submodule, "SHADOW", BLF_SHADOW);
PyModule_AddIntConstant(submodule, "KERNING_DEFAULT", BLF_KERNING_DEFAULT);
PyModule_AddIntConstant(submodule, "WORD_WRAP", BLF_WORD_WRAP);
PyModule_AddIntConstant(submodule, "MONOCHROME", BLF_MONOCHROME);
return submodule;
return submodule;
}

View File

@@ -23,4 +23,4 @@
PyObject *BPyInit_blf(void);
#endif /* __BLF_PY_API_H__ */
#endif /* __BLF_PY_API_H__ */

View File

@@ -24,7 +24,6 @@
* This should eventually be replaced by import hooks (pep 302).
*/
#include <Python.h>
#include <stddef.h>
@@ -39,18 +38,18 @@
#include "BKE_main.h"
/* UNUSED */
#include "BKE_text.h" /* txt_to_buf */
#include "BKE_text.h" /* txt_to_buf */
#include "py_capi_utils.h"
#include "bpy_internal_import.h" /* own include */
#include "bpy_internal_import.h" /* own include */
static Main *bpy_import_main = NULL;
static ListBase bpy_import_main_list;
static PyMethodDef bpy_import_meth;
static PyMethodDef bpy_reload_meth;
static PyObject *imp_reload_orig = NULL;
static PyObject *imp_reload_orig = NULL;
/* 'builtins' is most likely PyEval_GetBuiltins() */
@@ -68,304 +67,309 @@ static PyObject *imp_reload_orig = NULL;
*/
void bpy_import_init(PyObject *builtins)
{
PyObject *item;
PyObject *mod;
PyObject *item;
PyObject *mod;
PyDict_SetItemString(builtins, "__import__", item = PyCFunction_New(&bpy_import_meth, NULL)); Py_DECREF(item);
PyDict_SetItemString(builtins, "__import__", item = PyCFunction_New(&bpy_import_meth, NULL));
Py_DECREF(item);
/* move reload here
* XXX, use import hooks */
mod = PyImport_ImportModuleLevel("importlib", NULL, NULL, NULL, 0);
if (mod) {
PyObject *mod_dict = PyModule_GetDict(mod);
/* move reload here
* XXX, use import hooks */
mod = PyImport_ImportModuleLevel("importlib", NULL, NULL, NULL, 0);
if (mod) {
PyObject *mod_dict = PyModule_GetDict(mod);
/* blender owns the function */
imp_reload_orig = PyDict_GetItemString(mod_dict, "reload");
Py_INCREF(imp_reload_orig);
/* blender owns the function */
imp_reload_orig = PyDict_GetItemString(mod_dict, "reload");
Py_INCREF(imp_reload_orig);
PyDict_SetItemString(mod_dict, "reload", item = PyCFunction_New(&bpy_reload_meth, NULL)); Py_DECREF(item);
Py_DECREF(mod);
}
else {
BLI_assert(!"unable to load 'importlib' module.");
}
PyDict_SetItemString(mod_dict, "reload", item = PyCFunction_New(&bpy_reload_meth, NULL));
Py_DECREF(item);
Py_DECREF(mod);
}
else {
BLI_assert(!"unable to load 'importlib' module.");
}
}
static void free_compiled_text(Text *text)
{
if (text->compiled) {
Py_DECREF((PyObject *)text->compiled);
}
text->compiled = NULL;
if (text->compiled) {
Py_DECREF((PyObject *)text->compiled);
}
text->compiled = NULL;
}
struct Main *bpy_import_main_get(void)
{
return bpy_import_main;
return bpy_import_main;
}
void bpy_import_main_set(struct Main *maggie)
{
bpy_import_main = maggie;
bpy_import_main = maggie;
}
/* returns a dummy filename for a textblock so we can tell what file a text block comes from */
void bpy_text_filename_get(char *fn, size_t fn_len, Text *text)
{
BLI_snprintf(fn, fn_len, "%s%c%s", ID_BLEND_PATH(bpy_import_main, &text->id), SEP, text->id.name + 2);
BLI_snprintf(
fn, fn_len, "%s%c%s", ID_BLEND_PATH(bpy_import_main, &text->id), SEP, text->id.name + 2);
}
bool bpy_text_compile(Text *text)
{
char fn_dummy[FILE_MAX];
PyObject *fn_dummy_py;
char *buf;
char fn_dummy[FILE_MAX];
PyObject *fn_dummy_py;
char *buf;
bpy_text_filename_get(fn_dummy, sizeof(fn_dummy), text);
bpy_text_filename_get(fn_dummy, sizeof(fn_dummy), text);
/* if previously compiled, free the object */
free_compiled_text(text);
/* if previously compiled, free the object */
free_compiled_text(text);
fn_dummy_py = PyC_UnicodeFromByte(fn_dummy);
fn_dummy_py = PyC_UnicodeFromByte(fn_dummy);
buf = txt_to_buf(text);
text->compiled = Py_CompileStringObject(buf, fn_dummy_py, Py_file_input, NULL, -1);
MEM_freeN(buf);
buf = txt_to_buf(text);
text->compiled = Py_CompileStringObject(buf, fn_dummy_py, Py_file_input, NULL, -1);
MEM_freeN(buf);
Py_DECREF(fn_dummy_py);
Py_DECREF(fn_dummy_py);
if (PyErr_Occurred()) {
PyErr_Print();
PyErr_Clear();
PySys_SetObject("last_traceback", NULL);
free_compiled_text(text);
return false;
}
else {
return true;
}
if (PyErr_Occurred()) {
PyErr_Print();
PyErr_Clear();
PySys_SetObject("last_traceback", NULL);
free_compiled_text(text);
return false;
}
else {
return true;
}
}
PyObject *bpy_text_import(Text *text)
{
char modulename[MAX_ID_NAME + 2];
int len;
char modulename[MAX_ID_NAME + 2];
int len;
if (!text->compiled) {
if (bpy_text_compile(text) == false) {
return NULL;
}
}
if (!text->compiled) {
if (bpy_text_compile(text) == false) {
return NULL;
}
}
len = strlen(text->id.name + 2);
BLI_strncpy(modulename, text->id.name + 2, len);
modulename[len - 3] = '\0'; /* remove .py */
return PyImport_ExecCodeModule(modulename, text->compiled);
len = strlen(text->id.name + 2);
BLI_strncpy(modulename, text->id.name + 2, len);
modulename[len - 3] = '\0'; /* remove .py */
return PyImport_ExecCodeModule(modulename, text->compiled);
}
PyObject *bpy_text_import_name(const char *name, int *found)
{
Text *text;
char txtname[MAX_ID_NAME - 2];
int namelen = strlen(name);
//XXX Main *maggie = bpy_import_main ? bpy_import_main : G_MAIN;
Main *maggie = bpy_import_main;
Text *text;
char txtname[MAX_ID_NAME - 2];
int namelen = strlen(name);
//XXX Main *maggie = bpy_import_main ? bpy_import_main : G_MAIN;
Main *maggie = bpy_import_main;
*found = 0;
*found = 0;
if (!maggie) {
printf("ERROR: bpy_import_main_set() was not called before running python. this is a bug.\n");
return NULL;
}
if (!maggie) {
printf("ERROR: bpy_import_main_set() was not called before running python. this is a bug.\n");
return NULL;
}
/* we know this cant be importable, the name is too long for blender! */
if (namelen >= (MAX_ID_NAME - 2) - 3) {
return NULL;
}
/* we know this cant be importable, the name is too long for blender! */
if (namelen >= (MAX_ID_NAME - 2) - 3) {
return NULL;
}
memcpy(txtname, name, namelen);
memcpy(&txtname[namelen], ".py", 4);
memcpy(txtname, name, namelen);
memcpy(&txtname[namelen], ".py", 4);
text = BLI_findstring(&maggie->texts, txtname, offsetof(ID, name) + 2);
text = BLI_findstring(&maggie->texts, txtname, offsetof(ID, name) + 2);
if (text) {
*found = 1;
return bpy_text_import(text);
}
if (text) {
*found = 1;
return bpy_text_import(text);
}
/* If we still haven't found the module try additional modules form bpy_import_main_list */
maggie = bpy_import_main_list.first;
while (maggie && !text) {
text = BLI_findstring(&maggie->texts, txtname, offsetof(ID, name) + 2);
maggie = maggie->next;
}
/* If we still haven't found the module try additional modules form bpy_import_main_list */
maggie = bpy_import_main_list.first;
while (maggie && !text) {
text = BLI_findstring(&maggie->texts, txtname, offsetof(ID, name) + 2);
maggie = maggie->next;
}
if (!text) {
return NULL;
}
else {
*found = 1;
}
if (!text) {
return NULL;
}
else {
*found = 1;
}
return bpy_text_import(text);
return bpy_text_import(text);
}
/*
* find in-memory module and recompile
*/
PyObject *bpy_text_reimport(PyObject *module, int *found)
{
Text *text;
const char *name;
const char *filepath;
//XXX Main *maggie = bpy_import_main ? bpy_import_main : G_MAIN;
Main *maggie = bpy_import_main;
Text *text;
const char *name;
const char *filepath;
//XXX Main *maggie = bpy_import_main ? bpy_import_main : G_MAIN;
Main *maggie = bpy_import_main;
if (!maggie) {
printf("ERROR: bpy_import_main_set() was not called before running python. this is a bug.\n");
return NULL;
}
if (!maggie) {
printf("ERROR: bpy_import_main_set() was not called before running python. this is a bug.\n");
return NULL;
}
*found = 0;
*found = 0;
/* get name, filename from the module itself */
if ((name = PyModule_GetName(module)) == NULL) {
return NULL;
}
/* get name, filename from the module itself */
if ((name = PyModule_GetName(module)) == NULL) {
return NULL;
}
{
PyObject *module_file = PyModule_GetFilenameObject(module);
if (module_file == NULL) {
return NULL;
}
filepath = _PyUnicode_AsString(module_file);
Py_DECREF(module_file);
if (filepath == NULL) {
return NULL;
}
}
{
PyObject *module_file = PyModule_GetFilenameObject(module);
if (module_file == NULL) {
return NULL;
}
filepath = _PyUnicode_AsString(module_file);
Py_DECREF(module_file);
if (filepath == NULL) {
return NULL;
}
}
/* look up the text object */
text = BLI_findstring(&maggie->texts, BLI_path_basename(filepath), offsetof(ID, name) + 2);
/* look up the text object */
text = BLI_findstring(&maggie->texts, BLI_path_basename(filepath), offsetof(ID, name) + 2);
/* uh-oh.... didn't find it */
if (!text) {
return NULL;
}
else {
*found = 1;
}
/* uh-oh.... didn't find it */
if (!text) {
return NULL;
}
else {
*found = 1;
}
if (bpy_text_compile(text) == false) {
return NULL;
}
if (bpy_text_compile(text) == false) {
return NULL;
}
/* make into a module */
return PyImport_ExecCodeModule(name, text->compiled);
/* make into a module */
return PyImport_ExecCodeModule(name, text->compiled);
}
static PyObject *blender_import(PyObject *UNUSED(self), PyObject *args, PyObject *kw)
{
PyObject *exception, *err, *tb;
const char *name;
int found = 0;
PyObject *globals = NULL, *locals = NULL, *fromlist = NULL;
int level = 0; /* relative imports */
PyObject *newmodule;
PyObject *exception, *err, *tb;
const char *name;
int found = 0;
PyObject *globals = NULL, *locals = NULL, *fromlist = NULL;
int level = 0; /* relative imports */
PyObject *newmodule;
static const char *_keywords[] = {"name", "globals", "locals", "fromlist", "level", NULL};
static _PyArg_Parser _parser = {"s|OOOi:bpy_import_meth", _keywords, 0};
if (!_PyArg_ParseTupleAndKeywordsFast(
args, kw, &_parser,
&name, &globals, &locals, &fromlist, &level))
{
return NULL;
}
static const char *_keywords[] = {"name", "globals", "locals", "fromlist", "level", NULL};
static _PyArg_Parser _parser = {"s|OOOi:bpy_import_meth", _keywords, 0};
if (!_PyArg_ParseTupleAndKeywordsFast(
args, kw, &_parser, &name, &globals, &locals, &fromlist, &level)) {
return NULL;
}
/* import existing builtin modules or modules that have been imported already */
newmodule = PyImport_ImportModuleLevel(name, globals, locals, fromlist, level);
/* import existing builtin modules or modules that have been imported already */
newmodule = PyImport_ImportModuleLevel(name, globals, locals, fromlist, level);
if (newmodule) {
return newmodule;
}
if (newmodule) {
return newmodule;
}
PyErr_Fetch(&exception, &err, &tb); /* get the python error in case we cant import as blender text either */
PyErr_Fetch(&exception,
&err,
&tb); /* get the python error in case we cant import as blender text either */
/* importing from existing modules failed, see if we have this module as blender text */
newmodule = bpy_text_import_name(name, &found);
/* importing from existing modules failed, see if we have this module as blender text */
newmodule = bpy_text_import_name(name, &found);
if (newmodule) { /* found module as blender text, ignore above exception */
PyErr_Clear();
Py_XDECREF(exception);
Py_XDECREF(err);
Py_XDECREF(tb);
/* printf("imported from text buffer...\n"); */
}
else if (found == 1) { /* blender text module failed to execute but was found, use its error message */
Py_XDECREF(exception);
Py_XDECREF(err);
Py_XDECREF(tb);
return NULL;
}
else {
/* no blender text was found that could import the module
* reuse the original error from PyImport_ImportModuleEx */
PyErr_Restore(exception, err, tb);
}
return newmodule;
if (newmodule) { /* found module as blender text, ignore above exception */
PyErr_Clear();
Py_XDECREF(exception);
Py_XDECREF(err);
Py_XDECREF(tb);
/* printf("imported from text buffer...\n"); */
}
else if (found ==
1) { /* blender text module failed to execute but was found, use its error message */
Py_XDECREF(exception);
Py_XDECREF(err);
Py_XDECREF(tb);
return NULL;
}
else {
/* no blender text was found that could import the module
* reuse the original error from PyImport_ImportModuleEx */
PyErr_Restore(exception, err, tb);
}
return newmodule;
}
/*
* our reload() module, to handle reloading in-memory scripts
*/
static PyObject *blender_reload(PyObject *UNUSED(self), PyObject *module)
{
PyObject *exception, *err, *tb;
PyObject *newmodule = NULL;
int found = 0;
PyObject *exception, *err, *tb;
PyObject *newmodule = NULL;
int found = 0;
/* try reimporting from file */
/* try reimporting from file */
/* in Py3.3 this just calls imp.reload() which we overwrite, causing recursive calls */
//newmodule = PyImport_ReloadModule(module);
/* in Py3.3 this just calls imp.reload() which we overwrite, causing recursive calls */
//newmodule = PyImport_ReloadModule(module);
newmodule = PyObject_CallFunctionObjArgs(imp_reload_orig, module, NULL);
newmodule = PyObject_CallFunctionObjArgs(imp_reload_orig, module, NULL);
if (newmodule) {
return newmodule;
}
if (newmodule) {
return newmodule;
}
/* no file, try importing from memory */
PyErr_Fetch(&exception, &err, &tb); /*restore for probable later use */
/* no file, try importing from memory */
PyErr_Fetch(&exception, &err, &tb); /*restore for probable later use */
newmodule = bpy_text_reimport(module, &found);
if (newmodule) { /* found module as blender text, ignore above exception */
PyErr_Clear();
Py_XDECREF(exception);
Py_XDECREF(err);
Py_XDECREF(tb);
/* printf("imported from text buffer...\n"); */
}
else if (found == 1) { /* blender text module failed to execute but was found, use its error message */
Py_XDECREF(exception);
Py_XDECREF(err);
Py_XDECREF(tb);
return NULL;
}
else {
/* no blender text was found that could import the module
* reuse the original error from PyImport_ImportModuleEx */
PyErr_Restore(exception, err, tb);
}
newmodule = bpy_text_reimport(module, &found);
if (newmodule) { /* found module as blender text, ignore above exception */
PyErr_Clear();
Py_XDECREF(exception);
Py_XDECREF(err);
Py_XDECREF(tb);
/* printf("imported from text buffer...\n"); */
}
else if (found ==
1) { /* blender text module failed to execute but was found, use its error message */
Py_XDECREF(exception);
Py_XDECREF(err);
Py_XDECREF(tb);
return NULL;
}
else {
/* no blender text was found that could import the module
* reuse the original error from PyImport_ImportModuleEx */
PyErr_Restore(exception, err, tb);
}
return newmodule;
return newmodule;
}
static PyMethodDef bpy_import_meth = {"bpy_import_meth", (PyCFunction)blender_import, METH_VARARGS | METH_KEYWORDS, "blenders import"};
static PyMethodDef bpy_reload_meth = {"bpy_reload_meth", (PyCFunction)blender_reload, METH_O, "blenders reload"};
static PyMethodDef bpy_import_meth = {"bpy_import_meth",
(PyCFunction)blender_import,
METH_VARARGS | METH_KEYWORDS,
"blenders import"};
static PyMethodDef bpy_reload_meth = {
"bpy_reload_meth", (PyCFunction)blender_reload, METH_O, "blenders reload"};

View File

@@ -18,7 +18,6 @@
* \ingroup pygen
*/
/* Note, the BGE needs to use this too, keep it minimal */
#ifndef __BPY_INTERNAL_IMPORT_H__
@@ -26,26 +25,26 @@
/* python redefines :/ */
#ifdef _POSIX_C_SOURCE
#undef _POSIX_C_SOURCE
# undef _POSIX_C_SOURCE
#endif
#ifdef _XOPEN_SOURCE
#undef _XOPEN_SOURCE
# undef _XOPEN_SOURCE
#endif
struct Text;
void bpy_import_init(PyObject *builtins);
bool bpy_text_compile(struct Text *text);
PyObject *bpy_text_import(struct Text *text);
PyObject *bpy_text_import_name(const char *name, int *found);
PyObject *bpy_text_reimport(PyObject *module, int *found);
/* void bpy_text_clear_modules(int clear_all);*/ /* Clear user modules */
bool bpy_text_compile(struct Text *text);
PyObject *bpy_text_import(struct Text *text);
PyObject *bpy_text_import_name(const char *name, int *found);
PyObject *bpy_text_reimport(PyObject *module, int *found);
/* void bpy_text_clear_modules(int clear_all);*/ /* Clear user modules */
void bpy_text_filename_get(char *fn, size_t fn_len, struct Text *text);
struct Main *bpy_import_main_get(void);
void bpy_import_main_set(struct Main *maggie);
#endif /* __BPY_INTERNAL_IMPORT_H__ */
#endif /* __BPY_INTERNAL_IMPORT_H__ */

View File

@@ -29,20 +29,20 @@
/* analogue of PyEval_SaveThread() */
BPy_ThreadStatePtr BPY_thread_save(void)
{
PyThreadState *tstate = PyThreadState_Swap(NULL);
/* note: tstate can be NULL when quitting Blender */
PyThreadState *tstate = PyThreadState_Swap(NULL);
/* note: tstate can be NULL when quitting Blender */
if (tstate && PyEval_ThreadsInitialized()) {
PyEval_ReleaseLock();
}
if (tstate && PyEval_ThreadsInitialized()) {
PyEval_ReleaseLock();
}
return (BPy_ThreadStatePtr)tstate;
return (BPy_ThreadStatePtr)tstate;
}
/* analogue of PyEval_RestoreThread() */
void BPY_thread_restore(BPy_ThreadStatePtr tstate)
{
if (tstate) {
PyEval_RestoreThread((PyThreadState *)tstate);
}
if (tstate) {
PyEval_RestoreThread((PyThreadState *)tstate);
}
}

File diff suppressed because it is too large Load Diff

View File

@@ -18,7 +18,6 @@
* \ingroup pygen
*/
#ifndef __IDPROP_PY_API_H__
#define __IDPROP_PY_API_H__
@@ -30,32 +29,29 @@ extern PyTypeObject BPy_IDArray_Type;
extern PyTypeObject BPy_IDGroup_Iter_Type;
extern PyTypeObject BPy_IDGroup_Type;
#define BPy_IDArray_Check(v) (PyObject_TypeCheck(v, &BPy_IDArray_Type))
#define BPy_IDArray_CheckExact(v) (Py_TYPE(v) == &BPy_IDArray_Type)
#define BPy_IDGroup_Iter_Check(v) (PyObject_TypeCheck(v, &BPy_IDGroup_Iter_Type))
#define BPy_IDGroup_Iter_CheckExact(v) (Py_TYPE(v) == &BPy_IDGroup_Iter_Type)
#define BPy_IDGroup_Check(v) (PyObject_TypeCheck(v, &BPy_IDGroup_Type))
#define BPy_IDGroup_CheckExact(v) (Py_TYPE(v) == &BPy_IDGroup_Type)
#define BPy_IDArray_Check(v) (PyObject_TypeCheck(v, &BPy_IDArray_Type))
#define BPy_IDArray_CheckExact(v) (Py_TYPE(v) == &BPy_IDArray_Type)
#define BPy_IDGroup_Iter_Check(v) (PyObject_TypeCheck(v, &BPy_IDGroup_Iter_Type))
#define BPy_IDGroup_Iter_CheckExact(v) (Py_TYPE(v) == &BPy_IDGroup_Iter_Type)
#define BPy_IDGroup_Check(v) (PyObject_TypeCheck(v, &BPy_IDGroup_Type))
#define BPy_IDGroup_CheckExact(v) (Py_TYPE(v) == &BPy_IDGroup_Type)
typedef struct BPy_IDProperty {
PyObject_VAR_HEAD
struct ID *id; /* can be NULL */
struct IDProperty *prop; /* must be second member */
struct IDProperty *parent;
PyObject *data_wrap;
PyObject_VAR_HEAD struct ID *id; /* can be NULL */
struct IDProperty *prop; /* must be second member */
struct IDProperty *parent;
PyObject *data_wrap;
} BPy_IDProperty;
typedef struct BPy_IDArray {
PyObject_VAR_HEAD
struct ID *id; /* can be NULL */
struct IDProperty *prop; /* must be second member */
PyObject_VAR_HEAD struct ID *id; /* can be NULL */
struct IDProperty *prop; /* must be second member */
} BPy_IDArray;
typedef struct BPy_IDGroup_Iter {
PyObject_VAR_HEAD
BPy_IDProperty *group;
struct IDProperty *cur;
int mode;
PyObject_VAR_HEAD BPy_IDProperty *group;
struct IDProperty *cur;
int mode;
} BPy_IDGroup_Iter;
PyObject *BPy_Wrap_GetKeys(struct IDProperty *prop);
@@ -63,7 +59,6 @@ PyObject *BPy_Wrap_GetValues(struct ID *id, struct IDProperty *prop);
PyObject *BPy_Wrap_GetItems(struct ID *id, struct IDProperty *prop);
int BPy_Wrap_SetMapItem(struct IDProperty *prop, PyObject *key, PyObject *val);
PyObject *BPy_IDGroup_WrapData(struct ID *id, struct IDProperty *prop, struct IDProperty *parent);
bool BPy_IDProperty_Map_ValidateAndCreate(PyObject *key, struct IDProperty *group, PyObject *ob);
@@ -71,7 +66,7 @@ void IDProp_Init_Types(void);
PyObject *BPyInit_idprop(void);
#define IDPROP_ITER_KEYS 0
#define IDPROP_ITER_ITEMS 1
#define IDPROP_ITER_KEYS 0
#define IDPROP_ITER_ITEMS 1
#endif /* __IDPROP_PY_API_H__ */

View File

@@ -29,7 +29,7 @@
#include "python_utildefines.h"
#include "imbuf_py_api.h" /* own include */
#include "imbuf_py_api.h" /* own include */
#include "../../imbuf/IMB_imbuf.h"
#include "../../imbuf/IMB_imbuf_types.h"
@@ -46,28 +46,33 @@ static PyObject *Py_ImBuf_CreatePyObject(ImBuf *ibuf);
* \{ */
typedef struct Py_ImBuf {
PyObject_VAR_HEAD
/* can be NULL */
ImBuf *ibuf;
PyObject_VAR_HEAD
/* can be NULL */
ImBuf *ibuf;
} Py_ImBuf;
static int py_imbuf_valid_check(Py_ImBuf *self)
{
if (LIKELY(self->ibuf)) {
return 0;
}
else {
PyErr_Format(PyExc_ReferenceError,
"ImBuf data of type %.200s has been freed",
Py_TYPE(self)->tp_name);
return -1;
}
if (LIKELY(self->ibuf)) {
return 0;
}
else {
PyErr_Format(
PyExc_ReferenceError, "ImBuf data of type %.200s has been freed", Py_TYPE(self)->tp_name);
return -1;
}
}
#define PY_IMBUF_CHECK_OBJ(obj) \
if (UNLIKELY(py_imbuf_valid_check(obj) == -1)) { return NULL; } ((void)0)
if (UNLIKELY(py_imbuf_valid_check(obj) == -1)) { \
return NULL; \
} \
((void)0)
#define PY_IMBUF_CHECK_INT(obj) \
if (UNLIKELY(py_imbuf_valid_check(obj) == -1)) { return -1; } ((void)0)
if (UNLIKELY(py_imbuf_valid_check(obj) == -1)) { \
return -1; \
} \
((void)0)
/** \} */
@@ -76,77 +81,72 @@ static int py_imbuf_valid_check(Py_ImBuf *self)
* \{ */
PyDoc_STRVAR(py_imbuf_resize_doc,
".. method:: resize(size, method='FAST')\n"
"\n"
" Resize the image.\n"
"\n"
" :arg size: New size.\n"
" :type size: pair of ints\n"
" :arg method: Method of resizing (TODO)\n"
" :type method: str\n"
);
".. method:: resize(size, method='FAST')\n"
"\n"
" Resize the image.\n"
"\n"
" :arg size: New size.\n"
" :type size: pair of ints\n"
" :arg method: Method of resizing (TODO)\n"
" :type method: str\n");
static PyObject *py_imbuf_resize(Py_ImBuf *self, PyObject *args, PyObject *kw)
{
PY_IMBUF_CHECK_OBJ(self);
PY_IMBUF_CHECK_OBJ(self);
uint size[2];
char *method = NULL;
uint size[2];
char *method = NULL;
static const char *_keywords[] = {"size", "method", NULL};
static _PyArg_Parser _parser = {"(II)|s:resize", _keywords, 0};
if (!_PyArg_ParseTupleAndKeywordsFast(
args, kw, &_parser,
&size[0], &size[1],
&method))
{
return NULL;
}
IMB_scaleImBuf(self->ibuf, UNPACK2(size));
Py_RETURN_NONE;
static const char *_keywords[] = {"size", "method", NULL};
static _PyArg_Parser _parser = {"(II)|s:resize", _keywords, 0};
if (!_PyArg_ParseTupleAndKeywordsFast(args, kw, &_parser, &size[0], &size[1], &method)) {
return NULL;
}
IMB_scaleImBuf(self->ibuf, UNPACK2(size));
Py_RETURN_NONE;
}
PyDoc_STRVAR(py_imbuf_copy_doc,
".. method:: copy()\n"
"\n"
" :return: A copy of the image.\n"
" :rtype: :class:`ImBuf`\n"
);
".. method:: copy()\n"
"\n"
" :return: A copy of the image.\n"
" :rtype: :class:`ImBuf`\n");
static PyObject *py_imbuf_copy(Py_ImBuf *self)
{
PY_IMBUF_CHECK_OBJ(self);
return Py_ImBuf_CreatePyObject(self->ibuf);
PY_IMBUF_CHECK_OBJ(self);
return Py_ImBuf_CreatePyObject(self->ibuf);
}
static PyObject *py_imbuf_deepcopy(Py_ImBuf *self, PyObject *args)
{
if (!PyC_CheckArgs_DeepCopy(args)) {
return NULL;
}
return py_imbuf_copy(self);
if (!PyC_CheckArgs_DeepCopy(args)) {
return NULL;
}
return py_imbuf_copy(self);
}
PyDoc_STRVAR(py_imbuf_free_doc,
".. method:: free()\n"
"\n"
" Clear image data immediately (causing an error on re-use).\n"
);
".. method:: free()\n"
"\n"
" Clear image data immediately (causing an error on re-use).\n");
static PyObject *py_imbuf_free(Py_ImBuf *self)
{
if (self->ibuf) {
IMB_freeImBuf(self->ibuf);
self->ibuf = NULL;
}
Py_RETURN_NONE;
if (self->ibuf) {
IMB_freeImBuf(self->ibuf);
self->ibuf = NULL;
}
Py_RETURN_NONE;
}
static struct PyMethodDef Py_ImBuf_methods[] = {
{"resize", (PyCFunction)py_imbuf_resize, METH_VARARGS | METH_KEYWORDS, (char *)py_imbuf_resize_doc},
{"free", (PyCFunction)py_imbuf_free, METH_NOARGS, (char *)py_imbuf_free_doc},
{"copy", (PyCFunction)py_imbuf_copy, METH_NOARGS, (char *)py_imbuf_copy_doc},
{"__copy__", (PyCFunction)py_imbuf_copy, METH_NOARGS, (char *)py_imbuf_copy_doc},
{"__deepcopy__", (PyCFunction)py_imbuf_deepcopy, METH_VARARGS, (char *)py_imbuf_copy_doc},
{NULL, NULL, 0, NULL},
{"resize",
(PyCFunction)py_imbuf_resize,
METH_VARARGS | METH_KEYWORDS,
(char *)py_imbuf_resize_doc},
{"free", (PyCFunction)py_imbuf_free, METH_NOARGS, (char *)py_imbuf_free_doc},
{"copy", (PyCFunction)py_imbuf_copy, METH_NOARGS, (char *)py_imbuf_copy_doc},
{"__copy__", (PyCFunction)py_imbuf_copy, METH_NOARGS, (char *)py_imbuf_copy_doc},
{"__deepcopy__", (PyCFunction)py_imbuf_deepcopy, METH_VARARGS, (char *)py_imbuf_copy_doc},
{NULL, NULL, 0, NULL},
};
/** \} */
@@ -155,50 +155,50 @@ static struct PyMethodDef Py_ImBuf_methods[] = {
/** \name Attributes
* \{ */
PyDoc_STRVAR(py_imbuf_size_doc,
"size of the image in pixels.\n\n:type: pair of ints"
);
PyDoc_STRVAR(py_imbuf_size_doc, "size of the image in pixels.\n\n:type: pair of ints");
static PyObject *py_imbuf_size_get(Py_ImBuf *self, void *UNUSED(closure))
{
PY_IMBUF_CHECK_OBJ(self);
ImBuf *ibuf = self->ibuf;
return PyC_Tuple_Pack_I32(ibuf->x, ibuf->y);
PY_IMBUF_CHECK_OBJ(self);
ImBuf *ibuf = self->ibuf;
return PyC_Tuple_Pack_I32(ibuf->x, ibuf->y);
}
PyDoc_STRVAR(py_imbuf_ppm_doc,
"pixels per meter.\n\n:type: pair of floats"
);
PyDoc_STRVAR(py_imbuf_ppm_doc, "pixels per meter.\n\n:type: pair of floats");
static PyObject *py_imbuf_ppm_get(Py_ImBuf *self, void *UNUSED(closure))
{
PY_IMBUF_CHECK_OBJ(self);
ImBuf *ibuf = self->ibuf;
return PyC_Tuple_Pack_F64(ibuf->ppm[0], ibuf->ppm[1]);
PY_IMBUF_CHECK_OBJ(self);
ImBuf *ibuf = self->ibuf;
return PyC_Tuple_Pack_F64(ibuf->ppm[0], ibuf->ppm[1]);
}
static int py_imbuf_ppm_set(Py_ImBuf *self, PyObject *value, void *UNUSED(closure))
{
PY_IMBUF_CHECK_INT(self);
double ppm[2];
PY_IMBUF_CHECK_INT(self);
double ppm[2];
if (PyC_AsArray(ppm, value, 2, &PyFloat_Type, true, "ppm") == -1) {
return -1;
}
if (PyC_AsArray(ppm, value, 2, &PyFloat_Type, true, "ppm") == -1) {
return -1;
}
if (ppm[0] <= 0.0 || ppm[1] <= 0.0) {
PyErr_SetString(PyExc_ValueError, "invalid ppm value");
return -1;
}
if (ppm[0] <= 0.0 || ppm[1] <= 0.0) {
PyErr_SetString(PyExc_ValueError, "invalid ppm value");
return -1;
}
ImBuf *ibuf = self->ibuf;
ibuf->ppm[0] = ppm[0];
ibuf->ppm[1] = ppm[1];
return 0;
ImBuf *ibuf = self->ibuf;
ibuf->ppm[0] = ppm[0];
ibuf->ppm[1] = ppm[1];
return 0;
}
static PyGetSetDef Py_ImBuf_getseters[] = {
{(char *)"size", (getter)py_imbuf_size_get, (setter)NULL, (char *)py_imbuf_size_doc, NULL},
{(char *)"ppm", (getter)py_imbuf_ppm_get, (setter)py_imbuf_ppm_set, (char *)py_imbuf_ppm_doc, NULL},
{NULL, NULL, NULL, NULL, NULL} /* Sentinel */
{(char *)"size", (getter)py_imbuf_size_get, (setter)NULL, (char *)py_imbuf_size_doc, NULL},
{(char *)"ppm",
(getter)py_imbuf_ppm_get,
(setter)py_imbuf_ppm_set,
(char *)py_imbuf_ppm_doc,
NULL},
{NULL, NULL, NULL, NULL, NULL} /* Sentinel */
};
/** \} */
@@ -209,99 +209,97 @@ static PyGetSetDef Py_ImBuf_getseters[] = {
static void py_imbuf_dealloc(Py_ImBuf *self)
{
ImBuf *ibuf = self->ibuf;
if (ibuf != NULL) {
IMB_freeImBuf(self->ibuf);
self->ibuf = NULL;
}
PyObject_DEL(self);
ImBuf *ibuf = self->ibuf;
if (ibuf != NULL) {
IMB_freeImBuf(self->ibuf);
self->ibuf = NULL;
}
PyObject_DEL(self);
}
static PyObject *py_imbuf_repr(Py_ImBuf *self)
{
const ImBuf *ibuf = self->ibuf;
if (ibuf != NULL) {
return PyUnicode_FromFormat(
"<imbuf: address=%p, filename='%s', size=(%d, %d)>",
ibuf, ibuf->name, ibuf->x, ibuf->y);
}
else {
return PyUnicode_FromString(
"<imbuf: address=0x0>");
}
const ImBuf *ibuf = self->ibuf;
if (ibuf != NULL) {
return PyUnicode_FromFormat(
"<imbuf: address=%p, filename='%s', size=(%d, %d)>", ibuf, ibuf->name, ibuf->x, ibuf->y);
}
else {
return PyUnicode_FromString("<imbuf: address=0x0>");
}
}
static Py_hash_t py_imbuf_hash(Py_ImBuf *self)
{
return _Py_HashPointer(self->ibuf);
return _Py_HashPointer(self->ibuf);
}
PyTypeObject Py_ImBuf_Type = {
PyVarObject_HEAD_INIT(NULL, 0)
/* For printing, in format "<module>.<name>" */
"ImBuf", /* tp_name */
sizeof(Py_ImBuf), /* int tp_basicsize; */
0, /* tp_itemsize; For allocation */
PyVarObject_HEAD_INIT(NULL, 0)
/* For printing, in format "<module>.<name>" */
"ImBuf", /* tp_name */
sizeof(Py_ImBuf), /* int tp_basicsize; */
0, /* tp_itemsize; For allocation */
/* Methods to implement standard operations */
/* Methods to implement standard operations */
(destructor)py_imbuf_dealloc, /* destructor tp_dealloc; */
NULL, /* printfunc tp_print; */
NULL, /* getattrfunc tp_getattr; */
NULL, /* setattrfunc tp_setattr; */
NULL, /* cmpfunc tp_compare; */
(reprfunc)py_imbuf_repr, /* reprfunc tp_repr; */
(destructor)py_imbuf_dealloc, /* destructor tp_dealloc; */
NULL, /* printfunc tp_print; */
NULL, /* getattrfunc tp_getattr; */
NULL, /* setattrfunc tp_setattr; */
NULL, /* cmpfunc tp_compare; */
(reprfunc)py_imbuf_repr, /* reprfunc tp_repr; */
/* Method suites for standard classes */
/* Method suites for standard classes */
NULL, /* PyNumberMethods *tp_as_number; */
NULL, /* PySequenceMethods *tp_as_sequence; */
NULL, /* PyMappingMethods *tp_as_mapping; */
NULL, /* PyNumberMethods *tp_as_number; */
NULL, /* PySequenceMethods *tp_as_sequence; */
NULL, /* PyMappingMethods *tp_as_mapping; */
/* More standard operations (here for binary compatibility) */
/* More standard operations (here for binary compatibility) */
(hashfunc)py_imbuf_hash, /* hashfunc tp_hash; */
NULL, /* ternaryfunc tp_call; */
NULL, /* reprfunc tp_str; */
NULL, /* getattrofunc tp_getattro; */
NULL, /* setattrofunc tp_setattro; */
(hashfunc)py_imbuf_hash, /* hashfunc tp_hash; */
NULL, /* ternaryfunc tp_call; */
NULL, /* reprfunc tp_str; */
NULL, /* getattrofunc tp_getattro; */
NULL, /* setattrofunc tp_setattro; */
/* Functions to access object as input/output buffer */
NULL, /* PyBufferProcs *tp_as_buffer; */
/* Functions to access object as input/output buffer */
NULL, /* PyBufferProcs *tp_as_buffer; */
/*** Flags to define presence of optional/expanded features ***/
Py_TPFLAGS_DEFAULT, /* long tp_flags; */
/*** Flags to define presence of optional/expanded features ***/
Py_TPFLAGS_DEFAULT, /* long tp_flags; */
NULL, /* char *tp_doc; Documentation string */
/*** Assigned meaning in release 2.0 ***/
/* call function for all accessible objects */
NULL, /* traverseproc tp_traverse; */
NULL, /* char *tp_doc; Documentation string */
/*** Assigned meaning in release 2.0 ***/
/* call function for all accessible objects */
NULL, /* traverseproc tp_traverse; */
/* delete references to contained objects */
NULL, /* inquiry tp_clear; */
/* delete references to contained objects */
NULL, /* inquiry tp_clear; */
/*** Assigned meaning in release 2.1 ***/
/*** rich comparisons ***/
NULL, /* richcmpfunc tp_richcompare; */
/*** Assigned meaning in release 2.1 ***/
/*** rich comparisons ***/
NULL, /* richcmpfunc tp_richcompare; */
/*** weak reference enabler ***/
0, /* long tp_weaklistoffset; */
/*** weak reference enabler ***/
0, /* long tp_weaklistoffset; */
/*** Added in release 2.2 ***/
/* Iterators */
NULL, /* getiterfunc tp_iter; */
NULL, /* iternextfunc tp_iternext; */
/*** Attribute descriptor and subclassing stuff ***/
Py_ImBuf_methods, /* struct PyMethodDef *tp_methods; */
NULL, /* struct PyMemberDef *tp_members; */
Py_ImBuf_getseters, /* struct PyGetSetDef *tp_getset; */
/*** Added in release 2.2 ***/
/* Iterators */
NULL, /* getiterfunc tp_iter; */
NULL, /* iternextfunc tp_iternext; */
/*** Attribute descriptor and subclassing stuff ***/
Py_ImBuf_methods, /* struct PyMethodDef *tp_methods; */
NULL, /* struct PyMemberDef *tp_members; */
Py_ImBuf_getseters, /* struct PyGetSetDef *tp_getset; */
};
static PyObject *Py_ImBuf_CreatePyObject(ImBuf *ibuf)
{
Py_ImBuf *self = PyObject_New(Py_ImBuf, &Py_ImBuf_Type);
self->ibuf = ibuf;
return (PyObject *)self;
Py_ImBuf *self = PyObject_New(Py_ImBuf, &Py_ImBuf_Type);
self->ibuf = ibuf;
return (PyObject *)self;
}
/** \} */
@@ -311,118 +309,107 @@ static PyObject *Py_ImBuf_CreatePyObject(ImBuf *ibuf)
* \{ */
PyDoc_STRVAR(M_imbuf_new_doc,
".. function:: new(size)\n"
"\n"
" Load a new image.\n"
"\n"
" :arg size: The size of the image in pixels.\n"
" :type size: pair of ints\n"
" :return: the newly loaded image.\n"
" :rtype: :class:`ImBuf`\n"
);
".. function:: new(size)\n"
"\n"
" Load a new image.\n"
"\n"
" :arg size: The size of the image in pixels.\n"
" :type size: pair of ints\n"
" :return: the newly loaded image.\n"
" :rtype: :class:`ImBuf`\n");
static PyObject *M_imbuf_new(PyObject *UNUSED(self), PyObject *args, PyObject *kw)
{
int size[2];
static const char *_keywords[] = {"size", NULL};
static _PyArg_Parser _parser = {"(ii)|i:new", _keywords, 0};
if (!_PyArg_ParseTupleAndKeywordsFast(
args, kw, &_parser,
&size[0], &size[1]))
{
return NULL;
}
int size[2];
static const char *_keywords[] = {"size", NULL};
static _PyArg_Parser _parser = {"(ii)|i:new", _keywords, 0};
if (!_PyArg_ParseTupleAndKeywordsFast(args, kw, &_parser, &size[0], &size[1])) {
return NULL;
}
/* TODO, make options */
uchar planes = 4;
uint flags = IB_rect;
/* TODO, make options */
uchar planes = 4;
uint flags = IB_rect;
ImBuf *ibuf = IMB_allocImBuf(UNPACK2(size), planes, flags);
if (ibuf == NULL) {
PyErr_Format(PyExc_ValueError, "new: Unable to create image (%d, %d)", UNPACK2(size));
return NULL;
}
return Py_ImBuf_CreatePyObject(ibuf);
ImBuf *ibuf = IMB_allocImBuf(UNPACK2(size), planes, flags);
if (ibuf == NULL) {
PyErr_Format(PyExc_ValueError, "new: Unable to create image (%d, %d)", UNPACK2(size));
return NULL;
}
return Py_ImBuf_CreatePyObject(ibuf);
}
PyDoc_STRVAR(M_imbuf_load_doc,
".. function:: load(filename)\n"
"\n"
" Load an image from a file.\n"
"\n"
" :arg filename: the filename of the image.\n"
" :type filename: string\n"
" :return: the newly loaded image.\n"
" :rtype: :class:`ImBuf`\n"
);
".. function:: load(filename)\n"
"\n"
" Load an image from a file.\n"
"\n"
" :arg filename: the filename of the image.\n"
" :type filename: string\n"
" :return: the newly loaded image.\n"
" :rtype: :class:`ImBuf`\n");
static PyObject *M_imbuf_load(PyObject *UNUSED(self), PyObject *args, PyObject *kw)
{
const char *filename;
const char *filename;
static const char *_keywords[] = {"filename", NULL};
static _PyArg_Parser _parser = {"s:load", _keywords, 0};
if (!_PyArg_ParseTupleAndKeywordsFast(
args, kw, &_parser,
&filename))
{
return NULL;
}
static const char *_keywords[] = {"filename", NULL};
static _PyArg_Parser _parser = {"s:load", _keywords, 0};
if (!_PyArg_ParseTupleAndKeywordsFast(args, kw, &_parser, &filename)) {
return NULL;
}
const int file = BLI_open(filename, O_BINARY | O_RDONLY, 0);
if (file == -1) {
PyErr_Format(PyExc_IOError, "load: %s, failed to open file '%s'", strerror(errno));
return NULL;
}
const int file = BLI_open(filename, O_BINARY | O_RDONLY, 0);
if (file == -1) {
PyErr_Format(PyExc_IOError, "load: %s, failed to open file '%s'", strerror(errno));
return NULL;
}
ImBuf *ibuf = IMB_loadifffile(file, filename, IB_rect, NULL, filename);
ImBuf *ibuf = IMB_loadifffile(file, filename, IB_rect, NULL, filename);
close(file);
close(file);
if (ibuf == NULL) {
PyErr_Format(PyExc_ValueError, "load: Unable to recognize image format for file '%s'", filename);
return NULL;
}
if (ibuf == NULL) {
PyErr_Format(
PyExc_ValueError, "load: Unable to recognize image format for file '%s'", filename);
return NULL;
}
BLI_strncpy(ibuf->name, filename, sizeof(ibuf->name));
BLI_strncpy(ibuf->name, filename, sizeof(ibuf->name));
return Py_ImBuf_CreatePyObject(ibuf);
return Py_ImBuf_CreatePyObject(ibuf);
}
PyDoc_STRVAR(M_imbuf_write_doc,
".. function:: write(image, filename)\n"
"\n"
" Write an image.\n"
"\n"
" :arg image: the image to write.\n"
" :type image: :class:`ImBuf`\n"
" :arg filename: the filename of the image.\n"
" :type filename: string\n"
);
".. function:: write(image, filename)\n"
"\n"
" Write an image.\n"
"\n"
" :arg image: the image to write.\n"
" :type image: :class:`ImBuf`\n"
" :arg filename: the filename of the image.\n"
" :type filename: string\n");
static PyObject *M_imbuf_write(PyObject *UNUSED(self), PyObject *args, PyObject *kw)
{
Py_ImBuf *py_imb;
const char *filename = NULL;
Py_ImBuf *py_imb;
const char *filename = NULL;
static const char *_keywords[] = {"image", "filename", NULL};
static _PyArg_Parser _parser = {"O!|s:write", _keywords, 0};
if (!_PyArg_ParseTupleAndKeywordsFast(
args, kw, &_parser,
&Py_ImBuf_Type, &py_imb,
&filename))
{
return NULL;
}
static const char *_keywords[] = {"image", "filename", NULL};
static _PyArg_Parser _parser = {"O!|s:write", _keywords, 0};
if (!_PyArg_ParseTupleAndKeywordsFast(args, kw, &_parser, &Py_ImBuf_Type, &py_imb, &filename)) {
return NULL;
}
if (filename == NULL) {
filename = py_imb->ibuf->name;
}
if (filename == NULL) {
filename = py_imb->ibuf->name;
}
bool ok = IMB_saveiff(py_imb->ibuf, filename, IB_rect);
if (ok == false) {
PyErr_Format(PyExc_IOError, "write: Unable to write image file (%s) '%s'", strerror(errno), filename);
return NULL;
}
bool ok = IMB_saveiff(py_imb->ibuf, filename, IB_rect);
if (ok == false) {
PyErr_Format(
PyExc_IOError, "write: Unable to write image file (%s) '%s'", strerror(errno), filename);
return NULL;
}
Py_RETURN_NONE;
Py_RETURN_NONE;
}
/** \} */
@@ -432,36 +419,34 @@ static PyObject *M_imbuf_write(PyObject *UNUSED(self), PyObject *args, PyObject
* \{ */
static PyMethodDef IMB_methods[] = {
{"new", (PyCFunction) M_imbuf_new, METH_VARARGS | METH_KEYWORDS, M_imbuf_new_doc},
{"load", (PyCFunction) M_imbuf_load, METH_VARARGS | METH_KEYWORDS, M_imbuf_load_doc},
{"write", (PyCFunction) M_imbuf_write, METH_VARARGS | METH_KEYWORDS, M_imbuf_write_doc},
{NULL, NULL, 0, NULL},
{"new", (PyCFunction)M_imbuf_new, METH_VARARGS | METH_KEYWORDS, M_imbuf_new_doc},
{"load", (PyCFunction)M_imbuf_load, METH_VARARGS | METH_KEYWORDS, M_imbuf_load_doc},
{"write", (PyCFunction)M_imbuf_write, METH_VARARGS | METH_KEYWORDS, M_imbuf_write_doc},
{NULL, NULL, 0, NULL},
};
PyDoc_STRVAR(IMB_doc,
"This module provides access to Blender's image manipulation API."
);
PyDoc_STRVAR(IMB_doc, "This module provides access to Blender's image manipulation API.");
static struct PyModuleDef IMB_module_def = {
PyModuleDef_HEAD_INIT,
"imbuf", /* m_name */
IMB_doc, /* m_doc */
0, /* m_size */
IMB_methods, /* m_methods */
NULL, /* m_reload */
NULL, /* m_traverse */
NULL, /* m_clear */
NULL, /* m_free */
PyModuleDef_HEAD_INIT,
"imbuf", /* m_name */
IMB_doc, /* m_doc */
0, /* m_size */
IMB_methods, /* m_methods */
NULL, /* m_reload */
NULL, /* m_traverse */
NULL, /* m_clear */
NULL, /* m_free */
};
PyObject *BPyInit_imbuf(void)
{
PyObject *submodule;
PyObject *submodule;
submodule = PyModule_Create(&IMB_module_def);
submodule = PyModule_Create(&IMB_module_def);
PyType_Ready(&Py_ImBuf_Type);
PyType_Ready(&Py_ImBuf_Type);
return submodule;
return submodule;
}
/** \} */

View File

@@ -25,4 +25,4 @@ PyObject *BPyInit_imbuf(void);
extern PyTypeObject Py_ImBuf_Type;
#endif /* __IMBUF_PY_API_H__ */
#endif /* __IMBUF_PY_API_H__ */

File diff suppressed because it is too large Load Diff

View File

@@ -24,10 +24,10 @@
#include "BLI_sys_types.h"
#include "BLI_utildefines_variadic.h"
void PyC_ObSpit(const char *name, PyObject *var);
void PyC_ObSpitStr(char *result, size_t result_len, PyObject *var);
void PyC_LineSpit(void);
void PyC_StackSpit(void);
void PyC_ObSpit(const char *name, PyObject *var);
void PyC_ObSpitStr(char *result, size_t result_len, PyObject *var);
void PyC_LineSpit(void);
void PyC_StackSpit(void);
PyObject *PyC_ExceptionBuffer(void);
PyObject *PyC_ExceptionBuffer_Simple(void);
PyObject *PyC_Object_GetAttrStringArgs(PyObject *o, Py_ssize_t n, ...);
@@ -36,40 +36,46 @@ PyObject *PyC_FrozenSetFromStrings(const char **strings);
PyObject *PyC_Err_Format_Prefix(PyObject *exception_type_prefix, const char *format, ...);
PyObject *PyC_Err_SetString_Prefix(PyObject *exception_type_prefix, const char *str);
void PyC_Err_PrintWithFunc(PyObject *py_func);
void PyC_Err_PrintWithFunc(PyObject *py_func);
void PyC_FileAndNum(const char **filename, int *lineno);
void PyC_FileAndNum_Safe(const char **filename, int *lineno); /* checks python is running */
int PyC_AsArray_FAST(
void *array, PyObject *value_fast, const Py_ssize_t length,
const PyTypeObject *type, const bool is_double, const char *error_prefix);
int PyC_AsArray(
void *array, PyObject *value, const Py_ssize_t length,
const PyTypeObject *type, const bool is_double, const char *error_prefix);
void PyC_FileAndNum(const char **filename, int *lineno);
void PyC_FileAndNum_Safe(const char **filename, int *lineno); /* checks python is running */
int PyC_AsArray_FAST(void *array,
PyObject *value_fast,
const Py_ssize_t length,
const PyTypeObject *type,
const bool is_double,
const char *error_prefix);
int PyC_AsArray(void *array,
PyObject *value,
const Py_ssize_t length,
const PyTypeObject *type,
const bool is_double,
const char *error_prefix);
PyObject *PyC_Tuple_PackArray_F32(const float *array, uint len);
PyObject *PyC_Tuple_PackArray_F64(const double *array, uint len);
PyObject *PyC_Tuple_PackArray_I32(const int *array, uint len);
PyObject *PyC_Tuple_PackArray_I32FromBool(const int *array, uint len);
PyObject *PyC_Tuple_PackArray_Bool(const bool *array, uint len);
PyObject *PyC_Tuple_PackArray_F32(const float *array, uint len);
PyObject *PyC_Tuple_PackArray_F64(const double *array, uint len);
PyObject *PyC_Tuple_PackArray_I32(const int *array, uint len);
PyObject *PyC_Tuple_PackArray_I32FromBool(const int *array, uint len);
PyObject *PyC_Tuple_PackArray_Bool(const bool *array, uint len);
#define PyC_Tuple_Pack_F32(...) \
PyC_Tuple_PackArray_F32(((const float []){__VA_ARGS__}), VA_NARGS_COUNT(__VA_ARGS__))
PyC_Tuple_PackArray_F32(((const float[]){__VA_ARGS__}), VA_NARGS_COUNT(__VA_ARGS__))
#define PyC_Tuple_Pack_F64(...) \
PyC_Tuple_PackArray_F64(((const double []){__VA_ARGS__}), VA_NARGS_COUNT(__VA_ARGS__))
PyC_Tuple_PackArray_F64(((const double[]){__VA_ARGS__}), VA_NARGS_COUNT(__VA_ARGS__))
#define PyC_Tuple_Pack_I32(...) \
PyC_Tuple_PackArray_I32(((const int []){__VA_ARGS__}), VA_NARGS_COUNT(__VA_ARGS__))
PyC_Tuple_PackArray_I32(((const int[]){__VA_ARGS__}), VA_NARGS_COUNT(__VA_ARGS__))
#define PyC_Tuple_Pack_I32FromBool(...) \
PyC_Tuple_PackArray_I32FromBool(((const int []){__VA_ARGS__}), VA_NARGS_COUNT(__VA_ARGS__))
PyC_Tuple_PackArray_I32FromBool(((const int[]){__VA_ARGS__}), VA_NARGS_COUNT(__VA_ARGS__))
#define PyC_Tuple_Pack_Bool(...) \
PyC_Tuple_PackArray_Bool(((const bool []){__VA_ARGS__}), VA_NARGS_COUNT(__VA_ARGS__))
PyC_Tuple_PackArray_Bool(((const bool[]){__VA_ARGS__}), VA_NARGS_COUNT(__VA_ARGS__))
void PyC_Tuple_Fill(PyObject *tuple, PyObject *value);
void PyC_List_Fill(PyObject *list, PyObject *value);
void PyC_Tuple_Fill(PyObject *tuple, PyObject *value);
void PyC_List_Fill(PyObject *list, PyObject *value);
/* follow http://www.python.org/dev/peps/pep-0383/ */
PyObject *PyC_UnicodeFromByte(const char *str);
PyObject *PyC_UnicodeFromByteAndSize(const char *str, Py_ssize_t size);
PyObject *PyC_UnicodeFromByte(const char *str);
PyObject *PyC_UnicodeFromByteAndSize(const char *str, Py_ssize_t size);
const char *PyC_UnicodeAsByte(PyObject *py_str, PyObject **coerce); /* coerce must be NULL */
const char *PyC_UnicodeAsByteAndSize(PyObject *py_str, Py_ssize_t *size, PyObject **coerce);
@@ -89,34 +95,49 @@ void *PyC_RNA_AsPointer(PyObject *value, const char *type_name);
/* flag / set --- interchange */
typedef struct PyC_FlagSet {
int value;
const char *identifier;
int value;
const char *identifier;
} PyC_FlagSet;
char *PyC_FlagSet_AsString(PyC_FlagSet *item);
int PyC_FlagSet_ValueFromID_int(PyC_FlagSet *item, const char *identifier, int *r_value);
int PyC_FlagSet_ValueFromID(PyC_FlagSet *item, const char *identifier, int *r_value, const char *error_prefix);
int PyC_FlagSet_ToBitfield(PyC_FlagSet *items, PyObject *value, int *r_value, const char *error_prefix);
char *PyC_FlagSet_AsString(PyC_FlagSet *item);
int PyC_FlagSet_ValueFromID_int(PyC_FlagSet *item, const char *identifier, int *r_value);
int PyC_FlagSet_ValueFromID(PyC_FlagSet *item,
const char *identifier,
int *r_value,
const char *error_prefix);
int PyC_FlagSet_ToBitfield(PyC_FlagSet *items,
PyObject *value,
int *r_value,
const char *error_prefix);
PyObject *PyC_FlagSet_FromBitfield(PyC_FlagSet *items, int flag);
bool PyC_RunString_AsNumber(const char **imports, const char *expr, const char *filename, double *r_value);
bool PyC_RunString_AsIntPtr(const char **imports, const char *expr, const char *filename, intptr_t *r_value);
bool PyC_RunString_AsString(const char **imports, const char *expr, const char *filename, char **r_value);
bool PyC_RunString_AsNumber(const char **imports,
const char *expr,
const char *filename,
double *r_value);
bool PyC_RunString_AsIntPtr(const char **imports,
const char *expr,
const char *filename,
intptr_t *r_value);
bool PyC_RunString_AsString(const char **imports,
const char *expr,
const char *filename,
char **r_value);
int PyC_ParseBool(PyObject *o, void *p);
int PyC_CheckArgs_DeepCopy(PyObject *args);
/* Integer parsing (with overflow checks), -1 on error. */
int PyC_Long_AsBool(PyObject *value);
int8_t PyC_Long_AsI8(PyObject *value);
int PyC_Long_AsBool(PyObject *value);
int8_t PyC_Long_AsI8(PyObject *value);
int16_t PyC_Long_AsI16(PyObject *value);
#if 0 /* inline */
int32_t PyC_Long_AsI32(PyObject *value);
int64_t PyC_Long_AsI64(PyObject *value);
#endif
uint8_t PyC_Long_AsU8(PyObject *value);
uint8_t PyC_Long_AsU8(PyObject *value);
uint16_t PyC_Long_AsU16(PyObject *value);
uint32_t PyC_Long_AsU32(PyObject *value);
#if 0 /* inline */
@@ -124,9 +145,18 @@ uint64_t PyC_Long_AsU64(PyObject *value);
#endif
/* inline so type signatures match as expected */
Py_LOCAL_INLINE(int32_t) PyC_Long_AsI32(PyObject *value) { return (int32_t)_PyLong_AsInt(value); }
Py_LOCAL_INLINE(int64_t) PyC_Long_AsI64(PyObject *value) { return (int64_t)PyLong_AsLongLong(value); }
Py_LOCAL_INLINE(uint64_t) PyC_Long_AsU64(PyObject *value) { return (uint64_t)PyLong_AsUnsignedLongLong(value); }
Py_LOCAL_INLINE(int32_t) PyC_Long_AsI32(PyObject *value)
{
return (int32_t)_PyLong_AsInt(value);
}
Py_LOCAL_INLINE(int64_t) PyC_Long_AsI64(PyObject *value)
{
return (int64_t)PyLong_AsLongLong(value);
}
Py_LOCAL_INLINE(uint64_t) PyC_Long_AsU64(PyObject *value)
{
return (uint64_t)PyLong_AsUnsignedLongLong(value);
}
/* utils for format string in `struct` module style syntax */
char PyC_StructFmt_type_from_str(const char *typestr);
@@ -135,4 +165,4 @@ bool PyC_StructFmt_type_is_int_any(char format);
bool PyC_StructFmt_type_is_byte(char format);
bool PyC_StructFmt_type_is_bool(char format);
#endif /* __PY_CAPI_UTILS_H__ */
#endif /* __PY_CAPI_UTILS_H__ */

View File

@@ -28,28 +28,33 @@ extern "C" {
#endif
#define PyTuple_SET_ITEMS(op_arg, ...) \
{ \
PyTupleObject *op = (PyTupleObject *)op_arg; \
PyObject **ob_items = op->ob_item; \
CHECK_TYPE_ANY(op_arg, PyObject *, PyTupleObject *); \
BLI_assert(VA_NARGS_COUNT(__VA_ARGS__) == PyTuple_GET_SIZE(op)); \
ARRAY_SET_ITEMS(ob_items, __VA_ARGS__); \
} (void)0
{ \
PyTupleObject *op = (PyTupleObject *)op_arg; \
PyObject **ob_items = op->ob_item; \
CHECK_TYPE_ANY(op_arg, PyObject *, PyTupleObject *); \
BLI_assert(VA_NARGS_COUNT(__VA_ARGS__) == PyTuple_GET_SIZE(op)); \
ARRAY_SET_ITEMS(ob_items, __VA_ARGS__); \
} \
(void)0
/* wrap Py_INCREF & return the result,
* use sparingly to avoid comma operator or temp var assignment */
Py_LOCAL_INLINE(PyObject *)Py_INCREF_RET(PyObject *op) { Py_INCREF(op); return op; }
Py_LOCAL_INLINE(PyObject *) Py_INCREF_RET(PyObject *op)
{
Py_INCREF(op);
return op;
}
/* append & transfer ownership to the list, avoids inline Py_DECREF all over (which is quite a large macro) */
Py_LOCAL_INLINE(int) PyList_APPEND(PyObject *op, PyObject *v)
{
int ret = PyList_Append(op, v);
Py_DecRef(v);
return ret;
int ret = PyList_Append(op, v);
Py_DecRef(v);
return ret;
}
#ifdef __cplusplus
}
#endif
#endif /* __PYTHON_UTILDEFINES_H__ */
#endif /* __PYTHON_UTILDEFINES_H__ */

View File

@@ -16,42 +16,42 @@
# ***** END GPL LICENSE BLOCK *****
set(INC
.
../../blenkernel
../../blenlib
../../gpu
../../makesdna
../../../../intern/guardedalloc
../../../../intern/glew-mx
.
../../blenkernel
../../blenlib
../../gpu
../../makesdna
../../../../intern/guardedalloc
../../../../intern/glew-mx
)
set(INC_SYS
${GLEW_INCLUDE_PATH}
${PYTHON_INCLUDE_DIRS}
${GLEW_INCLUDE_PATH}
${PYTHON_INCLUDE_DIRS}
)
set(SRC
gpu_py_api.c
gpu_py_batch.c
gpu_py_element.c
gpu_py_matrix.c
gpu_py_offscreen.c
gpu_py_select.c
gpu_py_shader.c
gpu_py_types.c
gpu_py_vertex_buffer.c
gpu_py_vertex_format.c
gpu_py_api.c
gpu_py_batch.c
gpu_py_element.c
gpu_py_matrix.c
gpu_py_offscreen.c
gpu_py_select.c
gpu_py_shader.c
gpu_py_types.c
gpu_py_vertex_buffer.c
gpu_py_vertex_format.c
gpu_py_api.h
gpu_py_batch.h
gpu_py_element.h
gpu_py_matrix.h
gpu_py_offscreen.h
gpu_py_select.h
gpu_py_shader.h
gpu_py_types.h
gpu_py_vertex_buffer.h
gpu_py_vertex_format.h
gpu_py_api.h
gpu_py_batch.h
gpu_py_element.h
gpu_py_matrix.h
gpu_py_offscreen.h
gpu_py_select.h
gpu_py_shader.h
gpu_py_types.h
gpu_py_vertex_buffer.h
gpu_py_vertex_format.h
)
set(LIB

View File

@@ -39,120 +39,111 @@
#include "gpu_py_api.h" /* own include */
/* -------------------------------------------------------------------- */
/** \name Utils to invalidate functions
* \{ */
bool bpygpu_is_initialized_or_error(void)
{
if (!GPU_is_initialized()) {
PyErr_SetString(
PyExc_SystemError,
"GPU functions for drawing are not available in background mode");
if (!GPU_is_initialized()) {
PyErr_SetString(PyExc_SystemError,
"GPU functions for drawing are not available in background mode");
return false;
}
return false;
}
return true;
return true;
}
/** \} */
/* -------------------------------------------------------------------- */
/** \name Primitive Type Utils
* \{ */
int bpygpu_ParsePrimType(PyObject *o, void *p)
{
Py_ssize_t mode_id_len;
const char *mode_id = _PyUnicode_AsStringAndSize(o, &mode_id_len);
if (mode_id == NULL) {
PyErr_Format(PyExc_ValueError,
"expected a string, got %s",
Py_TYPE(o)->tp_name);
return 0;
}
Py_ssize_t mode_id_len;
const char *mode_id = _PyUnicode_AsStringAndSize(o, &mode_id_len);
if (mode_id == NULL) {
PyErr_Format(PyExc_ValueError, "expected a string, got %s", Py_TYPE(o)->tp_name);
return 0;
}
#define MATCH_ID(id) \
if (mode_id_len == strlen(STRINGIFY(id))) { \
if (STREQ(mode_id, STRINGIFY(id))) { \
mode = GPU_PRIM_##id; \
goto success; \
} \
} ((void)0)
if (mode_id_len == strlen(STRINGIFY(id))) { \
if (STREQ(mode_id, STRINGIFY(id))) { \
mode = GPU_PRIM_##id; \
goto success; \
} \
} \
((void)0)
GPUPrimType mode;
MATCH_ID(POINTS);
MATCH_ID(LINES);
MATCH_ID(TRIS);
MATCH_ID(LINE_STRIP);
MATCH_ID(LINE_LOOP);
MATCH_ID(TRI_STRIP);
MATCH_ID(TRI_FAN);
MATCH_ID(LINE_STRIP_ADJ);
GPUPrimType mode;
MATCH_ID(POINTS);
MATCH_ID(LINES);
MATCH_ID(TRIS);
MATCH_ID(LINE_STRIP);
MATCH_ID(LINE_LOOP);
MATCH_ID(TRI_STRIP);
MATCH_ID(TRI_FAN);
MATCH_ID(LINE_STRIP_ADJ);
#undef MATCH_ID
PyErr_Format(PyExc_ValueError,
"unknown type literal: '%s'",
mode_id);
return 0;
PyErr_Format(PyExc_ValueError, "unknown type literal: '%s'", mode_id);
return 0;
success:
(*(GPUPrimType *)p) = mode;
return 1;
(*(GPUPrimType *)p) = mode;
return 1;
}
/** \} */
/* -------------------------------------------------------------------- */
/** \name GPU Module
* \{ */
PyDoc_STRVAR(GPU_doc,
"This module provides Python wrappers for the GPU implementation in Blender. "
"Some higher level functions can be found in the `gpu_extras` module. "
"\n\n"
"Submodules:\n"
"\n"
".. toctree::\n"
" :maxdepth: 1\n"
"\n"
" gpu.types.rst\n"
" gpu.shader.rst\n"
" gpu.matrix.rst\n"
" gpu.select.rst\n"
"\n"
);
"This module provides Python wrappers for the GPU implementation in Blender. "
"Some higher level functions can be found in the `gpu_extras` module. "
"\n\n"
"Submodules:\n"
"\n"
".. toctree::\n"
" :maxdepth: 1\n"
"\n"
" gpu.types.rst\n"
" gpu.shader.rst\n"
" gpu.matrix.rst\n"
" gpu.select.rst\n"
"\n");
static struct PyModuleDef GPU_module_def = {
PyModuleDef_HEAD_INIT,
.m_name = "gpu",
.m_doc = GPU_doc,
PyModuleDef_HEAD_INIT,
.m_name = "gpu",
.m_doc = GPU_doc,
};
PyObject *BPyInit_gpu(void)
{
PyObject *sys_modules = PyImport_GetModuleDict();
PyObject *submodule;
PyObject *mod;
PyObject *sys_modules = PyImport_GetModuleDict();
PyObject *submodule;
PyObject *mod;
mod = PyModule_Create(&GPU_module_def);
mod = PyModule_Create(&GPU_module_def);
PyModule_AddObject(mod, "types", (submodule = BPyInit_gpu_types()));
PyDict_SetItem(sys_modules, PyModule_GetNameObject(submodule), submodule);
PyModule_AddObject(mod, "types", (submodule = BPyInit_gpu_types()));
PyDict_SetItem(sys_modules, PyModule_GetNameObject(submodule), submodule);
PyModule_AddObject(mod, "matrix", (submodule = BPyInit_gpu_matrix()));
PyDict_SetItem(sys_modules, PyModule_GetNameObject(submodule), submodule);
PyModule_AddObject(mod, "matrix", (submodule = BPyInit_gpu_matrix()));
PyDict_SetItem(sys_modules, PyModule_GetNameObject(submodule), submodule);
PyModule_AddObject(mod, "select", (submodule = BPyInit_gpu_select()));
PyDict_SetItem(sys_modules, PyModule_GetNameObject(submodule), submodule);
PyModule_AddObject(mod, "select", (submodule = BPyInit_gpu_select()));
PyDict_SetItem(sys_modules, PyModule_GetNameObject(submodule), submodule);
PyModule_AddObject(mod, "shader", (submodule = BPyInit_gpu_shader()));
PyDict_SetItem(sys_modules, PyModule_GetNameObject(submodule), submodule);
PyModule_AddObject(mod, "shader", (submodule = BPyInit_gpu_shader()));
PyDict_SetItem(sys_modules, PyModule_GetNameObject(submodule), submodule);
return mod;
return mod;
}
/** \} */

View File

@@ -21,13 +21,20 @@
#ifndef __GPU_PY_API_H__
#define __GPU_PY_API_H__
int bpygpu_ParsePrimType(PyObject *o, void *p);
PyObject *BPyInit_gpu(void);
bool bpygpu_is_initialized_or_error(void);
#define BPYGPU_IS_INIT_OR_ERROR_OBJ if (UNLIKELY(!bpygpu_is_initialized_or_error())) { return NULL; } ((void)0)
#define BPYGPU_IS_INIT_OR_ERROR_INT if (UNLIKELY(!bpygpu_is_initialized_or_error())) { return -1; } ((void)0)
#define BPYGPU_IS_INIT_OR_ERROR_OBJ \
if (UNLIKELY(!bpygpu_is_initialized_or_error())) { \
return NULL; \
} \
((void)0)
#define BPYGPU_IS_INIT_OR_ERROR_INT \
if (UNLIKELY(!bpygpu_is_initialized_or_error())) { \
return -1; \
} \
((void)0)
#endif /* __GPU_PY_API_H__ */
#endif /* __GPU_PY_API_H__ */

View File

@@ -32,7 +32,6 @@
#include "BLI_utildefines.h"
#include "GPU_batch.h"
#include "../mathutils/mathutils.h"
@@ -45,85 +44,81 @@
#include "gpu_py_element.h"
#include "gpu_py_batch.h" /* own include */
/* -------------------------------------------------------------------- */
/** \name Utility Functions
* \{ */
static bool bpygpu_batch_is_program_or_error(BPyGPUBatch *self)
{
if (!glIsProgram(self->batch->program)) {
PyErr_SetString(
PyExc_RuntimeError,
"batch does not have any program assigned to it");
return false;
}
return true;
if (!glIsProgram(self->batch->program)) {
PyErr_SetString(PyExc_RuntimeError, "batch does not have any program assigned to it");
return false;
}
return true;
}
/** \} */
/* -------------------------------------------------------------------- */
/** \name GPUBatch Type
* \{ */
static PyObject *bpygpu_Batch_new(PyTypeObject *UNUSED(type), PyObject *args, PyObject *kwds)
{
BPYGPU_IS_INIT_OR_ERROR_OBJ;
BPYGPU_IS_INIT_OR_ERROR_OBJ;
const char *exc_str_missing_arg = "GPUBatch.__new__() missing required argument '%s' (pos %d)";
const char *exc_str_missing_arg = "GPUBatch.__new__() missing required argument '%s' (pos %d)";
struct {
GPUPrimType type_id;
BPyGPUVertBuf *py_vertbuf;
BPyGPUIndexBuf *py_indexbuf;
} params = {GPU_PRIM_NONE, NULL, NULL};
struct {
GPUPrimType type_id;
BPyGPUVertBuf *py_vertbuf;
BPyGPUIndexBuf *py_indexbuf;
} params = {GPU_PRIM_NONE, NULL, NULL};
static const char *_keywords[] = {"type", "buf", "elem", NULL};
static _PyArg_Parser _parser = {"|$O&O!O!:GPUBatch.__new__", _keywords, 0};
if (!_PyArg_ParseTupleAndKeywordsFast(
args, kwds, &_parser,
bpygpu_ParsePrimType, &params.type_id,
&BPyGPUVertBuf_Type, &params.py_vertbuf,
&BPyGPUIndexBuf_Type, &params.py_indexbuf))
{
return NULL;
}
static const char *_keywords[] = {"type", "buf", "elem", NULL};
static _PyArg_Parser _parser = {"|$O&O!O!:GPUBatch.__new__", _keywords, 0};
if (!_PyArg_ParseTupleAndKeywordsFast(args,
kwds,
&_parser,
bpygpu_ParsePrimType,
&params.type_id,
&BPyGPUVertBuf_Type,
&params.py_vertbuf,
&BPyGPUIndexBuf_Type,
&params.py_indexbuf)) {
return NULL;
}
if (params.type_id == GPU_PRIM_NONE) {
PyErr_Format(PyExc_TypeError,
exc_str_missing_arg, _keywords[0], 1);
return NULL;
}
if (params.type_id == GPU_PRIM_NONE) {
PyErr_Format(PyExc_TypeError, exc_str_missing_arg, _keywords[0], 1);
return NULL;
}
if (params.py_vertbuf == NULL) {
PyErr_Format(PyExc_TypeError,
exc_str_missing_arg, _keywords[1], 2);
return NULL;
}
if (params.py_vertbuf == NULL) {
PyErr_Format(PyExc_TypeError, exc_str_missing_arg, _keywords[1], 2);
return NULL;
}
GPUBatch *batch = GPU_batch_create(
params.type_id,
params.py_vertbuf->buf,
params.py_indexbuf ? params.py_indexbuf->elem : NULL);
GPUBatch *batch = GPU_batch_create(params.type_id,
params.py_vertbuf->buf,
params.py_indexbuf ? params.py_indexbuf->elem : NULL);
BPyGPUBatch *ret = (BPyGPUBatch *)BPyGPUBatch_CreatePyObject(batch);
BPyGPUBatch *ret = (BPyGPUBatch *)BPyGPUBatch_CreatePyObject(batch);
#ifdef USE_GPU_PY_REFERENCES
ret->references = PyList_New(params.py_indexbuf ? 2 : 1);
PyList_SET_ITEM(ret->references, 0, (PyObject *)params.py_vertbuf);
Py_INCREF(params.py_vertbuf);
ret->references = PyList_New(params.py_indexbuf ? 2 : 1);
PyList_SET_ITEM(ret->references, 0, (PyObject *)params.py_vertbuf);
Py_INCREF(params.py_vertbuf);
if (params.py_indexbuf != NULL) {
PyList_SET_ITEM(ret->references, 1, (PyObject *)params.py_indexbuf);
Py_INCREF(params.py_indexbuf);
}
if (params.py_indexbuf != NULL) {
PyList_SET_ITEM(ret->references, 1, (PyObject *)params.py_indexbuf);
Py_INCREF(params.py_indexbuf);
}
PyObject_GC_Track(ret);
PyObject_GC_Track(ret);
#endif
return (PyObject *)ret;
return (PyObject *)ret;
}
PyDoc_STRVAR(bpygpu_Batch_vertbuf_add_doc,
@@ -140,240 +135,224 @@ PyDoc_STRVAR(bpygpu_Batch_vertbuf_add_doc,
);
static PyObject *bpygpu_Batch_vertbuf_add(BPyGPUBatch *self, BPyGPUVertBuf *py_buf)
{
if (!BPyGPUVertBuf_Check(py_buf)) {
PyErr_Format(PyExc_TypeError,
"Expected a GPUVertBuf, got %s",
Py_TYPE(py_buf)->tp_name);
return NULL;
}
if (!BPyGPUVertBuf_Check(py_buf)) {
PyErr_Format(PyExc_TypeError, "Expected a GPUVertBuf, got %s", Py_TYPE(py_buf)->tp_name);
return NULL;
}
if (self->batch->verts[0]->vertex_len != py_buf->buf->vertex_len) {
PyErr_Format(PyExc_TypeError,
"Expected %d length, got %d",
self->batch->verts[0]->vertex_len, py_buf->buf->vertex_len);
return NULL;
}
if (self->batch->verts[0]->vertex_len != py_buf->buf->vertex_len) {
PyErr_Format(PyExc_TypeError,
"Expected %d length, got %d",
self->batch->verts[0]->vertex_len,
py_buf->buf->vertex_len);
return NULL;
}
if (self->batch->verts[GPU_BATCH_VBO_MAX_LEN - 1] != NULL) {
PyErr_SetString(
PyExc_RuntimeError,
"Maximum number of vertex buffers exceeded: " STRINGIFY(GPU_BATCH_VBO_MAX_LEN));
return NULL;
}
if (self->batch->verts[GPU_BATCH_VBO_MAX_LEN - 1] != NULL) {
PyErr_SetString(
PyExc_RuntimeError,
"Maximum number of vertex buffers exceeded: " STRINGIFY(GPU_BATCH_VBO_MAX_LEN));
return NULL;
}
#ifdef USE_GPU_PY_REFERENCES
/* Hold user */
PyList_Append(self->references, (PyObject *)py_buf);
/* Hold user */
PyList_Append(self->references, (PyObject *)py_buf);
#endif
GPU_batch_vertbuf_add(self->batch, py_buf->buf);
Py_RETURN_NONE;
GPU_batch_vertbuf_add(self->batch, py_buf->buf);
Py_RETURN_NONE;
}
PyDoc_STRVAR(bpygpu_Batch_program_set_doc,
".. method:: program_set(program)\n"
"\n"
" Assign a shader to this batch that will be used for drawing when not overwritten later.\n"
" Note: This method has to be called in the draw context that the batch will be drawn in.\n"
" This function does not need to be called when you always set the shader when calling `batch.draw`.\n"
"\n"
" :param program: The program/shader the batch will use in future draw calls.\n"
" :type program: :class:`gpu.types.GPUShader`\n"
);
PyDoc_STRVAR(
bpygpu_Batch_program_set_doc,
".. method:: program_set(program)\n"
"\n"
" Assign a shader to this batch that will be used for drawing when not overwritten later.\n"
" Note: This method has to be called in the draw context that the batch will be drawn in.\n"
" This function does not need to be called when you always set the shader when calling "
"`batch.draw`.\n"
"\n"
" :param program: The program/shader the batch will use in future draw calls.\n"
" :type program: :class:`gpu.types.GPUShader`\n");
static PyObject *bpygpu_Batch_program_set(BPyGPUBatch *self, BPyGPUShader *py_shader)
{
if (!BPyGPUShader_Check(py_shader)) {
PyErr_Format(PyExc_TypeError,
"Expected a GPUShader, got %s",
Py_TYPE(py_shader)->tp_name);
return NULL;
}
if (!BPyGPUShader_Check(py_shader)) {
PyErr_Format(PyExc_TypeError, "Expected a GPUShader, got %s", Py_TYPE(py_shader)->tp_name);
return NULL;
}
GPUShader *shader = py_shader->shader;
GPU_batch_program_set(
self->batch,
GPU_shader_get_program(shader),
GPU_shader_get_interface(shader));
GPUShader *shader = py_shader->shader;
GPU_batch_program_set(
self->batch, GPU_shader_get_program(shader), GPU_shader_get_interface(shader));
#ifdef USE_GPU_PY_REFERENCES
/* Remove existing user (if any), hold new user. */
int i = PyList_GET_SIZE(self->references);
while (--i != -1) {
PyObject *py_shader_test = PyList_GET_ITEM(self->references, i);
if (BPyGPUShader_Check(py_shader_test)) {
PyList_SET_ITEM(self->references, i, (PyObject *)py_shader);
Py_INCREF(py_shader);
Py_DECREF(py_shader_test);
/* Only ever reference one shader. */
break;
}
}
if (i != -1) {
PyList_Append(self->references, (PyObject *)py_shader);
}
/* Remove existing user (if any), hold new user. */
int i = PyList_GET_SIZE(self->references);
while (--i != -1) {
PyObject *py_shader_test = PyList_GET_ITEM(self->references, i);
if (BPyGPUShader_Check(py_shader_test)) {
PyList_SET_ITEM(self->references, i, (PyObject *)py_shader);
Py_INCREF(py_shader);
Py_DECREF(py_shader_test);
/* Only ever reference one shader. */
break;
}
}
if (i != -1) {
PyList_Append(self->references, (PyObject *)py_shader);
}
#endif
Py_RETURN_NONE;
Py_RETURN_NONE;
}
PyDoc_STRVAR(bpygpu_Batch_draw_doc,
".. method:: draw(program=None)\n"
"\n"
" Run the drawing program with the parameters assigned to the batch.\n"
"\n"
" :param program: Program that performs the drawing operations.\n"
" If ``None`` is passed, the last program setted to this batch will run.\n"
" :type program: :class:`gpu.types.GPUShader`\n"
);
".. method:: draw(program=None)\n"
"\n"
" Run the drawing program with the parameters assigned to the batch.\n"
"\n"
" :param program: Program that performs the drawing operations.\n"
" If ``None`` is passed, the last program setted to this batch will run.\n"
" :type program: :class:`gpu.types.GPUShader`\n");
static PyObject *bpygpu_Batch_draw(BPyGPUBatch *self, PyObject *args)
{
BPyGPUShader *py_program = NULL;
BPyGPUShader *py_program = NULL;
if (!PyArg_ParseTuple(
args, "|O!:GPUBatch.draw",
&BPyGPUShader_Type, &py_program))
{
return NULL;
}
else if (py_program == NULL) {
if (!bpygpu_batch_is_program_or_error(self)) {
return NULL;
}
}
else if (self->batch->program != GPU_shader_get_program(py_program->shader)) {
GPU_batch_program_set(
self->batch,
GPU_shader_get_program(py_program->shader),
GPU_shader_get_interface(py_program->shader));
}
if (!PyArg_ParseTuple(args, "|O!:GPUBatch.draw", &BPyGPUShader_Type, &py_program)) {
return NULL;
}
else if (py_program == NULL) {
if (!bpygpu_batch_is_program_or_error(self)) {
return NULL;
}
}
else if (self->batch->program != GPU_shader_get_program(py_program->shader)) {
GPU_batch_program_set(self->batch,
GPU_shader_get_program(py_program->shader),
GPU_shader_get_interface(py_program->shader));
}
GPU_batch_draw(self->batch);
Py_RETURN_NONE;
GPU_batch_draw(self->batch);
Py_RETURN_NONE;
}
static PyObject *bpygpu_Batch_program_use_begin(BPyGPUBatch *self)
{
if (!bpygpu_batch_is_program_or_error(self)) {
return NULL;
}
GPU_batch_program_use_begin(self->batch);
Py_RETURN_NONE;
if (!bpygpu_batch_is_program_or_error(self)) {
return NULL;
}
GPU_batch_program_use_begin(self->batch);
Py_RETURN_NONE;
}
static PyObject *bpygpu_Batch_program_use_end(BPyGPUBatch *self)
{
if (!bpygpu_batch_is_program_or_error(self)) {
return NULL;
}
GPU_batch_program_use_end(self->batch);
Py_RETURN_NONE;
if (!bpygpu_batch_is_program_or_error(self)) {
return NULL;
}
GPU_batch_program_use_end(self->batch);
Py_RETURN_NONE;
}
static struct PyMethodDef bpygpu_Batch_methods[] = {
{"vertbuf_add", (PyCFunction)bpygpu_Batch_vertbuf_add,
METH_O, bpygpu_Batch_vertbuf_add_doc},
{"program_set", (PyCFunction)bpygpu_Batch_program_set,
METH_O, bpygpu_Batch_program_set_doc},
{"draw", (PyCFunction) bpygpu_Batch_draw,
METH_VARARGS, bpygpu_Batch_draw_doc},
{"_program_use_begin", (PyCFunction)bpygpu_Batch_program_use_begin,
METH_NOARGS, ""},
{"_program_use_end", (PyCFunction)bpygpu_Batch_program_use_end,
METH_NOARGS, ""},
{NULL, NULL, 0, NULL},
{"vertbuf_add", (PyCFunction)bpygpu_Batch_vertbuf_add, METH_O, bpygpu_Batch_vertbuf_add_doc},
{"program_set", (PyCFunction)bpygpu_Batch_program_set, METH_O, bpygpu_Batch_program_set_doc},
{"draw", (PyCFunction)bpygpu_Batch_draw, METH_VARARGS, bpygpu_Batch_draw_doc},
{"_program_use_begin", (PyCFunction)bpygpu_Batch_program_use_begin, METH_NOARGS, ""},
{"_program_use_end", (PyCFunction)bpygpu_Batch_program_use_end, METH_NOARGS, ""},
{NULL, NULL, 0, NULL},
};
#ifdef USE_GPU_PY_REFERENCES
static int bpygpu_Batch_traverse(BPyGPUBatch *self, visitproc visit, void *arg)
{
Py_VISIT(self->references);
return 0;
Py_VISIT(self->references);
return 0;
}
static int bpygpu_Batch_clear(BPyGPUBatch *self)
{
Py_CLEAR(self->references);
return 0;
Py_CLEAR(self->references);
return 0;
}
#endif
static void bpygpu_Batch_dealloc(BPyGPUBatch *self)
{
GPU_batch_discard(self->batch);
GPU_batch_discard(self->batch);
#ifdef USE_GPU_PY_REFERENCES
if (self->references) {
PyObject_GC_UnTrack(self);
bpygpu_Batch_clear(self);
Py_XDECREF(self->references);
}
if (self->references) {
PyObject_GC_UnTrack(self);
bpygpu_Batch_clear(self);
Py_XDECREF(self->references);
}
#endif
Py_TYPE(self)->tp_free(self);
Py_TYPE(self)->tp_free(self);
}
PyDoc_STRVAR(py_gpu_batch_doc,
".. class:: GPUBatch(type, buf, elem=None)\n"
"\n"
" Reusable container for drawable geometry.\n"
"\n"
" :arg type: One of these primitive types: {\n"
" `POINTS`,\n"
" `LINES`,\n"
" `TRIS`,\n"
" `LINE_STRIP`,\n"
" `LINE_LOOP`,\n"
" `TRI_STRIP`,\n"
" `TRI_FAN`,\n"
" `LINES_ADJ`,\n"
" `TRIS_ADJ`,\n"
" `LINE_STRIP_ADJ` }\n"
" :type type: `str`\n"
" :arg buf: Vertex buffer containing all or some of the attributes required for drawing.\n"
" :type buf: :class:`gpu.types.GPUVertBuf`\n"
" :arg elem: An optional index buffer.\n"
" :type elem: :class:`gpu.types.GPUIndexBuf`\n"
);
PyDoc_STRVAR(
py_gpu_batch_doc,
".. class:: GPUBatch(type, buf, elem=None)\n"
"\n"
" Reusable container for drawable geometry.\n"
"\n"
" :arg type: One of these primitive types: {\n"
" `POINTS`,\n"
" `LINES`,\n"
" `TRIS`,\n"
" `LINE_STRIP`,\n"
" `LINE_LOOP`,\n"
" `TRI_STRIP`,\n"
" `TRI_FAN`,\n"
" `LINES_ADJ`,\n"
" `TRIS_ADJ`,\n"
" `LINE_STRIP_ADJ` }\n"
" :type type: `str`\n"
" :arg buf: Vertex buffer containing all or some of the attributes required for drawing.\n"
" :type buf: :class:`gpu.types.GPUVertBuf`\n"
" :arg elem: An optional index buffer.\n"
" :type elem: :class:`gpu.types.GPUIndexBuf`\n");
PyTypeObject BPyGPUBatch_Type = {
PyVarObject_HEAD_INIT(NULL, 0)
.tp_name = "GPUBatch",
.tp_basicsize = sizeof(BPyGPUBatch),
.tp_dealloc = (destructor)bpygpu_Batch_dealloc,
PyVarObject_HEAD_INIT(NULL, 0).tp_name = "GPUBatch",
.tp_basicsize = sizeof(BPyGPUBatch),
.tp_dealloc = (destructor)bpygpu_Batch_dealloc,
#ifdef USE_GPU_PY_REFERENCES
.tp_flags = Py_TPFLAGS_DEFAULT | Py_TPFLAGS_HAVE_GC,
.tp_doc = py_gpu_batch_doc,
.tp_traverse = (traverseproc)bpygpu_Batch_traverse,
.tp_clear = (inquiry)bpygpu_Batch_clear,
.tp_flags = Py_TPFLAGS_DEFAULT | Py_TPFLAGS_HAVE_GC,
.tp_doc = py_gpu_batch_doc,
.tp_traverse = (traverseproc)bpygpu_Batch_traverse,
.tp_clear = (inquiry)bpygpu_Batch_clear,
#else
.tp_flags = Py_TPFLAGS_DEFAULT,
.tp_flags = Py_TPFLAGS_DEFAULT,
#endif
.tp_methods = bpygpu_Batch_methods,
.tp_new = bpygpu_Batch_new,
.tp_methods = bpygpu_Batch_methods,
.tp_new = bpygpu_Batch_new,
};
/** \} */
/* -------------------------------------------------------------------- */
/** \name Public API
* \{ */
PyObject *BPyGPUBatch_CreatePyObject(GPUBatch *batch)
{
BPyGPUBatch *self;
BPyGPUBatch *self;
#ifdef USE_GPU_PY_REFERENCES
self = (BPyGPUBatch *)_PyObject_GC_New(&BPyGPUBatch_Type);
self->references = NULL;
self = (BPyGPUBatch *)_PyObject_GC_New(&BPyGPUBatch_Type);
self->references = NULL;
#else
self = PyObject_New(BPyGPUBatch, &BPyGPUBatch_Type);
self = PyObject_New(BPyGPUBatch, &BPyGPUBatch_Type);
#endif
self->batch = batch;
self->batch = batch;
return (PyObject *)self;
return (PyObject *)self;
}
/** \} */

View File

@@ -27,15 +27,15 @@
extern PyTypeObject BPyGPUBatch_Type;
#define BPyGPUBatch_Check(v) (Py_TYPE(v) == &BPyGPUBatch_Type)
#define BPyGPUBatch_Check(v) (Py_TYPE(v) == &BPyGPUBatch_Type)
typedef struct BPyGPUBatch {
PyObject_VAR_HEAD
/* The batch is owned, we may support thin wrapped batches later. */
struct GPUBatch *batch;
PyObject_VAR_HEAD
/* The batch is owned, we may support thin wrapped batches later. */
struct GPUBatch *batch;
#ifdef USE_GPU_PY_REFERENCES
/* Just to keep a user to prevent freeing buf's we're using */
PyObject *references;
/* Just to keep a user to prevent freeing buf's we're using */
PyObject *references;
#endif
} BPyGPUBatch;

View File

@@ -35,204 +35,190 @@
#include "gpu_py_api.h"
#include "gpu_py_element.h" /* own include */
/* -------------------------------------------------------------------- */
/** \name IndexBuf Type
* \{ */
static PyObject *bpygpu_IndexBuf_new(PyTypeObject *UNUSED(type), PyObject *args, PyObject *kwds)
{
BPYGPU_IS_INIT_OR_ERROR_OBJ;
BPYGPU_IS_INIT_OR_ERROR_OBJ;
const char *error_prefix = "IndexBuf.__new__";
bool ok = true;
const char *error_prefix = "IndexBuf.__new__";
bool ok = true;
struct {
GPUPrimType type_id;
PyObject *seq;
} params;
struct {
GPUPrimType type_id;
PyObject *seq;
} params;
uint verts_per_prim;
uint index_len;
GPUIndexBufBuilder builder;
uint verts_per_prim;
uint index_len;
GPUIndexBufBuilder builder;
static const char *_keywords[] = {"type", "seq", NULL};
static _PyArg_Parser _parser = {"$O&O:IndexBuf.__new__", _keywords, 0};
if (!_PyArg_ParseTupleAndKeywordsFast(
args, kwds, &_parser,
bpygpu_ParsePrimType, &params.type_id,
&params.seq))
{
return NULL;
}
static const char *_keywords[] = {"type", "seq", NULL};
static _PyArg_Parser _parser = {"$O&O:IndexBuf.__new__", _keywords, 0};
if (!_PyArg_ParseTupleAndKeywordsFast(
args, kwds, &_parser, bpygpu_ParsePrimType, &params.type_id, &params.seq)) {
return NULL;
}
verts_per_prim = GPU_indexbuf_primitive_len(params.type_id);
if (verts_per_prim == -1) {
PyErr_Format(PyExc_ValueError,
"The argument 'type' must be "
"'POINTS', 'LINES', 'TRIS' or 'LINES_ADJ'");
return NULL;
}
verts_per_prim = GPU_indexbuf_primitive_len(params.type_id);
if (verts_per_prim == -1) {
PyErr_Format(PyExc_ValueError,
"The argument 'type' must be "
"'POINTS', 'LINES', 'TRIS' or 'LINES_ADJ'");
return NULL;
}
if (PyObject_CheckBuffer(params.seq)) {
Py_buffer pybuffer;
if (PyObject_CheckBuffer(params.seq)) {
Py_buffer pybuffer;
if (PyObject_GetBuffer(params.seq, &pybuffer, PyBUF_FORMAT | PyBUF_ND) == -1) {
/* PyObject_GetBuffer already handles error messages. */
return NULL;
}
if (PyObject_GetBuffer(params.seq, &pybuffer, PyBUF_FORMAT | PyBUF_ND) == -1) {
/* PyObject_GetBuffer already handles error messages. */
return NULL;
}
if (pybuffer.ndim != 1 && pybuffer.shape[1] != verts_per_prim) {
PyErr_Format(PyExc_ValueError,
"Each primitive must exactly %d indices",
verts_per_prim);
return NULL;
}
if (pybuffer.ndim != 1 && pybuffer.shape[1] != verts_per_prim) {
PyErr_Format(PyExc_ValueError, "Each primitive must exactly %d indices", verts_per_prim);
return NULL;
}
if (pybuffer.itemsize != 4 ||
PyC_StructFmt_type_is_float_any(PyC_StructFmt_type_from_str(pybuffer.format)))
{
PyErr_Format(PyExc_ValueError,
"Each index must be an 4-bytes integer value");
return NULL;
}
if (pybuffer.itemsize != 4 ||
PyC_StructFmt_type_is_float_any(PyC_StructFmt_type_from_str(pybuffer.format))) {
PyErr_Format(PyExc_ValueError, "Each index must be an 4-bytes integer value");
return NULL;
}
index_len = pybuffer.shape[0];
if (pybuffer.ndim != 1) {
index_len *= pybuffer.shape[1];
}
index_len = pybuffer.shape[0];
if (pybuffer.ndim != 1) {
index_len *= pybuffer.shape[1];
}
/* The `vertex_len` parameter is only used for asserts in the Debug build. */
/* Not very useful in python since scripts are often tested in Release build. */
/* Use `INT_MAX` instead of the actual number of vertices. */
GPU_indexbuf_init(
&builder, params.type_id, index_len, INT_MAX);
/* The `vertex_len` parameter is only used for asserts in the Debug build. */
/* Not very useful in python since scripts are often tested in Release build. */
/* Use `INT_MAX` instead of the actual number of vertices. */
GPU_indexbuf_init(&builder, params.type_id, index_len, INT_MAX);
#if 0
uint *buf = pybuffer.buf;
for (uint i = index_len; i--; buf++) {
GPU_indexbuf_add_generic_vert(&builder, *buf);
}
uint *buf = pybuffer.buf;
for (uint i = index_len; i--; buf++) {
GPU_indexbuf_add_generic_vert(&builder, *buf);
}
#else
memcpy(builder.data, pybuffer.buf, index_len * sizeof(*builder.data));
builder.index_len = index_len;
memcpy(builder.data, pybuffer.buf, index_len * sizeof(*builder.data));
builder.index_len = index_len;
#endif
PyBuffer_Release(&pybuffer);
}
else {
PyObject *seq_fast = PySequence_Fast(params.seq, error_prefix);
PyBuffer_Release(&pybuffer);
}
else {
PyObject *seq_fast = PySequence_Fast(params.seq, error_prefix);
if (seq_fast == NULL) {
return false;
}
if (seq_fast == NULL) {
return false;
}
const uint seq_len = PySequence_Fast_GET_SIZE(seq_fast);
const uint seq_len = PySequence_Fast_GET_SIZE(seq_fast);
PyObject **seq_items = PySequence_Fast_ITEMS(seq_fast);
PyObject **seq_items = PySequence_Fast_ITEMS(seq_fast);
index_len = seq_len * verts_per_prim;
index_len = seq_len * verts_per_prim;
/* The `vertex_len` parameter is only used for asserts in the Debug build. */
/* Not very useful in python since scripts are often tested in Release build. */
/* Use `INT_MAX` instead of the actual number of vertices. */
GPU_indexbuf_init(
&builder, params.type_id, index_len, INT_MAX);
/* The `vertex_len` parameter is only used for asserts in the Debug build. */
/* Not very useful in python since scripts are often tested in Release build. */
/* Use `INT_MAX` instead of the actual number of vertices. */
GPU_indexbuf_init(&builder, params.type_id, index_len, INT_MAX);
if (verts_per_prim == 1) {
for (uint i = 0; i < seq_len; i++) {
GPU_indexbuf_add_generic_vert(
&builder, PyC_Long_AsU32(seq_items[i]));
}
}
else {
int values[4];
for (uint i = 0; i < seq_len; i++) {
PyObject *seq_fast_item = PySequence_Fast(seq_items[i], error_prefix);
if (seq_fast_item == NULL) {
PyErr_Format(PyExc_TypeError,
"%s: expected a sequence, got %s",
error_prefix, Py_TYPE(seq_items[i])->tp_name);
ok = false;
goto finally;
}
if (verts_per_prim == 1) {
for (uint i = 0; i < seq_len; i++) {
GPU_indexbuf_add_generic_vert(&builder, PyC_Long_AsU32(seq_items[i]));
}
}
else {
int values[4];
for (uint i = 0; i < seq_len; i++) {
PyObject *seq_fast_item = PySequence_Fast(seq_items[i], error_prefix);
if (seq_fast_item == NULL) {
PyErr_Format(PyExc_TypeError,
"%s: expected a sequence, got %s",
error_prefix,
Py_TYPE(seq_items[i])->tp_name);
ok = false;
goto finally;
}
ok = PyC_AsArray_FAST(
values, seq_fast_item, verts_per_prim,
&PyLong_Type, false, error_prefix) == 0;
ok = PyC_AsArray_FAST(
values, seq_fast_item, verts_per_prim, &PyLong_Type, false, error_prefix) == 0;
if (ok) {
for (uint j = 0; j < verts_per_prim; j++) {
GPU_indexbuf_add_generic_vert(&builder, values[j]);
}
}
Py_DECREF(seq_fast_item);
}
}
if (ok) {
for (uint j = 0; j < verts_per_prim; j++) {
GPU_indexbuf_add_generic_vert(&builder, values[j]);
}
}
Py_DECREF(seq_fast_item);
}
}
if (PyErr_Occurred()) {
ok = false;
}
if (PyErr_Occurred()) {
ok = false;
}
finally:
finally:
Py_DECREF(seq_fast);
}
Py_DECREF(seq_fast);
}
if (ok == false) {
MEM_freeN(builder.data);
return NULL;
}
if (ok == false) {
MEM_freeN(builder.data);
return NULL;
}
return BPyGPUIndexBuf_CreatePyObject(GPU_indexbuf_build(&builder));
return BPyGPUIndexBuf_CreatePyObject(GPU_indexbuf_build(&builder));
}
static void bpygpu_IndexBuf_dealloc(BPyGPUIndexBuf *self)
{
GPU_indexbuf_discard(self->elem);
Py_TYPE(self)->tp_free(self);
GPU_indexbuf_discard(self->elem);
Py_TYPE(self)->tp_free(self);
}
PyDoc_STRVAR(py_gpu_element_doc,
".. class:: GPUIndexBuf(type, seq)\n"
"\n"
" Contains an index buffer.\n"
"\n"
" :param type: One of these primitive types: {\n"
" `POINTS`,\n"
" `LINES`,\n"
" `TRIS`,\n"
" `LINE_STRIP_ADJ` }\n"
" :type type: `str`\n"
" :param seq: Indices this index buffer will contain.\n"
" Whether a 1D or 2D sequence is required depends on the type.\n"
" Optionally the sequence can support the buffer protocol.\n"
" :type seq: 1D or 2D sequence\n"
);
".. class:: GPUIndexBuf(type, seq)\n"
"\n"
" Contains an index buffer.\n"
"\n"
" :param type: One of these primitive types: {\n"
" `POINTS`,\n"
" `LINES`,\n"
" `TRIS`,\n"
" `LINE_STRIP_ADJ` }\n"
" :type type: `str`\n"
" :param seq: Indices this index buffer will contain.\n"
" Whether a 1D or 2D sequence is required depends on the type.\n"
" Optionally the sequence can support the buffer protocol.\n"
" :type seq: 1D or 2D sequence\n");
PyTypeObject BPyGPUIndexBuf_Type = {
PyVarObject_HEAD_INIT(NULL, 0)
.tp_name = "GPUIndexBuf",
.tp_basicsize = sizeof(BPyGPUIndexBuf),
.tp_dealloc = (destructor)bpygpu_IndexBuf_dealloc,
.tp_flags = Py_TPFLAGS_DEFAULT,
.tp_doc = py_gpu_element_doc,
.tp_new = bpygpu_IndexBuf_new,
PyVarObject_HEAD_INIT(NULL, 0).tp_name = "GPUIndexBuf",
.tp_basicsize = sizeof(BPyGPUIndexBuf),
.tp_dealloc = (destructor)bpygpu_IndexBuf_dealloc,
.tp_flags = Py_TPFLAGS_DEFAULT,
.tp_doc = py_gpu_element_doc,
.tp_new = bpygpu_IndexBuf_new,
};
/** \} */
/* -------------------------------------------------------------------- */
/** \name Public API
* \{ */
PyObject *BPyGPUIndexBuf_CreatePyObject(GPUIndexBuf *elem)
{
BPyGPUIndexBuf *self;
BPyGPUIndexBuf *self;
self = PyObject_New(BPyGPUIndexBuf, &BPyGPUIndexBuf_Type);
self->elem = elem;
self = PyObject_New(BPyGPUIndexBuf, &BPyGPUIndexBuf_Type);
self->elem = elem;
return (PyObject *)self;
return (PyObject *)self;
}
/** \} */

View File

@@ -23,11 +23,10 @@
extern PyTypeObject BPyGPUIndexBuf_Type;
#define BPyGPUIndexBuf_Check(v) (Py_TYPE(v) == &BPyGPUIndexBuf_Type)
#define BPyGPUIndexBuf_Check(v) (Py_TYPE(v) == &BPyGPUIndexBuf_Type)
typedef struct BPyGPUIndexBuf {
PyObject_VAR_HEAD
struct GPUIndexBuf *elem;
PyObject_VAR_HEAD struct GPUIndexBuf *elem;
} BPyGPUIndexBuf;
PyObject *BPyGPUIndexBuf_CreatePyObject(struct GPUIndexBuf *elem);

View File

@@ -28,7 +28,6 @@
#include <Python.h>
#include "BLI_utildefines.h"
#include "../mathutils/mathutils.h"
@@ -47,42 +46,42 @@
static bool bpygpu_stack_is_push_model_view_ok_or_error(void)
{
if (GPU_matrix_stack_level_get_model_view() >= GPU_PY_MATRIX_STACK_LEN) {
PyErr_SetString(PyExc_RuntimeError,
"Maximum model-view stack depth " STRINGIFY(GPU_PY_MATRIX_STACK_DEPTH) " reached");
return false;
}
return true;
if (GPU_matrix_stack_level_get_model_view() >= GPU_PY_MATRIX_STACK_LEN) {
PyErr_SetString(
PyExc_RuntimeError,
"Maximum model-view stack depth " STRINGIFY(GPU_PY_MATRIX_STACK_DEPTH) " reached");
return false;
}
return true;
}
static bool bpygpu_stack_is_push_projection_ok_or_error(void)
{
if (GPU_matrix_stack_level_get_projection() >= GPU_PY_MATRIX_STACK_LEN) {
PyErr_SetString(PyExc_RuntimeError,
"Maximum projection stack depth " STRINGIFY(GPU_PY_MATRIX_STACK_DEPTH) " reached");
return false;
}
return true;
if (GPU_matrix_stack_level_get_projection() >= GPU_PY_MATRIX_STACK_LEN) {
PyErr_SetString(
PyExc_RuntimeError,
"Maximum projection stack depth " STRINGIFY(GPU_PY_MATRIX_STACK_DEPTH) " reached");
return false;
}
return true;
}
static bool bpygpu_stack_is_pop_model_view_ok_or_error(void)
{
if (GPU_matrix_stack_level_get_model_view() == 0) {
PyErr_SetString(PyExc_RuntimeError,
"Minimum model-view stack depth reached");
return false;
}
return true;
if (GPU_matrix_stack_level_get_model_view() == 0) {
PyErr_SetString(PyExc_RuntimeError, "Minimum model-view stack depth reached");
return false;
}
return true;
}
static bool bpygpu_stack_is_pop_projection_ok_or_error(void)
{
if (GPU_matrix_stack_level_get_projection() == 0) {
PyErr_SetString(PyExc_RuntimeError,
"Minimum projection stack depth reached");
return false;
}
return true;
if (GPU_matrix_stack_level_get_projection() == 0) {
PyErr_SetString(PyExc_RuntimeError, "Minimum projection stack depth reached");
return false;
}
return true;
}
/** \} */
@@ -92,59 +91,55 @@ static bool bpygpu_stack_is_pop_projection_ok_or_error(void)
* \{ */
PyDoc_STRVAR(bpygpu_matrix_push_doc,
".. function:: push()\n"
"\n"
" Add to the model-view matrix stack.\n"
);
".. function:: push()\n"
"\n"
" Add to the model-view matrix stack.\n");
static PyObject *bpygpu_matrix_push(PyObject *UNUSED(self))
{
if (!bpygpu_stack_is_push_model_view_ok_or_error()) {
return NULL;
}
GPU_matrix_push();
Py_RETURN_NONE;
if (!bpygpu_stack_is_push_model_view_ok_or_error()) {
return NULL;
}
GPU_matrix_push();
Py_RETURN_NONE;
}
PyDoc_STRVAR(bpygpu_matrix_pop_doc,
".. function:: pop()\n"
"\n"
" Remove the last model-view matrix from the stack.\n"
);
".. function:: pop()\n"
"\n"
" Remove the last model-view matrix from the stack.\n");
static PyObject *bpygpu_matrix_pop(PyObject *UNUSED(self))
{
if (!bpygpu_stack_is_pop_model_view_ok_or_error()) {
return NULL;
}
GPU_matrix_pop();
Py_RETURN_NONE;
if (!bpygpu_stack_is_pop_model_view_ok_or_error()) {
return NULL;
}
GPU_matrix_pop();
Py_RETURN_NONE;
}
PyDoc_STRVAR(bpygpu_matrix_push_projection_doc,
".. function:: push_projection()\n"
"\n"
" Add to the projection matrix stack.\n"
);
".. function:: push_projection()\n"
"\n"
" Add to the projection matrix stack.\n");
static PyObject *bpygpu_matrix_push_projection(PyObject *UNUSED(self))
{
if (!bpygpu_stack_is_push_projection_ok_or_error()) {
return NULL;
}
GPU_matrix_push_projection();
Py_RETURN_NONE;
if (!bpygpu_stack_is_push_projection_ok_or_error()) {
return NULL;
}
GPU_matrix_push_projection();
Py_RETURN_NONE;
}
PyDoc_STRVAR(bpygpu_matrix_pop_projection_doc,
".. function:: pop_projection()\n"
"\n"
" Remove the last projection matrix from the stack.\n"
);
".. function:: pop_projection()\n"
"\n"
" Remove the last projection matrix from the stack.\n");
static PyObject *bpygpu_matrix_pop_projection(PyObject *UNUSED(self))
{
if (!bpygpu_stack_is_pop_projection_ok_or_error()) {
return NULL;
}
GPU_matrix_pop_projection();
Py_RETURN_NONE;
if (!bpygpu_stack_is_pop_projection_ok_or_error()) {
return NULL;
}
GPU_matrix_pop_projection();
Py_RETURN_NONE;
}
/** \} */
@@ -157,120 +152,121 @@ static PyObject *bpygpu_matrix_pop_projection(PyObject *UNUSED(self))
* \{ */
typedef struct {
PyObject_HEAD /* required python macro */
int type;
int level;
PyObject_HEAD /* required python macro */
int type;
int level;
} BPyGPU_MatrixStackContext;
enum {
PYGPU_MATRIX_TYPE_MODEL_VIEW = 1,
PYGPU_MATRIX_TYPE_PROJECTION = 2,
PYGPU_MATRIX_TYPE_MODEL_VIEW = 1,
PYGPU_MATRIX_TYPE_PROJECTION = 2,
};
static PyObject *bpygpu_matrix_stack_context_enter(BPyGPU_MatrixStackContext *self);
static PyObject *bpygpu_matrix_stack_context_exit(BPyGPU_MatrixStackContext *self, PyObject *args);
static PyMethodDef bpygpu_matrix_stack_context_methods[] = {
{"__enter__", (PyCFunction)bpygpu_matrix_stack_context_enter, METH_NOARGS},
{"__exit__", (PyCFunction)bpygpu_matrix_stack_context_exit, METH_VARARGS},
{NULL},
{"__enter__", (PyCFunction)bpygpu_matrix_stack_context_enter, METH_NOARGS},
{"__exit__", (PyCFunction)bpygpu_matrix_stack_context_exit, METH_VARARGS},
{NULL},
};
static PyTypeObject BPyGPU_matrix_stack_context_Type = {
PyVarObject_HEAD_INIT(NULL, 0)
.tp_name = "GPUMatrixStackContext",
.tp_basicsize = sizeof(BPyGPU_MatrixStackContext),
.tp_flags = Py_TPFLAGS_DEFAULT,
.tp_methods = bpygpu_matrix_stack_context_methods,
PyVarObject_HEAD_INIT(NULL, 0).tp_name = "GPUMatrixStackContext",
.tp_basicsize = sizeof(BPyGPU_MatrixStackContext),
.tp_flags = Py_TPFLAGS_DEFAULT,
.tp_methods = bpygpu_matrix_stack_context_methods,
};
static PyObject *bpygpu_matrix_stack_context_enter(BPyGPU_MatrixStackContext *self)
{
/* sanity - should never happen */
if (self->level != -1) {
PyErr_SetString(PyExc_RuntimeError, "Already in use");
return NULL;
}
/* sanity - should never happen */
if (self->level != -1) {
PyErr_SetString(PyExc_RuntimeError, "Already in use");
return NULL;
}
if (self->type == PYGPU_MATRIX_TYPE_MODEL_VIEW) {
if (!bpygpu_stack_is_push_model_view_ok_or_error()) {
return NULL;
}
GPU_matrix_push();
self->level = GPU_matrix_stack_level_get_model_view();
}
else if (self->type == PYGPU_MATRIX_TYPE_PROJECTION) {
if (!bpygpu_stack_is_push_projection_ok_or_error()) {
return NULL;
}
GPU_matrix_push_projection();
self->level = GPU_matrix_stack_level_get_projection();
}
else {
BLI_assert(0);
}
Py_RETURN_NONE;
if (self->type == PYGPU_MATRIX_TYPE_MODEL_VIEW) {
if (!bpygpu_stack_is_push_model_view_ok_or_error()) {
return NULL;
}
GPU_matrix_push();
self->level = GPU_matrix_stack_level_get_model_view();
}
else if (self->type == PYGPU_MATRIX_TYPE_PROJECTION) {
if (!bpygpu_stack_is_push_projection_ok_or_error()) {
return NULL;
}
GPU_matrix_push_projection();
self->level = GPU_matrix_stack_level_get_projection();
}
else {
BLI_assert(0);
}
Py_RETURN_NONE;
}
static PyObject *bpygpu_matrix_stack_context_exit(BPyGPU_MatrixStackContext *self, PyObject *UNUSED(args))
static PyObject *bpygpu_matrix_stack_context_exit(BPyGPU_MatrixStackContext *self,
PyObject *UNUSED(args))
{
/* sanity - should never happen */
if (self->level == -1) {
fprintf(stderr, "Not yet in use\n");
goto finally;
}
/* sanity - should never happen */
if (self->level == -1) {
fprintf(stderr, "Not yet in use\n");
goto finally;
}
if (self->type == PYGPU_MATRIX_TYPE_MODEL_VIEW) {
const int level = GPU_matrix_stack_level_get_model_view();
if (level != self->level) {
fprintf(stderr, "Level push/pop mismatch, expected %d, got %d\n", self->level, level);
}
if (level != 0) {
GPU_matrix_pop();
}
}
else if (self->type == PYGPU_MATRIX_TYPE_PROJECTION) {
const int level = GPU_matrix_stack_level_get_projection();
if (level != self->level) {
fprintf(stderr, "Level push/pop mismatch, expected %d, got %d", self->level, level);
}
if (level != 0) {
GPU_matrix_pop_projection();
}
}
else {
BLI_assert(0);
}
if (self->type == PYGPU_MATRIX_TYPE_MODEL_VIEW) {
const int level = GPU_matrix_stack_level_get_model_view();
if (level != self->level) {
fprintf(stderr, "Level push/pop mismatch, expected %d, got %d\n", self->level, level);
}
if (level != 0) {
GPU_matrix_pop();
}
}
else if (self->type == PYGPU_MATRIX_TYPE_PROJECTION) {
const int level = GPU_matrix_stack_level_get_projection();
if (level != self->level) {
fprintf(stderr, "Level push/pop mismatch, expected %d, got %d", self->level, level);
}
if (level != 0) {
GPU_matrix_pop_projection();
}
}
else {
BLI_assert(0);
}
finally:
Py_RETURN_NONE;
Py_RETURN_NONE;
}
static PyObject *bpygpu_matrix_push_pop_impl(int type)
{
BPyGPU_MatrixStackContext *ret = PyObject_New(BPyGPU_MatrixStackContext, &BPyGPU_matrix_stack_context_Type);
ret->type = type;
ret->level = -1;
return (PyObject *)ret;
BPyGPU_MatrixStackContext *ret = PyObject_New(BPyGPU_MatrixStackContext,
&BPyGPU_matrix_stack_context_Type);
ret->type = type;
ret->level = -1;
return (PyObject *)ret;
}
PyDoc_STRVAR(bpygpu_matrix_push_pop_doc,
".. function:: push_pop()\n"
"\n"
" Context manager to ensure balanced push/pop calls, even in the case of an error.\n"
);
PyDoc_STRVAR(
bpygpu_matrix_push_pop_doc,
".. function:: push_pop()\n"
"\n"
" Context manager to ensure balanced push/pop calls, even in the case of an error.\n");
static PyObject *bpygpu_matrix_push_pop(PyObject *UNUSED(self))
{
return bpygpu_matrix_push_pop_impl(PYGPU_MATRIX_TYPE_MODEL_VIEW);
return bpygpu_matrix_push_pop_impl(PYGPU_MATRIX_TYPE_MODEL_VIEW);
}
PyDoc_STRVAR(bpygpu_matrix_push_pop_projection_doc,
".. function:: push_pop_projection()\n"
"\n"
" Context manager to ensure balanced push/pop calls, even in the case of an error.\n"
);
PyDoc_STRVAR(
bpygpu_matrix_push_pop_projection_doc,
".. function:: push_pop_projection()\n"
"\n"
" Context manager to ensure balanced push/pop calls, even in the case of an error.\n");
static PyObject *bpygpu_matrix_push_pop_projection(PyObject *UNUSED(self))
{
return bpygpu_matrix_push_pop_impl(PYGPU_MATRIX_TYPE_PROJECTION);
return bpygpu_matrix_push_pop_impl(PYGPU_MATRIX_TYPE_PROJECTION);
}
/** \} */
@@ -280,88 +276,84 @@ static PyObject *bpygpu_matrix_push_pop_projection(PyObject *UNUSED(self))
* \{ */
PyDoc_STRVAR(bpygpu_matrix_multiply_matrix_doc,
".. function:: multiply_matrix(matrix)\n"
"\n"
" Multiply the current stack matrix.\n"
"\n"
" :param matrix: A 4x4 matrix.\n"
" :type matrix: :class:`mathutils.Matrix`\n"
);
".. function:: multiply_matrix(matrix)\n"
"\n"
" Multiply the current stack matrix.\n"
"\n"
" :param matrix: A 4x4 matrix.\n"
" :type matrix: :class:`mathutils.Matrix`\n");
static PyObject *bpygpu_matrix_multiply_matrix(PyObject *UNUSED(self), PyObject *value)
{
MatrixObject *pymat;
if (!Matrix_Parse4x4(value, &pymat)) {
return NULL;
}
GPU_matrix_mul(pymat->matrix);
Py_RETURN_NONE;
MatrixObject *pymat;
if (!Matrix_Parse4x4(value, &pymat)) {
return NULL;
}
GPU_matrix_mul(pymat->matrix);
Py_RETURN_NONE;
}
PyDoc_STRVAR(bpygpu_matrix_scale_doc,
".. function:: scale(scale)\n"
"\n"
" Scale the current stack matrix.\n"
"\n"
" :param scale: Scale the current stack matrix.\n"
" :type scale: sequence of 2 or 3 floats\n"
);
".. function:: scale(scale)\n"
"\n"
" Scale the current stack matrix.\n"
"\n"
" :param scale: Scale the current stack matrix.\n"
" :type scale: sequence of 2 or 3 floats\n");
static PyObject *bpygpu_matrix_scale(PyObject *UNUSED(self), PyObject *value)
{
float scale[3];
int len;
if ((len = mathutils_array_parse(scale, 2, 3, value, "gpu.matrix.scale(): invalid vector arg")) == -1) {
return NULL;
}
if (len == 2) {
GPU_matrix_scale_2fv(scale);
}
else {
GPU_matrix_scale_3fv(scale);
}
Py_RETURN_NONE;
float scale[3];
int len;
if ((len = mathutils_array_parse(
scale, 2, 3, value, "gpu.matrix.scale(): invalid vector arg")) == -1) {
return NULL;
}
if (len == 2) {
GPU_matrix_scale_2fv(scale);
}
else {
GPU_matrix_scale_3fv(scale);
}
Py_RETURN_NONE;
}
PyDoc_STRVAR(bpygpu_matrix_scale_uniform_doc,
".. function:: scale_uniform(scale)\n"
"\n"
" :param scale: Scale the current stack matrix.\n"
" :type scale: float\n"
);
".. function:: scale_uniform(scale)\n"
"\n"
" :param scale: Scale the current stack matrix.\n"
" :type scale: float\n");
static PyObject *bpygpu_matrix_scale_uniform(PyObject *UNUSED(self), PyObject *value)
{
float scalar;
if ((scalar = PyFloat_AsDouble(value)) == -1.0f && PyErr_Occurred()) {
PyErr_Format(PyExc_TypeError,
"expected a number, not %.200s",
Py_TYPE(value)->tp_name);
return NULL;
}
GPU_matrix_scale_1f(scalar);
Py_RETURN_NONE;
float scalar;
if ((scalar = PyFloat_AsDouble(value)) == -1.0f && PyErr_Occurred()) {
PyErr_Format(PyExc_TypeError, "expected a number, not %.200s", Py_TYPE(value)->tp_name);
return NULL;
}
GPU_matrix_scale_1f(scalar);
Py_RETURN_NONE;
}
PyDoc_STRVAR(bpygpu_matrix_translate_doc,
".. function:: translate(offset)\n"
"\n"
" Scale the current stack matrix.\n"
"\n"
" :param offset: Translate the current stack matrix.\n"
" :type offset: sequence of 2 or 3 floats\n"
);
".. function:: translate(offset)\n"
"\n"
" Scale the current stack matrix.\n"
"\n"
" :param offset: Translate the current stack matrix.\n"
" :type offset: sequence of 2 or 3 floats\n");
static PyObject *bpygpu_matrix_translate(PyObject *UNUSED(self), PyObject *value)
{
float offset[3];
int len;
if ((len = mathutils_array_parse(offset, 2, 3, value, "gpu.matrix.translate(): invalid vector arg")) == -1) {
return NULL;
}
if (len == 2) {
GPU_matrix_translate_2fv(offset);
}
else {
GPU_matrix_translate_3fv(offset);
}
Py_RETURN_NONE;
float offset[3];
int len;
if ((len = mathutils_array_parse(
offset, 2, 3, value, "gpu.matrix.translate(): invalid vector arg")) == -1) {
return NULL;
}
if (len == 2) {
GPU_matrix_translate_2fv(offset);
}
else {
GPU_matrix_translate_3fv(offset);
}
Py_RETURN_NONE;
}
/** \} */
@@ -371,61 +363,57 @@ static PyObject *bpygpu_matrix_translate(PyObject *UNUSED(self), PyObject *value
* \{ */
PyDoc_STRVAR(bpygpu_matrix_reset_doc,
".. function:: reset()\n"
"\n"
" Empty stack and set to identity.\n"
);
".. function:: reset()\n"
"\n"
" Empty stack and set to identity.\n");
static PyObject *bpygpu_matrix_reset(PyObject *UNUSED(self))
{
GPU_matrix_reset();
Py_RETURN_NONE;
GPU_matrix_reset();
Py_RETURN_NONE;
}
PyDoc_STRVAR(bpygpu_matrix_load_identity_doc,
".. function:: load_identity()\n"
"\n"
" Empty stack and set to identity.\n"
);
".. function:: load_identity()\n"
"\n"
" Empty stack and set to identity.\n");
static PyObject *bpygpu_matrix_load_identity(PyObject *UNUSED(self))
{
GPU_matrix_identity_set();
Py_RETURN_NONE;
GPU_matrix_identity_set();
Py_RETURN_NONE;
}
PyDoc_STRVAR(bpygpu_matrix_load_matrix_doc,
".. function:: load_matrix(matrix)\n"
"\n"
" Load a matrix into the stack.\n"
"\n"
" :param matrix: A 4x4 matrix.\n"
" :type matrix: :class:`mathutils.Matrix`\n"
);
".. function:: load_matrix(matrix)\n"
"\n"
" Load a matrix into the stack.\n"
"\n"
" :param matrix: A 4x4 matrix.\n"
" :type matrix: :class:`mathutils.Matrix`\n");
static PyObject *bpygpu_matrix_load_matrix(PyObject *UNUSED(self), PyObject *value)
{
MatrixObject *pymat;
if (!Matrix_Parse4x4(value, &pymat)) {
return NULL;
}
GPU_matrix_set(pymat->matrix);
Py_RETURN_NONE;
MatrixObject *pymat;
if (!Matrix_Parse4x4(value, &pymat)) {
return NULL;
}
GPU_matrix_set(pymat->matrix);
Py_RETURN_NONE;
}
PyDoc_STRVAR(bpygpu_matrix_load_projection_matrix_doc,
".. function:: load_projection_matrix(matrix)\n"
"\n"
" Load a projection matrix into the stack.\n"
"\n"
" :param matrix: A 4x4 matrix.\n"
" :type matrix: :class:`mathutils.Matrix`\n"
);
".. function:: load_projection_matrix(matrix)\n"
"\n"
" Load a projection matrix into the stack.\n"
"\n"
" :param matrix: A 4x4 matrix.\n"
" :type matrix: :class:`mathutils.Matrix`\n");
static PyObject *bpygpu_matrix_load_projection_matrix(PyObject *UNUSED(self), PyObject *value)
{
MatrixObject *pymat;
if (!Matrix_Parse4x4(value, &pymat)) {
return NULL;
}
GPU_matrix_projection_set(pymat->matrix);
Py_RETURN_NONE;
MatrixObject *pymat;
if (!Matrix_Parse4x4(value, &pymat)) {
return NULL;
}
GPU_matrix_projection_set(pymat->matrix);
Py_RETURN_NONE;
}
/** \} */
@@ -435,49 +423,45 @@ static PyObject *bpygpu_matrix_load_projection_matrix(PyObject *UNUSED(self), Py
* \{ */
PyDoc_STRVAR(bpygpu_matrix_get_projection_matrix_doc,
".. function:: get_projection_matrix()\n"
"\n"
" Return a copy of the projection matrix.\n"
"\n"
" :return: A 4x4 projection matrix.\n"
" :rtype: :class:`mathutils.Matrix`\n"
);
".. function:: get_projection_matrix()\n"
"\n"
" Return a copy of the projection matrix.\n"
"\n"
" :return: A 4x4 projection matrix.\n"
" :rtype: :class:`mathutils.Matrix`\n");
static PyObject *bpygpu_matrix_get_projection_matrix(PyObject *UNUSED(self))
{
float matrix[4][4];
GPU_matrix_projection_get(matrix);
return Matrix_CreatePyObject(&matrix[0][0], 4, 4, NULL);
float matrix[4][4];
GPU_matrix_projection_get(matrix);
return Matrix_CreatePyObject(&matrix[0][0], 4, 4, NULL);
}
PyDoc_STRVAR(bpygpu_matrix_get_model_view_matrix_doc,
".. function:: get_model_view_matrix()\n"
"\n"
" Return a copy of the model-view matrix.\n"
"\n"
" :return: A 4x4 view matrix.\n"
" :rtype: :class:`mathutils.Matrix`\n"
);
".. function:: get_model_view_matrix()\n"
"\n"
" Return a copy of the model-view matrix.\n"
"\n"
" :return: A 4x4 view matrix.\n"
" :rtype: :class:`mathutils.Matrix`\n");
static PyObject *bpygpu_matrix_get_model_view_matrix(PyObject *UNUSED(self))
{
float matrix[4][4];
GPU_matrix_model_view_get(matrix);
return Matrix_CreatePyObject(&matrix[0][0], 4, 4, NULL);
float matrix[4][4];
GPU_matrix_model_view_get(matrix);
return Matrix_CreatePyObject(&matrix[0][0], 4, 4, NULL);
}
PyDoc_STRVAR(bpygpu_matrix_get_normal_matrix_doc,
".. function:: get_normal_matrix()\n"
"\n"
" Return a copy of the normal matrix.\n"
"\n"
" :return: A 3x3 normal matrix.\n"
" :rtype: :class:`mathutils.Matrix`\n"
);
".. function:: get_normal_matrix()\n"
"\n"
" Return a copy of the normal matrix.\n"
"\n"
" :return: A 3x3 normal matrix.\n"
" :rtype: :class:`mathutils.Matrix`\n");
static PyObject *bpygpu_matrix_get_normal_matrix(PyObject *UNUSED(self))
{
float matrix[3][3];
GPU_matrix_normal_get(matrix);
return Matrix_CreatePyObject(&matrix[0][0], 3, 3, NULL);
float matrix[3][3];
GPU_matrix_normal_get(matrix);
return Matrix_CreatePyObject(&matrix[0][0], 3, 3, NULL);
}
/** \} */
@@ -487,85 +471,96 @@ static PyObject *bpygpu_matrix_get_normal_matrix(PyObject *UNUSED(self))
* \{ */
static struct PyMethodDef bpygpu_matrix_methods[] = {
/* Manage Stack */
{"push", (PyCFunction)bpygpu_matrix_push,
METH_NOARGS, bpygpu_matrix_push_doc},
{"pop", (PyCFunction)bpygpu_matrix_pop,
METH_NOARGS, bpygpu_matrix_pop_doc},
/* Manage Stack */
{"push", (PyCFunction)bpygpu_matrix_push, METH_NOARGS, bpygpu_matrix_push_doc},
{"pop", (PyCFunction)bpygpu_matrix_pop, METH_NOARGS, bpygpu_matrix_pop_doc},
{"push_projection", (PyCFunction)bpygpu_matrix_push_projection,
METH_NOARGS, bpygpu_matrix_push_projection_doc},
{"pop_projection", (PyCFunction)bpygpu_matrix_pop_projection,
METH_NOARGS, bpygpu_matrix_pop_projection_doc},
{"push_projection",
(PyCFunction)bpygpu_matrix_push_projection,
METH_NOARGS,
bpygpu_matrix_push_projection_doc},
{"pop_projection",
(PyCFunction)bpygpu_matrix_pop_projection,
METH_NOARGS,
bpygpu_matrix_pop_projection_doc},
/* Stack (Context Manager) */
{"push_pop", (PyCFunction)bpygpu_matrix_push_pop,
METH_NOARGS, bpygpu_matrix_push_pop_doc},
{"push_pop_projection", (PyCFunction)bpygpu_matrix_push_pop_projection,
METH_NOARGS, bpygpu_matrix_push_pop_projection_doc},
/* Stack (Context Manager) */
{"push_pop", (PyCFunction)bpygpu_matrix_push_pop, METH_NOARGS, bpygpu_matrix_push_pop_doc},
{"push_pop_projection",
(PyCFunction)bpygpu_matrix_push_pop_projection,
METH_NOARGS,
bpygpu_matrix_push_pop_projection_doc},
/* Manipulate State */
{"multiply_matrix", (PyCFunction)bpygpu_matrix_multiply_matrix,
METH_O, bpygpu_matrix_multiply_matrix_doc},
{"scale", (PyCFunction)bpygpu_matrix_scale,
METH_O, bpygpu_matrix_scale_doc},
{"scale_uniform", (PyCFunction)bpygpu_matrix_scale_uniform,
METH_O, bpygpu_matrix_scale_uniform_doc},
{"translate", (PyCFunction)bpygpu_matrix_translate,
METH_O, bpygpu_matrix_translate_doc},
/* Manipulate State */
{"multiply_matrix",
(PyCFunction)bpygpu_matrix_multiply_matrix,
METH_O,
bpygpu_matrix_multiply_matrix_doc},
{"scale", (PyCFunction)bpygpu_matrix_scale, METH_O, bpygpu_matrix_scale_doc},
{"scale_uniform",
(PyCFunction)bpygpu_matrix_scale_uniform,
METH_O,
bpygpu_matrix_scale_uniform_doc},
{"translate", (PyCFunction)bpygpu_matrix_translate, METH_O, bpygpu_matrix_translate_doc},
/* TODO */
/* TODO */
#if 0
{"rotate", (PyCFunction)bpygpu_matrix_rotate,
METH_O, bpygpu_matrix_rotate_doc},
{"rotate_axis", (PyCFunction)bpygpu_matrix_rotate_axis,
METH_O, bpygpu_matrix_rotate_axis_doc},
{"look_at", (PyCFunction)bpygpu_matrix_look_at,
METH_O, bpygpu_matrix_look_at_doc},
{"rotate", (PyCFunction)bpygpu_matrix_rotate,
METH_O, bpygpu_matrix_rotate_doc},
{"rotate_axis", (PyCFunction)bpygpu_matrix_rotate_axis,
METH_O, bpygpu_matrix_rotate_axis_doc},
{"look_at", (PyCFunction)bpygpu_matrix_look_at,
METH_O, bpygpu_matrix_look_at_doc},
#endif
/* Write State */
{"reset", (PyCFunction)bpygpu_matrix_reset,
METH_NOARGS, bpygpu_matrix_reset_doc},
{"load_identity", (PyCFunction)bpygpu_matrix_load_identity,
METH_NOARGS, bpygpu_matrix_load_identity_doc},
{"load_matrix", (PyCFunction)bpygpu_matrix_load_matrix,
METH_O, bpygpu_matrix_load_matrix_doc},
{"load_projection_matrix", (PyCFunction)bpygpu_matrix_load_projection_matrix,
METH_O, bpygpu_matrix_load_projection_matrix_doc},
/* Write State */
{"reset", (PyCFunction)bpygpu_matrix_reset, METH_NOARGS, bpygpu_matrix_reset_doc},
{"load_identity",
(PyCFunction)bpygpu_matrix_load_identity,
METH_NOARGS,
bpygpu_matrix_load_identity_doc},
{"load_matrix", (PyCFunction)bpygpu_matrix_load_matrix, METH_O, bpygpu_matrix_load_matrix_doc},
{"load_projection_matrix",
(PyCFunction)bpygpu_matrix_load_projection_matrix,
METH_O,
bpygpu_matrix_load_projection_matrix_doc},
/* Read State */
{"get_projection_matrix", (PyCFunction)bpygpu_matrix_get_projection_matrix,
METH_NOARGS, bpygpu_matrix_get_projection_matrix_doc},
{"get_model_view_matrix", (PyCFunction)bpygpu_matrix_get_model_view_matrix,
METH_NOARGS, bpygpu_matrix_get_model_view_matrix_doc},
{"get_normal_matrix", (PyCFunction)bpygpu_matrix_get_normal_matrix,
METH_NOARGS, bpygpu_matrix_get_normal_matrix_doc},
/* Read State */
{"get_projection_matrix",
(PyCFunction)bpygpu_matrix_get_projection_matrix,
METH_NOARGS,
bpygpu_matrix_get_projection_matrix_doc},
{"get_model_view_matrix",
(PyCFunction)bpygpu_matrix_get_model_view_matrix,
METH_NOARGS,
bpygpu_matrix_get_model_view_matrix_doc},
{"get_normal_matrix",
(PyCFunction)bpygpu_matrix_get_normal_matrix,
METH_NOARGS,
bpygpu_matrix_get_normal_matrix_doc},
{NULL, NULL, 0, NULL},
{NULL, NULL, 0, NULL},
};
PyDoc_STRVAR(bpygpu_matrix_doc,
"This module provides access to the matrix stack."
);
PyDoc_STRVAR(bpygpu_matrix_doc, "This module provides access to the matrix stack.");
static PyModuleDef BPyGPU_matrix_module_def = {
PyModuleDef_HEAD_INIT,
.m_name = "gpu.matrix",
.m_doc = bpygpu_matrix_doc,
.m_methods = bpygpu_matrix_methods,
PyModuleDef_HEAD_INIT,
.m_name = "gpu.matrix",
.m_doc = bpygpu_matrix_doc,
.m_methods = bpygpu_matrix_methods,
};
PyObject *BPyInit_gpu_matrix(void)
{
PyObject *submodule;
PyObject *submodule;
submodule = PyModule_Create(&BPyGPU_matrix_module_def);
submodule = PyModule_Create(&BPyGPU_matrix_module_def);
if (PyType_Ready(&BPyGPU_matrix_stack_context_Type) < 0) {
return NULL;
}
if (PyType_Ready(&BPyGPU_matrix_stack_context_Type) < 0) {
return NULL;
}
return submodule;
return submodule;
}
/** \} */

View File

@@ -23,4 +23,4 @@
PyObject *BPyInit_gpu_matrix(void);
#endif /* __GPU_PY_MATRIX_H__ */
#endif /* __GPU_PY_MATRIX_H__ */

View File

@@ -51,316 +51,331 @@
#include "gpu_py_api.h"
#include "gpu_py_offscreen.h" /* own include */
/* -------------------------------------------------------------------- */
/** \name GPUOffScreen Common Utilities
* \{ */
static int bpygpu_offscreen_valid_check(BPyGPUOffScreen *bpygpu_ofs)
{
if (UNLIKELY(bpygpu_ofs->ofs == NULL)) {
PyErr_SetString(PyExc_ReferenceError, "GPU offscreen was freed, no further access is valid");
return -1;
}
return 0;
if (UNLIKELY(bpygpu_ofs->ofs == NULL)) {
PyErr_SetString(PyExc_ReferenceError, "GPU offscreen was freed, no further access is valid");
return -1;
}
return 0;
}
#define BPY_GPU_OFFSCREEN_CHECK_OBJ(bpygpu) { \
if (UNLIKELY(bpygpu_offscreen_valid_check(bpygpu) == -1)) { \
return NULL; \
} \
} ((void)0)
#define BPY_GPU_OFFSCREEN_CHECK_OBJ(bpygpu) \
{ \
if (UNLIKELY(bpygpu_offscreen_valid_check(bpygpu) == -1)) { \
return NULL; \
} \
} \
((void)0)
/** \} */
/* -------------------------------------------------------------------- */
/** \name GPUOffscreen Type
* \{ */
static PyObject *bpygpu_offscreen_new(PyTypeObject *UNUSED(self), PyObject *args, PyObject *kwds)
{
BPYGPU_IS_INIT_OR_ERROR_OBJ;
BPYGPU_IS_INIT_OR_ERROR_OBJ;
GPUOffScreen *ofs;
int width, height, samples = 0;
char err_out[256];
GPUOffScreen *ofs;
int width, height, samples = 0;
char err_out[256];
static const char *_keywords[] = {"width", "height", "samples", NULL};
static _PyArg_Parser _parser = {"ii|i:GPUOffScreen.__new__", _keywords, 0};
if (!_PyArg_ParseTupleAndKeywordsFast(
args, kwds, &_parser,
&width, &height, &samples))
{
return NULL;
}
static const char *_keywords[] = {"width", "height", "samples", NULL};
static _PyArg_Parser _parser = {"ii|i:GPUOffScreen.__new__", _keywords, 0};
if (!_PyArg_ParseTupleAndKeywordsFast(args, kwds, &_parser, &width, &height, &samples)) {
return NULL;
}
ofs = GPU_offscreen_create(width, height, samples, true, false, err_out);
ofs = GPU_offscreen_create(width, height, samples, true, false, err_out);
if (ofs == NULL) {
PyErr_Format(PyExc_RuntimeError,
"gpu.offscreen.new(...) failed with '%s'",
err_out[0] ? err_out : "unknown error");
return NULL;
}
if (ofs == NULL) {
PyErr_Format(PyExc_RuntimeError,
"gpu.offscreen.new(...) failed with '%s'",
err_out[0] ? err_out : "unknown error");
return NULL;
}
return BPyGPUOffScreen_CreatePyObject(ofs);
return BPyGPUOffScreen_CreatePyObject(ofs);
}
PyDoc_STRVAR(bpygpu_offscreen_width_doc, "Width of the texture.\n\n:type: `int`");
static PyObject *bpygpu_offscreen_width_get(BPyGPUOffScreen *self, void *UNUSED(type))
{
BPY_GPU_OFFSCREEN_CHECK_OBJ(self);
return PyLong_FromLong(GPU_offscreen_width(self->ofs));
BPY_GPU_OFFSCREEN_CHECK_OBJ(self);
return PyLong_FromLong(GPU_offscreen_width(self->ofs));
}
PyDoc_STRVAR(bpygpu_offscreen_height_doc, "Height of the texture.\n\n:type: `int`");
static PyObject *bpygpu_offscreen_height_get(BPyGPUOffScreen *self, void *UNUSED(type))
{
BPY_GPU_OFFSCREEN_CHECK_OBJ(self);
return PyLong_FromLong(GPU_offscreen_height(self->ofs));
BPY_GPU_OFFSCREEN_CHECK_OBJ(self);
return PyLong_FromLong(GPU_offscreen_height(self->ofs));
}
PyDoc_STRVAR(bpygpu_offscreen_color_texture_doc, "OpenGL bindcode for the color texture.\n\n:type: `int`");
PyDoc_STRVAR(bpygpu_offscreen_color_texture_doc,
"OpenGL bindcode for the color texture.\n\n:type: `int`");
static PyObject *bpygpu_offscreen_color_texture_get(BPyGPUOffScreen *self, void *UNUSED(type))
{
BPY_GPU_OFFSCREEN_CHECK_OBJ(self);
GPUTexture *texture = GPU_offscreen_color_texture(self->ofs);
return PyLong_FromLong(GPU_texture_opengl_bindcode(texture));
BPY_GPU_OFFSCREEN_CHECK_OBJ(self);
GPUTexture *texture = GPU_offscreen_color_texture(self->ofs);
return PyLong_FromLong(GPU_texture_opengl_bindcode(texture));
}
PyDoc_STRVAR(bpygpu_offscreen_bind_doc,
".. method:: bind(save=True)\n"
"\n"
" Bind the offscreen object.\n"
" To make sure that the offscreen gets unbind whether an exception occurs or not, pack it into a `with` statement.\n"
"\n"
" :arg save: Save the current OpenGL state, so that it can be restored when unbinding.\n"
" :type save: `bool`\n"
);
PyDoc_STRVAR(
bpygpu_offscreen_bind_doc,
".. method:: bind(save=True)\n"
"\n"
" Bind the offscreen object.\n"
" To make sure that the offscreen gets unbind whether an exception occurs or not, pack it "
"into a `with` statement.\n"
"\n"
" :arg save: Save the current OpenGL state, so that it can be restored when unbinding.\n"
" :type save: `bool`\n");
static PyObject *bpygpu_offscreen_bind(BPyGPUOffScreen *self, PyObject *args, PyObject *kwds)
{
BPY_GPU_OFFSCREEN_CHECK_OBJ(self);
bool save = true;
BPY_GPU_OFFSCREEN_CHECK_OBJ(self);
bool save = true;
static const char *_keywords[] = {"save", NULL};
static _PyArg_Parser _parser = {"|O&:bind", _keywords, 0};
if (!_PyArg_ParseTupleAndKeywordsFast(
args, kwds, &_parser,
PyC_ParseBool, &save))
{
return NULL;
}
static const char *_keywords[] = {"save", NULL};
static _PyArg_Parser _parser = {"|O&:bind", _keywords, 0};
if (!_PyArg_ParseTupleAndKeywordsFast(args, kwds, &_parser, PyC_ParseBool, &save)) {
return NULL;
}
GPU_offscreen_bind(self->ofs, save);
GPU_offscreen_bind(self->ofs, save);
self->is_saved = save;
Py_INCREF(self);
self->is_saved = save;
Py_INCREF(self);
return (PyObject *)self;
return (PyObject *)self;
}
PyDoc_STRVAR(bpygpu_offscreen_unbind_doc,
".. method:: unbind(restore=True)\n"
"\n"
" Unbind the offscreen object.\n"
"\n"
" :arg restore: Restore the OpenGL state, can only be used when the state has been saved before.\n"
" :type restore: `bool`\n"
);
".. method:: unbind(restore=True)\n"
"\n"
" Unbind the offscreen object.\n"
"\n"
" :arg restore: Restore the OpenGL state, can only be used when the state has been "
"saved before.\n"
" :type restore: `bool`\n");
static PyObject *bpygpu_offscreen_unbind(BPyGPUOffScreen *self, PyObject *args, PyObject *kwds)
{
bool restore = true;
bool restore = true;
BPY_GPU_OFFSCREEN_CHECK_OBJ(self);
BPY_GPU_OFFSCREEN_CHECK_OBJ(self);
static const char *_keywords[] = {"restore", NULL};
static _PyArg_Parser _parser = {"|O&:unbind", _keywords, 0};
if (!_PyArg_ParseTupleAndKeywordsFast(
args, kwds, &_parser,
PyC_ParseBool, &restore))
{
return NULL;
}
static const char *_keywords[] = {"restore", NULL};
static _PyArg_Parser _parser = {"|O&:unbind", _keywords, 0};
if (!_PyArg_ParseTupleAndKeywordsFast(args, kwds, &_parser, PyC_ParseBool, &restore)) {
return NULL;
}
GPU_offscreen_unbind(self->ofs, restore);
Py_RETURN_NONE;
GPU_offscreen_unbind(self->ofs, restore);
Py_RETURN_NONE;
}
PyDoc_STRVAR(bpygpu_offscreen_draw_view3d_doc,
".. method:: draw_view3d(scene, view3d, region, view_matrix, projection_matrix)\n"
"\n"
" Draw the 3d viewport in the offscreen object.\n"
"\n"
" :arg scene: Scene to draw.\n"
" :type scene: :class:`bpy.types.Scene`\n"
" :arg view_layer: View layer to draw.\n"
" :type view_layer: :class:`bpy.types.ViewLayer`\n"
" :arg view3d: 3D View to get the drawing settings from.\n"
" :type view3d: :class:`bpy.types.SpaceView3D`\n"
" :arg region: Region of the 3D View (required as temporary draw target).\n"
" :type region: :class:`bpy.types.Region`\n"
" :arg view_matrix: View Matrix (e.g. ``camera.matrix_world.inverted()``).\n"
" :type view_matrix: :class:`mathutils.Matrix`\n"
" :arg projection_matrix: Projection Matrix (e.g. ``camera.calc_matrix_camera(...)``).\n"
" :type projection_matrix: :class:`mathutils.Matrix`\n"
);
static PyObject *bpygpu_offscreen_draw_view3d(BPyGPUOffScreen *self, PyObject *args, PyObject *kwds)
PyDoc_STRVAR(
bpygpu_offscreen_draw_view3d_doc,
".. method:: draw_view3d(scene, view3d, region, view_matrix, projection_matrix)\n"
"\n"
" Draw the 3d viewport in the offscreen object.\n"
"\n"
" :arg scene: Scene to draw.\n"
" :type scene: :class:`bpy.types.Scene`\n"
" :arg view_layer: View layer to draw.\n"
" :type view_layer: :class:`bpy.types.ViewLayer`\n"
" :arg view3d: 3D View to get the drawing settings from.\n"
" :type view3d: :class:`bpy.types.SpaceView3D`\n"
" :arg region: Region of the 3D View (required as temporary draw target).\n"
" :type region: :class:`bpy.types.Region`\n"
" :arg view_matrix: View Matrix (e.g. ``camera.matrix_world.inverted()``).\n"
" :type view_matrix: :class:`mathutils.Matrix`\n"
" :arg projection_matrix: Projection Matrix (e.g. ``camera.calc_matrix_camera(...)``).\n"
" :type projection_matrix: :class:`mathutils.Matrix`\n");
static PyObject *bpygpu_offscreen_draw_view3d(BPyGPUOffScreen *self,
PyObject *args,
PyObject *kwds)
{
MatrixObject *py_mat_view, *py_mat_projection;
PyObject *py_scene, *py_view_layer, *py_region, *py_view3d;
MatrixObject *py_mat_view, *py_mat_projection;
PyObject *py_scene, *py_view_layer, *py_region, *py_view3d;
struct Depsgraph *depsgraph;
struct Scene *scene;
struct ViewLayer *view_layer;
View3D *v3d;
ARegion *ar;
struct RV3DMatrixStore *rv3d_mats;
struct Depsgraph *depsgraph;
struct Scene *scene;
struct ViewLayer *view_layer;
View3D *v3d;
ARegion *ar;
struct RV3DMatrixStore *rv3d_mats;
BPY_GPU_OFFSCREEN_CHECK_OBJ(self);
BPY_GPU_OFFSCREEN_CHECK_OBJ(self);
static const char *_keywords[] = {
"scene", "view_layer", "view3d", "region",
"view_matrix", "projection_matrix", NULL};
static const char *_keywords[] = {
"scene", "view_layer", "view3d", "region", "view_matrix", "projection_matrix", NULL};
static _PyArg_Parser _parser = {"OOOOO&O&:draw_view3d", _keywords, 0};
if (!_PyArg_ParseTupleAndKeywordsFast(
args, kwds, &_parser,
&py_scene, &py_view_layer, &py_view3d, &py_region,
Matrix_Parse4x4, &py_mat_view,
Matrix_Parse4x4, &py_mat_projection) ||
(!(scene = PyC_RNA_AsPointer(py_scene, "Scene")) ||
!(view_layer = PyC_RNA_AsPointer(py_view_layer, "ViewLayer")) ||
!(v3d = PyC_RNA_AsPointer(py_view3d, "SpaceView3D")) ||
!(ar = PyC_RNA_AsPointer(py_region, "Region"))))
{
return NULL;
}
static _PyArg_Parser _parser = {"OOOOO&O&:draw_view3d", _keywords, 0};
if (!_PyArg_ParseTupleAndKeywordsFast(args,
kwds,
&_parser,
&py_scene,
&py_view_layer,
&py_view3d,
&py_region,
Matrix_Parse4x4,
&py_mat_view,
Matrix_Parse4x4,
&py_mat_projection) ||
(!(scene = PyC_RNA_AsPointer(py_scene, "Scene")) ||
!(view_layer = PyC_RNA_AsPointer(py_view_layer, "ViewLayer")) ||
!(v3d = PyC_RNA_AsPointer(py_view3d, "SpaceView3D")) ||
!(ar = PyC_RNA_AsPointer(py_region, "Region")))) {
return NULL;
}
BLI_assert(BKE_id_is_in_global_main(&scene->id));
BLI_assert(BKE_id_is_in_global_main(&scene->id));
depsgraph = BKE_scene_get_depsgraph(scene, view_layer, true);
depsgraph = BKE_scene_get_depsgraph(scene, view_layer, true);
rv3d_mats = ED_view3d_mats_rv3d_backup(ar->regiondata);
rv3d_mats = ED_view3d_mats_rv3d_backup(ar->regiondata);
GPU_offscreen_bind(self->ofs, true);
GPU_offscreen_bind(self->ofs, true);
ED_view3d_draw_offscreen(depsgraph,
scene,
v3d->shading.type,
v3d,
ar,
GPU_offscreen_width(self->ofs),
GPU_offscreen_height(self->ofs),
(float(*)[4])py_mat_view->matrix,
(float(*)[4])py_mat_projection->matrix,
false,
true,
"",
NULL,
true,
self->ofs,
NULL);
ED_view3d_draw_offscreen(depsgraph,
scene,
v3d->shading.type,
v3d,
ar,
GPU_offscreen_width(self->ofs),
GPU_offscreen_height(self->ofs),
(float(*)[4])py_mat_view->matrix,
(float(*)[4])py_mat_projection->matrix,
false,
true,
"",
NULL,
true,
self->ofs,
NULL);
GPU_offscreen_unbind(self->ofs, true);
GPU_offscreen_unbind(self->ofs, true);
ED_view3d_mats_rv3d_restore(ar->regiondata, rv3d_mats);
MEM_freeN(rv3d_mats);
ED_view3d_mats_rv3d_restore(ar->regiondata, rv3d_mats);
MEM_freeN(rv3d_mats);
Py_RETURN_NONE;
Py_RETURN_NONE;
}
PyDoc_STRVAR(bpygpu_offscreen_free_doc,
".. method:: free()\n"
"\n"
" Free the offscreen object.\n"
" The framebuffer, texture and render objects will no longer be accessible.\n"
);
".. method:: free()\n"
"\n"
" Free the offscreen object.\n"
" The framebuffer, texture and render objects will no longer be accessible.\n");
static PyObject *bpygpu_offscreen_free(BPyGPUOffScreen *self)
{
BPY_GPU_OFFSCREEN_CHECK_OBJ(self);
BPY_GPU_OFFSCREEN_CHECK_OBJ(self);
GPU_offscreen_free(self->ofs);
self->ofs = NULL;
Py_RETURN_NONE;
GPU_offscreen_free(self->ofs);
self->ofs = NULL;
Py_RETURN_NONE;
}
static PyObject *bpygpu_offscreen_bind_context_enter(BPyGPUOffScreen *UNUSED(self))
{
Py_RETURN_NONE;
Py_RETURN_NONE;
}
static PyObject *bpygpu_offscreen_bind_context_exit(BPyGPUOffScreen *self, PyObject *UNUSED(args))
{
GPU_offscreen_unbind(self->ofs, self->is_saved);
Py_RETURN_NONE;
GPU_offscreen_unbind(self->ofs, self->is_saved);
Py_RETURN_NONE;
}
static void BPyGPUOffScreen__tp_dealloc(BPyGPUOffScreen *self)
{
if (self->ofs) {
GPU_offscreen_free(self->ofs);
}
Py_TYPE(self)->tp_free((PyObject *)self);
if (self->ofs) {
GPU_offscreen_free(self->ofs);
}
Py_TYPE(self)->tp_free((PyObject *)self);
}
static PyGetSetDef bpygpu_offscreen_getseters[] = {
{(char *)"color_texture", (getter)bpygpu_offscreen_color_texture_get, (setter)NULL, bpygpu_offscreen_color_texture_doc, NULL},
{(char *)"width", (getter)bpygpu_offscreen_width_get, (setter)NULL, bpygpu_offscreen_width_doc, NULL},
{(char *)"height", (getter)bpygpu_offscreen_height_get, (setter)NULL, bpygpu_offscreen_height_doc, NULL},
{NULL, NULL, NULL, NULL, NULL} /* Sentinel */
{(char *)"color_texture",
(getter)bpygpu_offscreen_color_texture_get,
(setter)NULL,
bpygpu_offscreen_color_texture_doc,
NULL},
{(char *)"width",
(getter)bpygpu_offscreen_width_get,
(setter)NULL,
bpygpu_offscreen_width_doc,
NULL},
{(char *)"height",
(getter)bpygpu_offscreen_height_get,
(setter)NULL,
bpygpu_offscreen_height_doc,
NULL},
{NULL, NULL, NULL, NULL, NULL} /* Sentinel */
};
static struct PyMethodDef bpygpu_offscreen_methods[] = {
{"bind", (PyCFunction)bpygpu_offscreen_bind, METH_VARARGS | METH_KEYWORDS, bpygpu_offscreen_bind_doc},
{"unbind", (PyCFunction)bpygpu_offscreen_unbind, METH_VARARGS | METH_KEYWORDS, bpygpu_offscreen_unbind_doc},
{"draw_view3d", (PyCFunction)bpygpu_offscreen_draw_view3d, METH_VARARGS | METH_KEYWORDS, bpygpu_offscreen_draw_view3d_doc},
{"free", (PyCFunction)bpygpu_offscreen_free, METH_NOARGS, bpygpu_offscreen_free_doc},
{"__enter__", (PyCFunction)bpygpu_offscreen_bind_context_enter, METH_NOARGS},
{"__exit__", (PyCFunction)bpygpu_offscreen_bind_context_exit, METH_VARARGS},
{NULL, NULL, 0, NULL},
{"bind",
(PyCFunction)bpygpu_offscreen_bind,
METH_VARARGS | METH_KEYWORDS,
bpygpu_offscreen_bind_doc},
{"unbind",
(PyCFunction)bpygpu_offscreen_unbind,
METH_VARARGS | METH_KEYWORDS,
bpygpu_offscreen_unbind_doc},
{"draw_view3d",
(PyCFunction)bpygpu_offscreen_draw_view3d,
METH_VARARGS | METH_KEYWORDS,
bpygpu_offscreen_draw_view3d_doc},
{"free", (PyCFunction)bpygpu_offscreen_free, METH_NOARGS, bpygpu_offscreen_free_doc},
{"__enter__", (PyCFunction)bpygpu_offscreen_bind_context_enter, METH_NOARGS},
{"__exit__", (PyCFunction)bpygpu_offscreen_bind_context_exit, METH_VARARGS},
{NULL, NULL, 0, NULL},
};
PyDoc_STRVAR(bpygpu_offscreen_doc,
".. class:: GPUOffScreen(width, height, samples=0)\n"
"\n"
" This object gives access to off screen buffers.\n"
"\n"
" :arg width: Horizontal dimension of the buffer.\n"
" :type width: `int`\n"
" :arg height: Vertical dimension of the buffer.\n"
" :type height: `int`\n"
" :arg samples: OpenGL samples to use for MSAA or zero to disable.\n"
" :type samples: `int`\n"
);
".. class:: GPUOffScreen(width, height, samples=0)\n"
"\n"
" This object gives access to off screen buffers.\n"
"\n"
" :arg width: Horizontal dimension of the buffer.\n"
" :type width: `int`\n"
" :arg height: Vertical dimension of the buffer.\n"
" :type height: `int`\n"
" :arg samples: OpenGL samples to use for MSAA or zero to disable.\n"
" :type samples: `int`\n");
PyTypeObject BPyGPUOffScreen_Type = {
PyVarObject_HEAD_INIT(NULL, 0)
.tp_name = "GPUOffScreen",
.tp_basicsize = sizeof(BPyGPUOffScreen),
.tp_dealloc = (destructor)BPyGPUOffScreen__tp_dealloc,
.tp_flags = Py_TPFLAGS_DEFAULT,
.tp_doc = bpygpu_offscreen_doc,
.tp_methods = bpygpu_offscreen_methods,
.tp_getset = bpygpu_offscreen_getseters,
.tp_new = bpygpu_offscreen_new,
PyVarObject_HEAD_INIT(NULL, 0).tp_name = "GPUOffScreen",
.tp_basicsize = sizeof(BPyGPUOffScreen),
.tp_dealloc = (destructor)BPyGPUOffScreen__tp_dealloc,
.tp_flags = Py_TPFLAGS_DEFAULT,
.tp_doc = bpygpu_offscreen_doc,
.tp_methods = bpygpu_offscreen_methods,
.tp_getset = bpygpu_offscreen_getseters,
.tp_new = bpygpu_offscreen_new,
};
/** \} */
/* -------------------------------------------------------------------- */
/** \name Public API
* \{ */
PyObject *BPyGPUOffScreen_CreatePyObject(GPUOffScreen *ofs)
{
BPyGPUOffScreen *self;
BPyGPUOffScreen *self;
self = PyObject_New(BPyGPUOffScreen, &BPyGPUOffScreen_Type);
self->ofs = ofs;
self = PyObject_New(BPyGPUOffScreen, &BPyGPUOffScreen_Type);
self->ofs = ofs;
return (PyObject *)self;
return (PyObject *)self;
}
/** \} */

View File

@@ -25,12 +25,11 @@
extern PyTypeObject BPyGPUOffScreen_Type;
#define BPyGPUOffScreen_Check(v) (Py_TYPE(v) == &BPyGPUOffScreen_Type)
#define BPyGPUOffScreen_Check(v) (Py_TYPE(v) == &BPyGPUOffScreen_Type)
typedef struct BPyGPUOffScreen {
PyObject_HEAD
struct GPUOffScreen *ofs;
bool is_saved;
PyObject_HEAD struct GPUOffScreen *ofs;
bool is_saved;
} BPyGPUOffScreen;
PyObject *BPyGPUOffScreen_CreatePyObject(struct GPUOffScreen *ofs) ATTR_NONNULL(1);

View File

@@ -41,21 +41,20 @@
* \{ */
PyDoc_STRVAR(bpygpu_select_load_id_doc,
"load_id(id)\n"
"\n"
" Set the selection ID.\n"
"\n"
" :param id: Number (32-bit unsigned int).\n"
" :type select: int\n"
);
"load_id(id)\n"
"\n"
" Set the selection ID.\n"
"\n"
" :param id: Number (32-bit unsigned int).\n"
" :type select: int\n");
static PyObject *bpygpu_select_load_id(PyObject *UNUSED(self), PyObject *value)
{
uint id;
if ((id = PyC_Long_AsU32(value)) == (uint)-1) {
return NULL;
}
GPU_select_load_id(id);
Py_RETURN_NONE;
uint id;
if ((id = PyC_Long_AsU32(value)) == (uint)-1) {
return NULL;
}
GPU_select_load_id(id);
Py_RETURN_NONE;
}
/** \} */
@@ -64,28 +63,26 @@ static PyObject *bpygpu_select_load_id(PyObject *UNUSED(self), PyObject *value)
* \{ */
static struct PyMethodDef bpygpu_select_methods[] = {
/* Manage Stack */
{"load_id", (PyCFunction)bpygpu_select_load_id, METH_O, bpygpu_select_load_id_doc},
{NULL, NULL, 0, NULL},
/* Manage Stack */
{"load_id", (PyCFunction)bpygpu_select_load_id, METH_O, bpygpu_select_load_id_doc},
{NULL, NULL, 0, NULL},
};
PyDoc_STRVAR(bpygpu_select_doc,
"This module provides access to selection."
);
PyDoc_STRVAR(bpygpu_select_doc, "This module provides access to selection.");
static PyModuleDef BPyGPU_select_module_def = {
PyModuleDef_HEAD_INIT,
.m_name = "gpu.select",
.m_doc = bpygpu_select_doc,
.m_methods = bpygpu_select_methods,
PyModuleDef_HEAD_INIT,
.m_name = "gpu.select",
.m_doc = bpygpu_select_doc,
.m_methods = bpygpu_select_methods,
};
PyObject *BPyInit_gpu_select(void)
{
PyObject *submodule;
PyObject *submodule;
submodule = PyModule_Create(&BPyGPU_select_module_def);
submodule = PyModule_Create(&BPyGPU_select_module_def);
return submodule;
return submodule;
}
/** \} */

View File

@@ -23,4 +23,4 @@
PyObject *BPyInit_gpu_select(void);
#endif /* __GPU_PY_SELECT_H__ */
#endif /* __GPU_PY_SELECT_H__ */

File diff suppressed because it is too large Load Diff

View File

@@ -23,12 +23,11 @@
extern PyTypeObject BPyGPUShader_Type;
#define BPyGPUShader_Check(v) (Py_TYPE(v) == &BPyGPUShader_Type)
#define BPyGPUShader_Check(v) (Py_TYPE(v) == &BPyGPUShader_Type)
typedef struct BPyGPUShader {
PyObject_VAR_HEAD
struct GPUShader *shader;
bool is_builtin;
PyObject_VAR_HEAD struct GPUShader *shader;
bool is_builtin;
} BPyGPUShader;
PyObject *BPyGPUShader_CreatePyObject(struct GPUShader *shader, bool is_builtin);

View File

@@ -30,53 +30,53 @@
/* -------------------------------------------------------------------- */
/** \name GPU Types Module
* \{ */
static struct PyModuleDef BPyGPU_types_module_def = {
PyModuleDef_HEAD_INIT,
.m_name = "gpu.types",
PyModuleDef_HEAD_INIT,
.m_name = "gpu.types",
};
PyObject *BPyInit_gpu_types(void)
{
PyObject *submodule;
PyObject *submodule;
submodule = PyModule_Create(&BPyGPU_types_module_def);
submodule = PyModule_Create(&BPyGPU_types_module_def);
if (PyType_Ready(&BPyGPUVertFormat_Type) < 0) {
return NULL;
}
if (PyType_Ready(&BPyGPUVertBuf_Type) < 0) {
return NULL;
}
if (PyType_Ready(&BPyGPUIndexBuf_Type) < 0) {
return NULL;
}
if (PyType_Ready(&BPyGPUBatch_Type) < 0) {
return NULL;
}
if (PyType_Ready(&BPyGPUOffScreen_Type) < 0) {
return NULL;
}
if (PyType_Ready(&BPyGPUShader_Type) < 0) {
return NULL;
}
if (PyType_Ready(&BPyGPUVertFormat_Type) < 0) {
return NULL;
}
if (PyType_Ready(&BPyGPUVertBuf_Type) < 0) {
return NULL;
}
if (PyType_Ready(&BPyGPUIndexBuf_Type) < 0) {
return NULL;
}
if (PyType_Ready(&BPyGPUBatch_Type) < 0) {
return NULL;
}
if (PyType_Ready(&BPyGPUOffScreen_Type) < 0) {
return NULL;
}
if (PyType_Ready(&BPyGPUShader_Type) < 0) {
return NULL;
}
#define MODULE_TYPE_ADD(s, t) \
PyModule_AddObject(s, t.tp_name, (PyObject *)&t); Py_INCREF((PyObject *)&t)
PyModule_AddObject(s, t.tp_name, (PyObject *)&t); \
Py_INCREF((PyObject *)&t)
MODULE_TYPE_ADD(submodule, BPyGPUVertFormat_Type);
MODULE_TYPE_ADD(submodule, BPyGPUVertBuf_Type);
MODULE_TYPE_ADD(submodule, BPyGPUIndexBuf_Type);
MODULE_TYPE_ADD(submodule, BPyGPUBatch_Type);
MODULE_TYPE_ADD(submodule, BPyGPUOffScreen_Type);
MODULE_TYPE_ADD(submodule, BPyGPUShader_Type);
MODULE_TYPE_ADD(submodule, BPyGPUVertFormat_Type);
MODULE_TYPE_ADD(submodule, BPyGPUVertBuf_Type);
MODULE_TYPE_ADD(submodule, BPyGPUIndexBuf_Type);
MODULE_TYPE_ADD(submodule, BPyGPUBatch_Type);
MODULE_TYPE_ADD(submodule, BPyGPUOffScreen_Type);
MODULE_TYPE_ADD(submodule, BPyGPUShader_Type);
#undef MODULE_TYPE_ADD
return submodule;
return submodule;
}
/** \} */

View File

@@ -40,48 +40,74 @@
* \{ */
#define PY_AS_NATIVE_SWITCH(attr) \
switch (attr->comp_type) { \
case GPU_COMP_I8: { PY_AS_NATIVE(int8_t, PyC_Long_AsI8); break; } \
case GPU_COMP_U8: { PY_AS_NATIVE(uint8_t, PyC_Long_AsU8); break; } \
case GPU_COMP_I16: { PY_AS_NATIVE(int16_t, PyC_Long_AsI16); break; } \
case GPU_COMP_U16: { PY_AS_NATIVE(uint16_t, PyC_Long_AsU16); break; } \
case GPU_COMP_I32: { PY_AS_NATIVE(int32_t, PyC_Long_AsI32); break; } \
case GPU_COMP_U32: { PY_AS_NATIVE(uint32_t, PyC_Long_AsU32); break; } \
case GPU_COMP_F32: { PY_AS_NATIVE(float, PyFloat_AsDouble); break; } \
default: \
BLI_assert(0); \
} ((void)0)
switch (attr->comp_type) { \
case GPU_COMP_I8: { \
PY_AS_NATIVE(int8_t, PyC_Long_AsI8); \
break; \
} \
case GPU_COMP_U8: { \
PY_AS_NATIVE(uint8_t, PyC_Long_AsU8); \
break; \
} \
case GPU_COMP_I16: { \
PY_AS_NATIVE(int16_t, PyC_Long_AsI16); \
break; \
} \
case GPU_COMP_U16: { \
PY_AS_NATIVE(uint16_t, PyC_Long_AsU16); \
break; \
} \
case GPU_COMP_I32: { \
PY_AS_NATIVE(int32_t, PyC_Long_AsI32); \
break; \
} \
case GPU_COMP_U32: { \
PY_AS_NATIVE(uint32_t, PyC_Long_AsU32); \
break; \
} \
case GPU_COMP_F32: { \
PY_AS_NATIVE(float, PyFloat_AsDouble); \
break; \
} \
default: \
BLI_assert(0); \
} \
((void)0)
/* No error checking, callers must run PyErr_Occurred */
static void fill_format_elem(void *data_dst_void, PyObject *py_src, const GPUVertAttr *attr)
{
#define PY_AS_NATIVE(ty_dst, py_as_native) \
{ \
ty_dst *data_dst = data_dst_void; \
*data_dst = py_as_native(py_src); \
} ((void)0)
{ \
ty_dst *data_dst = data_dst_void; \
*data_dst = py_as_native(py_src); \
} \
((void)0)
PY_AS_NATIVE_SWITCH(attr);
PY_AS_NATIVE_SWITCH(attr);
#undef PY_AS_NATIVE
}
/* No error checking, callers must run PyErr_Occurred */
static void fill_format_sequence(void *data_dst_void, PyObject *py_seq_fast, const GPUVertAttr *attr)
static void fill_format_sequence(void *data_dst_void,
PyObject *py_seq_fast,
const GPUVertAttr *attr)
{
const uint len = attr->comp_len;
PyObject **value_fast_items = PySequence_Fast_ITEMS(py_seq_fast);
const uint len = attr->comp_len;
PyObject **value_fast_items = PySequence_Fast_ITEMS(py_seq_fast);
/**
* Args are constants, so range checks will be optimized out if they're nop's.
*/
#define PY_AS_NATIVE(ty_dst, py_as_native) \
ty_dst *data_dst = data_dst_void; \
for (uint i = 0; i < len; i++) { \
data_dst[i] = py_as_native(value_fast_items[i]); \
} ((void)0)
ty_dst *data_dst = data_dst_void; \
for (uint i = 0; i < len; i++) { \
data_dst[i] = py_as_native(value_fast_items[i]); \
} \
((void)0)
PY_AS_NATIVE_SWITCH(attr);
PY_AS_NATIVE_SWITCH(attr);
#undef PY_AS_NATIVE
}
@@ -90,256 +116,244 @@ static void fill_format_sequence(void *data_dst_void, PyObject *py_seq_fast, con
#undef WARN_TYPE_LIMIT_PUSH
#undef WARN_TYPE_LIMIT_POP
static bool bpygpu_vertbuf_fill_impl(
GPUVertBuf *vbo,
uint data_id, PyObject *seq, const char *error_prefix)
static bool bpygpu_vertbuf_fill_impl(GPUVertBuf *vbo,
uint data_id,
PyObject *seq,
const char *error_prefix)
{
const char *exc_str_size_mismatch = "Expected a %s of size %d, got %u";
const char *exc_str_size_mismatch = "Expected a %s of size %d, got %u";
bool ok = true;
const GPUVertAttr *attr = &vbo->format.attrs[data_id];
bool ok = true;
const GPUVertAttr *attr = &vbo->format.attrs[data_id];
if (PyObject_CheckBuffer(seq)) {
Py_buffer pybuffer;
if (PyObject_CheckBuffer(seq)) {
Py_buffer pybuffer;
if (PyObject_GetBuffer(seq, &pybuffer, PyBUF_STRIDES | PyBUF_ND) == -1) {
/* PyObject_GetBuffer raise a PyExc_BufferError */
return false;
}
if (PyObject_GetBuffer(seq, &pybuffer, PyBUF_STRIDES | PyBUF_ND) == -1) {
/* PyObject_GetBuffer raise a PyExc_BufferError */
return false;
}
uint comp_len = pybuffer.ndim == 1 ? 1 : (uint)pybuffer.shape[1];
uint comp_len = pybuffer.ndim == 1 ? 1 : (uint)pybuffer.shape[1];
if (pybuffer.shape[0] != vbo->vertex_len) {
PyErr_Format(PyExc_ValueError, exc_str_size_mismatch,
"sequence", vbo->vertex_len, pybuffer.shape[0]);
ok = false;
}
else if (comp_len != attr->comp_len) {
PyErr_Format(PyExc_ValueError, exc_str_size_mismatch,
"component", attr->comp_len, comp_len);
ok = false;
}
else {
GPU_vertbuf_attr_fill_stride(vbo, data_id, pybuffer.strides[0], pybuffer.buf);
}
if (pybuffer.shape[0] != vbo->vertex_len) {
PyErr_Format(
PyExc_ValueError, exc_str_size_mismatch, "sequence", vbo->vertex_len, pybuffer.shape[0]);
ok = false;
}
else if (comp_len != attr->comp_len) {
PyErr_Format(PyExc_ValueError, exc_str_size_mismatch, "component", attr->comp_len, comp_len);
ok = false;
}
else {
GPU_vertbuf_attr_fill_stride(vbo, data_id, pybuffer.strides[0], pybuffer.buf);
}
PyBuffer_Release(&pybuffer);
}
else {
GPUVertBufRaw data_step;
GPU_vertbuf_attr_get_raw_data(vbo, data_id, &data_step);
PyBuffer_Release(&pybuffer);
}
else {
GPUVertBufRaw data_step;
GPU_vertbuf_attr_get_raw_data(vbo, data_id, &data_step);
PyObject *seq_fast = PySequence_Fast(seq, "Vertex buffer fill");
if (seq_fast == NULL) {
return false;
}
PyObject *seq_fast = PySequence_Fast(seq, "Vertex buffer fill");
if (seq_fast == NULL) {
return false;
}
const uint seq_len = PySequence_Fast_GET_SIZE(seq_fast);
const uint seq_len = PySequence_Fast_GET_SIZE(seq_fast);
if (seq_len != vbo->vertex_len) {
PyErr_Format(PyExc_ValueError, exc_str_size_mismatch,
"sequence", vbo->vertex_len, seq_len);
}
if (seq_len != vbo->vertex_len) {
PyErr_Format(PyExc_ValueError, exc_str_size_mismatch, "sequence", vbo->vertex_len, seq_len);
}
PyObject **seq_items = PySequence_Fast_ITEMS(seq_fast);
PyObject **seq_items = PySequence_Fast_ITEMS(seq_fast);
if (attr->comp_len == 1) {
for (uint i = 0; i < seq_len; i++) {
uchar *data = (uchar *)GPU_vertbuf_raw_step(&data_step);
PyObject *item = seq_items[i];
fill_format_elem(data, item, attr);
}
}
else {
for (uint i = 0; i < seq_len; i++) {
uchar *data = (uchar *)GPU_vertbuf_raw_step(&data_step);
PyObject *seq_fast_item = PySequence_Fast(seq_items[i], error_prefix);
if (attr->comp_len == 1) {
for (uint i = 0; i < seq_len; i++) {
uchar *data = (uchar *)GPU_vertbuf_raw_step(&data_step);
PyObject *item = seq_items[i];
fill_format_elem(data, item, attr);
}
}
else {
for (uint i = 0; i < seq_len; i++) {
uchar *data = (uchar *)GPU_vertbuf_raw_step(&data_step);
PyObject *seq_fast_item = PySequence_Fast(seq_items[i], error_prefix);
if (seq_fast_item == NULL) {
ok = false;
goto finally;
}
if (PySequence_Fast_GET_SIZE(seq_fast_item) != attr->comp_len) {
PyErr_Format(PyExc_ValueError, exc_str_size_mismatch,
"sequence", attr->comp_len, PySequence_Fast_GET_SIZE(seq_fast_item));
ok = false;
Py_DECREF(seq_fast_item);
goto finally;
}
if (seq_fast_item == NULL) {
ok = false;
goto finally;
}
if (PySequence_Fast_GET_SIZE(seq_fast_item) != attr->comp_len) {
PyErr_Format(PyExc_ValueError,
exc_str_size_mismatch,
"sequence",
attr->comp_len,
PySequence_Fast_GET_SIZE(seq_fast_item));
ok = false;
Py_DECREF(seq_fast_item);
goto finally;
}
/* May trigger error, check below */
fill_format_sequence(data, seq_fast_item, attr);
Py_DECREF(seq_fast_item);
}
}
/* May trigger error, check below */
fill_format_sequence(data, seq_fast_item, attr);
Py_DECREF(seq_fast_item);
}
}
if (PyErr_Occurred()) {
ok = false;
}
if (PyErr_Occurred()) {
ok = false;
}
finally:
finally:
Py_DECREF(seq_fast);
}
return ok;
Py_DECREF(seq_fast);
}
return ok;
}
static int bpygpu_attr_fill(GPUVertBuf *buf, int id, PyObject *py_seq_data, const char *error_prefix)
static int bpygpu_attr_fill(GPUVertBuf *buf,
int id,
PyObject *py_seq_data,
const char *error_prefix)
{
if (id < 0 || id >= buf->format.attr_len) {
PyErr_Format(PyExc_ValueError,
"Format id %d out of range",
id);
return 0;
}
if (id < 0 || id >= buf->format.attr_len) {
PyErr_Format(PyExc_ValueError, "Format id %d out of range", id);
return 0;
}
if (buf->data == NULL) {
PyErr_SetString(PyExc_ValueError,
"Can't fill, static buffer already in use");
return 0;
}
if (buf->data == NULL) {
PyErr_SetString(PyExc_ValueError, "Can't fill, static buffer already in use");
return 0;
}
if (!bpygpu_vertbuf_fill_impl(buf, (uint)id, py_seq_data, error_prefix)) {
return 0;
}
if (!bpygpu_vertbuf_fill_impl(buf, (uint)id, py_seq_data, error_prefix)) {
return 0;
}
return 1;
return 1;
}
/** \} */
/* -------------------------------------------------------------------- */
/** \name VertBuf Type
* \{ */
static PyObject *bpygpu_VertBuf_new(PyTypeObject *UNUSED(type), PyObject *args, PyObject *kwds)
{
struct {
PyObject *py_fmt;
uint len;
} params;
struct {
PyObject *py_fmt;
uint len;
} params;
static const char *_keywords[] = {"format", "len", NULL};
static _PyArg_Parser _parser = {"O!I:GPUVertBuf.__new__", _keywords, 0};
if (!_PyArg_ParseTupleAndKeywordsFast(
args, kwds, &_parser,
&BPyGPUVertFormat_Type, &params.py_fmt,
&params.len))
{
return NULL;
}
static const char *_keywords[] = {"format", "len", NULL};
static _PyArg_Parser _parser = {"O!I:GPUVertBuf.__new__", _keywords, 0};
if (!_PyArg_ParseTupleAndKeywordsFast(
args, kwds, &_parser, &BPyGPUVertFormat_Type, &params.py_fmt, &params.len)) {
return NULL;
}
const GPUVertFormat *fmt = &((BPyGPUVertFormat *)params.py_fmt)->fmt;
GPUVertBuf *vbo = GPU_vertbuf_create_with_format(fmt);
const GPUVertFormat *fmt = &((BPyGPUVertFormat *)params.py_fmt)->fmt;
GPUVertBuf *vbo = GPU_vertbuf_create_with_format(fmt);
GPU_vertbuf_data_alloc(vbo, params.len);
GPU_vertbuf_data_alloc(vbo, params.len);
return BPyGPUVertBuf_CreatePyObject(vbo);
return BPyGPUVertBuf_CreatePyObject(vbo);
}
PyDoc_STRVAR(bpygpu_VertBuf_attr_fill_doc,
".. method:: attr_fill(id, data)\n"
"\n"
" Insert data into the buffer for a single attribute.\n"
"\n"
" :param id: Either the name or the id of the attribute.\n"
" :type id: int or str\n"
" :param data: Sequence of data that should be stored in the buffer\n"
" :type data: sequence of values or tuples\n"
);
".. method:: attr_fill(id, data)\n"
"\n"
" Insert data into the buffer for a single attribute.\n"
"\n"
" :param id: Either the name or the id of the attribute.\n"
" :type id: int or str\n"
" :param data: Sequence of data that should be stored in the buffer\n"
" :type data: sequence of values or tuples\n");
static PyObject *bpygpu_VertBuf_attr_fill(BPyGPUVertBuf *self, PyObject *args, PyObject *kwds)
{
PyObject *data;
PyObject *identifier;
PyObject *data;
PyObject *identifier;
static const char *_keywords[] = {"id", "data", NULL};
static _PyArg_Parser _parser = {"OO:attr_fill", _keywords, 0};
if (!_PyArg_ParseTupleAndKeywordsFast(
args, kwds, &_parser,
&identifier, &data))
{
return NULL;
}
static const char *_keywords[] = {"id", "data", NULL};
static _PyArg_Parser _parser = {"OO:attr_fill", _keywords, 0};
if (!_PyArg_ParseTupleAndKeywordsFast(args, kwds, &_parser, &identifier, &data)) {
return NULL;
}
int id;
int id;
if (PyLong_Check(identifier)) {
id = PyLong_AsLong(identifier);
}
else if (PyUnicode_Check(identifier)) {
const char *name = PyUnicode_AsUTF8(identifier);
id = GPU_vertformat_attr_id_get(&self->buf->format, name);
if (id == -1) {
PyErr_SetString(PyExc_ValueError,
"Unknown attribute name");
return NULL;
}
}
else {
PyErr_SetString(PyExc_TypeError,
"expected int or str type as identifier");
return NULL;
}
if (PyLong_Check(identifier)) {
id = PyLong_AsLong(identifier);
}
else if (PyUnicode_Check(identifier)) {
const char *name = PyUnicode_AsUTF8(identifier);
id = GPU_vertformat_attr_id_get(&self->buf->format, name);
if (id == -1) {
PyErr_SetString(PyExc_ValueError, "Unknown attribute name");
return NULL;
}
}
else {
PyErr_SetString(PyExc_TypeError, "expected int or str type as identifier");
return NULL;
}
if (!bpygpu_attr_fill(self->buf, id, data, "GPUVertBuf.attr_fill")) {
return NULL;
}
if (!bpygpu_attr_fill(self->buf, id, data, "GPUVertBuf.attr_fill")) {
return NULL;
}
Py_RETURN_NONE;
Py_RETURN_NONE;
}
static struct PyMethodDef bpygpu_VertBuf_methods[] = {
{"attr_fill", (PyCFunction) bpygpu_VertBuf_attr_fill,
METH_VARARGS | METH_KEYWORDS, bpygpu_VertBuf_attr_fill_doc},
{NULL, NULL, 0, NULL},
{"attr_fill",
(PyCFunction)bpygpu_VertBuf_attr_fill,
METH_VARARGS | METH_KEYWORDS,
bpygpu_VertBuf_attr_fill_doc},
{NULL, NULL, 0, NULL},
};
static void bpygpu_VertBuf_dealloc(BPyGPUVertBuf *self)
{
GPU_vertbuf_discard(self->buf);
Py_TYPE(self)->tp_free(self);
GPU_vertbuf_discard(self->buf);
Py_TYPE(self)->tp_free(self);
}
PyDoc_STRVAR(py_gpu_vertex_buffer_doc,
".. class:: GPUVertBuf(len, format)\n"
"\n"
" Contains a VBO.\n"
"\n"
" :param len: Amount of vertices that will fit into this buffer.\n"
" :type type: `int`\n"
" :param format: Vertex format.\n"
" :type buf: :class:`gpu.types.GPUVertFormat`\n"
);
".. class:: GPUVertBuf(len, format)\n"
"\n"
" Contains a VBO.\n"
"\n"
" :param len: Amount of vertices that will fit into this buffer.\n"
" :type type: `int`\n"
" :param format: Vertex format.\n"
" :type buf: :class:`gpu.types.GPUVertFormat`\n");
PyTypeObject BPyGPUVertBuf_Type = {
PyVarObject_HEAD_INIT(NULL, 0)
.tp_name = "GPUVertBuf",
.tp_basicsize = sizeof(BPyGPUVertBuf),
.tp_dealloc = (destructor)bpygpu_VertBuf_dealloc,
.tp_flags = Py_TPFLAGS_DEFAULT,
.tp_doc = py_gpu_vertex_buffer_doc,
.tp_methods = bpygpu_VertBuf_methods,
.tp_new = bpygpu_VertBuf_new,
PyVarObject_HEAD_INIT(NULL, 0).tp_name = "GPUVertBuf",
.tp_basicsize = sizeof(BPyGPUVertBuf),
.tp_dealloc = (destructor)bpygpu_VertBuf_dealloc,
.tp_flags = Py_TPFLAGS_DEFAULT,
.tp_doc = py_gpu_vertex_buffer_doc,
.tp_methods = bpygpu_VertBuf_methods,
.tp_new = bpygpu_VertBuf_new,
};
/** \} */
/* -------------------------------------------------------------------- */
/** \name Public API
* \{ */
PyObject *BPyGPUVertBuf_CreatePyObject(GPUVertBuf *buf)
{
BPyGPUVertBuf *self;
BPyGPUVertBuf *self;
self = PyObject_New(BPyGPUVertBuf, &BPyGPUVertBuf_Type);
self->buf = buf;
self = PyObject_New(BPyGPUVertBuf, &BPyGPUVertBuf_Type);
self->buf = buf;
return (PyObject *)self;
return (PyObject *)self;
}
/** \} */

View File

@@ -25,12 +25,12 @@
extern PyTypeObject BPyGPUVertBuf_Type;
#define BPyGPUVertBuf_Check(v) (Py_TYPE(v) == &BPyGPUVertBuf_Type)
#define BPyGPUVertBuf_Check(v) (Py_TYPE(v) == &BPyGPUVertBuf_Type)
typedef struct BPyGPUVertBuf {
PyObject_VAR_HEAD
/* The buf is owned, we may support thin wrapped batches later. */
struct GPUVertBuf *buf;
PyObject_VAR_HEAD
/* The buf is owned, we may support thin wrapped batches later. */
struct GPUVertBuf *buf;
} BPyGPUVertBuf;
PyObject *BPyGPUVertBuf_CreatePyObject(struct GPUVertBuf *vbo) ATTR_NONNULL(1);

View File

@@ -33,15 +33,15 @@
#include "gpu_py_vertex_format.h" /* own include */
#ifdef __BIG_ENDIAN__
/* big endian */
# define MAKE_ID2(c, d) ((c) << 8 | (d))
# define MAKE_ID3(a, b, c) ( (int)(a) << 24 | (int)(b) << 16 | (c) << 8 )
# define MAKE_ID4(a, b, c, d) ( (int)(a) << 24 | (int)(b) << 16 | (c) << 8 | (d) )
/* big endian */
# define MAKE_ID2(c, d) ((c) << 8 | (d))
# define MAKE_ID3(a, b, c) ((int)(a) << 24 | (int)(b) << 16 | (c) << 8)
# define MAKE_ID4(a, b, c, d) ((int)(a) << 24 | (int)(b) << 16 | (c) << 8 | (d))
#else
/* little endian */
# define MAKE_ID2(c, d) ((d) << 8 | (c))
# define MAKE_ID3(a, b, c) ( (int)(c) << 16 | (b) << 8 | (a) )
# define MAKE_ID4(a, b, c, d) ( (int)(d) << 24 | (int)(c) << 16 | (b) << 8 | (a) )
/* little endian */
# define MAKE_ID2(c, d) ((d) << 8 | (c))
# define MAKE_ID3(a, b, c) ((int)(c) << 16 | (b) << 8 | (a))
# define MAKE_ID4(a, b, c, d) ((int)(d) << 24 | (int)(c) << 16 | (b) << 8 | (a))
#endif
/* -------------------------------------------------------------------- */
@@ -52,205 +52,211 @@
static int bpygpu_parse_component_type(const char *str, int length)
{
if (length == 2) {
switch (*((ushort *)str)) {
case MAKE_ID2('I', '8'): return GPU_COMP_I8;
case MAKE_ID2('U', '8'): return GPU_COMP_U8;
default: break;
}
}
else if (length == 3) {
switch (*((uint *)str)) {
case MAKE_ID3('I', '1', '6'): return GPU_COMP_I16;
case MAKE_ID3('U', '1', '6'): return GPU_COMP_U16;
case MAKE_ID3('I', '3', '2'): return GPU_COMP_I32;
case MAKE_ID3('U', '3', '2'): return GPU_COMP_U32;
case MAKE_ID3('F', '3', '2'): return GPU_COMP_F32;
case MAKE_ID3('I', '1', '0'): return GPU_COMP_I10;
default: break;
}
}
return -1;
if (length == 2) {
switch (*((ushort *)str)) {
case MAKE_ID2('I', '8'):
return GPU_COMP_I8;
case MAKE_ID2('U', '8'):
return GPU_COMP_U8;
default:
break;
}
}
else if (length == 3) {
switch (*((uint *)str)) {
case MAKE_ID3('I', '1', '6'):
return GPU_COMP_I16;
case MAKE_ID3('U', '1', '6'):
return GPU_COMP_U16;
case MAKE_ID3('I', '3', '2'):
return GPU_COMP_I32;
case MAKE_ID3('U', '3', '2'):
return GPU_COMP_U32;
case MAKE_ID3('F', '3', '2'):
return GPU_COMP_F32;
case MAKE_ID3('I', '1', '0'):
return GPU_COMP_I10;
default:
break;
}
}
return -1;
}
static int bpygpu_parse_fetch_mode(const char *str, int length)
{
#define MATCH_ID(id) \
if (length == strlen(STRINGIFY(id))) { \
if (STREQ(str, STRINGIFY(id))) { \
return GPU_FETCH_##id; \
} \
} ((void)0)
if (length == strlen(STRINGIFY(id))) { \
if (STREQ(str, STRINGIFY(id))) { \
return GPU_FETCH_##id; \
} \
} \
((void)0)
MATCH_ID(FLOAT);
MATCH_ID(INT);
MATCH_ID(INT_TO_FLOAT_UNIT);
MATCH_ID(INT_TO_FLOAT);
MATCH_ID(FLOAT);
MATCH_ID(INT);
MATCH_ID(INT_TO_FLOAT_UNIT);
MATCH_ID(INT_TO_FLOAT);
#undef MATCH_ID
return -1;
return -1;
}
static int bpygpu_ParseVertCompType(PyObject *o, void *p)
{
Py_ssize_t length;
const char *str = _PyUnicode_AsStringAndSize(o, &length);
Py_ssize_t length;
const char *str = _PyUnicode_AsStringAndSize(o, &length);
if (str == NULL) {
PyErr_Format(PyExc_ValueError,
"expected a string, got %s",
Py_TYPE(o)->tp_name);
return 0;
}
if (str == NULL) {
PyErr_Format(PyExc_ValueError, "expected a string, got %s", Py_TYPE(o)->tp_name);
return 0;
}
int comp_type = bpygpu_parse_component_type(str, length);
if (comp_type == -1) {
PyErr_Format(PyExc_ValueError,
"unkown component type: '%s",
str);
return 0;
}
int comp_type = bpygpu_parse_component_type(str, length);
if (comp_type == -1) {
PyErr_Format(PyExc_ValueError, "unkown component type: '%s", str);
return 0;
}
*((GPUVertCompType *)p) = comp_type;
return 1;
*((GPUVertCompType *)p) = comp_type;
return 1;
}
static int bpygpu_ParseVertFetchMode(PyObject *o, void *p)
{
Py_ssize_t length;
const char *str = _PyUnicode_AsStringAndSize(o, &length);
Py_ssize_t length;
const char *str = _PyUnicode_AsStringAndSize(o, &length);
if (str == NULL) {
PyErr_Format(PyExc_ValueError,
"expected a string, got %s",
Py_TYPE(o)->tp_name);
return 0;
}
if (str == NULL) {
PyErr_Format(PyExc_ValueError, "expected a string, got %s", Py_TYPE(o)->tp_name);
return 0;
}
int fetch_mode = bpygpu_parse_fetch_mode(str, length);
if (fetch_mode == -1) {
PyErr_Format(PyExc_ValueError,
"unknown type literal: '%s'",
str);
return 0;
}
int fetch_mode = bpygpu_parse_fetch_mode(str, length);
if (fetch_mode == -1) {
PyErr_Format(PyExc_ValueError, "unknown type literal: '%s'", str);
return 0;
}
(*(GPUVertFetchMode *)p) = fetch_mode;
return 1;
(*(GPUVertFetchMode *)p) = fetch_mode;
return 1;
}
/** \} */
/* -------------------------------------------------------------------- */
/** \name VertFormat Type
* \{ */
static PyObject *bpygpu_VertFormat_new(PyTypeObject *UNUSED(type), PyObject *args, PyObject *kwds)
{
if (PyTuple_GET_SIZE(args) || (kwds && PyDict_Size(kwds))) {
PyErr_SetString(PyExc_ValueError, "This function takes no arguments");
return NULL;
}
return BPyGPUVertFormat_CreatePyObject(NULL);
if (PyTuple_GET_SIZE(args) || (kwds && PyDict_Size(kwds))) {
PyErr_SetString(PyExc_ValueError, "This function takes no arguments");
return NULL;
}
return BPyGPUVertFormat_CreatePyObject(NULL);
}
PyDoc_STRVAR(bpygpu_VertFormat_attr_add_doc,
".. method:: attr_add(id, comp_type, len, fetch_mode)\n"
"\n"
" Add a new attribute to the format.\n"
"\n"
" :param id: Name the attribute. Often `position`, `normal`, ...\n"
" :type id: str\n"
" :param comp_type: The data type that will be used store the value in memory.\n"
" Possible values are `I8`, `U8`, `I16`, `U16`, `I32`, `U32`, `F32` and `I10`.\n"
" :type comp_type: `str`\n"
" :param len: How many individual values the attribute consists of (e.g. 2 for uv coordinates).\n"
" :type len: int\n"
" :param fetch_mode: How values from memory will be converted when used in the shader.\n"
" This is mainly useful for memory optimizations when you want to store values with reduced precision.\n"
" E.g. you can store a float in only 1 byte but it will be converted to a normal 4 byte float when used.\n"
" Possible values are `FLOAT`, `INT`, `INT_TO_FLOAT_UNIT` and `INT_TO_FLOAT`.\n"
" :type fetch_mode: `str`\n"
);
PyDoc_STRVAR(
bpygpu_VertFormat_attr_add_doc,
".. method:: attr_add(id, comp_type, len, fetch_mode)\n"
"\n"
" Add a new attribute to the format.\n"
"\n"
" :param id: Name the attribute. Often `position`, `normal`, ...\n"
" :type id: str\n"
" :param comp_type: The data type that will be used store the value in memory.\n"
" Possible values are `I8`, `U8`, `I16`, `U16`, `I32`, `U32`, `F32` and `I10`.\n"
" :type comp_type: `str`\n"
" :param len: How many individual values the attribute consists of (e.g. 2 for uv "
"coordinates).\n"
" :type len: int\n"
" :param fetch_mode: How values from memory will be converted when used in the shader.\n"
" This is mainly useful for memory optimizations when you want to store values with "
"reduced precision.\n"
" E.g. you can store a float in only 1 byte but it will be converted to a normal 4 byte "
"float when used.\n"
" Possible values are `FLOAT`, `INT`, `INT_TO_FLOAT_UNIT` and `INT_TO_FLOAT`.\n"
" :type fetch_mode: `str`\n");
static PyObject *bpygpu_VertFormat_attr_add(BPyGPUVertFormat *self, PyObject *args, PyObject *kwds)
{
struct {
const char *id;
GPUVertCompType comp_type;
uint len;
GPUVertFetchMode fetch_mode;
} params;
struct {
const char *id;
GPUVertCompType comp_type;
uint len;
GPUVertFetchMode fetch_mode;
} params;
if (self->fmt.attr_len == GPU_VERT_ATTR_MAX_LEN) {
PyErr_SetString(PyExc_ValueError, "Maxumum attr reached " STRINGIFY(GPU_VERT_ATTR_MAX_LEN));
return NULL;
}
if (self->fmt.attr_len == GPU_VERT_ATTR_MAX_LEN) {
PyErr_SetString(PyExc_ValueError, "Maxumum attr reached " STRINGIFY(GPU_VERT_ATTR_MAX_LEN));
return NULL;
}
static const char *_keywords[] = {"id", "comp_type", "len", "fetch_mode", NULL};
static _PyArg_Parser _parser = {"$sO&IO&:attr_add", _keywords, 0};
if (!_PyArg_ParseTupleAndKeywordsFast(
args, kwds, &_parser,
&params.id,
bpygpu_ParseVertCompType, &params.comp_type,
&params.len,
bpygpu_ParseVertFetchMode, &params.fetch_mode))
{
return NULL;
}
static const char *_keywords[] = {"id", "comp_type", "len", "fetch_mode", NULL};
static _PyArg_Parser _parser = {"$sO&IO&:attr_add", _keywords, 0};
if (!_PyArg_ParseTupleAndKeywordsFast(args,
kwds,
&_parser,
&params.id,
bpygpu_ParseVertCompType,
&params.comp_type,
&params.len,
bpygpu_ParseVertFetchMode,
&params.fetch_mode)) {
return NULL;
}
uint attr_id = GPU_vertformat_attr_add(&self->fmt, params.id, params.comp_type, params.len, params.fetch_mode);
return PyLong_FromLong(attr_id);
uint attr_id = GPU_vertformat_attr_add(
&self->fmt, params.id, params.comp_type, params.len, params.fetch_mode);
return PyLong_FromLong(attr_id);
}
static struct PyMethodDef bpygpu_VertFormat_methods[] = {
{"attr_add", (PyCFunction)bpygpu_VertFormat_attr_add,
METH_VARARGS | METH_KEYWORDS, bpygpu_VertFormat_attr_add_doc},
{NULL, NULL, 0, NULL},
{"attr_add",
(PyCFunction)bpygpu_VertFormat_attr_add,
METH_VARARGS | METH_KEYWORDS,
bpygpu_VertFormat_attr_add_doc},
{NULL, NULL, 0, NULL},
};
static void bpygpu_VertFormat_dealloc(BPyGPUVertFormat *self)
{
Py_TYPE(self)->tp_free(self);
Py_TYPE(self)->tp_free(self);
}
PyDoc_STRVAR(bpygpu_VertFormat_doc,
".. class:: GPUVertFormat()\n"
"\n"
" This object contains information about the structure of a vertex buffer.\n"
);
".. class:: GPUVertFormat()\n"
"\n"
" This object contains information about the structure of a vertex buffer.\n");
PyTypeObject BPyGPUVertFormat_Type = {
PyVarObject_HEAD_INIT(NULL, 0)
.tp_name = "GPUVertFormat",
.tp_basicsize = sizeof(BPyGPUVertFormat),
.tp_dealloc = (destructor)bpygpu_VertFormat_dealloc,
.tp_flags = Py_TPFLAGS_DEFAULT,
.tp_doc = bpygpu_VertFormat_doc,
.tp_methods = bpygpu_VertFormat_methods,
.tp_new = bpygpu_VertFormat_new,
PyVarObject_HEAD_INIT(NULL, 0).tp_name = "GPUVertFormat",
.tp_basicsize = sizeof(BPyGPUVertFormat),
.tp_dealloc = (destructor)bpygpu_VertFormat_dealloc,
.tp_flags = Py_TPFLAGS_DEFAULT,
.tp_doc = bpygpu_VertFormat_doc,
.tp_methods = bpygpu_VertFormat_methods,
.tp_new = bpygpu_VertFormat_new,
};
/** \} */
/* -------------------------------------------------------------------- */
/** \name Public API
* \{ */
PyObject *BPyGPUVertFormat_CreatePyObject(GPUVertFormat *fmt)
{
BPyGPUVertFormat *self;
BPyGPUVertFormat *self;
self = PyObject_New(BPyGPUVertFormat, &BPyGPUVertFormat_Type);
if (fmt) {
self->fmt = *fmt;
}
else {
memset(&self->fmt, 0, sizeof(self->fmt));
}
self = PyObject_New(BPyGPUVertFormat, &BPyGPUVertFormat_Type);
if (fmt) {
self->fmt = *fmt;
}
else {
memset(&self->fmt, 0, sizeof(self->fmt));
}
return (PyObject *)self;
return (PyObject *)self;
}
/** \} */

View File

@@ -25,11 +25,10 @@
extern PyTypeObject BPyGPUVertFormat_Type;
#define BPyGPUVertFormat_Check(v) (Py_TYPE(v) == &BPyGPUVertFormat_Type)
#define BPyGPUVertFormat_Check(v) (Py_TYPE(v) == &BPyGPUVertFormat_Type)
typedef struct BPyGPUVertFormat {
PyObject_VAR_HEAD
struct GPUVertFormat fmt;
PyObject_VAR_HEAD struct GPUVertFormat fmt;
} BPyGPUVertFormat;
PyObject *BPyGPUVertFormat_CreatePyObject(struct GPUVertFormat *fmt);

View File

@@ -19,293 +19,293 @@
# ***** END GPL LICENSE BLOCK *****
set(INC
..
../../blenkernel
../../blenlib
../../blenloader
../../blentranslation
../../editors/include
../../gpu
../../imbuf
../../makesdna
../../makesrna
../../windowmanager
../../../../intern/clog
../../../../intern/guardedalloc
../../../../intern/opencolorio
..
../../blenkernel
../../blenlib
../../blenloader
../../blentranslation
../../editors/include
../../gpu
../../imbuf
../../makesdna
../../makesrna
../../windowmanager
../../../../intern/clog
../../../../intern/guardedalloc
../../../../intern/opencolorio
)
set(INC_SYS
${PYTHON_INCLUDE_DIRS}
${PYTHON_INCLUDE_DIRS}
)
set(SRC
bpy.c
bpy_app.c
bpy_app_alembic.c
bpy_app_build_options.c
bpy_app_ffmpeg.c
bpy_app_handlers.c
bpy_app_icons.c
bpy_app_ocio.c
bpy_app_oiio.c
bpy_app_opensubdiv.c
bpy_app_openvdb.c
bpy_app_sdl.c
bpy_app_timers.c
bpy_app_translations.c
bpy_capi_utils.c
bpy_driver.c
bpy_gizmo_wrap.c
bpy_interface.c
bpy_interface_atexit.c
bpy_intern_string.c
bpy_library_load.c
bpy_library_write.c
bpy_msgbus.c
bpy_operator.c
bpy_operator_wrap.c
bpy_path.c
bpy_props.c
bpy_rna.c
bpy_rna_anim.c
bpy_rna_array.c
bpy_rna_callback.c
bpy_rna_driver.c
bpy_rna_gizmo.c
bpy_rna_id_collection.c
bpy_traceback.c
bpy_utils_previews.c
bpy_utils_units.c
stubs.c
bpy.c
bpy_app.c
bpy_app_alembic.c
bpy_app_build_options.c
bpy_app_ffmpeg.c
bpy_app_handlers.c
bpy_app_icons.c
bpy_app_ocio.c
bpy_app_oiio.c
bpy_app_opensubdiv.c
bpy_app_openvdb.c
bpy_app_sdl.c
bpy_app_timers.c
bpy_app_translations.c
bpy_capi_utils.c
bpy_driver.c
bpy_gizmo_wrap.c
bpy_interface.c
bpy_interface_atexit.c
bpy_intern_string.c
bpy_library_load.c
bpy_library_write.c
bpy_msgbus.c
bpy_operator.c
bpy_operator_wrap.c
bpy_path.c
bpy_props.c
bpy_rna.c
bpy_rna_anim.c
bpy_rna_array.c
bpy_rna_callback.c
bpy_rna_driver.c
bpy_rna_gizmo.c
bpy_rna_id_collection.c
bpy_traceback.c
bpy_utils_previews.c
bpy_utils_units.c
stubs.c
bpy.h
bpy_app.h
bpy_app_alembic.h
bpy_app_build_options.h
bpy_app_ffmpeg.h
bpy_app_handlers.h
bpy_app_icons.h
bpy_app_ocio.h
bpy_app_oiio.h
bpy_app_opensubdiv.h
bpy_app_openvdb.h
bpy_app_sdl.h
bpy_app_timers.h
bpy_app_translations.h
bpy_capi_utils.h
bpy_driver.h
bpy_gizmo_wrap.h
bpy_intern_string.h
bpy_library.h
bpy_msgbus.h
bpy_operator.h
bpy_operator_wrap.h
bpy_path.h
bpy_props.h
bpy_rna.h
bpy_rna_anim.h
bpy_rna_callback.h
bpy_rna_driver.h
bpy_rna_gizmo.h
bpy_rna_id_collection.h
bpy_traceback.h
bpy_utils_previews.h
bpy_utils_units.h
../BPY_extern.h
../BPY_extern_clog.h
bpy.h
bpy_app.h
bpy_app_alembic.h
bpy_app_build_options.h
bpy_app_ffmpeg.h
bpy_app_handlers.h
bpy_app_icons.h
bpy_app_ocio.h
bpy_app_oiio.h
bpy_app_opensubdiv.h
bpy_app_openvdb.h
bpy_app_sdl.h
bpy_app_timers.h
bpy_app_translations.h
bpy_capi_utils.h
bpy_driver.h
bpy_gizmo_wrap.h
bpy_intern_string.h
bpy_library.h
bpy_msgbus.h
bpy_operator.h
bpy_operator_wrap.h
bpy_path.h
bpy_props.h
bpy_rna.h
bpy_rna_anim.h
bpy_rna_callback.h
bpy_rna_driver.h
bpy_rna_gizmo.h
bpy_rna_id_collection.h
bpy_traceback.h
bpy_utils_previews.h
bpy_utils_units.h
../BPY_extern.h
../BPY_extern_clog.h
)
set(LIB
bf_editor_animation
bf_editor_interface
bf_editor_space_api
bf_python_gpu
bf_editor_animation
bf_editor_interface
bf_editor_space_api
bf_python_gpu
)
# only to check if buildinfo is available
if(WITH_BUILDINFO)
add_definitions(-DBUILD_DATE)
add_definitions(-DBUILD_DATE)
endif()
if(WITH_PYTHON_MODULE)
add_definitions(-DWITH_PYTHON_MODULE)
add_definitions(-DWITH_PYTHON_MODULE)
endif()
if(WITH_PYTHON_SAFETY)
add_definitions(-DWITH_PYTHON_SAFETY)
add_definitions(-DWITH_PYTHON_SAFETY)
endif()
if(WITH_AUDASPACE)
add_definitions(-DWITH_AUDASPACE)
add_definitions(-DWITH_AUDASPACE)
endif()
if(WITH_BULLET)
add_definitions(-DWITH_BULLET)
add_definitions(-DWITH_BULLET)
endif()
if(WITH_CODEC_AVI)
add_definitions(-DWITH_AVI)
add_definitions(-DWITH_AVI)
endif()
if(WITH_CODEC_FFMPEG)
list(APPEND INC_SYS
${FFMPEG_INCLUDE_DIRS}
)
add_definitions(-DWITH_FFMPEG)
list(APPEND INC_SYS
${FFMPEG_INCLUDE_DIRS}
)
add_definitions(-DWITH_FFMPEG)
endif()
if(WITH_CODEC_SNDFILE)
add_definitions(-DWITH_SNDFILE)
add_definitions(-DWITH_SNDFILE)
endif()
if(WITH_COMPOSITOR)
add_definitions(-DWITH_COMPOSITOR)
add_definitions(-DWITH_COMPOSITOR)
endif()
if(WITH_CYCLES)
list(APPEND INC
../../../../intern/cycles/blender
)
list(APPEND LIB
bf_intern_cycles
)
add_definitions(-DWITH_CYCLES)
list(APPEND INC
../../../../intern/cycles/blender
)
list(APPEND LIB
bf_intern_cycles
)
add_definitions(-DWITH_CYCLES)
endif()
if(WITH_CYCLES_OSL)
add_definitions(-DWITH_CYCLES_OSL)
add_definitions(-DWITH_CYCLES_OSL)
endif()
if(WITH_CYCLES_EMBREE)
add_definitions(-DWITH_CYCLES_EMBREE)
add_definitions(-DWITH_CYCLES_EMBREE)
endif()
if(WITH_FREESTYLE)
list(APPEND INC
../../freestyle/intern/python
)
add_definitions(-DWITH_FREESTYLE)
list(APPEND INC
../../freestyle/intern/python
)
add_definitions(-DWITH_FREESTYLE)
endif()
if(WITH_IMAGE_CINEON)
add_definitions(-DWITH_CINEON)
add_definitions(-DWITH_CINEON)
endif()
if(WITH_IMAGE_DDS)
add_definitions(-DWITH_DDS)
add_definitions(-DWITH_DDS)
endif()
if(WITH_IMAGE_HDR)
add_definitions(-DWITH_HDR)
add_definitions(-DWITH_HDR)
endif()
if(WITH_IMAGE_OPENEXR)
add_definitions(-DWITH_OPENEXR)
add_definitions(-DWITH_OPENEXR)
endif()
if(WITH_OPENIMAGEIO)
add_definitions(-DWITH_OPENIMAGEIO)
add_definitions(-DWITH_OPENIMAGEIO)
endif()
if(WITH_IMAGE_OPENJPEG)
add_definitions(-DWITH_OPENJPEG)
add_definitions(-DWITH_OPENJPEG)
endif()
if(WITH_IMAGE_TIFF)
add_definitions(-DWITH_TIFF)
add_definitions(-DWITH_TIFF)
endif()
if(WITH_INPUT_NDOF)
add_definitions(-DWITH_INPUT_NDOF)
add_definitions(-DWITH_INPUT_NDOF)
endif()
if(WITH_INTERNATIONAL)
add_definitions(-DWITH_INTERNATIONAL)
add_definitions(-DWITH_INTERNATIONAL)
endif()
if(WITH_OPENAL)
add_definitions(-DWITH_OPENAL)
add_definitions(-DWITH_OPENAL)
endif()
if(WITH_SDL)
list(APPEND INC_SYS
${SDL_INCLUDE_DIR}
)
add_definitions(-DWITH_SDL)
list(APPEND INC_SYS
${SDL_INCLUDE_DIR}
)
add_definitions(-DWITH_SDL)
endif()
if(WITH_SDL_DYNLOAD)
list(APPEND INC
../../../../extern/sdlew/include
)
add_definitions(-DWITH_SDL_DYNLOAD)
list(APPEND INC
../../../../extern/sdlew/include
)
add_definitions(-DWITH_SDL_DYNLOAD)
endif()
if(WITH_JACK)
add_definitions(-DWITH_JACK)
add_definitions(-DWITH_JACK)
endif()
if(WITH_LIBMV)
add_definitions(-DWITH_LIBMV)
add_definitions(-DWITH_LIBMV)
endif()
if(WITH_MOD_FLUID)
add_definitions(-DWITH_MOD_FLUID)
add_definitions(-DWITH_MOD_FLUID)
endif()
if(WITH_MOD_OCEANSIM)
add_definitions(-DWITH_OCEANSIM)
add_definitions(-DWITH_OCEANSIM)
endif()
if(WITH_MOD_REMESH)
add_definitions(-DWITH_MOD_REMESH)
add_definitions(-DWITH_MOD_REMESH)
endif()
if(WITH_MOD_SMOKE)
add_definitions(-DWITH_SMOKE)
add_definitions(-DWITH_SMOKE)
endif()
if(WITH_OPENCOLLADA)
add_definitions(-DWITH_COLLADA)
add_definitions(-DWITH_COLLADA)
endif()
if(WITH_ALEMBIC)
add_definitions(-DWITH_ALEMBIC)
add_definitions(-DWITH_ALEMBIC)
endif()
if(WITH_OPENCOLORIO)
add_definitions(-DWITH_OCIO)
add_definitions(-DWITH_OCIO)
endif()
if(WITH_OPENVDB)
add_definitions(-DWITH_OPENVDB)
list(APPEND INC
../../../../intern/openvdb
)
add_definitions(-DWITH_OPENVDB)
list(APPEND INC
../../../../intern/openvdb
)
endif()
if(WITH_ALEMBIC)
add_definitions(-DWITH_ALEMBIC)
list(APPEND INC
../../alembic
)
add_definitions(-DWITH_ALEMBIC)
list(APPEND INC
../../alembic
)
endif()
if(WITH_OPENIMAGEIO)
add_definitions(-DWITH_OPENIMAGEIO)
list(APPEND INC
../../imbuf/intern/oiio
)
add_definitions(-DWITH_OPENIMAGEIO)
list(APPEND INC
../../imbuf/intern/oiio
)
endif()
if(WITH_OPENSUBDIV)
add_definitions(-DWITH_OPENSUBDIV)
list(APPEND INC
../../../../intern/opensubdiv
)
add_definitions(-DWITH_OPENSUBDIV)
list(APPEND INC
../../../../intern/opensubdiv
)
endif()
add_definitions(${GL_DEFINITIONS})

View File

@@ -61,320 +61,347 @@
PyObject *bpy_package_py = NULL;
PyDoc_STRVAR(bpy_script_paths_doc,
".. function:: script_paths()\n"
"\n"
" Return 2 paths to blender scripts directories.\n"
"\n"
" :return: (system, user) strings will be empty when not found.\n"
" :rtype: tuple of strings\n"
);
".. function:: script_paths()\n"
"\n"
" Return 2 paths to blender scripts directories.\n"
"\n"
" :return: (system, user) strings will be empty when not found.\n"
" :rtype: tuple of strings\n");
static PyObject *bpy_script_paths(PyObject *UNUSED(self))
{
PyObject *ret = PyTuple_New(2);
PyObject *item;
const char *path;
PyObject *ret = PyTuple_New(2);
PyObject *item;
const char *path;
path = BKE_appdir_folder_id(BLENDER_SYSTEM_SCRIPTS, NULL);
item = PyC_UnicodeFromByte(path ? path : "");
BLI_assert(item != NULL);
PyTuple_SET_ITEM(ret, 0, item);
path = BKE_appdir_folder_id(BLENDER_USER_SCRIPTS, NULL);
item = PyC_UnicodeFromByte(path ? path : "");
BLI_assert(item != NULL);
PyTuple_SET_ITEM(ret, 1, item);
path = BKE_appdir_folder_id(BLENDER_SYSTEM_SCRIPTS, NULL);
item = PyC_UnicodeFromByte(path ? path : "");
BLI_assert(item != NULL);
PyTuple_SET_ITEM(ret, 0, item);
path = BKE_appdir_folder_id(BLENDER_USER_SCRIPTS, NULL);
item = PyC_UnicodeFromByte(path ? path : "");
BLI_assert(item != NULL);
PyTuple_SET_ITEM(ret, 1, item);
return ret;
return ret;
}
static bool bpy_blend_paths_visit_cb(void *userdata, char *UNUSED(path_dst), const char *path_src)
{
PyList_APPEND((PyObject *)userdata, PyC_UnicodeFromByte(path_src));
return false; /* never edits the path */
PyList_APPEND((PyObject *)userdata, PyC_UnicodeFromByte(path_src));
return false; /* never edits the path */
}
PyDoc_STRVAR(bpy_blend_paths_doc,
".. function:: blend_paths(absolute=False, packed=False, local=False)\n"
"\n"
" Returns a list of paths to external files referenced by the loaded .blend file.\n"
"\n"
" :arg absolute: When true the paths returned are made absolute.\n"
" :type absolute: boolean\n"
" :arg packed: When true skip file paths for packed data.\n"
" :type packed: boolean\n"
" :arg local: When true skip linked library paths.\n"
" :type local: boolean\n"
" :return: path list.\n"
" :rtype: list of strings\n"
);
".. function:: blend_paths(absolute=False, packed=False, local=False)\n"
"\n"
" Returns a list of paths to external files referenced by the loaded .blend file.\n"
"\n"
" :arg absolute: When true the paths returned are made absolute.\n"
" :type absolute: boolean\n"
" :arg packed: When true skip file paths for packed data.\n"
" :type packed: boolean\n"
" :arg local: When true skip linked library paths.\n"
" :type local: boolean\n"
" :return: path list.\n"
" :rtype: list of strings\n");
static PyObject *bpy_blend_paths(PyObject *UNUSED(self), PyObject *args, PyObject *kw)
{
int flag = 0;
PyObject *list;
int flag = 0;
PyObject *list;
bool absolute = false;
bool packed = false;
bool local = false;
bool absolute = false;
bool packed = false;
bool local = false;
static const char *_keywords[] = {"absolute", "packed", "local", NULL};
static _PyArg_Parser _parser = {"|O&O&O&:blend_paths", _keywords, 0};
if (!_PyArg_ParseTupleAndKeywordsFast(
args, kw, &_parser,
PyC_ParseBool, &absolute,
PyC_ParseBool, &packed,
PyC_ParseBool, &local))
{
return NULL;
}
static const char *_keywords[] = {"absolute", "packed", "local", NULL};
static _PyArg_Parser _parser = {"|O&O&O&:blend_paths", _keywords, 0};
if (!_PyArg_ParseTupleAndKeywordsFast(args,
kw,
&_parser,
PyC_ParseBool,
&absolute,
PyC_ParseBool,
&packed,
PyC_ParseBool,
&local)) {
return NULL;
}
if (absolute) {
flag |= BKE_BPATH_TRAVERSE_ABS;
}
if (!packed) {
flag |= BKE_BPATH_TRAVERSE_SKIP_PACKED;
}
if (local) {
flag |= BKE_BPATH_TRAVERSE_SKIP_LIBRARY;
}
if (absolute) {
flag |= BKE_BPATH_TRAVERSE_ABS;
}
if (!packed) {
flag |= BKE_BPATH_TRAVERSE_SKIP_PACKED;
}
if (local) {
flag |= BKE_BPATH_TRAVERSE_SKIP_LIBRARY;
}
list = PyList_New(0);
list = PyList_New(0);
BKE_bpath_traverse_main(G_MAIN, bpy_blend_paths_visit_cb, flag, (void *)list);
BKE_bpath_traverse_main(G_MAIN, bpy_blend_paths_visit_cb, flag, (void *)list);
return list;
return list;
}
// PyDoc_STRVAR(bpy_user_resource_doc[] = // now in bpy/utils.py
static PyObject *bpy_user_resource(PyObject *UNUSED(self), PyObject *args, PyObject *kw)
{
const char *type;
const char *subdir = NULL;
int folder_id;
const char *type;
const char *subdir = NULL;
int folder_id;
const char *path;
const char *path;
static const char *_keywords[] = {"type", "subdir", NULL};
static _PyArg_Parser _parser = {"s|s:user_resource", _keywords, 0};
if (!_PyArg_ParseTupleAndKeywordsFast(
args, kw, &_parser,
&type, &subdir))
{
return NULL;
}
static const char *_keywords[] = {"type", "subdir", NULL};
static _PyArg_Parser _parser = {"s|s:user_resource", _keywords, 0};
if (!_PyArg_ParseTupleAndKeywordsFast(args, kw, &_parser, &type, &subdir)) {
return NULL;
}
/* stupid string compare */
if (STREQ(type, "DATAFILES")) { folder_id = BLENDER_USER_DATAFILES; }
else if (STREQ(type, "CONFIG")) { folder_id = BLENDER_USER_CONFIG; }
else if (STREQ(type, "SCRIPTS")) { folder_id = BLENDER_USER_SCRIPTS; }
else if (STREQ(type, "AUTOSAVE")) { folder_id = BLENDER_USER_AUTOSAVE; }
else {
PyErr_SetString(PyExc_ValueError, "invalid resource argument");
return NULL;
}
/* stupid string compare */
if (STREQ(type, "DATAFILES")) {
folder_id = BLENDER_USER_DATAFILES;
}
else if (STREQ(type, "CONFIG")) {
folder_id = BLENDER_USER_CONFIG;
}
else if (STREQ(type, "SCRIPTS")) {
folder_id = BLENDER_USER_SCRIPTS;
}
else if (STREQ(type, "AUTOSAVE")) {
folder_id = BLENDER_USER_AUTOSAVE;
}
else {
PyErr_SetString(PyExc_ValueError, "invalid resource argument");
return NULL;
}
/* same logic as BKE_appdir_folder_id_create(), but best leave it up to the script author to create */
path = BKE_appdir_folder_id_user_notest(folder_id, subdir);
/* same logic as BKE_appdir_folder_id_create(), but best leave it up to the script author to create */
path = BKE_appdir_folder_id_user_notest(folder_id, subdir);
return PyC_UnicodeFromByte(path ? path : "");
return PyC_UnicodeFromByte(path ? path : "");
}
PyDoc_STRVAR(bpy_resource_path_doc,
".. function:: resource_path(type, major=bpy.app.version[0], minor=bpy.app.version[1])\n"
"\n"
" Return the base path for storing system files.\n"
"\n"
" :arg type: string in ['USER', 'LOCAL', 'SYSTEM'].\n"
" :type type: string\n"
" :arg major: major version, defaults to current.\n"
" :type major: int\n"
" :arg minor: minor version, defaults to current.\n"
" :type minor: string\n"
" :return: the resource path (not necessarily existing).\n"
" :rtype: string\n"
);
PyDoc_STRVAR(
bpy_resource_path_doc,
".. function:: resource_path(type, major=bpy.app.version[0], minor=bpy.app.version[1])\n"
"\n"
" Return the base path for storing system files.\n"
"\n"
" :arg type: string in ['USER', 'LOCAL', 'SYSTEM'].\n"
" :type type: string\n"
" :arg major: major version, defaults to current.\n"
" :type major: int\n"
" :arg minor: minor version, defaults to current.\n"
" :type minor: string\n"
" :return: the resource path (not necessarily existing).\n"
" :rtype: string\n");
static PyObject *bpy_resource_path(PyObject *UNUSED(self), PyObject *args, PyObject *kw)
{
const char *type;
int major = BLENDER_VERSION / 100, minor = BLENDER_VERSION % 100;
int folder_id;
const char *path;
const char *type;
int major = BLENDER_VERSION / 100, minor = BLENDER_VERSION % 100;
int folder_id;
const char *path;
static const char *_keywords[] = {"type", "major", "minor", NULL};
static _PyArg_Parser _parser = {"s|ii:resource_path", _keywords, 0};
if (!_PyArg_ParseTupleAndKeywordsFast(
args, kw, &_parser,
&type, &major, &minor))
{
return NULL;
}
static const char *_keywords[] = {"type", "major", "minor", NULL};
static _PyArg_Parser _parser = {"s|ii:resource_path", _keywords, 0};
if (!_PyArg_ParseTupleAndKeywordsFast(args, kw, &_parser, &type, &major, &minor)) {
return NULL;
}
/* stupid string compare */
if (STREQ(type, "USER")) { folder_id = BLENDER_RESOURCE_PATH_USER; }
else if (STREQ(type, "LOCAL")) { folder_id = BLENDER_RESOURCE_PATH_LOCAL; }
else if (STREQ(type, "SYSTEM")) { folder_id = BLENDER_RESOURCE_PATH_SYSTEM; }
else {
PyErr_SetString(PyExc_ValueError, "invalid resource argument");
return NULL;
}
/* stupid string compare */
if (STREQ(type, "USER")) {
folder_id = BLENDER_RESOURCE_PATH_USER;
}
else if (STREQ(type, "LOCAL")) {
folder_id = BLENDER_RESOURCE_PATH_LOCAL;
}
else if (STREQ(type, "SYSTEM")) {
folder_id = BLENDER_RESOURCE_PATH_SYSTEM;
}
else {
PyErr_SetString(PyExc_ValueError, "invalid resource argument");
return NULL;
}
path = BKE_appdir_folder_id_version(folder_id, (major * 100) + minor, false);
path = BKE_appdir_folder_id_version(folder_id, (major * 100) + minor, false);
return PyC_UnicodeFromByte(path ? path : "");
return PyC_UnicodeFromByte(path ? path : "");
}
PyDoc_STRVAR(bpy_escape_identifier_doc,
".. function:: escape_identifier(string)\n"
"\n"
" Simple string escaping function used for animation paths.\n"
"\n"
" :arg string: text\n"
" :type string: string\n"
" :return: The escaped string.\n"
" :rtype: string\n"
);
".. function:: escape_identifier(string)\n"
"\n"
" Simple string escaping function used for animation paths.\n"
"\n"
" :arg string: text\n"
" :type string: string\n"
" :return: The escaped string.\n"
" :rtype: string\n");
static PyObject *bpy_escape_identifier(PyObject *UNUSED(self), PyObject *value)
{
const char *value_str;
Py_ssize_t value_str_len;
const char *value_str;
Py_ssize_t value_str_len;
char *value_escape_str;
Py_ssize_t value_escape_str_len;
PyObject *value_escape;
size_t size;
char *value_escape_str;
Py_ssize_t value_escape_str_len;
PyObject *value_escape;
size_t size;
value_str = _PyUnicode_AsStringAndSize(value, &value_str_len);
value_str = _PyUnicode_AsStringAndSize(value, &value_str_len);
if (value_str == NULL) {
PyErr_SetString(PyExc_TypeError, "expected a string");
return NULL;
}
if (value_str == NULL) {
PyErr_SetString(PyExc_TypeError, "expected a string");
return NULL;
}
size = (value_str_len * 2) + 1;
value_escape_str = PyMem_MALLOC(size);
value_escape_str_len = BLI_strescape(value_escape_str, value_str, size);
size = (value_str_len * 2) + 1;
value_escape_str = PyMem_MALLOC(size);
value_escape_str_len = BLI_strescape(value_escape_str, value_str, size);
if (value_escape_str_len == value_str_len) {
Py_INCREF(value);
value_escape = value;
}
else {
value_escape = PyUnicode_FromStringAndSize(value_escape_str, value_escape_str_len);
}
if (value_escape_str_len == value_str_len) {
Py_INCREF(value);
value_escape = value;
}
else {
value_escape = PyUnicode_FromStringAndSize(value_escape_str, value_escape_str_len);
}
PyMem_FREE(value_escape_str);
PyMem_FREE(value_escape_str);
return value_escape;
return value_escape;
}
static PyMethodDef meth_bpy_script_paths =
{"script_paths", (PyCFunction)bpy_script_paths, METH_NOARGS, bpy_script_paths_doc};
static PyMethodDef meth_bpy_blend_paths =
{"blend_paths", (PyCFunction)bpy_blend_paths, METH_VARARGS | METH_KEYWORDS, bpy_blend_paths_doc};
static PyMethodDef meth_bpy_user_resource =
{"user_resource", (PyCFunction)bpy_user_resource, METH_VARARGS | METH_KEYWORDS, NULL};
static PyMethodDef meth_bpy_resource_path =
{"resource_path", (PyCFunction)bpy_resource_path, METH_VARARGS | METH_KEYWORDS, bpy_resource_path_doc};
static PyMethodDef meth_bpy_escape_identifier =
{"escape_identifier", (PyCFunction)bpy_escape_identifier, METH_O, bpy_escape_identifier_doc};
static PyMethodDef meth_bpy_script_paths = {
"script_paths", (PyCFunction)bpy_script_paths, METH_NOARGS, bpy_script_paths_doc};
static PyMethodDef meth_bpy_blend_paths = {"blend_paths",
(PyCFunction)bpy_blend_paths,
METH_VARARGS | METH_KEYWORDS,
bpy_blend_paths_doc};
static PyMethodDef meth_bpy_user_resource = {
"user_resource", (PyCFunction)bpy_user_resource, METH_VARARGS | METH_KEYWORDS, NULL};
static PyMethodDef meth_bpy_resource_path = {"resource_path",
(PyCFunction)bpy_resource_path,
METH_VARARGS | METH_KEYWORDS,
bpy_resource_path_doc};
static PyMethodDef meth_bpy_escape_identifier = {
"escape_identifier", (PyCFunction)bpy_escape_identifier, METH_O, bpy_escape_identifier_doc};
static PyObject *bpy_import_test(const char *modname)
{
PyObject *mod = PyImport_ImportModuleLevel(modname, NULL, NULL, NULL, 0);
if (mod) {
Py_DECREF(mod);
}
else {
PyErr_Print();
PyErr_Clear();
}
PyObject *mod = PyImport_ImportModuleLevel(modname, NULL, NULL, NULL, 0);
if (mod) {
Py_DECREF(mod);
}
else {
PyErr_Print();
PyErr_Clear();
}
return mod;
return mod;
}
/******************************************************************************
* Description: Creates the bpy module and adds it to sys.modules for importing
******************************************************************************/
void BPy_init_modules(void)
{
PointerRNA ctx_ptr;
PyObject *mod;
PointerRNA ctx_ptr;
PyObject *mod;
/* Needs to be first since this dir is needed for future modules */
const char * const modpath = BKE_appdir_folder_id(BLENDER_SYSTEM_SCRIPTS, "modules");
if (modpath) {
// printf("bpy: found module path '%s'.\n", modpath);
PyObject *sys_path = PySys_GetObject("path"); /* borrow */
PyObject *py_modpath = PyUnicode_FromString(modpath);
PyList_Insert(sys_path, 0, py_modpath); /* add first */
Py_DECREF(py_modpath);
}
else {
printf("bpy: couldnt find 'scripts/modules', blender probably wont start.\n");
}
/* stand alone utility modules not related to blender directly */
IDProp_Init_Types(); /* not actually a submodule, just types */
/* Needs to be first since this dir is needed for future modules */
const char *const modpath = BKE_appdir_folder_id(BLENDER_SYSTEM_SCRIPTS, "modules");
if (modpath) {
// printf("bpy: found module path '%s'.\n", modpath);
PyObject *sys_path = PySys_GetObject("path"); /* borrow */
PyObject *py_modpath = PyUnicode_FromString(modpath);
PyList_Insert(sys_path, 0, py_modpath); /* add first */
Py_DECREF(py_modpath);
}
else {
printf("bpy: couldnt find 'scripts/modules', blender probably wont start.\n");
}
/* stand alone utility modules not related to blender directly */
IDProp_Init_Types(); /* not actually a submodule, just types */
#ifdef WITH_FREESTYLE
Freestyle_Init();
Freestyle_Init();
#endif
mod = PyModule_New("_bpy");
mod = PyModule_New("_bpy");
/* add the module so we can import it */
PyDict_SetItemString(PyImport_GetModuleDict(), "_bpy", mod);
Py_DECREF(mod);
/* add the module so we can import it */
PyDict_SetItemString(PyImport_GetModuleDict(), "_bpy", mod);
Py_DECREF(mod);
/* run first, initializes rna types */
BPY_rna_init();
/* run first, initializes rna types */
BPY_rna_init();
/* needs to be first so bpy_types can run */
PyModule_AddObject(mod, "types", BPY_rna_types());
/* needs to be first so bpy_types can run */
PyModule_AddObject(mod, "types", BPY_rna_types());
/* needs to be first so bpy_types can run */
BPY_library_load_module(mod);
BPY_library_write_module(mod);
/* needs to be first so bpy_types can run */
BPY_library_load_module(mod);
BPY_library_write_module(mod);
BPY_rna_id_collection_module(mod);
BPY_rna_id_collection_module(mod);
BPY_rna_gizmo_module(mod);
BPY_rna_gizmo_module(mod);
bpy_import_test("bpy_types");
PyModule_AddObject(mod, "data", BPY_rna_module()); /* imports bpy_types by running this */
bpy_import_test("bpy_types");
PyModule_AddObject(mod, "props", BPY_rna_props());
/* ops is now a python module that does the conversion from SOME_OT_foo -> some.foo */
PyModule_AddObject(mod, "ops", BPY_operator_module());
PyModule_AddObject(mod, "app", BPY_app_struct());
PyModule_AddObject(mod, "_utils_units", BPY_utils_units());
PyModule_AddObject(mod, "_utils_previews", BPY_utils_previews_module());
PyModule_AddObject(mod, "msgbus", BPY_msgbus_module());
bpy_import_test("bpy_types");
PyModule_AddObject(mod, "data", BPY_rna_module()); /* imports bpy_types by running this */
bpy_import_test("bpy_types");
PyModule_AddObject(mod, "props", BPY_rna_props());
/* ops is now a python module that does the conversion from SOME_OT_foo -> some.foo */
PyModule_AddObject(mod, "ops", BPY_operator_module());
PyModule_AddObject(mod, "app", BPY_app_struct());
PyModule_AddObject(mod, "_utils_units", BPY_utils_units());
PyModule_AddObject(mod, "_utils_previews", BPY_utils_previews_module());
PyModule_AddObject(mod, "msgbus", BPY_msgbus_module());
/* bpy context */
RNA_pointer_create(NULL, &RNA_Context, (void *)BPy_GetContext(), &ctx_ptr);
bpy_context_module = (BPy_StructRNA *)pyrna_struct_CreatePyObject(&ctx_ptr);
/* odd that this is needed, 1 ref on creation and another for the module
* but without we get a crash on exit */
Py_INCREF(bpy_context_module);
/* bpy context */
RNA_pointer_create(NULL, &RNA_Context, (void *)BPy_GetContext(), &ctx_ptr);
bpy_context_module = (BPy_StructRNA *)pyrna_struct_CreatePyObject(&ctx_ptr);
/* odd that this is needed, 1 ref on creation and another for the module
* but without we get a crash on exit */
Py_INCREF(bpy_context_module);
PyModule_AddObject(mod, "context", (PyObject *)bpy_context_module);
PyModule_AddObject(mod, "context", (PyObject *)bpy_context_module);
/* register bpy/rna classmethod callbacks */
BPY_rna_register_cb();
/* register bpy/rna classmethod callbacks */
BPY_rna_register_cb();
/* utility func's that have nowhere else to go */
PyModule_AddObject(mod, meth_bpy_script_paths.ml_name, (PyObject *)PyCFunction_New(&meth_bpy_script_paths, NULL));
PyModule_AddObject(mod, meth_bpy_blend_paths.ml_name, (PyObject *)PyCFunction_New(&meth_bpy_blend_paths, NULL));
PyModule_AddObject(mod, meth_bpy_user_resource.ml_name, (PyObject *)PyCFunction_New(&meth_bpy_user_resource, NULL));
PyModule_AddObject(mod, meth_bpy_resource_path.ml_name, (PyObject *)PyCFunction_New(&meth_bpy_resource_path, NULL));
PyModule_AddObject(mod, meth_bpy_escape_identifier.ml_name, (PyObject *)PyCFunction_New(&meth_bpy_escape_identifier, NULL));
/* utility func's that have nowhere else to go */
PyModule_AddObject(mod,
meth_bpy_script_paths.ml_name,
(PyObject *)PyCFunction_New(&meth_bpy_script_paths, NULL));
PyModule_AddObject(
mod, meth_bpy_blend_paths.ml_name, (PyObject *)PyCFunction_New(&meth_bpy_blend_paths, NULL));
PyModule_AddObject(mod,
meth_bpy_user_resource.ml_name,
(PyObject *)PyCFunction_New(&meth_bpy_user_resource, NULL));
PyModule_AddObject(mod,
meth_bpy_resource_path.ml_name,
(PyObject *)PyCFunction_New(&meth_bpy_resource_path, NULL));
PyModule_AddObject(mod,
meth_bpy_escape_identifier.ml_name,
(PyObject *)PyCFunction_New(&meth_bpy_escape_identifier, NULL));
/* register funcs (bpy_rna.c) */
PyModule_AddObject(mod, meth_bpy_register_class.ml_name, (PyObject *)PyCFunction_New(&meth_bpy_register_class, NULL));
PyModule_AddObject(mod, meth_bpy_unregister_class.ml_name, (PyObject *)PyCFunction_New(&meth_bpy_unregister_class, NULL));
/* register funcs (bpy_rna.c) */
PyModule_AddObject(mod,
meth_bpy_register_class.ml_name,
(PyObject *)PyCFunction_New(&meth_bpy_register_class, NULL));
PyModule_AddObject(mod,
meth_bpy_unregister_class.ml_name,
(PyObject *)PyCFunction_New(&meth_bpy_unregister_class, NULL));
PyModule_AddObject(mod, meth_bpy_owner_id_get.ml_name, (PyObject *)PyCFunction_New(&meth_bpy_owner_id_get, NULL));
PyModule_AddObject(mod, meth_bpy_owner_id_set.ml_name, (PyObject *)PyCFunction_New(&meth_bpy_owner_id_set, NULL));
PyModule_AddObject(mod,
meth_bpy_owner_id_get.ml_name,
(PyObject *)PyCFunction_New(&meth_bpy_owner_id_get, NULL));
PyModule_AddObject(mod,
meth_bpy_owner_id_set.ml_name,
(PyObject *)PyCFunction_New(&meth_bpy_owner_id_set, NULL));
/* add our own modules dir, this is a python package */
bpy_package_py = bpy_import_test("bpy");
/* add our own modules dir, this is a python package */
bpy_package_py = bpy_import_test("bpy");
}

View File

@@ -31,4 +31,4 @@ void BPY_atexit_unregister(void);
extern struct CLG_LogRef *BPY_LOG_CONTEXT;
extern struct CLG_LogRef *BPY_LOG_RNA;
#endif /* __BPY_H__ */
#endif /* __BPY_H__ */

View File

@@ -22,7 +22,6 @@
* however some writable variables have been added such as 'debug' and 'tempdir'
*/
#include <Python.h>
#include "bpy_app.h"
@@ -82,407 +81,504 @@ extern char build_system[];
static PyTypeObject BlenderAppType;
static PyStructSequence_Field app_info_fields[] = {
{(char *)"version", (char *)"The Blender version as a tuple of 3 numbers. eg. (2, 50, 11)"},
{(char *)"version_string", (char *)"The Blender version formatted as a string"},
{(char *)"version_char", (char *)"The Blender version character (for minor releases)"},
{(char *)"version_cycle", (char *)"The release status of this build alpha/beta/rc/release"},
{(char *)"binary_path", (char *)"The location of blenders executable, useful for utilities that spawn new instances"},
{(char *)"background", (char *)"Boolean, True when blender is running without a user interface (started with -b)"},
{(char *)"factory_startup", (char *)"Boolean, True when blender is running with --factory-startup)"},
{(char *)"version", (char *)"The Blender version as a tuple of 3 numbers. eg. (2, 50, 11)"},
{(char *)"version_string", (char *)"The Blender version formatted as a string"},
{(char *)"version_char", (char *)"The Blender version character (for minor releases)"},
{(char *)"version_cycle", (char *)"The release status of this build alpha/beta/rc/release"},
{(char *)"binary_path",
(char *)"The location of blenders executable, useful for utilities that spawn new instances"},
{(char *)"background",
(char *)"Boolean, True when blender is running without a user interface (started with -b)"},
{(char *)"factory_startup",
(char *)"Boolean, True when blender is running with --factory-startup)"},
/* buildinfo */
{(char *)"build_date", (char *)"The date this blender instance was built"},
{(char *)"build_time", (char *)"The time this blender instance was built"},
{(char *)"build_commit_timestamp", (char *)"The unix timestamp of commit this blender instance was built"},
{(char *)"build_commit_date", (char *)"The date of commit this blender instance was built"},
{(char *)"build_commit_time", (char *)"The time of commit this blender instance was built"},
{(char *)"build_hash", (char *)"The commit hash this blender instance was built with"},
{(char *)"build_branch", (char *)"The branch this blender instance was built from"},
{(char *)"build_platform", (char *)"The platform this blender instance was built for"},
{(char *)"build_type", (char *)"The type of build (Release, Debug)"},
{(char *)"build_cflags", (char *)"C compiler flags"},
{(char *)"build_cxxflags", (char *)"C++ compiler flags"},
{(char *)"build_linkflags", (char *)"Binary linking flags"},
{(char *)"build_system", (char *)"Build system used"},
/* buildinfo */
{(char *)"build_date", (char *)"The date this blender instance was built"},
{(char *)"build_time", (char *)"The time this blender instance was built"},
{(char *)"build_commit_timestamp",
(char *)"The unix timestamp of commit this blender instance was built"},
{(char *)"build_commit_date", (char *)"The date of commit this blender instance was built"},
{(char *)"build_commit_time", (char *)"The time of commit this blender instance was built"},
{(char *)"build_hash", (char *)"The commit hash this blender instance was built with"},
{(char *)"build_branch", (char *)"The branch this blender instance was built from"},
{(char *)"build_platform", (char *)"The platform this blender instance was built for"},
{(char *)"build_type", (char *)"The type of build (Release, Debug)"},
{(char *)"build_cflags", (char *)"C compiler flags"},
{(char *)"build_cxxflags", (char *)"C++ compiler flags"},
{(char *)"build_linkflags", (char *)"Binary linking flags"},
{(char *)"build_system", (char *)"Build system used"},
/* submodules */
{(char *)"alembic", (char *)"Alembic library information backend"},
{(char *)"ffmpeg", (char *)"FFmpeg library information backend"},
{(char *)"ocio", (char *)"OpenColorIO library information backend"},
{(char *)"oiio", (char *)"OpenImageIO library information backend"},
{(char *)"opensubdiv", (char *)"OpenSubdiv library information backend"},
{(char *)"openvdb", (char *)"OpenVDB library information backend"},
{(char *)"sdl", (char *)"SDL library information backend"},
{(char *)"build_options", (char *)"A set containing most important enabled optional build features"},
{(char *)"handlers", (char *)"Application handler callbacks"},
{(char *)"translations", (char *)"Application and addons internationalization API"},
/* submodules */
{(char *)"alembic", (char *)"Alembic library information backend"},
{(char *)"ffmpeg", (char *)"FFmpeg library information backend"},
{(char *)"ocio", (char *)"OpenColorIO library information backend"},
{(char *)"oiio", (char *)"OpenImageIO library information backend"},
{(char *)"opensubdiv", (char *)"OpenSubdiv library information backend"},
{(char *)"openvdb", (char *)"OpenVDB library information backend"},
{(char *)"sdl", (char *)"SDL library information backend"},
{(char *)"build_options",
(char *)"A set containing most important enabled optional build features"},
{(char *)"handlers", (char *)"Application handler callbacks"},
{(char *)"translations", (char *)"Application and addons internationalization API"},
/* Modules (not struct sequence). */
{(char *)"icons", (char *)"Manage custom icons"},
{(char *)"timers", (char *)"Manage timers"},
{NULL},
/* Modules (not struct sequence). */
{(char *)"icons", (char *)"Manage custom icons"},
{(char *)"timers", (char *)"Manage timers"},
{NULL},
};
PyDoc_STRVAR(bpy_app_doc,
"This module contains application values that remain unchanged during runtime.\n"
"\n"
"Submodules:\n"
"\n"
".. toctree::\n"
" :maxdepth: 1\n"
"\n"
" bpy.app.handlers.rst\n"
" bpy.app.icons.rst\n"
" bpy.app.timers.rst\n"
" bpy.app.translations.rst\n"
);
"This module contains application values that remain unchanged during runtime.\n"
"\n"
"Submodules:\n"
"\n"
".. toctree::\n"
" :maxdepth: 1\n"
"\n"
" bpy.app.handlers.rst\n"
" bpy.app.icons.rst\n"
" bpy.app.timers.rst\n"
" bpy.app.translations.rst\n");
static PyStructSequence_Desc app_info_desc = {
(char *)"bpy.app", /* name */
bpy_app_doc, /* doc */
app_info_fields, /* fields */
ARRAY_SIZE(app_info_fields) - 1,
(char *)"bpy.app", /* name */
bpy_app_doc, /* doc */
app_info_fields, /* fields */
ARRAY_SIZE(app_info_fields) - 1,
};
static PyObject *make_app_info(void)
{
PyObject *app_info;
int pos = 0;
PyObject *app_info;
int pos = 0;
app_info = PyStructSequence_New(&BlenderAppType);
if (app_info == NULL) {
return NULL;
}
#define SetIntItem(flag) \
PyStructSequence_SET_ITEM(app_info, pos++, PyLong_FromLong(flag))
#define SetStrItem(str) \
PyStructSequence_SET_ITEM(app_info, pos++, PyUnicode_FromString(str))
#define SetBytesItem(str) \
PyStructSequence_SET_ITEM(app_info, pos++, PyBytes_FromString(str))
#define SetObjItem(obj) \
PyStructSequence_SET_ITEM(app_info, pos++, obj)
app_info = PyStructSequence_New(&BlenderAppType);
if (app_info == NULL) {
return NULL;
}
#define SetIntItem(flag) PyStructSequence_SET_ITEM(app_info, pos++, PyLong_FromLong(flag))
#define SetStrItem(str) PyStructSequence_SET_ITEM(app_info, pos++, PyUnicode_FromString(str))
#define SetBytesItem(str) PyStructSequence_SET_ITEM(app_info, pos++, PyBytes_FromString(str))
#define SetObjItem(obj) PyStructSequence_SET_ITEM(app_info, pos++, obj)
SetObjItem(PyC_Tuple_Pack_I32(BLENDER_VERSION / 100, BLENDER_VERSION % 100, BLENDER_SUBVERSION));
SetObjItem(PyUnicode_FromFormat("%d.%02d (sub %d)",
BLENDER_VERSION / 100, BLENDER_VERSION % 100, BLENDER_SUBVERSION));
SetObjItem(PyC_Tuple_Pack_I32(BLENDER_VERSION / 100, BLENDER_VERSION % 100, BLENDER_SUBVERSION));
SetObjItem(PyUnicode_FromFormat(
"%d.%02d (sub %d)", BLENDER_VERSION / 100, BLENDER_VERSION % 100, BLENDER_SUBVERSION));
SetStrItem(STRINGIFY(BLENDER_VERSION_CHAR));
SetStrItem(STRINGIFY(BLENDER_VERSION_CYCLE));
SetStrItem(BKE_appdir_program_path());
SetObjItem(PyBool_FromLong(G.background));
SetObjItem(PyBool_FromLong(G.factory_startup));
SetStrItem(STRINGIFY(BLENDER_VERSION_CHAR));
SetStrItem(STRINGIFY(BLENDER_VERSION_CYCLE));
SetStrItem(BKE_appdir_program_path());
SetObjItem(PyBool_FromLong(G.background));
SetObjItem(PyBool_FromLong(G.factory_startup));
/* build info, use bytes since we can't assume _any_ encoding:
* see patch [#30154] for issue */
/* build info, use bytes since we can't assume _any_ encoding:
* see patch [#30154] for issue */
#ifdef BUILD_DATE
SetBytesItem(build_date);
SetBytesItem(build_time);
SetIntItem(build_commit_timestamp);
SetBytesItem(build_commit_date);
SetBytesItem(build_commit_time);
SetBytesItem(build_hash);
SetBytesItem(build_branch);
SetBytesItem(build_platform);
SetBytesItem(build_type);
SetBytesItem(build_cflags);
SetBytesItem(build_cxxflags);
SetBytesItem(build_linkflags);
SetBytesItem(build_system);
SetBytesItem(build_date);
SetBytesItem(build_time);
SetIntItem(build_commit_timestamp);
SetBytesItem(build_commit_date);
SetBytesItem(build_commit_time);
SetBytesItem(build_hash);
SetBytesItem(build_branch);
SetBytesItem(build_platform);
SetBytesItem(build_type);
SetBytesItem(build_cflags);
SetBytesItem(build_cxxflags);
SetBytesItem(build_linkflags);
SetBytesItem(build_system);
#else
SetBytesItem("Unknown");
SetBytesItem("Unknown");
SetIntItem(0);
SetBytesItem("Unknown");
SetBytesItem("Unknown");
SetBytesItem("Unknown");
SetBytesItem("Unknown");
SetBytesItem("Unknown");
SetBytesItem("Unknown");
SetBytesItem("Unknown");
SetBytesItem("Unknown");
SetBytesItem("Unknown");
SetBytesItem("Unknown");
SetBytesItem("Unknown");
SetBytesItem("Unknown");
SetIntItem(0);
SetBytesItem("Unknown");
SetBytesItem("Unknown");
SetBytesItem("Unknown");
SetBytesItem("Unknown");
SetBytesItem("Unknown");
SetBytesItem("Unknown");
SetBytesItem("Unknown");
SetBytesItem("Unknown");
SetBytesItem("Unknown");
SetBytesItem("Unknown");
#endif
SetObjItem(BPY_app_alembic_struct());
SetObjItem(BPY_app_ffmpeg_struct());
SetObjItem(BPY_app_ocio_struct());
SetObjItem(BPY_app_oiio_struct());
SetObjItem(BPY_app_opensubdiv_struct());
SetObjItem(BPY_app_openvdb_struct());
SetObjItem(BPY_app_sdl_struct());
SetObjItem(BPY_app_build_options_struct());
SetObjItem(BPY_app_handlers_struct());
SetObjItem(BPY_app_translations_struct());
SetObjItem(BPY_app_alembic_struct());
SetObjItem(BPY_app_ffmpeg_struct());
SetObjItem(BPY_app_ocio_struct());
SetObjItem(BPY_app_oiio_struct());
SetObjItem(BPY_app_opensubdiv_struct());
SetObjItem(BPY_app_openvdb_struct());
SetObjItem(BPY_app_sdl_struct());
SetObjItem(BPY_app_build_options_struct());
SetObjItem(BPY_app_handlers_struct());
SetObjItem(BPY_app_translations_struct());
/* modules */
SetObjItem(BPY_app_icons_module());
SetObjItem(BPY_app_timers_module());
/* modules */
SetObjItem(BPY_app_icons_module());
SetObjItem(BPY_app_timers_module());
#undef SetIntItem
#undef SetStrItem
#undef SetBytesItem
#undef SetObjItem
if (PyErr_Occurred()) {
Py_CLEAR(app_info);
return NULL;
}
return app_info;
if (PyErr_Occurred()) {
Py_CLEAR(app_info);
return NULL;
}
return app_info;
}
/* a few getsets because it makes sense for them to be in bpy.app even though
* they are not static */
PyDoc_STRVAR(bpy_app_debug_doc,
"Boolean, for debug info (started with --debug / --debug_* matching this attribute name)"
);
PyDoc_STRVAR(
bpy_app_debug_doc,
"Boolean, for debug info (started with --debug / --debug_* matching this attribute name)");
static PyObject *bpy_app_debug_get(PyObject *UNUSED(self), void *closure)
{
const int flag = POINTER_AS_INT(closure);
return PyBool_FromLong(G.debug & flag);
const int flag = POINTER_AS_INT(closure);
return PyBool_FromLong(G.debug & flag);
}
static int bpy_app_debug_set(PyObject *UNUSED(self), PyObject *value, void *closure)
{
const int flag = POINTER_AS_INT(closure);
const int param = PyObject_IsTrue(value);
const int flag = POINTER_AS_INT(closure);
const int param = PyObject_IsTrue(value);
if (param == -1) {
PyErr_SetString(PyExc_TypeError, "bpy.app.debug can only be True/False");
return -1;
}
if (param == -1) {
PyErr_SetString(PyExc_TypeError, "bpy.app.debug can only be True/False");
return -1;
}
if (param) {
G.debug |= flag;
}
else {
G.debug &= ~flag;
}
if (param) {
G.debug |= flag;
}
else {
G.debug &= ~flag;
}
return 0;
return 0;
}
PyDoc_STRVAR(bpy_app_global_flag_doc,
"Boolean, for application behavior (started with --enable-* matching this attribute name)"
);
PyDoc_STRVAR(
bpy_app_global_flag_doc,
"Boolean, for application behavior (started with --enable-* matching this attribute name)");
static PyObject *bpy_app_global_flag_get(PyObject *UNUSED(self), void *closure)
{
const int flag = POINTER_AS_INT(closure);
return PyBool_FromLong(G.f & flag);
const int flag = POINTER_AS_INT(closure);
return PyBool_FromLong(G.f & flag);
}
static int bpy_app_global_flag_set(PyObject *UNUSED(self), PyObject *value, void *closure)
{
const int flag = POINTER_AS_INT(closure);
const int param = PyObject_IsTrue(value);
const int flag = POINTER_AS_INT(closure);
const int param = PyObject_IsTrue(value);
if (param == -1) {
PyErr_SetString(PyExc_TypeError, "bpy.app.use_* can only be True/False");
return -1;
}
if (param == -1) {
PyErr_SetString(PyExc_TypeError, "bpy.app.use_* can only be True/False");
return -1;
}
if (param) {
G.f |= flag;
}
else {
G.f &= ~flag;
}
if (param) {
G.f |= flag;
}
else {
G.f &= ~flag;
}
return 0;
return 0;
}
static int bpy_app_global_flag_set__only_disable(PyObject *UNUSED(self), PyObject *value, void *closure)
static int bpy_app_global_flag_set__only_disable(PyObject *UNUSED(self),
PyObject *value,
void *closure)
{
const int param = PyObject_IsTrue(value);
if (param == 1) {
PyErr_SetString(PyExc_ValueError, "This bpy.app.use_* option can only be disabled");
return -1;
}
return bpy_app_global_flag_set(NULL, value, closure);
const int param = PyObject_IsTrue(value);
if (param == 1) {
PyErr_SetString(PyExc_ValueError, "This bpy.app.use_* option can only be disabled");
return -1;
}
return bpy_app_global_flag_set(NULL, value, closure);
}
#define BROKEN_BINARY_PATH_PYTHON_HACK
PyDoc_STRVAR(bpy_app_binary_path_python_doc,
"String, the path to the python executable (read-only)"
);
"String, the path to the python executable (read-only)");
static PyObject *bpy_app_binary_path_python_get(PyObject *self, void *UNUSED(closure))
{
/* refcount is held in BlenderAppType.tp_dict */
static PyObject *ret = NULL;
/* refcount is held in BlenderAppType.tp_dict */
static PyObject *ret = NULL;
if (ret == NULL) {
/* only run once */
char fullpath[1024];
BKE_appdir_program_python_search(
fullpath, sizeof(fullpath),
PY_MAJOR_VERSION, PY_MINOR_VERSION);
ret = PyC_UnicodeFromByte(fullpath);
if (ret == NULL) {
/* only run once */
char fullpath[1024];
BKE_appdir_program_python_search(
fullpath, sizeof(fullpath), PY_MAJOR_VERSION, PY_MINOR_VERSION);
ret = PyC_UnicodeFromByte(fullpath);
#ifdef BROKEN_BINARY_PATH_PYTHON_HACK
Py_INCREF(ret);
UNUSED_VARS(self);
Py_INCREF(ret);
UNUSED_VARS(self);
#else
PyDict_SetItem(BlenderAppType.tp_dict, /* XXX BAAAADDDDDD! self is not a PyDescr at all! it's bpy.app!!! */ PyDescr_NAME(self), ret);
PyDict_SetItem(
BlenderAppType.tp_dict,
/* XXX BAAAADDDDDD! self is not a PyDescr at all! it's bpy.app!!! */ PyDescr_NAME(self),
ret);
#endif
}
else {
Py_INCREF(ret);
}
}
else {
Py_INCREF(ret);
}
return ret;
return ret;
}
PyDoc_STRVAR(bpy_app_debug_value_doc,
"Short, number which can be set to non-zero values for testing purposes"
);
"Short, number which can be set to non-zero values for testing purposes");
static PyObject *bpy_app_debug_value_get(PyObject *UNUSED(self), void *UNUSED(closure))
{
return PyLong_FromLong(G.debug_value);
return PyLong_FromLong(G.debug_value);
}
static int bpy_app_debug_value_set(PyObject *UNUSED(self), PyObject *value, void *UNUSED(closure))
{
short param = PyC_Long_AsI16(value);
short param = PyC_Long_AsI16(value);
if (param == -1 && PyErr_Occurred()) {
PyC_Err_SetString_Prefix(
PyExc_TypeError,
"bpy.app.debug_value can only be set to a whole number");
return -1;
}
if (param == -1 && PyErr_Occurred()) {
PyC_Err_SetString_Prefix(PyExc_TypeError,
"bpy.app.debug_value can only be set to a whole number");
return -1;
}
G.debug_value = param;
G.debug_value = param;
WM_main_add_notifier(NC_WINDOW, NULL);
WM_main_add_notifier(NC_WINDOW, NULL);
return 0;
return 0;
}
PyDoc_STRVAR(bpy_app_tempdir_doc,
"String, the temp directory used by blender (read-only)"
);
PyDoc_STRVAR(bpy_app_tempdir_doc, "String, the temp directory used by blender (read-only)");
static PyObject *bpy_app_tempdir_get(PyObject *UNUSED(self), void *UNUSED(closure))
{
return PyC_UnicodeFromByte(BKE_tempdir_session());
return PyC_UnicodeFromByte(BKE_tempdir_session());
}
PyDoc_STRVAR(bpy_app_driver_dict_doc,
"Dictionary for drivers namespace, editable in-place, reset on file load (read-only)"
);
PyDoc_STRVAR(
bpy_app_driver_dict_doc,
"Dictionary for drivers namespace, editable in-place, reset on file load (read-only)");
static PyObject *bpy_app_driver_dict_get(PyObject *UNUSED(self), void *UNUSED(closure))
{
if (bpy_pydriver_Dict == NULL) {
if (bpy_pydriver_create_dict() != 0) {
PyErr_SetString(PyExc_RuntimeError, "bpy.app.driver_namespace failed to create dictionary");
return NULL;
}
}
if (bpy_pydriver_Dict == NULL) {
if (bpy_pydriver_create_dict() != 0) {
PyErr_SetString(PyExc_RuntimeError, "bpy.app.driver_namespace failed to create dictionary");
return NULL;
}
}
return Py_INCREF_RET(bpy_pydriver_Dict);
return Py_INCREF_RET(bpy_pydriver_Dict);
}
PyDoc_STRVAR(bpy_app_preview_render_size_doc,
"Reference size for icon/preview renders (read-only)"
);
"Reference size for icon/preview renders (read-only)");
static PyObject *bpy_app_preview_render_size_get(PyObject *UNUSED(self), void *closure)
{
return PyLong_FromLong((long)UI_preview_render_size(POINTER_AS_INT(closure)));
return PyLong_FromLong((long)UI_preview_render_size(POINTER_AS_INT(closure)));
}
static PyObject *bpy_app_autoexec_fail_message_get(PyObject *UNUSED(self), void *UNUSED(closure))
{
return PyC_UnicodeFromByte(G.autoexec_fail);
return PyC_UnicodeFromByte(G.autoexec_fail);
}
PyDoc_STRVAR(bpy_app_use_static_override_doc,
"Boolean, whether static override is exposed in UI or not."
);
"Boolean, whether static override is exposed in UI or not.");
static PyObject *bpy_app_use_static_override_get(PyObject *UNUSED(self), void *UNUSED(closure))
{
return PyBool_FromLong((long)BKE_override_static_is_enabled());
return PyBool_FromLong((long)BKE_override_static_is_enabled());
}
static int bpy_app_use_static_override_set(PyObject *UNUSED(self), PyObject *value, void *UNUSED(closure))
static int bpy_app_use_static_override_set(PyObject *UNUSED(self),
PyObject *value,
void *UNUSED(closure))
{
const int param = PyC_Long_AsBool(value);
const int param = PyC_Long_AsBool(value);
if (param == -1 && PyErr_Occurred()) {
PyErr_SetString(PyExc_TypeError, "bpy.app.use_static_override must be a boolean");
return -1;
}
if (param == -1 && PyErr_Occurred()) {
PyErr_SetString(PyExc_TypeError, "bpy.app.use_static_override must be a boolean");
return -1;
}
BKE_override_static_enable((const bool)param);
BKE_override_static_enable((const bool)param);
return 0;
return 0;
}
static PyGetSetDef bpy_app_getsets[] = {
{(char *)"debug", bpy_app_debug_get, bpy_app_debug_set, (char *)bpy_app_debug_doc, (void *)G_DEBUG},
{(char *)"debug_ffmpeg", bpy_app_debug_get, bpy_app_debug_set, (char *)bpy_app_debug_doc, (void *)G_DEBUG_FFMPEG},
{(char *)"debug_freestyle", bpy_app_debug_get, bpy_app_debug_set, (char *)bpy_app_debug_doc, (void *)G_DEBUG_FREESTYLE},
{(char *)"debug_python", bpy_app_debug_get, bpy_app_debug_set, (char *)bpy_app_debug_doc, (void *)G_DEBUG_PYTHON},
{(char *)"debug_events", bpy_app_debug_get, bpy_app_debug_set, (char *)bpy_app_debug_doc, (void *)G_DEBUG_EVENTS},
{(char *)"debug_handlers", bpy_app_debug_get, bpy_app_debug_set, (char *)bpy_app_debug_doc, (void *)G_DEBUG_HANDLERS},
{(char *)"debug_wm", bpy_app_debug_get, bpy_app_debug_set, (char *)bpy_app_debug_doc, (void *)G_DEBUG_WM},
{(char *)"debug_depsgraph", bpy_app_debug_get, bpy_app_debug_set, (char *)bpy_app_debug_doc, (void *)G_DEBUG_DEPSGRAPH},
{(char *)"debug_depsgraph_build", bpy_app_debug_get, bpy_app_debug_set, (char *)bpy_app_debug_doc, (void *)G_DEBUG_DEPSGRAPH_BUILD},
{(char *)"debug_depsgraph_eval", bpy_app_debug_get, bpy_app_debug_set, (char *)bpy_app_debug_doc, (void *)G_DEBUG_DEPSGRAPH_EVAL},
{(char *)"debug_depsgraph_tag", bpy_app_debug_get, bpy_app_debug_set, (char *)bpy_app_debug_doc, (void *)G_DEBUG_DEPSGRAPH_TAG},
{(char *)"debug_depsgraph_time", bpy_app_debug_get, bpy_app_debug_set, (char *)bpy_app_debug_doc, (void *)G_DEBUG_DEPSGRAPH_TIME},
{(char *)"debug_depsgraph_pretty", bpy_app_debug_get, bpy_app_debug_set, (char *)bpy_app_debug_doc, (void *)G_DEBUG_DEPSGRAPH_PRETTY},
{(char *)"debug_simdata", bpy_app_debug_get, bpy_app_debug_set, (char *)bpy_app_debug_doc, (void *)G_DEBUG_SIMDATA},
{(char *)"debug_gpumem", bpy_app_debug_get, bpy_app_debug_set, (char *)bpy_app_debug_doc, (void *)G_DEBUG_GPU_MEM},
{(char *)"debug_io", bpy_app_debug_get, bpy_app_debug_set, (char *)bpy_app_debug_doc, (void *)G_DEBUG_IO},
{(char *)"debug",
bpy_app_debug_get,
bpy_app_debug_set,
(char *)bpy_app_debug_doc,
(void *)G_DEBUG},
{(char *)"debug_ffmpeg",
bpy_app_debug_get,
bpy_app_debug_set,
(char *)bpy_app_debug_doc,
(void *)G_DEBUG_FFMPEG},
{(char *)"debug_freestyle",
bpy_app_debug_get,
bpy_app_debug_set,
(char *)bpy_app_debug_doc,
(void *)G_DEBUG_FREESTYLE},
{(char *)"debug_python",
bpy_app_debug_get,
bpy_app_debug_set,
(char *)bpy_app_debug_doc,
(void *)G_DEBUG_PYTHON},
{(char *)"debug_events",
bpy_app_debug_get,
bpy_app_debug_set,
(char *)bpy_app_debug_doc,
(void *)G_DEBUG_EVENTS},
{(char *)"debug_handlers",
bpy_app_debug_get,
bpy_app_debug_set,
(char *)bpy_app_debug_doc,
(void *)G_DEBUG_HANDLERS},
{(char *)"debug_wm",
bpy_app_debug_get,
bpy_app_debug_set,
(char *)bpy_app_debug_doc,
(void *)G_DEBUG_WM},
{(char *)"debug_depsgraph",
bpy_app_debug_get,
bpy_app_debug_set,
(char *)bpy_app_debug_doc,
(void *)G_DEBUG_DEPSGRAPH},
{(char *)"debug_depsgraph_build",
bpy_app_debug_get,
bpy_app_debug_set,
(char *)bpy_app_debug_doc,
(void *)G_DEBUG_DEPSGRAPH_BUILD},
{(char *)"debug_depsgraph_eval",
bpy_app_debug_get,
bpy_app_debug_set,
(char *)bpy_app_debug_doc,
(void *)G_DEBUG_DEPSGRAPH_EVAL},
{(char *)"debug_depsgraph_tag",
bpy_app_debug_get,
bpy_app_debug_set,
(char *)bpy_app_debug_doc,
(void *)G_DEBUG_DEPSGRAPH_TAG},
{(char *)"debug_depsgraph_time",
bpy_app_debug_get,
bpy_app_debug_set,
(char *)bpy_app_debug_doc,
(void *)G_DEBUG_DEPSGRAPH_TIME},
{(char *)"debug_depsgraph_pretty",
bpy_app_debug_get,
bpy_app_debug_set,
(char *)bpy_app_debug_doc,
(void *)G_DEBUG_DEPSGRAPH_PRETTY},
{(char *)"debug_simdata",
bpy_app_debug_get,
bpy_app_debug_set,
(char *)bpy_app_debug_doc,
(void *)G_DEBUG_SIMDATA},
{(char *)"debug_gpumem",
bpy_app_debug_get,
bpy_app_debug_set,
(char *)bpy_app_debug_doc,
(void *)G_DEBUG_GPU_MEM},
{(char *)"debug_io",
bpy_app_debug_get,
bpy_app_debug_set,
(char *)bpy_app_debug_doc,
(void *)G_DEBUG_IO},
{(char *)"use_static_override", bpy_app_use_static_override_get, bpy_app_use_static_override_set, (char *)bpy_app_use_static_override_doc, NULL},
{(char *)"use_event_simulate", bpy_app_global_flag_get, bpy_app_global_flag_set__only_disable, (char *)bpy_app_global_flag_doc, (void *)G_FLAG_EVENT_SIMULATE},
{(char *)"use_static_override",
bpy_app_use_static_override_get,
bpy_app_use_static_override_set,
(char *)bpy_app_use_static_override_doc,
NULL},
{(char *)"use_event_simulate",
bpy_app_global_flag_get,
bpy_app_global_flag_set__only_disable,
(char *)bpy_app_global_flag_doc,
(void *)G_FLAG_EVENT_SIMULATE},
{(char *)"binary_path_python", bpy_app_binary_path_python_get, NULL, (char *)bpy_app_binary_path_python_doc, NULL},
{(char *)"binary_path_python",
bpy_app_binary_path_python_get,
NULL,
(char *)bpy_app_binary_path_python_doc,
NULL},
{(char *)"debug_value", bpy_app_debug_value_get, bpy_app_debug_value_set, (char *)bpy_app_debug_value_doc, NULL},
{(char *)"tempdir", bpy_app_tempdir_get, NULL, (char *)bpy_app_tempdir_doc, NULL},
{(char *)"driver_namespace", bpy_app_driver_dict_get, NULL, (char *)bpy_app_driver_dict_doc, NULL},
{(char *)"debug_value",
bpy_app_debug_value_get,
bpy_app_debug_value_set,
(char *)bpy_app_debug_value_doc,
NULL},
{(char *)"tempdir", bpy_app_tempdir_get, NULL, (char *)bpy_app_tempdir_doc, NULL},
{(char *)"driver_namespace",
bpy_app_driver_dict_get,
NULL,
(char *)bpy_app_driver_dict_doc,
NULL},
{(char *)"render_icon_size", bpy_app_preview_render_size_get, NULL, (char *)bpy_app_preview_render_size_doc, (void *)ICON_SIZE_ICON},
{(char *)"render_preview_size", bpy_app_preview_render_size_get, NULL, (char *)bpy_app_preview_render_size_doc, (void *)ICON_SIZE_PREVIEW},
{(char *)"render_icon_size",
bpy_app_preview_render_size_get,
NULL,
(char *)bpy_app_preview_render_size_doc,
(void *)ICON_SIZE_ICON},
{(char *)"render_preview_size",
bpy_app_preview_render_size_get,
NULL,
(char *)bpy_app_preview_render_size_doc,
(void *)ICON_SIZE_PREVIEW},
/* security */
{(char *)"autoexec_fail", bpy_app_global_flag_get, NULL, NULL, (void *)G_FLAG_SCRIPT_AUTOEXEC_FAIL},
{(char *)"autoexec_fail_quiet", bpy_app_global_flag_get, NULL, NULL, (void *)G_FLAG_SCRIPT_AUTOEXEC_FAIL_QUIET},
{(char *)"autoexec_fail_message", bpy_app_autoexec_fail_message_get, NULL, NULL, NULL},
{NULL, NULL, NULL, NULL, NULL},
/* security */
{(char *)"autoexec_fail",
bpy_app_global_flag_get,
NULL,
NULL,
(void *)G_FLAG_SCRIPT_AUTOEXEC_FAIL},
{(char *)"autoexec_fail_quiet",
bpy_app_global_flag_get,
NULL,
NULL,
(void *)G_FLAG_SCRIPT_AUTOEXEC_FAIL_QUIET},
{(char *)"autoexec_fail_message", bpy_app_autoexec_fail_message_get, NULL, NULL, NULL},
{NULL, NULL, NULL, NULL, NULL},
};
static void py_struct_seq_getset_init(void)
{
/* tricky dynamic members, not to py-spec! */
for (PyGetSetDef *getset = bpy_app_getsets; getset->name; getset++) {
PyObject *item = PyDescr_NewGetSet(&BlenderAppType, getset);
PyDict_SetItem(BlenderAppType.tp_dict, PyDescr_NAME(item), item);
Py_DECREF(item);
}
/* tricky dynamic members, not to py-spec! */
for (PyGetSetDef *getset = bpy_app_getsets; getset->name; getset++) {
PyObject *item = PyDescr_NewGetSet(&BlenderAppType, getset);
PyDict_SetItem(BlenderAppType.tp_dict, PyDescr_NAME(item), item);
Py_DECREF(item);
}
}
/* end dynamic bpy.app */
PyObject *BPY_app_struct(void)
{
PyObject *ret;
PyObject *ret;
PyStructSequence_InitType(&BlenderAppType, &app_info_desc);
PyStructSequence_InitType(&BlenderAppType, &app_info_desc);
ret = make_app_info();
ret = make_app_info();
/* prevent user from creating new instances */
BlenderAppType.tp_init = NULL;
BlenderAppType.tp_new = NULL;
BlenderAppType.tp_hash = (hashfunc)_Py_HashPointer; /* without this we can't do set(sys.modules) [#29635] */
/* prevent user from creating new instances */
BlenderAppType.tp_init = NULL;
BlenderAppType.tp_new = NULL;
BlenderAppType.tp_hash = (hashfunc)
_Py_HashPointer; /* without this we can't do set(sys.modules) [#29635] */
/* kindof a hack ontop of PyStructSequence */
py_struct_seq_getset_init();
/* kindof a hack ontop of PyStructSequence */
py_struct_seq_getset_init();
return ret;
return ret;
}

View File

@@ -23,4 +23,4 @@
PyObject *BPY_app_struct(void);
#endif /* __BPY_APP_H__ */
#endif /* __BPY_APP_H__ */

View File

@@ -35,73 +35,72 @@
static PyTypeObject BlenderAppABCType;
static PyStructSequence_Field app_alembic_info_fields[] = {
{(char *)"supported", (char *)"Boolean, True when Blender is built with Alembic support"},
{(char *)"version", (char *)"The Alembic version as a tuple of 3 numbers"},
{(char *)"version_string", (char *)"The Alembic version formatted as a string"},
{NULL},
{(char *)"supported", (char *)"Boolean, True when Blender is built with Alembic support"},
{(char *)"version", (char *)"The Alembic version as a tuple of 3 numbers"},
{(char *)"version_string", (char *)"The Alembic version formatted as a string"},
{NULL},
};
static PyStructSequence_Desc app_alembic_info_desc = {
(char *)"bpy.app.alembic", /* name */
(char *)"This module contains information about Alembic blender is linked against", /* doc */
app_alembic_info_fields, /* fields */
ARRAY_SIZE(app_alembic_info_fields) - 1,
(char *)"bpy.app.alembic", /* name */
(char *)"This module contains information about Alembic blender is linked against", /* doc */
app_alembic_info_fields, /* fields */
ARRAY_SIZE(app_alembic_info_fields) - 1,
};
static PyObject *make_alembic_info(void)
{
PyObject *alembic_info = PyStructSequence_New(&BlenderAppABCType);
PyObject *alembic_info = PyStructSequence_New(&BlenderAppABCType);
if (alembic_info == NULL) {
return NULL;
}
if (alembic_info == NULL) {
return NULL;
}
int pos = 0;
int pos = 0;
#ifndef WITH_ALEMBIC
# define SetStrItem(str) \
PyStructSequence_SET_ITEM(alembic_info, pos++, PyUnicode_FromString(str))
# define SetStrItem(str) PyStructSequence_SET_ITEM(alembic_info, pos++, PyUnicode_FromString(str))
#endif
#define SetObjItem(obj) \
PyStructSequence_SET_ITEM(alembic_info, pos++, obj)
#define SetObjItem(obj) PyStructSequence_SET_ITEM(alembic_info, pos++, obj)
#ifdef WITH_ALEMBIC
const int curversion = ABC_get_version();
const int major = curversion / 10000;
const int minor = (curversion / 100) - (major * 100);
const int patch = curversion - ((curversion / 100 ) * 100);
const int curversion = ABC_get_version();
const int major = curversion / 10000;
const int minor = (curversion / 100) - (major * 100);
const int patch = curversion - ((curversion / 100) * 100);
SetObjItem(PyBool_FromLong(1));
SetObjItem(PyC_Tuple_Pack_I32(major, minor, patch));
SetObjItem(PyUnicode_FromFormat("%2d, %2d, %2d", major, minor, patch));
SetObjItem(PyBool_FromLong(1));
SetObjItem(PyC_Tuple_Pack_I32(major, minor, patch));
SetObjItem(PyUnicode_FromFormat("%2d, %2d, %2d", major, minor, patch));
#else
SetObjItem(PyBool_FromLong(0));
SetObjItem(PyC_Tuple_Pack_I32(0, 0, 0));
SetStrItem("Unknown");
SetObjItem(PyBool_FromLong(0));
SetObjItem(PyC_Tuple_Pack_I32(0, 0, 0));
SetStrItem("Unknown");
#endif
if (PyErr_Occurred()) {
Py_CLEAR(alembic_info);
return NULL;
}
if (PyErr_Occurred()) {
Py_CLEAR(alembic_info);
return NULL;
}
#undef SetStrItem
#undef SetObjItem
return alembic_info;
return alembic_info;
}
PyObject *BPY_app_alembic_struct(void)
{
PyStructSequence_InitType(&BlenderAppABCType, &app_alembic_info_desc);
PyStructSequence_InitType(&BlenderAppABCType, &app_alembic_info_desc);
PyObject *ret = make_alembic_info();
PyObject *ret = make_alembic_info();
/* prevent user from creating new instances */
BlenderAppABCType.tp_init = NULL;
BlenderAppABCType.tp_new = NULL;
BlenderAppABCType.tp_hash = (hashfunc)_Py_HashPointer; /* without this we can't do set(sys.modules) [#29635] */
/* prevent user from creating new instances */
BlenderAppABCType.tp_init = NULL;
BlenderAppABCType.tp_new = NULL;
BlenderAppABCType.tp_hash = (hashfunc)
_Py_HashPointer; /* without this we can't do set(sys.modules) [#29635] */
return ret;
return ret;
}

View File

@@ -26,4 +26,4 @@
PyObject *BPY_app_alembic_struct(void);
#endif /* __BPY_APP_ALEMBIC_H__ */
#endif /* __BPY_APP_ALEMBIC_H__ */

View File

@@ -27,265 +27,265 @@
static PyTypeObject BlenderAppBuildOptionsType;
static PyStructSequence_Field app_builtopts_info_fields[] = {
/* names mostly follow CMake options, lowercase, after WITH_ */
{(char *)"bullet", NULL},
{(char *)"codec_avi", NULL},
{(char *)"codec_ffmpeg", NULL},
{(char *)"codec_sndfile", NULL},
{(char *)"compositor", NULL},
{(char *)"cycles", NULL},
{(char *)"cycles_osl", NULL},
{(char *)"freestyle", NULL},
{(char *)"image_cineon", NULL},
{(char *)"image_dds", NULL},
{(char *)"image_hdr", NULL},
{(char *)"image_openexr", NULL},
{(char *)"image_openjpeg", NULL},
{(char *)"image_tiff", NULL},
{(char *)"input_ndof", NULL},
{(char *)"audaspace", NULL},
{(char *)"international", NULL},
{(char *)"openal", NULL},
{(char *)"sdl", NULL},
{(char *)"sdl_dynload", NULL},
{(char *)"jack", NULL},
{(char *)"libmv", NULL},
{(char *)"mod_fluid", NULL},
{(char *)"mod_oceansim", NULL},
{(char *)"mod_remesh", NULL},
{(char *)"mod_smoke", NULL},
{(char *)"collada", NULL},
{(char *)"opencolorio", NULL},
{(char *)"openmp", NULL},
{(char *)"openvdb", NULL},
{(char *)"alembic", NULL},
{NULL},
/* names mostly follow CMake options, lowercase, after WITH_ */
{(char *)"bullet", NULL},
{(char *)"codec_avi", NULL},
{(char *)"codec_ffmpeg", NULL},
{(char *)"codec_sndfile", NULL},
{(char *)"compositor", NULL},
{(char *)"cycles", NULL},
{(char *)"cycles_osl", NULL},
{(char *)"freestyle", NULL},
{(char *)"image_cineon", NULL},
{(char *)"image_dds", NULL},
{(char *)"image_hdr", NULL},
{(char *)"image_openexr", NULL},
{(char *)"image_openjpeg", NULL},
{(char *)"image_tiff", NULL},
{(char *)"input_ndof", NULL},
{(char *)"audaspace", NULL},
{(char *)"international", NULL},
{(char *)"openal", NULL},
{(char *)"sdl", NULL},
{(char *)"sdl_dynload", NULL},
{(char *)"jack", NULL},
{(char *)"libmv", NULL},
{(char *)"mod_fluid", NULL},
{(char *)"mod_oceansim", NULL},
{(char *)"mod_remesh", NULL},
{(char *)"mod_smoke", NULL},
{(char *)"collada", NULL},
{(char *)"opencolorio", NULL},
{(char *)"openmp", NULL},
{(char *)"openvdb", NULL},
{(char *)"alembic", NULL},
{NULL},
};
static PyStructSequence_Desc app_builtopts_info_desc = {
(char *)"bpy.app.build_options", /* name */
(char *)"This module contains information about options blender is built with", /* doc */
app_builtopts_info_fields, /* fields */
ARRAY_SIZE(app_builtopts_info_fields) - 1,
(char *)"bpy.app.build_options", /* name */
(char *)"This module contains information about options blender is built with", /* doc */
app_builtopts_info_fields, /* fields */
ARRAY_SIZE(app_builtopts_info_fields) - 1,
};
static PyObject *make_builtopts_info(void)
{
PyObject *builtopts_info;
int pos = 0;
PyObject *builtopts_info;
int pos = 0;
builtopts_info = PyStructSequence_New(&BlenderAppBuildOptionsType);
if (builtopts_info == NULL) {
return NULL;
}
builtopts_info = PyStructSequence_New(&BlenderAppBuildOptionsType);
if (builtopts_info == NULL) {
return NULL;
}
#define SetObjIncref(item) \
PyStructSequence_SET_ITEM(builtopts_info, pos++, (Py_IncRef(item), item))
PyStructSequence_SET_ITEM(builtopts_info, pos++, (Py_IncRef(item), item))
#ifdef WITH_BULLET
SetObjIncref(Py_True);
SetObjIncref(Py_True);
#else
SetObjIncref(Py_False);
SetObjIncref(Py_False);
#endif
#ifdef WITH_AVI
SetObjIncref(Py_True);
SetObjIncref(Py_True);
#else
SetObjIncref(Py_False);
SetObjIncref(Py_False);
#endif
#ifdef WITH_FFMPEG
SetObjIncref(Py_True);
SetObjIncref(Py_True);
#else
SetObjIncref(Py_False);
SetObjIncref(Py_False);
#endif
#ifdef WITH_SNDFILE
SetObjIncref(Py_True);
SetObjIncref(Py_True);
#else
SetObjIncref(Py_False);
SetObjIncref(Py_False);
#endif
#ifdef WITH_COMPOSITOR
SetObjIncref(Py_True);
SetObjIncref(Py_True);
#else
SetObjIncref(Py_False);
SetObjIncref(Py_False);
#endif
#ifdef WITH_CYCLES
SetObjIncref(Py_True);
SetObjIncref(Py_True);
#else
SetObjIncref(Py_False);
SetObjIncref(Py_False);
#endif
#ifdef WITH_CYCLES_OSL
SetObjIncref(Py_True);
SetObjIncref(Py_True);
#else
SetObjIncref(Py_False);
SetObjIncref(Py_False);
#endif
#ifdef WITH_FREESTYLE
SetObjIncref(Py_True);
SetObjIncref(Py_True);
#else
SetObjIncref(Py_False);
SetObjIncref(Py_False);
#endif
#ifdef WITH_CINEON
SetObjIncref(Py_True);
SetObjIncref(Py_True);
#else
SetObjIncref(Py_False);
SetObjIncref(Py_False);
#endif
#ifdef WITH_DDS
SetObjIncref(Py_True);
SetObjIncref(Py_True);
#else
SetObjIncref(Py_False);
SetObjIncref(Py_False);
#endif
#ifdef WITH_HDR
SetObjIncref(Py_True);
SetObjIncref(Py_True);
#else
SetObjIncref(Py_False);
SetObjIncref(Py_False);
#endif
#ifdef WITH_OPENEXR
SetObjIncref(Py_True);
SetObjIncref(Py_True);
#else
SetObjIncref(Py_False);
SetObjIncref(Py_False);
#endif
#ifdef WITH_OPENJPEG
SetObjIncref(Py_True);
SetObjIncref(Py_True);
#else
SetObjIncref(Py_False);
SetObjIncref(Py_False);
#endif
#ifdef WITH_TIFF
SetObjIncref(Py_True);
SetObjIncref(Py_True);
#else
SetObjIncref(Py_False);
SetObjIncref(Py_False);
#endif
#ifdef WITH_INPUT_NDOF
SetObjIncref(Py_True);
SetObjIncref(Py_True);
#else
SetObjIncref(Py_False);
SetObjIncref(Py_False);
#endif
#ifdef WITH_AUDASPACE
SetObjIncref(Py_True);
SetObjIncref(Py_True);
#else
SetObjIncref(Py_False);
SetObjIncref(Py_False);
#endif
#ifdef WITH_INTERNATIONAL
SetObjIncref(Py_True);
SetObjIncref(Py_True);
#else
SetObjIncref(Py_False);
SetObjIncref(Py_False);
#endif
#ifdef WITH_OPENAL
SetObjIncref(Py_True);
SetObjIncref(Py_True);
#else
SetObjIncref(Py_False);
SetObjIncref(Py_False);
#endif
#ifdef WITH_SDL
SetObjIncref(Py_True);
SetObjIncref(Py_True);
#else
SetObjIncref(Py_False);
SetObjIncref(Py_False);
#endif
#ifdef WITH_SDL_DYNLOAD
SetObjIncref(Py_True);
SetObjIncref(Py_True);
#else
SetObjIncref(Py_False);
SetObjIncref(Py_False);
#endif
#ifdef WITH_JACK
SetObjIncref(Py_True);
SetObjIncref(Py_True);
#else
SetObjIncref(Py_False);
SetObjIncref(Py_False);
#endif
#ifdef WITH_LIBMV
SetObjIncref(Py_True);
SetObjIncref(Py_True);
#else
SetObjIncref(Py_False);
SetObjIncref(Py_False);
#endif
#ifdef WITH_MOD_FLUID
SetObjIncref(Py_True);
SetObjIncref(Py_True);
#else
SetObjIncref(Py_False);
SetObjIncref(Py_False);
#endif
#ifdef WITH_OCEANSIM
SetObjIncref(Py_True);
SetObjIncref(Py_True);
#else
SetObjIncref(Py_False);
SetObjIncref(Py_False);
#endif
#ifdef WITH_MOD_REMESH
SetObjIncref(Py_True);
SetObjIncref(Py_True);
#else
SetObjIncref(Py_False);
SetObjIncref(Py_False);
#endif
#ifdef WITH_SMOKE
SetObjIncref(Py_True);
SetObjIncref(Py_True);
#else
SetObjIncref(Py_False);
SetObjIncref(Py_False);
#endif
#ifdef WITH_COLLADA
SetObjIncref(Py_True);
SetObjIncref(Py_True);
#else
SetObjIncref(Py_False);
SetObjIncref(Py_False);
#endif
#ifdef WITH_OCIO
SetObjIncref(Py_True);
SetObjIncref(Py_True);
#else
SetObjIncref(Py_False);
SetObjIncref(Py_False);
#endif
#ifdef _OPENMP
SetObjIncref(Py_True);
SetObjIncref(Py_True);
#else
SetObjIncref(Py_False);
SetObjIncref(Py_False);
#endif
#ifdef WITH_OPENVDB
SetObjIncref(Py_True);
SetObjIncref(Py_True);
#else
SetObjIncref(Py_False);
SetObjIncref(Py_False);
#endif
#ifdef WITH_ALEMBIC
SetObjIncref(Py_True);
SetObjIncref(Py_True);
#else
SetObjIncref(Py_False);
SetObjIncref(Py_False);
#endif
#undef SetObjIncref
return builtopts_info;
return builtopts_info;
}
PyObject *BPY_app_build_options_struct(void)
{
PyObject *ret;
PyObject *ret;
PyStructSequence_InitType(&BlenderAppBuildOptionsType, &app_builtopts_info_desc);
PyStructSequence_InitType(&BlenderAppBuildOptionsType, &app_builtopts_info_desc);
ret = make_builtopts_info();
ret = make_builtopts_info();
/* prevent user from creating new instances */
BlenderAppBuildOptionsType.tp_init = NULL;
BlenderAppBuildOptionsType.tp_new = NULL;
BlenderAppBuildOptionsType.tp_hash = (hashfunc)_Py_HashPointer; /* without this we can't do set(sys.modules) [#29635] */
/* prevent user from creating new instances */
BlenderAppBuildOptionsType.tp_init = NULL;
BlenderAppBuildOptionsType.tp_new = NULL;
BlenderAppBuildOptionsType.tp_hash = (hashfunc)
_Py_HashPointer; /* without this we can't do set(sys.modules) [#29635] */
return ret;
return ret;
}

View File

@@ -23,4 +23,4 @@
PyObject *BPY_app_build_options_struct(void);
#endif /* __BPY_APP_BUILD_OPTIONS_H__ */
#endif /* __BPY_APP_BUILD_OPTIONS_H__ */

View File

@@ -26,116 +26,121 @@
#include "../generic/py_capi_utils.h"
#ifdef WITH_FFMPEG
#include <libavcodec/avcodec.h>
#include <libavdevice/avdevice.h>
#include <libavformat/avformat.h>
#include <libavutil/avutil.h>
#include <libswscale/swscale.h>
# include <libavcodec/avcodec.h>
# include <libavdevice/avdevice.h>
# include <libavformat/avformat.h>
# include <libavutil/avutil.h>
# include <libswscale/swscale.h>
#endif
static PyTypeObject BlenderAppFFmpegType;
#define DEF_FFMPEG_LIB_VERSION(lib) \
{(char *)(#lib "_version"), (char *)("The " #lib " version as a tuple of 3 numbers")}, \
{(char *)(#lib "_version_string"), (char *)("The " #lib " version formatted as a string")}
{(char *)(#lib "_version"), (char *)("The " #lib " version as a tuple of 3 numbers")}, \
{ \
(char *)(#lib "_version_string"), (char *)("The " #lib " version formatted as a string") \
}
static PyStructSequence_Field app_ffmpeg_info_fields[] = {
{(char *)"supported", (char *)("Boolean, True when Blender is built with FFmpeg support")},
{(char *)"supported", (char *)("Boolean, True when Blender is built with FFmpeg support")},
DEF_FFMPEG_LIB_VERSION(avcodec),
DEF_FFMPEG_LIB_VERSION(avdevice),
DEF_FFMPEG_LIB_VERSION(avformat),
DEF_FFMPEG_LIB_VERSION(avutil),
DEF_FFMPEG_LIB_VERSION(swscale),
{NULL},
DEF_FFMPEG_LIB_VERSION(avcodec),
DEF_FFMPEG_LIB_VERSION(avdevice),
DEF_FFMPEG_LIB_VERSION(avformat),
DEF_FFMPEG_LIB_VERSION(avutil),
DEF_FFMPEG_LIB_VERSION(swscale),
{NULL},
};
#undef DEF_FFMPEG_LIB_VERSION
static PyStructSequence_Desc app_ffmpeg_info_desc = {
(char *)"bpy.app.ffmpeg", /* name */
(char *)"This module contains information about FFmpeg blender is linked against", /* doc */
app_ffmpeg_info_fields, /* fields */
ARRAY_SIZE(app_ffmpeg_info_fields) - 1,
(char *)"bpy.app.ffmpeg", /* name */
(char *)"This module contains information about FFmpeg blender is linked against", /* doc */
app_ffmpeg_info_fields, /* fields */
ARRAY_SIZE(app_ffmpeg_info_fields) - 1,
};
static PyObject *make_ffmpeg_info(void)
{
PyObject *ffmpeg_info;
int pos = 0;
PyObject *ffmpeg_info;
int pos = 0;
#ifdef WITH_FFMPEG
int curversion;
int curversion;
#endif
ffmpeg_info = PyStructSequence_New(&BlenderAppFFmpegType);
if (ffmpeg_info == NULL) {
return NULL;
}
ffmpeg_info = PyStructSequence_New(&BlenderAppFFmpegType);
if (ffmpeg_info == NULL) {
return NULL;
}
#if 0 // UNUSED
#define SetIntItem(flag) \
PyStructSequence_SET_ITEM(ffmpeg_info, pos++, PyLong_FromLong(flag))
#if 0 // UNUSED
# define SetIntItem(flag) PyStructSequence_SET_ITEM(ffmpeg_info, pos++, PyLong_FromLong(flag))
#endif
#ifndef WITH_FFMPEG
#define SetStrItem(str) \
PyStructSequence_SET_ITEM(ffmpeg_info, pos++, PyUnicode_FromString(str))
# define SetStrItem(str) PyStructSequence_SET_ITEM(ffmpeg_info, pos++, PyUnicode_FromString(str))
#endif
#define SetObjItem(obj) \
PyStructSequence_SET_ITEM(ffmpeg_info, pos++, obj)
#define SetObjItem(obj) PyStructSequence_SET_ITEM(ffmpeg_info, pos++, obj)
#ifdef WITH_FFMPEG
# define FFMPEG_LIB_VERSION(lib) { \
curversion = lib ## _version(); \
SetObjItem(PyC_Tuple_Pack_I32(curversion >> 16, (curversion >> 8) % 256, curversion % 256)); \
SetObjItem(PyUnicode_FromFormat("%2d, %2d, %2d", \
curversion >> 16, (curversion >> 8) % 256, curversion % 256)); \
} (void)0
# define FFMPEG_LIB_VERSION(lib) \
{ \
curversion = lib##_version(); \
SetObjItem( \
PyC_Tuple_Pack_I32(curversion >> 16, (curversion >> 8) % 256, curversion % 256)); \
SetObjItem(PyUnicode_FromFormat( \
"%2d, %2d, %2d", curversion >> 16, (curversion >> 8) % 256, curversion % 256)); \
} \
(void)0
#else
# define FFMPEG_LIB_VERSION(lib) { \
SetStrItem("Unknown"); \
SetStrItem("Unknown"); \
} (void)0
# define FFMPEG_LIB_VERSION(lib) \
{ \
SetStrItem("Unknown"); \
SetStrItem("Unknown"); \
} \
(void)0
#endif
#ifdef WITH_FFMPEG
SetObjItem(PyBool_FromLong(1));
SetObjItem(PyBool_FromLong(1));
#else
SetObjItem(PyBool_FromLong(0));
SetObjItem(PyBool_FromLong(0));
#endif
FFMPEG_LIB_VERSION(avcodec);
FFMPEG_LIB_VERSION(avdevice);
FFMPEG_LIB_VERSION(avformat);
FFMPEG_LIB_VERSION(avutil);
FFMPEG_LIB_VERSION(swscale);
FFMPEG_LIB_VERSION(avcodec);
FFMPEG_LIB_VERSION(avdevice);
FFMPEG_LIB_VERSION(avformat);
FFMPEG_LIB_VERSION(avutil);
FFMPEG_LIB_VERSION(swscale);
#undef FFMPEG_LIB_VERSION
if (PyErr_Occurred()) {
Py_CLEAR(ffmpeg_info);
return NULL;
}
if (PyErr_Occurred()) {
Py_CLEAR(ffmpeg_info);
return NULL;
}
// #undef SetIntItem
#undef SetStrItem
#undef SetObjItem
return ffmpeg_info;
return ffmpeg_info;
}
PyObject *BPY_app_ffmpeg_struct(void)
{
PyObject *ret;
PyObject *ret;
PyStructSequence_InitType(&BlenderAppFFmpegType, &app_ffmpeg_info_desc);
PyStructSequence_InitType(&BlenderAppFFmpegType, &app_ffmpeg_info_desc);
ret = make_ffmpeg_info();
ret = make_ffmpeg_info();
/* prevent user from creating new instances */
BlenderAppFFmpegType.tp_init = NULL;
BlenderAppFFmpegType.tp_new = NULL;
BlenderAppFFmpegType.tp_hash = (hashfunc)_Py_HashPointer; /* without this we can't do set(sys.modules) [#29635] */
/* prevent user from creating new instances */
BlenderAppFFmpegType.tp_init = NULL;
BlenderAppFFmpegType.tp_new = NULL;
BlenderAppFFmpegType.tp_hash = (hashfunc)
_Py_HashPointer; /* without this we can't do set(sys.modules) [#29635] */
return ret;
return ret;
}

View File

@@ -23,4 +23,4 @@
PyObject *BPY_app_ffmpeg_struct(void);
#endif /* __BPY_APP_FFMPEG_H__ */
#endif /* __BPY_APP_FFMPEG_H__ */

View File

@@ -40,40 +40,42 @@ void bpy_app_generic_callback(struct Main *main, struct ID *id, void *arg);
static PyTypeObject BlenderAppCbType;
static PyStructSequence_Field app_cb_info_fields[] = {
{(char *)"frame_change_pre", (char *)"on frame change for playback and rendering (before)"},
{(char *)"frame_change_post", (char *)"on frame change for playback and rendering (after)"},
{(char *)"render_pre", (char *)"on render (before)"},
{(char *)"render_post", (char *)"on render (after)"},
{(char *)"render_write", (char *)"on writing a render frame (directly after the frame is written)"},
{(char *)"render_stats", (char *)"on printing render statistics"},
{(char *)"render_init", (char *)"on initialization of a render job"},
{(char *)"render_complete", (char *)"on completion of render job"},
{(char *)"render_cancel", (char *)"on canceling a render job"},
{(char *)"load_pre", (char *)"on loading a new blend file (before)"},
{(char *)"load_post", (char *)"on loading a new blend file (after)"},
{(char *)"save_pre", (char *)"on saving a blend file (before)"},
{(char *)"save_post", (char *)"on saving a blend file (after)"},
{(char *)"undo_pre", (char *)"on loading an undo step (before)"},
{(char *)"undo_post", (char *)"on loading an undo step (after)"},
{(char *)"redo_pre", (char *)"on loading a redo step (before)"},
{(char *)"redo_post", (char *)"on loading a redo step (after)"},
{(char *)"depsgraph_update_pre", (char *)"on depsgraph update (pre)"},
{(char *)"depsgraph_update_post", (char *)"on depsgraph update (post)"},
{(char *)"version_update", (char *)"on ending the versioning code"},
{(char *)"load_factory_startup_post", (char *)"on loading factory startup (after)"},
{(char *)"frame_change_pre", (char *)"on frame change for playback and rendering (before)"},
{(char *)"frame_change_post", (char *)"on frame change for playback and rendering (after)"},
{(char *)"render_pre", (char *)"on render (before)"},
{(char *)"render_post", (char *)"on render (after)"},
{(char *)"render_write",
(char *)"on writing a render frame (directly after the frame is written)"},
{(char *)"render_stats", (char *)"on printing render statistics"},
{(char *)"render_init", (char *)"on initialization of a render job"},
{(char *)"render_complete", (char *)"on completion of render job"},
{(char *)"render_cancel", (char *)"on canceling a render job"},
{(char *)"load_pre", (char *)"on loading a new blend file (before)"},
{(char *)"load_post", (char *)"on loading a new blend file (after)"},
{(char *)"save_pre", (char *)"on saving a blend file (before)"},
{(char *)"save_post", (char *)"on saving a blend file (after)"},
{(char *)"undo_pre", (char *)"on loading an undo step (before)"},
{(char *)"undo_post", (char *)"on loading an undo step (after)"},
{(char *)"redo_pre", (char *)"on loading a redo step (before)"},
{(char *)"redo_post", (char *)"on loading a redo step (after)"},
{(char *)"depsgraph_update_pre", (char *)"on depsgraph update (pre)"},
{(char *)"depsgraph_update_post", (char *)"on depsgraph update (post)"},
{(char *)"version_update", (char *)"on ending the versioning code"},
{(char *)"load_factory_startup_post", (char *)"on loading factory startup (after)"},
/* sets the permanent tag */
/* sets the permanent tag */
#define APP_CB_OTHER_FIELDS 1
{(char *)"persistent", (char *)"Function decorator for callback functions not to be removed when loading new files"},
{(char *)"persistent",
(char *)"Function decorator for callback functions not to be removed when loading new files"},
{NULL},
{NULL},
};
static PyStructSequence_Desc app_cb_info_desc = {
(char *)"bpy.app.handlers", /* name */
(char *)"This module contains callback lists", /* doc */
app_cb_info_fields, /* fields */
ARRAY_SIZE(app_cb_info_fields) - 1,
(char *)"bpy.app.handlers", /* name */
(char *)"This module contains callback lists", /* doc */
app_cb_info_fields, /* fields */
ARRAY_SIZE(app_cb_info_fields) - 1,
};
#if 0
@@ -86,251 +88,250 @@ static PyStructSequence_Desc app_cb_info_desc = {
/* permanent tagging code */
#define PERMINENT_CB_ID "_bpy_persistent"
static PyObject *bpy_app_handlers_persistent_new(PyTypeObject *UNUSED(type), PyObject *args, PyObject *UNUSED(kwds))
static PyObject *bpy_app_handlers_persistent_new(PyTypeObject *UNUSED(type),
PyObject *args,
PyObject *UNUSED(kwds))
{
PyObject *value;
PyObject *value;
if (!PyArg_ParseTuple(args, "O:bpy.app.handlers.persistent", &value)) {
return NULL;
}
if (!PyArg_ParseTuple(args, "O:bpy.app.handlers.persistent", &value)) {
return NULL;
}
if (PyFunction_Check(value)) {
PyObject **dict_ptr = _PyObject_GetDictPtr(value);
if (dict_ptr == NULL) {
PyErr_SetString(PyExc_ValueError,
"bpy.app.handlers.persistent wasn't able to "
"get the dictionary from the function passed");
return NULL;
}
else {
/* set id */
if (*dict_ptr == NULL) {
*dict_ptr = PyDict_New();
}
if (PyFunction_Check(value)) {
PyObject **dict_ptr = _PyObject_GetDictPtr(value);
if (dict_ptr == NULL) {
PyErr_SetString(PyExc_ValueError,
"bpy.app.handlers.persistent wasn't able to "
"get the dictionary from the function passed");
return NULL;
}
else {
/* set id */
if (*dict_ptr == NULL) {
*dict_ptr = PyDict_New();
}
PyDict_SetItemString(*dict_ptr, PERMINENT_CB_ID, Py_None);
}
PyDict_SetItemString(*dict_ptr, PERMINENT_CB_ID, Py_None);
}
Py_INCREF(value);
return value;
}
else {
PyErr_SetString(PyExc_ValueError,
"bpy.app.handlers.persistent expected a function");
return NULL;
}
Py_INCREF(value);
return value;
}
else {
PyErr_SetString(PyExc_ValueError, "bpy.app.handlers.persistent expected a function");
return NULL;
}
}
/* dummy type because decorators can't be PyCFunctions */
static PyTypeObject BPyPersistent_Type = {
#if defined(_MSC_VER)
PyVarObject_HEAD_INIT(NULL, 0)
PyVarObject_HEAD_INIT(NULL, 0)
#else
PyVarObject_HEAD_INIT(&PyType_Type, 0)
PyVarObject_HEAD_INIT(&PyType_Type, 0)
#endif
"persistent", /* tp_name */
0, /* tp_basicsize */
0, /* tp_itemsize */
/* methods */
0, /* tp_dealloc */
0, /* tp_print */
0, /* tp_getattr */
0, /* tp_setattr */
0, /* tp_reserved */
0, /* tp_repr */
0, /* tp_as_number */
0, /* tp_as_sequence */
0, /* tp_as_mapping */
0, /* tp_hash */
0, /* tp_call */
0, /* tp_str */
0, /* tp_getattro */
0, /* tp_setattro */
0, /* tp_as_buffer */
Py_TPFLAGS_DEFAULT | Py_TPFLAGS_HAVE_GC |
Py_TPFLAGS_BASETYPE, /* tp_flags */
0, /* tp_doc */
0, /* tp_traverse */
0, /* tp_clear */
0, /* tp_richcompare */
0, /* tp_weaklistoffset */
0, /* tp_iter */
0, /* tp_iternext */
0, /* tp_methods */
0, /* tp_members */
0, /* tp_getset */
0, /* tp_base */
0, /* tp_dict */
0, /* tp_descr_get */
0, /* tp_descr_set */
0, /* tp_dictoffset */
0, /* tp_init */
0, /* tp_alloc */
bpy_app_handlers_persistent_new, /* tp_new */
0, /* tp_free */
"persistent", /* tp_name */
0, /* tp_basicsize */
0, /* tp_itemsize */
/* methods */
0, /* tp_dealloc */
0, /* tp_print */
0, /* tp_getattr */
0, /* tp_setattr */
0, /* tp_reserved */
0, /* tp_repr */
0, /* tp_as_number */
0, /* tp_as_sequence */
0, /* tp_as_mapping */
0, /* tp_hash */
0, /* tp_call */
0, /* tp_str */
0, /* tp_getattro */
0, /* tp_setattro */
0, /* tp_as_buffer */
Py_TPFLAGS_DEFAULT | Py_TPFLAGS_HAVE_GC | Py_TPFLAGS_BASETYPE, /* tp_flags */
0, /* tp_doc */
0, /* tp_traverse */
0, /* tp_clear */
0, /* tp_richcompare */
0, /* tp_weaklistoffset */
0, /* tp_iter */
0, /* tp_iternext */
0, /* tp_methods */
0, /* tp_members */
0, /* tp_getset */
0, /* tp_base */
0, /* tp_dict */
0, /* tp_descr_get */
0, /* tp_descr_set */
0, /* tp_dictoffset */
0, /* tp_init */
0, /* tp_alloc */
bpy_app_handlers_persistent_new, /* tp_new */
0, /* tp_free */
};
static PyObject *py_cb_array[BLI_CB_EVT_TOT] = {NULL};
static PyObject *make_app_cb_info(void)
{
PyObject *app_cb_info;
int pos;
PyObject *app_cb_info;
int pos;
app_cb_info = PyStructSequence_New(&BlenderAppCbType);
if (app_cb_info == NULL) {
return NULL;
}
app_cb_info = PyStructSequence_New(&BlenderAppCbType);
if (app_cb_info == NULL) {
return NULL;
}
for (pos = 0; pos < BLI_CB_EVT_TOT; pos++) {
if (app_cb_info_fields[pos].name == NULL) {
Py_FatalError("invalid callback slots 1");
}
PyStructSequence_SET_ITEM(app_cb_info, pos, (py_cb_array[pos] = PyList_New(0)));
}
if (app_cb_info_fields[pos + APP_CB_OTHER_FIELDS].name != NULL) {
Py_FatalError("invalid callback slots 2");
}
for (pos = 0; pos < BLI_CB_EVT_TOT; pos++) {
if (app_cb_info_fields[pos].name == NULL) {
Py_FatalError("invalid callback slots 1");
}
PyStructSequence_SET_ITEM(app_cb_info, pos, (py_cb_array[pos] = PyList_New(0)));
}
if (app_cb_info_fields[pos + APP_CB_OTHER_FIELDS].name != NULL) {
Py_FatalError("invalid callback slots 2");
}
/* custom function */
PyStructSequence_SET_ITEM(app_cb_info, pos++, (PyObject *)&BPyPersistent_Type);
/* custom function */
PyStructSequence_SET_ITEM(app_cb_info, pos++, (PyObject *)&BPyPersistent_Type);
return app_cb_info;
return app_cb_info;
}
PyObject *BPY_app_handlers_struct(void)
{
PyObject *ret;
PyObject *ret;
#if defined(_MSC_VER)
BPyPersistent_Type.ob_base.ob_base.ob_type = &PyType_Type;
BPyPersistent_Type.ob_base.ob_base.ob_type = &PyType_Type;
#endif
if (PyType_Ready(&BPyPersistent_Type) < 0) {
BLI_assert(!"error initializing 'bpy.app.handlers.persistent'");
}
if (PyType_Ready(&BPyPersistent_Type) < 0) {
BLI_assert(!"error initializing 'bpy.app.handlers.persistent'");
}
PyStructSequence_InitType(&BlenderAppCbType, &app_cb_info_desc);
PyStructSequence_InitType(&BlenderAppCbType, &app_cb_info_desc);
ret = make_app_cb_info();
ret = make_app_cb_info();
/* prevent user from creating new instances */
BlenderAppCbType.tp_init = NULL;
BlenderAppCbType.tp_new = NULL;
BlenderAppCbType.tp_hash = (hashfunc)_Py_HashPointer; /* without this we can't do set(sys.modules) [#29635] */
/* prevent user from creating new instances */
BlenderAppCbType.tp_init = NULL;
BlenderAppCbType.tp_new = NULL;
BlenderAppCbType.tp_hash = (hashfunc)
_Py_HashPointer; /* without this we can't do set(sys.modules) [#29635] */
/* assign the C callbacks */
if (ret) {
static bCallbackFuncStore funcstore_array[BLI_CB_EVT_TOT] = {{NULL}};
bCallbackFuncStore *funcstore;
int pos = 0;
/* assign the C callbacks */
if (ret) {
static bCallbackFuncStore funcstore_array[BLI_CB_EVT_TOT] = {{NULL}};
bCallbackFuncStore *funcstore;
int pos = 0;
for (pos = 0; pos < BLI_CB_EVT_TOT; pos++) {
funcstore = &funcstore_array[pos];
funcstore->func = bpy_app_generic_callback;
funcstore->alloc = 0;
funcstore->arg = POINTER_FROM_INT(pos);
BLI_callback_add(funcstore, pos);
}
}
for (pos = 0; pos < BLI_CB_EVT_TOT; pos++) {
funcstore = &funcstore_array[pos];
funcstore->func = bpy_app_generic_callback;
funcstore->alloc = 0;
funcstore->arg = POINTER_FROM_INT(pos);
BLI_callback_add(funcstore, pos);
}
}
return ret;
return ret;
}
void BPY_app_handlers_reset(const short do_all)
{
PyGILState_STATE gilstate;
int pos = 0;
PyGILState_STATE gilstate;
int pos = 0;
gilstate = PyGILState_Ensure();
gilstate = PyGILState_Ensure();
if (do_all) {
for (pos = 0; pos < BLI_CB_EVT_TOT; pos++) {
/* clear list */
PyList_SetSlice(py_cb_array[pos], 0, PY_SSIZE_T_MAX, NULL);
}
}
else {
/* save string conversion thrashing */
PyObject *perm_id_str = PyUnicode_FromString(PERMINENT_CB_ID);
if (do_all) {
for (pos = 0; pos < BLI_CB_EVT_TOT; pos++) {
/* clear list */
PyList_SetSlice(py_cb_array[pos], 0, PY_SSIZE_T_MAX, NULL);
}
}
else {
/* save string conversion thrashing */
PyObject *perm_id_str = PyUnicode_FromString(PERMINENT_CB_ID);
for (pos = 0; pos < BLI_CB_EVT_TOT; pos++) {
/* clear only items without PERMINENT_CB_ID */
PyObject *ls = py_cb_array[pos];
Py_ssize_t i;
for (pos = 0; pos < BLI_CB_EVT_TOT; pos++) {
/* clear only items without PERMINENT_CB_ID */
PyObject *ls = py_cb_array[pos];
Py_ssize_t i;
PyObject *item;
PyObject **dict_ptr;
PyObject *item;
PyObject **dict_ptr;
for (i = PyList_GET_SIZE(ls) - 1; i >= 0; i--) {
for (i = PyList_GET_SIZE(ls) - 1; i >= 0; i--) {
if ((PyFunction_Check((item = PyList_GET_ITEM(ls, i)))) &&
(dict_ptr = _PyObject_GetDictPtr(item)) &&
(*dict_ptr) &&
(PyDict_GetItem(*dict_ptr, perm_id_str) != NULL))
{
/* keep */
}
else {
/* remove */
/* PySequence_DelItem(ls, i); */ /* more obvious buw slower */
PyList_SetSlice(ls, i, i + 1, NULL);
}
}
}
if ((PyFunction_Check((item = PyList_GET_ITEM(ls, i)))) &&
(dict_ptr = _PyObject_GetDictPtr(item)) && (*dict_ptr) &&
(PyDict_GetItem(*dict_ptr, perm_id_str) != NULL)) {
/* keep */
}
else {
/* remove */
/* PySequence_DelItem(ls, i); */ /* more obvious buw slower */
PyList_SetSlice(ls, i, i + 1, NULL);
}
}
}
Py_DECREF(perm_id_str);
}
Py_DECREF(perm_id_str);
}
PyGILState_Release(gilstate);
PyGILState_Release(gilstate);
}
/* the actual callback - not necessarily called from py */
void bpy_app_generic_callback(struct Main *UNUSED(main), struct ID *id, void *arg)
{
PyObject *cb_list = py_cb_array[POINTER_AS_INT(arg)];
if (PyList_GET_SIZE(cb_list) > 0) {
PyGILState_STATE gilstate = PyGILState_Ensure();
PyObject *cb_list = py_cb_array[POINTER_AS_INT(arg)];
if (PyList_GET_SIZE(cb_list) > 0) {
PyGILState_STATE gilstate = PyGILState_Ensure();
PyObject *args = PyTuple_New(1); /* save python creating each call */
PyObject *func;
PyObject *ret;
Py_ssize_t pos;
PyObject *args = PyTuple_New(1); /* save python creating each call */
PyObject *func;
PyObject *ret;
Py_ssize_t pos;
/* setup arguments */
if (id) {
PointerRNA id_ptr;
RNA_id_pointer_create(id, &id_ptr);
PyTuple_SET_ITEM(args, 0, pyrna_struct_CreatePyObject(&id_ptr));
}
else {
PyTuple_SET_ITEM(args, 0, Py_INCREF_RET(Py_None));
}
/* setup arguments */
if (id) {
PointerRNA id_ptr;
RNA_id_pointer_create(id, &id_ptr);
PyTuple_SET_ITEM(args, 0, pyrna_struct_CreatePyObject(&id_ptr));
}
else {
PyTuple_SET_ITEM(args, 0, Py_INCREF_RET(Py_None));
}
/* Iterate the list and run the callbacks
* note: don't store the list size since the scripts may remove themselves */
for (pos = 0; pos < PyList_GET_SIZE(cb_list); pos++) {
func = PyList_GET_ITEM(cb_list, pos);
ret = PyObject_Call(func, args, NULL);
if (ret == NULL) {
/* Don't set last system variables because they might cause some
* dangling pointers to external render engines (when exception
* happens during rendering) which will break logic of render pipeline
* which expects to be the only user of render engine when rendering
* is finished.
*/
PyErr_PrintEx(0);
PyErr_Clear();
}
else {
Py_DECREF(ret);
}
}
/* Iterate the list and run the callbacks
* note: don't store the list size since the scripts may remove themselves */
for (pos = 0; pos < PyList_GET_SIZE(cb_list); pos++) {
func = PyList_GET_ITEM(cb_list, pos);
ret = PyObject_Call(func, args, NULL);
if (ret == NULL) {
/* Don't set last system variables because they might cause some
* dangling pointers to external render engines (when exception
* happens during rendering) which will break logic of render pipeline
* which expects to be the only user of render engine when rendering
* is finished.
*/
PyErr_PrintEx(0);
PyErr_Clear();
}
else {
Py_DECREF(ret);
}
}
Py_DECREF(args);
Py_DECREF(args);
PyGILState_Release(gilstate);
}
PyGILState_Release(gilstate);
}
}

View File

@@ -33,151 +33,149 @@
#include "bpy_app_icons.h"
/* We may want to load direct from file. */
PyDoc_STRVAR(bpy_app_icons_new_triangles_doc,
".. function:: new_triangles(range, coords, colors)"
"\n"
" Create a new icon from triangle geometry.\n"
"\n"
" :arg range: Pair of ints.\n"
" :type range: tuple.\n"
" :arg coords: Sequence of bytes (6 floats for one triangle) for (X, Y) coordinates.\n"
" :type coords: byte sequence.\n"
" :arg colors: Sequence of ints (12 for one triangles) for RGBA.\n"
" :type colors: byte sequence.\n"
" :return: Unique icon value (pass to interface ``icon_value`` argument).\n"
" :rtype: int\n"
);
PyDoc_STRVAR(
bpy_app_icons_new_triangles_doc,
".. function:: new_triangles(range, coords, colors)"
"\n"
" Create a new icon from triangle geometry.\n"
"\n"
" :arg range: Pair of ints.\n"
" :type range: tuple.\n"
" :arg coords: Sequence of bytes (6 floats for one triangle) for (X, Y) coordinates.\n"
" :type coords: byte sequence.\n"
" :arg colors: Sequence of ints (12 for one triangles) for RGBA.\n"
" :type colors: byte sequence.\n"
" :return: Unique icon value (pass to interface ``icon_value`` argument).\n"
" :rtype: int\n");
static PyObject *bpy_app_icons_new_triangles(PyObject *UNUSED(self), PyObject *args, PyObject *kw)
{
/* bytes */
uchar coords_range[2];
PyObject *py_coords, *py_colors;
/* bytes */
uchar coords_range[2];
PyObject *py_coords, *py_colors;
static const char *_keywords[] = {"range", "coords", "colors", NULL};
static _PyArg_Parser _parser = {"(BB)SS:new_triangles", _keywords, 0};
if (!_PyArg_ParseTupleAndKeywordsFast(
args, kw, &_parser,
&coords_range[0], &coords_range[1], &py_coords, &py_colors))
{
return NULL;
}
static const char *_keywords[] = {"range", "coords", "colors", NULL};
static _PyArg_Parser _parser = {"(BB)SS:new_triangles", _keywords, 0};
if (!_PyArg_ParseTupleAndKeywordsFast(
args, kw, &_parser, &coords_range[0], &coords_range[1], &py_coords, &py_colors)) {
return NULL;
}
const int coords_len = PyBytes_GET_SIZE(py_coords);
const int tris_len = coords_len / 6;
if (tris_len * 6 != coords_len) {
PyErr_SetString(PyExc_ValueError, "coords must be multiple of 6");
return NULL;
}
if (PyBytes_GET_SIZE(py_colors) != 2 * coords_len) {
PyErr_SetString(PyExc_ValueError, "colors must be twice size of coords");
return NULL;
}
const int coords_len = PyBytes_GET_SIZE(py_coords);
const int tris_len = coords_len / 6;
if (tris_len * 6 != coords_len) {
PyErr_SetString(PyExc_ValueError, "coords must be multiple of 6");
return NULL;
}
if (PyBytes_GET_SIZE(py_colors) != 2 * coords_len) {
PyErr_SetString(PyExc_ValueError, "colors must be twice size of coords");
return NULL;
}
int coords_size = sizeof(uchar[2]) * tris_len * 3;
int colors_size = sizeof(uchar[4]) * tris_len * 3;
uchar (*coords)[2] = MEM_mallocN(coords_size, __func__);
uchar (*colors)[4] = MEM_mallocN(colors_size, __func__);
int coords_size = sizeof(uchar[2]) * tris_len * 3;
int colors_size = sizeof(uchar[4]) * tris_len * 3;
uchar(*coords)[2] = MEM_mallocN(coords_size, __func__);
uchar(*colors)[4] = MEM_mallocN(colors_size, __func__);
memcpy(coords, PyBytes_AS_STRING(py_coords), coords_size);
memcpy(colors, PyBytes_AS_STRING(py_colors), colors_size);
memcpy(coords, PyBytes_AS_STRING(py_coords), coords_size);
memcpy(colors, PyBytes_AS_STRING(py_colors), colors_size);
struct Icon_Geom *geom = MEM_mallocN(sizeof(*geom), __func__);
geom->coords_len = tris_len;
geom->coords_range[0] = coords_range[0];
geom->coords_range[1] = coords_range[1];
geom->coords = coords;
geom->colors = colors;
geom->icon_id = 0;
int icon_id = BKE_icon_geom_ensure(geom);
return PyLong_FromLong(icon_id);
struct Icon_Geom *geom = MEM_mallocN(sizeof(*geom), __func__);
geom->coords_len = tris_len;
geom->coords_range[0] = coords_range[0];
geom->coords_range[1] = coords_range[1];
geom->coords = coords;
geom->colors = colors;
geom->icon_id = 0;
int icon_id = BKE_icon_geom_ensure(geom);
return PyLong_FromLong(icon_id);
}
PyDoc_STRVAR(bpy_app_icons_new_triangles_from_file_doc,
".. function:: new_triangles_from_file(filename)"
"\n"
" Create a new icon from triangle geometry.\n"
"\n"
" :arg filename: File path.\n"
" :type filename: string.\n"
" :return: Unique icon value (pass to interface ``icon_value`` argument).\n"
" :rtype: int\n"
);
static PyObject *bpy_app_icons_new_triangles_from_file(PyObject *UNUSED(self), PyObject *args, PyObject *kw)
".. function:: new_triangles_from_file(filename)"
"\n"
" Create a new icon from triangle geometry.\n"
"\n"
" :arg filename: File path.\n"
" :type filename: string.\n"
" :return: Unique icon value (pass to interface ``icon_value`` argument).\n"
" :rtype: int\n");
static PyObject *bpy_app_icons_new_triangles_from_file(PyObject *UNUSED(self),
PyObject *args,
PyObject *kw)
{
/* bytes */
char *filename;
/* bytes */
char *filename;
static const char *_keywords[] = {"filename", NULL};
static _PyArg_Parser _parser = {"s:new_triangles_from_file", _keywords, 0};
if (!_PyArg_ParseTupleAndKeywordsFast(
args, kw, &_parser,
&filename))
{
return NULL;
}
static const char *_keywords[] = {"filename", NULL};
static _PyArg_Parser _parser = {"s:new_triangles_from_file", _keywords, 0};
if (!_PyArg_ParseTupleAndKeywordsFast(args, kw, &_parser, &filename)) {
return NULL;
}
struct Icon_Geom *geom = BKE_icon_geom_from_file(filename);
if (geom == NULL) {
PyErr_SetString(PyExc_ValueError, "Unable to load from file");
return NULL;
}
int icon_id = BKE_icon_geom_ensure(geom);
return PyLong_FromLong(icon_id);
struct Icon_Geom *geom = BKE_icon_geom_from_file(filename);
if (geom == NULL) {
PyErr_SetString(PyExc_ValueError, "Unable to load from file");
return NULL;
}
int icon_id = BKE_icon_geom_ensure(geom);
return PyLong_FromLong(icon_id);
}
PyDoc_STRVAR(bpy_app_icons_release_doc,
".. function:: release(icon_id)"
"\n"
" Release the icon.\n"
);
".. function:: release(icon_id)"
"\n"
" Release the icon.\n");
static PyObject *bpy_app_icons_release(PyObject *UNUSED(self), PyObject *args, PyObject *kw)
{
int icon_id;
static const char *_keywords[] = {"icon_id", NULL};
static _PyArg_Parser _parser = {"i:release", _keywords, 0};
if (!_PyArg_ParseTupleAndKeywordsFast(
args, kw, &_parser,
&icon_id))
{
return NULL;
}
int icon_id;
static const char *_keywords[] = {"icon_id", NULL};
static _PyArg_Parser _parser = {"i:release", _keywords, 0};
if (!_PyArg_ParseTupleAndKeywordsFast(args, kw, &_parser, &icon_id)) {
return NULL;
}
if (!BKE_icon_delete_unmanaged(icon_id)) {
PyErr_SetString(PyExc_ValueError, "invalid icon_id");
return NULL;
}
Py_RETURN_NONE;
if (!BKE_icon_delete_unmanaged(icon_id)) {
PyErr_SetString(PyExc_ValueError, "invalid icon_id");
return NULL;
}
Py_RETURN_NONE;
}
static struct PyMethodDef M_AppIcons_methods[] = {
{"new_triangles", (PyCFunction)bpy_app_icons_new_triangles,
METH_VARARGS | METH_KEYWORDS, bpy_app_icons_new_triangles_doc},
{"new_triangles_from_file", (PyCFunction)bpy_app_icons_new_triangles_from_file,
METH_VARARGS | METH_KEYWORDS, bpy_app_icons_new_triangles_from_file_doc},
{"release", (PyCFunction)bpy_app_icons_release,
METH_VARARGS | METH_KEYWORDS, bpy_app_icons_release_doc},
{NULL, NULL, 0, NULL},
{"new_triangles",
(PyCFunction)bpy_app_icons_new_triangles,
METH_VARARGS | METH_KEYWORDS,
bpy_app_icons_new_triangles_doc},
{"new_triangles_from_file",
(PyCFunction)bpy_app_icons_new_triangles_from_file,
METH_VARARGS | METH_KEYWORDS,
bpy_app_icons_new_triangles_from_file_doc},
{"release",
(PyCFunction)bpy_app_icons_release,
METH_VARARGS | METH_KEYWORDS,
bpy_app_icons_release_doc},
{NULL, NULL, 0, NULL},
};
static struct PyModuleDef M_AppIcons_module_def = {
PyModuleDef_HEAD_INIT,
"bpy.app.icons", /* m_name */
NULL, /* m_doc */
0, /* m_size */
M_AppIcons_methods, /* m_methods */
NULL, /* m_reload */
NULL, /* m_traverse */
NULL, /* m_clear */
NULL, /* m_free */
PyModuleDef_HEAD_INIT,
"bpy.app.icons", /* m_name */
NULL, /* m_doc */
0, /* m_size */
M_AppIcons_methods, /* m_methods */
NULL, /* m_reload */
NULL, /* m_traverse */
NULL, /* m_clear */
NULL, /* m_free */
};
PyObject *BPY_app_icons_module(void)
{
PyObject *sys_modules = PyImport_GetModuleDict();
PyObject *sys_modules = PyImport_GetModuleDict();
PyObject *mod = PyModule_Create(&M_AppIcons_module_def);
PyObject *mod = PyModule_Create(&M_AppIcons_module_def);
PyDict_SetItem(sys_modules, PyModule_GetNameObject(mod), mod);
PyDict_SetItem(sys_modules, PyModule_GetNameObject(mod), mod);
return mod;
return mod;
}

View File

@@ -32,76 +32,78 @@
static PyTypeObject BlenderAppOCIOType;
static PyStructSequence_Field app_ocio_info_fields[] = {
{(char *)"supported", (char *)("Boolean, True when Blender is built with OpenColorIO support")},
{(char *)("version"), (char *)("The OpenColorIO version as a tuple of 3 numbers")},
{(char *)("version_string"), (char *)("The OpenColorIO version formatted as a string")},
{NULL},
{(char *)"supported",
(char *)("Boolean, True when Blender is built with OpenColorIO support")},
{(char *)("version"), (char *)("The OpenColorIO version as a tuple of 3 numbers")},
{(char *)("version_string"), (char *)("The OpenColorIO version formatted as a string")},
{NULL},
};
static PyStructSequence_Desc app_ocio_info_desc = {
(char *)"bpy.app.ocio", /* name */
(char *)"This module contains information about OpenColorIO blender is linked against", /* doc */
app_ocio_info_fields, /* fields */
ARRAY_SIZE(app_ocio_info_fields) - 1,
(char *)"bpy.app.ocio", /* name */
(char
*)"This module contains information about OpenColorIO blender is linked against", /* doc */
app_ocio_info_fields, /* fields */
ARRAY_SIZE(app_ocio_info_fields) - 1,
};
static PyObject *make_ocio_info(void)
{
PyObject *ocio_info;
int pos = 0;
PyObject *ocio_info;
int pos = 0;
#ifdef WITH_OCIO
int curversion;
int curversion;
#endif
ocio_info = PyStructSequence_New(&BlenderAppOCIOType);
if (ocio_info == NULL) {
return NULL;
}
ocio_info = PyStructSequence_New(&BlenderAppOCIOType);
if (ocio_info == NULL) {
return NULL;
}
#ifndef WITH_OCIO
#define SetStrItem(str) \
PyStructSequence_SET_ITEM(ocio_info, pos++, PyUnicode_FromString(str))
# define SetStrItem(str) PyStructSequence_SET_ITEM(ocio_info, pos++, PyUnicode_FromString(str))
#endif
#define SetObjItem(obj) \
PyStructSequence_SET_ITEM(ocio_info, pos++, obj)
#define SetObjItem(obj) PyStructSequence_SET_ITEM(ocio_info, pos++, obj)
#ifdef WITH_OCIO
curversion = OCIO_getVersionHex();
SetObjItem(PyBool_FromLong(1));
SetObjItem(PyC_Tuple_Pack_I32(curversion >> 24, (curversion >> 16) % 256, (curversion >> 8) % 256));
SetObjItem(PyUnicode_FromFormat("%2d, %2d, %2d",
curversion >> 24, (curversion >> 16) % 256, (curversion >> 8) % 256));
curversion = OCIO_getVersionHex();
SetObjItem(PyBool_FromLong(1));
SetObjItem(
PyC_Tuple_Pack_I32(curversion >> 24, (curversion >> 16) % 256, (curversion >> 8) % 256));
SetObjItem(PyUnicode_FromFormat(
"%2d, %2d, %2d", curversion >> 24, (curversion >> 16) % 256, (curversion >> 8) % 256));
#else
SetObjItem(PyBool_FromLong(0));
SetObjItem(PyC_Tuple_Pack_I32(0, 0, 0));
SetStrItem("Unknown");
SetObjItem(PyBool_FromLong(0));
SetObjItem(PyC_Tuple_Pack_I32(0, 0, 0));
SetStrItem("Unknown");
#endif
if (PyErr_Occurred()) {
Py_CLEAR(ocio_info);
return NULL;
}
if (PyErr_Occurred()) {
Py_CLEAR(ocio_info);
return NULL;
}
#undef SetStrItem
#undef SetObjItem
return ocio_info;
return ocio_info;
}
PyObject *BPY_app_ocio_struct(void)
{
PyObject *ret;
PyObject *ret;
PyStructSequence_InitType(&BlenderAppOCIOType, &app_ocio_info_desc);
PyStructSequence_InitType(&BlenderAppOCIOType, &app_ocio_info_desc);
ret = make_ocio_info();
ret = make_ocio_info();
/* prevent user from creating new instances */
BlenderAppOCIOType.tp_init = NULL;
BlenderAppOCIOType.tp_new = NULL;
BlenderAppOCIOType.tp_hash = (hashfunc)_Py_HashPointer; /* without this we can't do set(sys.modules) [#29635] */
/* prevent user from creating new instances */
BlenderAppOCIOType.tp_init = NULL;
BlenderAppOCIOType.tp_new = NULL;
BlenderAppOCIOType.tp_hash = (hashfunc)
_Py_HashPointer; /* without this we can't do set(sys.modules) [#29635] */
return ret;
return ret;
}

View File

@@ -23,4 +23,4 @@
PyObject *BPY_app_ocio_struct(void);
#endif /* __BPY_APP_OCIO_H__ */
#endif /* __BPY_APP_OCIO_H__ */

View File

@@ -32,76 +32,77 @@
static PyTypeObject BlenderAppOIIOType;
static PyStructSequence_Field app_oiio_info_fields[] = {
{(char *)"supported", (char *)("Boolean, True when Blender is built with OpenImageIO support")},
{(char *)("version"), (char *)("The OpenImageIO version as a tuple of 3 numbers")},
{(char *)("version_string"), (char *)("The OpenImageIO version formatted as a string")},
{NULL},
{(char *)"supported",
(char *)("Boolean, True when Blender is built with OpenImageIO support")},
{(char *)("version"), (char *)("The OpenImageIO version as a tuple of 3 numbers")},
{(char *)("version_string"), (char *)("The OpenImageIO version formatted as a string")},
{NULL},
};
static PyStructSequence_Desc app_oiio_info_desc = {
(char *)"bpy.app.oiio", /* name */
(char *)"This module contains information about OpeImageIO blender is linked against", /* doc */
app_oiio_info_fields, /* fields */
ARRAY_SIZE(app_oiio_info_fields) - 1,
(char *)"bpy.app.oiio", /* name */
(char
*)"This module contains information about OpeImageIO blender is linked against", /* doc */
app_oiio_info_fields, /* fields */
ARRAY_SIZE(app_oiio_info_fields) - 1,
};
static PyObject *make_oiio_info(void)
{
PyObject *oiio_info;
int pos = 0;
PyObject *oiio_info;
int pos = 0;
#ifdef WITH_OPENIMAGEIO
int curversion;
int curversion;
#endif
oiio_info = PyStructSequence_New(&BlenderAppOIIOType);
if (oiio_info == NULL) {
return NULL;
}
oiio_info = PyStructSequence_New(&BlenderAppOIIOType);
if (oiio_info == NULL) {
return NULL;
}
#ifndef WITH_OPENIMAGEIO
#define SetStrItem(str) \
PyStructSequence_SET_ITEM(oiio_info, pos++, PyUnicode_FromString(str))
# define SetStrItem(str) PyStructSequence_SET_ITEM(oiio_info, pos++, PyUnicode_FromString(str))
#endif
#define SetObjItem(obj) \
PyStructSequence_SET_ITEM(oiio_info, pos++, obj)
#define SetObjItem(obj) PyStructSequence_SET_ITEM(oiio_info, pos++, obj)
#ifdef WITH_OPENIMAGEIO
curversion = OIIO_getVersionHex();
SetObjItem(PyBool_FromLong(1));
SetObjItem(PyC_Tuple_Pack_I32(curversion / 10000, (curversion / 100) % 100, curversion % 100));
SetObjItem(PyUnicode_FromFormat("%2d, %2d, %2d",
curversion / 10000, (curversion / 100) % 100, curversion % 100));
curversion = OIIO_getVersionHex();
SetObjItem(PyBool_FromLong(1));
SetObjItem(PyC_Tuple_Pack_I32(curversion / 10000, (curversion / 100) % 100, curversion % 100));
SetObjItem(PyUnicode_FromFormat(
"%2d, %2d, %2d", curversion / 10000, (curversion / 100) % 100, curversion % 100));
#else
SetObjItem(PyBool_FromLong(0));
SetObjItem(PyC_Tuple_Pack_I32(0, 0, 0));
SetStrItem("Unknown");
SetObjItem(PyBool_FromLong(0));
SetObjItem(PyC_Tuple_Pack_I32(0, 0, 0));
SetStrItem("Unknown");
#endif
if (PyErr_Occurred()) {
Py_CLEAR(oiio_info);
return NULL;
}
if (PyErr_Occurred()) {
Py_CLEAR(oiio_info);
return NULL;
}
#undef SetStrItem
#undef SetObjItem
return oiio_info;
return oiio_info;
}
PyObject *BPY_app_oiio_struct(void)
{
PyObject *ret;
PyObject *ret;
PyStructSequence_InitType(&BlenderAppOIIOType, &app_oiio_info_desc);
PyStructSequence_InitType(&BlenderAppOIIOType, &app_oiio_info_desc);
ret = make_oiio_info();
ret = make_oiio_info();
/* prevent user from creating new instances */
BlenderAppOIIOType.tp_init = NULL;
BlenderAppOIIOType.tp_new = NULL;
BlenderAppOIIOType.tp_hash = (hashfunc)_Py_HashPointer; /* without this we can't do set(sys.modules) [#29635] */
/* prevent user from creating new instances */
BlenderAppOIIOType.tp_init = NULL;
BlenderAppOIIOType.tp_new = NULL;
BlenderAppOIIOType.tp_hash = (hashfunc)
_Py_HashPointer; /* without this we can't do set(sys.modules) [#29635] */
return ret;
return ret;
}

View File

@@ -23,4 +23,4 @@
PyObject *BPY_app_oiio_struct(void);
#endif /* __BPY_APP_OIIO_H__ */
#endif /* __BPY_APP_OIIO_H__ */

View File

@@ -32,73 +32,73 @@
static PyTypeObject BlenderAppOpenSubdivType;
static PyStructSequence_Field app_opensubdiv_info_fields[] = {
{(char *)"supported", (char *)("Boolean, True when Blender is built with OpenSubdiv support")},
{(char *)("version"), (char *)("The OpenSubdiv version as a tuple of 3 numbers")},
{(char *)("version_string"), (char *)("The OpenSubdiv version formatted as a string")},
{NULL},
{(char *)"supported", (char *)("Boolean, True when Blender is built with OpenSubdiv support")},
{(char *)("version"), (char *)("The OpenSubdiv version as a tuple of 3 numbers")},
{(char *)("version_string"), (char *)("The OpenSubdiv version formatted as a string")},
{NULL},
};
static PyStructSequence_Desc app_opensubdiv_info_desc = {
(char *)"bpy.app.opensubdiv", /* name */
(char *)"This module contains information about OpenSubdiv blender is linked against", /* doc */
app_opensubdiv_info_fields, /* fields */
ARRAY_SIZE(app_opensubdiv_info_fields) - 1,
(char *)"bpy.app.opensubdiv", /* name */
(char
*)"This module contains information about OpenSubdiv blender is linked against", /* doc */
app_opensubdiv_info_fields, /* fields */
ARRAY_SIZE(app_opensubdiv_info_fields) - 1,
};
static PyObject *make_opensubdiv_info(void)
{
PyObject *opensubdiv_info;
int pos = 0;
PyObject *opensubdiv_info;
int pos = 0;
opensubdiv_info = PyStructSequence_New(&BlenderAppOpenSubdivType);
if (opensubdiv_info == NULL) {
return NULL;
}
opensubdiv_info = PyStructSequence_New(&BlenderAppOpenSubdivType);
if (opensubdiv_info == NULL) {
return NULL;
}
#ifndef WITH_OPENSUBDIV
#define SetStrItem(str) \
PyStructSequence_SET_ITEM(opensubdiv_info, pos++, PyUnicode_FromString(str))
# define SetStrItem(str) \
PyStructSequence_SET_ITEM(opensubdiv_info, pos++, PyUnicode_FromString(str))
#endif
#define SetObjItem(obj) \
PyStructSequence_SET_ITEM(opensubdiv_info, pos++, obj)
#define SetObjItem(obj) PyStructSequence_SET_ITEM(opensubdiv_info, pos++, obj)
#ifdef WITH_OPENSUBDIV
int curversion = openSubdiv_getVersionHex();
SetObjItem(PyBool_FromLong(1));
SetObjItem(PyC_Tuple_Pack_I32(curversion / 10000, (curversion / 100) % 100, curversion % 100));
SetObjItem(PyUnicode_FromFormat("%2d, %2d, %2d",
curversion / 10000, (curversion / 100) % 100, curversion % 100));
int curversion = openSubdiv_getVersionHex();
SetObjItem(PyBool_FromLong(1));
SetObjItem(PyC_Tuple_Pack_I32(curversion / 10000, (curversion / 100) % 100, curversion % 100));
SetObjItem(PyUnicode_FromFormat(
"%2d, %2d, %2d", curversion / 10000, (curversion / 100) % 100, curversion % 100));
#else
SetObjItem(PyBool_FromLong(0));
SetObjItem(PyC_Tuple_Pack_I32(0, 0, 0));
SetStrItem("Unknown");
SetObjItem(PyBool_FromLong(0));
SetObjItem(PyC_Tuple_Pack_I32(0, 0, 0));
SetStrItem("Unknown");
#endif
if (PyErr_Occurred()) {
Py_CLEAR(opensubdiv_info);
return NULL;
}
if (PyErr_Occurred()) {
Py_CLEAR(opensubdiv_info);
return NULL;
}
#undef SetStrItem
#undef SetObjItem
return opensubdiv_info;
return opensubdiv_info;
}
PyObject *BPY_app_opensubdiv_struct(void)
{
PyObject *ret;
PyObject *ret;
PyStructSequence_InitType(&BlenderAppOpenSubdivType, &app_opensubdiv_info_desc);
PyStructSequence_InitType(&BlenderAppOpenSubdivType, &app_opensubdiv_info_desc);
ret = make_opensubdiv_info();
ret = make_opensubdiv_info();
/* prevent user from creating new instances */
BlenderAppOpenSubdivType.tp_init = NULL;
BlenderAppOpenSubdivType.tp_new = NULL;
/* without this we can't do set(sys.modules) [#29635] */
BlenderAppOpenSubdivType.tp_hash = (hashfunc)_Py_HashPointer;
/* prevent user from creating new instances */
BlenderAppOpenSubdivType.tp_init = NULL;
BlenderAppOpenSubdivType.tp_new = NULL;
/* without this we can't do set(sys.modules) [#29635] */
BlenderAppOpenSubdivType.tp_hash = (hashfunc)_Py_HashPointer;
return ret;
return ret;
}

View File

@@ -23,4 +23,4 @@
PyObject *BPY_app_opensubdiv_struct(void);
#endif /* __BPY_APP_OPENSUBDIV_H__ */
#endif /* __BPY_APP_OPENSUBDIV_H__ */

View File

@@ -35,76 +35,76 @@
static PyTypeObject BlenderAppOVDBType;
static PyStructSequence_Field app_openvdb_info_fields[] = {
{(char *)"supported", (char *)("Boolean, True when Blender is built with OpenVDB support")},
{(char *)("version"), (char *)("The OpenVDB version as a tuple of 3 numbers")},
{(char *)("version_string"), (char *)("The OpenVDB version formatted as a string")},
{NULL},
{(char *)"supported", (char *)("Boolean, True when Blender is built with OpenVDB support")},
{(char *)("version"), (char *)("The OpenVDB version as a tuple of 3 numbers")},
{(char *)("version_string"), (char *)("The OpenVDB version formatted as a string")},
{NULL},
};
static PyStructSequence_Desc app_openvdb_info_desc = {
(char *)"bpy.app.openvdb", /* name */
(char *)"This module contains information about OpenVDB blender is linked against", /* doc */
app_openvdb_info_fields, /* fields */
ARRAY_SIZE(app_openvdb_info_fields) - 1,
(char *)"bpy.app.openvdb", /* name */
(char *)"This module contains information about OpenVDB blender is linked against", /* doc */
app_openvdb_info_fields, /* fields */
ARRAY_SIZE(app_openvdb_info_fields) - 1,
};
static PyObject *make_openvdb_info(void)
{
PyObject *openvdb_info;
int pos = 0;
PyObject *openvdb_info;
int pos = 0;
#ifdef WITH_OPENVDB
int curversion;
int curversion;
#endif
openvdb_info = PyStructSequence_New(&BlenderAppOVDBType);
if (openvdb_info == NULL) {
return NULL;
}
openvdb_info = PyStructSequence_New(&BlenderAppOVDBType);
if (openvdb_info == NULL) {
return NULL;
}
#ifndef WITH_OPENVDB
#define SetStrItem(str) \
PyStructSequence_SET_ITEM(openvdb_info, pos++, PyUnicode_FromString(str))
# define SetStrItem(str) PyStructSequence_SET_ITEM(openvdb_info, pos++, PyUnicode_FromString(str))
#endif
#define SetObjItem(obj) \
PyStructSequence_SET_ITEM(openvdb_info, pos++, obj)
#define SetObjItem(obj) PyStructSequence_SET_ITEM(openvdb_info, pos++, obj)
#ifdef WITH_OPENVDB
curversion = OpenVDB_getVersionHex();
SetObjItem(PyBool_FromLong(1));
SetObjItem(PyC_Tuple_Pack_I32(curversion >> 24, (curversion >> 16) % 256, (curversion >> 8) % 256));
SetObjItem(PyUnicode_FromFormat("%2d, %2d, %2d",
curversion >> 24, (curversion >> 16) % 256, (curversion >> 8) % 256));
curversion = OpenVDB_getVersionHex();
SetObjItem(PyBool_FromLong(1));
SetObjItem(
PyC_Tuple_Pack_I32(curversion >> 24, (curversion >> 16) % 256, (curversion >> 8) % 256));
SetObjItem(PyUnicode_FromFormat(
"%2d, %2d, %2d", curversion >> 24, (curversion >> 16) % 256, (curversion >> 8) % 256));
#else
SetObjItem(PyBool_FromLong(0));
SetObjItem(PyC_Tuple_Pack_I32(0, 0, 0));
SetStrItem("Unknown");
SetObjItem(PyBool_FromLong(0));
SetObjItem(PyC_Tuple_Pack_I32(0, 0, 0));
SetStrItem("Unknown");
#endif
if (PyErr_Occurred()) {
Py_CLEAR(openvdb_info);
return NULL;
}
if (PyErr_Occurred()) {
Py_CLEAR(openvdb_info);
return NULL;
}
#undef SetStrItem
#undef SetObjItem
return openvdb_info;
return openvdb_info;
}
PyObject *BPY_app_openvdb_struct(void)
{
PyObject *ret;
PyObject *ret;
PyStructSequence_InitType(&BlenderAppOVDBType, &app_openvdb_info_desc);
PyStructSequence_InitType(&BlenderAppOVDBType, &app_openvdb_info_desc);
ret = make_openvdb_info();
ret = make_openvdb_info();
/* prevent user from creating new instances */
BlenderAppOVDBType.tp_init = NULL;
BlenderAppOVDBType.tp_new = NULL;
BlenderAppOVDBType.tp_hash = (hashfunc)_Py_HashPointer; /* without this we can't do set(sys.modules) [#29635] */
/* prevent user from creating new instances */
BlenderAppOVDBType.tp_init = NULL;
BlenderAppOVDBType.tp_new = NULL;
BlenderAppOVDBType.tp_hash = (hashfunc)
_Py_HashPointer; /* without this we can't do set(sys.modules) [#29635] */
return ret;
return ret;
}

View File

@@ -26,4 +26,4 @@
PyObject *BPY_app_openvdb_struct(void);
#endif /* __BPY_APP_OPENVDB_H__ */
#endif /* __BPY_APP_OPENVDB_H__ */

View File

@@ -46,98 +46,98 @@
static PyTypeObject BlenderAppSDLType;
static PyStructSequence_Field app_sdl_info_fields[] = {
{(char *)"supported", (char *)("Boolean, True when Blender is built with SDL support")},
{(char *)"version", (char *)("The SDL version as a tuple of 3 numbers")},
{(char *)"version_string", (char *)("The SDL version formatted as a string")},
{(char *)"available", (char *)("Boolean, True when SDL is available. This is False when "
"either *supported* is False, or *dynload* is True and "
"Blender cannot find the correct library.")},
{NULL},
{(char *)"supported", (char *)("Boolean, True when Blender is built with SDL support")},
{(char *)"version", (char *)("The SDL version as a tuple of 3 numbers")},
{(char *)"version_string", (char *)("The SDL version formatted as a string")},
{(char *)"available",
(char *)("Boolean, True when SDL is available. This is False when "
"either *supported* is False, or *dynload* is True and "
"Blender cannot find the correct library.")},
{NULL},
};
static PyStructSequence_Desc app_sdl_info_desc = {
(char *)"bpy.app.sdl", /* name */
(char *)"This module contains information about SDL blender is linked against", /* doc */
app_sdl_info_fields, /* fields */
ARRAY_SIZE(app_sdl_info_fields) - 1,
(char *)"bpy.app.sdl", /* name */
(char *)"This module contains information about SDL blender is linked against", /* doc */
app_sdl_info_fields, /* fields */
ARRAY_SIZE(app_sdl_info_fields) - 1,
};
static PyObject *make_sdl_info(void)
{
PyObject *sdl_info;
int pos = 0;
PyObject *sdl_info;
int pos = 0;
#ifdef WITH_SDL
bool sdl_available = false;
SDL_version version = {0, 0, 0};
bool sdl_available = false;
SDL_version version = {0, 0, 0};
#endif
sdl_info = PyStructSequence_New(&BlenderAppSDLType);
if (sdl_info == NULL) {
return NULL;
}
sdl_info = PyStructSequence_New(&BlenderAppSDLType);
if (sdl_info == NULL) {
return NULL;
}
#define SetStrItem(str) \
PyStructSequence_SET_ITEM(sdl_info, pos++, PyUnicode_FromString(str))
#define SetStrItem(str) PyStructSequence_SET_ITEM(sdl_info, pos++, PyUnicode_FromString(str))
#define SetObjItem(obj) \
PyStructSequence_SET_ITEM(sdl_info, pos++, obj)
#define SetObjItem(obj) PyStructSequence_SET_ITEM(sdl_info, pos++, obj)
#ifdef WITH_SDL
SetObjItem(PyBool_FromLong(1));
SetObjItem(PyBool_FromLong(1));
# ifdef WITH_SDL_DYNLOAD
if (sdlewInit() == SDLEW_SUCCESS) {
SDL_GetVersion(&version);
sdl_available = true;
}
# else // WITH_SDL_DYNLOAD=OFF
sdl_available = true;
# if SDL_MAJOR_VERSION >= 2
SDL_GetVersion(&version);
# else
SDL_VERSION(&version);
# ifdef WITH_SDL_DYNLOAD
if (sdlewInit() == SDLEW_SUCCESS) {
SDL_GetVersion(&version);
sdl_available = true;
}
# else // WITH_SDL_DYNLOAD=OFF
sdl_available = true;
# if SDL_MAJOR_VERSION >= 2
SDL_GetVersion(&version);
# else
SDL_VERSION(&version);
# endif
# endif
# endif
SetObjItem(PyC_Tuple_Pack_I32(version.major, version.minor, version.patch));
if (sdl_available) {
SetObjItem(PyUnicode_FromFormat("%d.%d.%d", version.major, version.minor, version.patch));
}
else {
SetStrItem("Unknown");
}
SetObjItem(PyBool_FromLong(sdl_available));
SetObjItem(PyC_Tuple_Pack_I32(version.major, version.minor, version.patch));
if (sdl_available) {
SetObjItem(PyUnicode_FromFormat("%d.%d.%d", version.major, version.minor, version.patch));
}
else {
SetStrItem("Unknown");
}
SetObjItem(PyBool_FromLong(sdl_available));
#else // WITH_SDL=OFF
SetObjItem(PyBool_FromLong(0));
SetObjItem(PyC_Tuple_Pack_I32(0, 0, 0));
SetStrItem("Unknown");
SetObjItem(PyBool_FromLong(0));
#else // WITH_SDL=OFF
SetObjItem(PyBool_FromLong(0));
SetObjItem(PyC_Tuple_Pack_I32(0, 0, 0));
SetStrItem("Unknown");
SetObjItem(PyBool_FromLong(0));
#endif
if (PyErr_Occurred()) {
Py_CLEAR(sdl_info);
return NULL;
}
if (PyErr_Occurred()) {
Py_CLEAR(sdl_info);
return NULL;
}
#undef SetStrItem
#undef SetObjItem
return sdl_info;
return sdl_info;
}
PyObject *BPY_app_sdl_struct(void)
{
PyObject *ret;
PyObject *ret;
PyStructSequence_InitType(&BlenderAppSDLType, &app_sdl_info_desc);
PyStructSequence_InitType(&BlenderAppSDLType, &app_sdl_info_desc);
ret = make_sdl_info();
ret = make_sdl_info();
/* prevent user from creating new instances */
BlenderAppSDLType.tp_init = NULL;
BlenderAppSDLType.tp_new = NULL;
BlenderAppSDLType.tp_hash = (hashfunc)_Py_HashPointer; /* without this we can't do set(sys.modules) [#29635] */
/* prevent user from creating new instances */
BlenderAppSDLType.tp_init = NULL;
BlenderAppSDLType.tp_new = NULL;
BlenderAppSDLType.tp_hash = (hashfunc)
_Py_HashPointer; /* without this we can't do set(sys.modules) [#29635] */
return ret;
return ret;
}

View File

@@ -23,4 +23,4 @@
PyObject *BPY_app_sdl_struct(void);
#endif /* __BPY_APP_SDL_H__ */
#endif /* __BPY_APP_SDL_H__ */

View File

@@ -29,167 +29,161 @@
#include "../generic/py_capi_utils.h"
#include "../generic/python_utildefines.h"
static double handle_returned_value(PyObject *function, PyObject *ret)
{
if (ret == NULL) {
PyErr_PrintEx(0);
PyErr_Clear();
return -1;
}
if (ret == NULL) {
PyErr_PrintEx(0);
PyErr_Clear();
return -1;
}
if (ret == Py_None) {
return -1;
}
if (ret == Py_None) {
return -1;
}
double value = PyFloat_AsDouble(ret);
if (value == -1.0f && PyErr_Occurred()) {
PyErr_Clear();
printf("Error: 'bpy.app.timers' callback ");
PyObject_Print(function, stdout, Py_PRINT_RAW);
printf(" did not return None or float.\n");
return -1;
}
double value = PyFloat_AsDouble(ret);
if (value == -1.0f && PyErr_Occurred()) {
PyErr_Clear();
printf("Error: 'bpy.app.timers' callback ");
PyObject_Print(function, stdout, Py_PRINT_RAW);
printf(" did not return None or float.\n");
return -1;
}
if (value < 0.0) {
value = 0.0;
}
if (value < 0.0) {
value = 0.0;
}
return value;
return value;
}
static double py_timer_execute(uintptr_t UNUSED(uuid), void *user_data)
{
PyObject *function = user_data;
PyObject *function = user_data;
PyGILState_STATE gilstate;
gilstate = PyGILState_Ensure();
PyGILState_STATE gilstate;
gilstate = PyGILState_Ensure();
PyObject *py_ret = PyObject_CallObject(function, NULL);
double ret = handle_returned_value(function, py_ret);
PyObject *py_ret = PyObject_CallObject(function, NULL);
double ret = handle_returned_value(function, py_ret);
PyGILState_Release(gilstate);
PyGILState_Release(gilstate);
return ret;
return ret;
}
static void py_timer_free(uintptr_t UNUSED(uuid), void *user_data)
{
PyObject *function = user_data;
PyObject *function = user_data;
PyGILState_STATE gilstate;
gilstate = PyGILState_Ensure();
PyGILState_STATE gilstate;
gilstate = PyGILState_Ensure();
Py_DECREF(function);
Py_DECREF(function);
PyGILState_Release(gilstate);
PyGILState_Release(gilstate);
}
PyDoc_STRVAR(bpy_app_timers_register_doc,
".. function:: register(function, first_interval=0, persistent=False)\n"
"\n"
" Add a new function that will be called after the specified amount of seconds.\n"
" The function gets no arguments and is expected to return either None or a float.\n"
" If ``None`` is returned, the timer will be unregistered.\n"
" A returned number specifies the delay until the function is called again.\n"
" ``functools.partial`` can be used to assign some parameters.\n"
"\n"
" :arg function: The function that should called.\n"
" :type function: Callable[[], Union[float, None]]\n"
" :arg first_interval: Seconds until the callback should be called the first time.\n"
" :type first_interval: float\n"
" :arg persistent: Don't remove timer when a new file is loaded.\n"
" :type persistent: bool\n"
);
PyDoc_STRVAR(
bpy_app_timers_register_doc,
".. function:: register(function, first_interval=0, persistent=False)\n"
"\n"
" Add a new function that will be called after the specified amount of seconds.\n"
" The function gets no arguments and is expected to return either None or a float.\n"
" If ``None`` is returned, the timer will be unregistered.\n"
" A returned number specifies the delay until the function is called again.\n"
" ``functools.partial`` can be used to assign some parameters.\n"
"\n"
" :arg function: The function that should called.\n"
" :type function: Callable[[], Union[float, None]]\n"
" :arg first_interval: Seconds until the callback should be called the first time.\n"
" :type first_interval: float\n"
" :arg persistent: Don't remove timer when a new file is loaded.\n"
" :type persistent: bool\n");
static PyObject *bpy_app_timers_register(PyObject *UNUSED(self), PyObject *args, PyObject *kw)
{
PyObject *function;
double first_interval = 0;
int persistent = false;
PyObject *function;
double first_interval = 0;
int persistent = false;
static const char *_keywords[] = {"function", "first_interval", "persistent", NULL};
static _PyArg_Parser _parser = {"O|$dp:register", _keywords, 0};
if (!_PyArg_ParseTupleAndKeywordsFast(
args, kw, &_parser,
&function, &first_interval, &persistent))
{
return NULL;
}
static const char *_keywords[] = {"function", "first_interval", "persistent", NULL};
static _PyArg_Parser _parser = {"O|$dp:register", _keywords, 0};
if (!_PyArg_ParseTupleAndKeywordsFast(
args, kw, &_parser, &function, &first_interval, &persistent)) {
return NULL;
}
if (!PyCallable_Check(function)) {
PyErr_SetString(PyExc_TypeError, "function is not callable");
return NULL;
}
if (!PyCallable_Check(function)) {
PyErr_SetString(PyExc_TypeError, "function is not callable");
return NULL;
}
Py_INCREF(function);
BLI_timer_register(
(intptr_t)function,
py_timer_execute, function, py_timer_free,
first_interval, persistent);
Py_RETURN_NONE;
Py_INCREF(function);
BLI_timer_register(
(intptr_t)function, py_timer_execute, function, py_timer_free, first_interval, persistent);
Py_RETURN_NONE;
}
PyDoc_STRVAR(bpy_app_timers_unregister_doc,
".. function:: unregister(function)\n"
"\n"
" Unregister timer.\n"
"\n"
" :arg function: Function to unregister.\n"
" :type function: function\n"
);
".. function:: unregister(function)\n"
"\n"
" Unregister timer.\n"
"\n"
" :arg function: Function to unregister.\n"
" :type function: function\n");
static PyObject *bpy_app_timers_unregister(PyObject *UNUSED(self), PyObject *function)
{
if (!BLI_timer_unregister((intptr_t)function)) {
PyErr_SetString(PyExc_ValueError, "Error: function is not registered");
return NULL;
}
Py_RETURN_NONE;
if (!BLI_timer_unregister((intptr_t)function)) {
PyErr_SetString(PyExc_ValueError, "Error: function is not registered");
return NULL;
}
Py_RETURN_NONE;
}
PyDoc_STRVAR(bpy_app_timers_is_registered_doc,
".. function:: is_registered(function)\n"
"\n"
" Check if this function is registered as a timer.\n"
"\n"
" :arg function: Function to check.\n"
" :type function: int\n"
" :return: True when this function is registered, otherwise False.\n"
" :rtype: bool\n"
);
".. function:: is_registered(function)\n"
"\n"
" Check if this function is registered as a timer.\n"
"\n"
" :arg function: Function to check.\n"
" :type function: int\n"
" :return: True when this function is registered, otherwise False.\n"
" :rtype: bool\n");
static PyObject *bpy_app_timers_is_registered(PyObject *UNUSED(self), PyObject *function)
{
bool ret = BLI_timer_is_registered((intptr_t)function);
return PyBool_FromLong(ret);
bool ret = BLI_timer_is_registered((intptr_t)function);
return PyBool_FromLong(ret);
}
static struct PyMethodDef M_AppTimers_methods[] = {
{"register", (PyCFunction)bpy_app_timers_register,
METH_VARARGS | METH_KEYWORDS, bpy_app_timers_register_doc},
{"unregister", (PyCFunction)bpy_app_timers_unregister,
METH_O, bpy_app_timers_unregister_doc},
{"is_registered", (PyCFunction)bpy_app_timers_is_registered,
METH_O, bpy_app_timers_is_registered_doc},
{NULL, NULL, 0, NULL},
{"register",
(PyCFunction)bpy_app_timers_register,
METH_VARARGS | METH_KEYWORDS,
bpy_app_timers_register_doc},
{"unregister", (PyCFunction)bpy_app_timers_unregister, METH_O, bpy_app_timers_unregister_doc},
{"is_registered",
(PyCFunction)bpy_app_timers_is_registered,
METH_O,
bpy_app_timers_is_registered_doc},
{NULL, NULL, 0, NULL},
};
static struct PyModuleDef M_AppTimers_module_def = {
PyModuleDef_HEAD_INIT,
"bpy.app.timers", /* m_name */
NULL, /* m_doc */
0, /* m_size */
M_AppTimers_methods, /* m_methods */
NULL, /* m_reload */
NULL, /* m_traverse */
NULL, /* m_clear */
NULL, /* m_free */
PyModuleDef_HEAD_INIT,
"bpy.app.timers", /* m_name */
NULL, /* m_doc */
0, /* m_size */
M_AppTimers_methods, /* m_methods */
NULL, /* m_reload */
NULL, /* m_traverse */
NULL, /* m_clear */
NULL, /* m_free */
};
PyObject *BPY_app_timers_module(void)
{
PyObject *sys_modules = PyImport_GetModuleDict();
PyObject *mod = PyModule_Create(&M_AppTimers_module_def);
PyDict_SetItem(sys_modules, PyModule_GetNameObject(mod), mod);
return mod;
PyObject *sys_modules = PyImport_GetModuleDict();
PyObject *mod = PyModule_Create(&M_AppTimers_module_def);
PyDict_SetItem(sys_modules, PyModule_GetNameObject(mod), mod);
return mod;
}

File diff suppressed because it is too large Load Diff

View File

@@ -22,6 +22,6 @@
#define __BPY_APP_TRANSLATIONS_H__
PyObject *BPY_app_translations_struct(void);
void BPY_app_translations_end(void);
void BPY_app_translations_end(void);
#endif /* __BPY_APP_TRANSLATIONS_H__ */

View File

@@ -38,42 +38,48 @@
#include "../generic/py_capi_utils.h"
static bContext *__py_context = NULL;
bContext *BPy_GetContext(void) { return __py_context; }
void BPy_SetContext(bContext *C) { __py_context = C; }
bContext *BPy_GetContext(void)
{
return __py_context;
}
void BPy_SetContext(bContext *C)
{
__py_context = C;
}
char *BPy_enum_as_string(const EnumPropertyItem *item)
{
DynStr *dynstr = BLI_dynstr_new();
const EnumPropertyItem *e;
char *cstring;
DynStr *dynstr = BLI_dynstr_new();
const EnumPropertyItem *e;
char *cstring;
for (e = item; item->identifier; item++) {
if (item->identifier[0]) {
BLI_dynstr_appendf(dynstr, (e == item) ? "'%s'" : ", '%s'", item->identifier);
}
}
for (e = item; item->identifier; item++) {
if (item->identifier[0]) {
BLI_dynstr_appendf(dynstr, (e == item) ? "'%s'" : ", '%s'", item->identifier);
}
}
cstring = BLI_dynstr_get_cstring(dynstr);
BLI_dynstr_free(dynstr);
return cstring;
cstring = BLI_dynstr_get_cstring(dynstr);
BLI_dynstr_free(dynstr);
return cstring;
}
short BPy_reports_to_error(ReportList *reports, PyObject *exception, const bool clear)
{
char *report_str;
char *report_str;
report_str = BKE_reports_string(reports, RPT_ERROR);
report_str = BKE_reports_string(reports, RPT_ERROR);
if (clear == true) {
BKE_reports_clear(reports);
}
if (clear == true) {
BKE_reports_clear(reports);
}
if (report_str) {
PyErr_SetString(exception, report_str);
MEM_freeN(report_str);
}
if (report_str) {
PyErr_SetString(exception, report_str);
MEM_freeN(report_str);
}
return (report_str == NULL) ? 0 : -1;
return (report_str == NULL) ? 0 : -1;
}
/**
@@ -81,80 +87,78 @@ short BPy_reports_to_error(ReportList *reports, PyObject *exception, const bool
*/
void BPy_reports_write_stdout(const ReportList *reports, const char *header)
{
if (header) {
PySys_WriteStdout("%s\n", header);
}
if (header) {
PySys_WriteStdout("%s\n", header);
}
for (const Report *report = reports->list.first; report; report = report->next) {
PySys_WriteStdout("%s: %s\n", report->typestr, report->message);
}
for (const Report *report = reports->list.first; report; report = report->next) {
PySys_WriteStdout("%s: %s\n", report->typestr, report->message);
}
}
bool BPy_errors_to_report_ex(ReportList *reports, const bool use_full, const bool use_location)
{
PyObject *pystring;
PyObject *pystring;
if (!PyErr_Occurred()) {
return 1;
}
if (!PyErr_Occurred()) {
return 1;
}
/* less hassle if we allow NULL */
if (reports == NULL) {
PyErr_Print();
PyErr_Clear();
return 1;
}
/* less hassle if we allow NULL */
if (reports == NULL) {
PyErr_Print();
PyErr_Clear();
return 1;
}
if (use_full) {
pystring = PyC_ExceptionBuffer();
}
else {
pystring = PyC_ExceptionBuffer_Simple();
}
if (use_full) {
pystring = PyC_ExceptionBuffer();
}
else {
pystring = PyC_ExceptionBuffer_Simple();
}
if (pystring == NULL) {
BKE_report(reports, RPT_ERROR, "Unknown py-exception, could not convert");
return 0;
}
if (pystring == NULL) {
BKE_report(reports, RPT_ERROR, "Unknown py-exception, could not convert");
return 0;
}
if (use_location) {
const char *filename;
int lineno;
if (use_location) {
const char *filename;
int lineno;
PyObject *pystring_format; /* workaround, see below */
const char *cstring;
PyObject *pystring_format; /* workaround, see below */
const char *cstring;
PyC_FileAndNum(&filename, &lineno);
if (filename == NULL) {
filename = "<unknown location>";
}
PyC_FileAndNum(&filename, &lineno);
if (filename == NULL) {
filename = "<unknown location>";
}
#if 0 /* ARG!. workaround for a bug in blenders use of vsnprintf */
BKE_reportf(reports, RPT_ERROR, "%s\nlocation: %s:%d\n", _PyUnicode_AsString(pystring), filename, lineno);
BKE_reportf(reports, RPT_ERROR, "%s\nlocation: %s:%d\n", _PyUnicode_AsString(pystring), filename, lineno);
#else
pystring_format = PyUnicode_FromFormat(
TIP_("%s\nlocation: %s:%d\n"),
_PyUnicode_AsString(pystring), filename, lineno);
pystring_format = PyUnicode_FromFormat(
TIP_("%s\nlocation: %s:%d\n"), _PyUnicode_AsString(pystring), filename, lineno);
cstring = _PyUnicode_AsString(pystring_format);
BKE_report(reports, RPT_ERROR, cstring);
cstring = _PyUnicode_AsString(pystring_format);
BKE_report(reports, RPT_ERROR, cstring);
/* not exactly needed. just for testing */
fprintf(stderr, TIP_("%s\nlocation: %s:%d\n"), cstring, filename, lineno);
/* not exactly needed. just for testing */
fprintf(stderr, TIP_("%s\nlocation: %s:%d\n"), cstring, filename, lineno);
Py_DECREF(pystring_format); /* workaround */
Py_DECREF(pystring_format); /* workaround */
#endif
}
else {
BKE_report(reports, RPT_ERROR, _PyUnicode_AsString(pystring));
}
}
else {
BKE_report(reports, RPT_ERROR, _PyUnicode_AsString(pystring));
}
Py_DECREF(pystring);
return 1;
Py_DECREF(pystring);
return 1;
}
bool BPy_errors_to_report(ReportList *reports)
{
return BPy_errors_to_report_ex(reports, true, true);
return BPy_errors_to_report_ex(reports, true, true);
}

View File

@@ -30,12 +30,17 @@ struct ReportList;
char *BPy_enum_as_string(const struct EnumPropertyItem *item);
#define BLANK_PYTHON_TYPE {PyVarObject_HEAD_INIT(NULL, 0) NULL}
#define BLANK_PYTHON_TYPE \
{ \
PyVarObject_HEAD_INIT(NULL, 0) NULL \
}
/* error reporting */
short BPy_reports_to_error(struct ReportList *reports, PyObject *exception, const bool clear);
void BPy_reports_write_stdout(const struct ReportList *reports, const char *header);
bool BPy_errors_to_report_ex(struct ReportList *reports, const bool use_full, const bool use_location);
bool BPy_errors_to_report_ex(struct ReportList *reports,
const bool use_full,
const bool use_location);
bool BPy_errors_to_report(struct ReportList *reports);
/* TODO - find a better solution! */
@@ -45,4 +50,4 @@ void BPy_SetContext(struct bContext *C);
extern void bpy_context_set(struct bContext *C, PyGILState_STATE *gilstate);
extern void bpy_context_clear(struct bContext *C, PyGILState_STATE *gilstate);
#endif /* __BPY_CAPI_UTILS_H__ */
#endif /* __BPY_CAPI_UTILS_H__ */

View File

@@ -36,7 +36,7 @@
#include "BKE_fcurve.h"
#include "BKE_global.h"
#include "bpy_rna_driver.h" /* for pyrna_driver_get_variable_value */
#include "bpy_rna_driver.h" /* for pyrna_driver_get_variable_value */
#include "bpy_intern_string.h"
@@ -66,137 +66,136 @@ static PyObject *bpy_pydriver_Dict__whitelist = NULL;
*/
int bpy_pydriver_create_dict(void)
{
PyObject *d, *mod;
PyObject *d, *mod;
/* validate namespace for driver evaluation */
if (bpy_pydriver_Dict) {
return -1;
}
/* validate namespace for driver evaluation */
if (bpy_pydriver_Dict) {
return -1;
}
d = PyDict_New();
if (d == NULL) {
return -1;
}
else {
bpy_pydriver_Dict = d;
}
d = PyDict_New();
if (d == NULL) {
return -1;
}
else {
bpy_pydriver_Dict = d;
}
/* import some modules: builtins, bpy, math, (Blender.noise)*/
PyDict_SetItemString(d, "__builtins__", PyEval_GetBuiltins());
/* import some modules: builtins, bpy, math, (Blender.noise)*/
PyDict_SetItemString(d, "__builtins__", PyEval_GetBuiltins());
mod = PyImport_ImportModule("math");
if (mod) {
PyDict_Merge(d, PyModule_GetDict(mod), 0); /* 0 - don't overwrite existing values */
Py_DECREF(mod);
}
mod = PyImport_ImportModule("math");
if (mod) {
PyDict_Merge(d, PyModule_GetDict(mod), 0); /* 0 - don't overwrite existing values */
Py_DECREF(mod);
}
#ifdef USE_BYTECODE_WHITELIST
PyObject *mod_math = mod;
PyObject *mod_math = mod;
#endif
/* add bpy to global namespace */
mod = PyImport_ImportModuleLevel("bpy", NULL, NULL, NULL, 0);
if (mod) {
PyDict_SetItemString(bpy_pydriver_Dict, "bpy", mod);
Py_DECREF(mod);
}
/* add bpy to global namespace */
mod = PyImport_ImportModuleLevel("bpy", NULL, NULL, NULL, 0);
if (mod) {
PyDict_SetItemString(bpy_pydriver_Dict, "bpy", mod);
Py_DECREF(mod);
}
/* add noise to global namespace */
mod = PyImport_ImportModuleLevel("mathutils", NULL, NULL, NULL, 0);
if (mod) {
PyObject *modsub = PyDict_GetItemString(PyModule_GetDict(mod), "noise");
PyDict_SetItemString(bpy_pydriver_Dict, "noise", modsub);
Py_DECREF(mod);
}
/* add noise to global namespace */
mod = PyImport_ImportModuleLevel("mathutils", NULL, NULL, NULL, 0);
if (mod) {
PyObject *modsub = PyDict_GetItemString(PyModule_GetDict(mod), "noise");
PyDict_SetItemString(bpy_pydriver_Dict, "noise", modsub);
Py_DECREF(mod);
}
#ifdef USE_BYTECODE_WHITELIST
/* setup the whitelist */
{
bpy_pydriver_Dict__whitelist = PyDict_New();
const char *whitelist[] = {
/* builtins (basic) */
"all",
"any",
"len",
/* builtins (numeric) */
"max",
"min",
"pow",
"round",
"sum",
/* types */
"bool",
"float",
"int",
/* setup the whitelist */
{
bpy_pydriver_Dict__whitelist = PyDict_New();
const char *whitelist[] = {
/* builtins (basic) */
"all",
"any",
"len",
/* builtins (numeric) */
"max",
"min",
"pow",
"round",
"sum",
/* types */
"bool",
"float",
"int",
NULL,
};
NULL,
};
for (int i = 0; whitelist[i]; i++) {
PyDict_SetItemString(bpy_pydriver_Dict__whitelist, whitelist[i], Py_None);
}
for (int i = 0; whitelist[i]; i++) {
PyDict_SetItemString(bpy_pydriver_Dict__whitelist, whitelist[i], Py_None);
}
/* Add all of 'math' functions. */
if (mod_math != NULL) {
PyObject *mod_math_dict = PyModule_GetDict(mod_math);
PyObject *arg_key, *arg_value;
Py_ssize_t arg_pos = 0;
while (PyDict_Next(mod_math_dict, &arg_pos, &arg_key, &arg_value)) {
const char *arg_str = _PyUnicode_AsString(arg_key);
if (arg_str[0] && arg_str[1] != '_') {
PyDict_SetItem(bpy_pydriver_Dict__whitelist, arg_key, Py_None);
}
}
}
}
#endif /* USE_BYTECODE_WHITELIST */
/* Add all of 'math' functions. */
if (mod_math != NULL) {
PyObject *mod_math_dict = PyModule_GetDict(mod_math);
PyObject *arg_key, *arg_value;
Py_ssize_t arg_pos = 0;
while (PyDict_Next(mod_math_dict, &arg_pos, &arg_key, &arg_value)) {
const char *arg_str = _PyUnicode_AsString(arg_key);
if (arg_str[0] && arg_str[1] != '_') {
PyDict_SetItem(bpy_pydriver_Dict__whitelist, arg_key, Py_None);
}
}
}
}
#endif /* USE_BYTECODE_WHITELIST */
return 0;
return 0;
}
/* note, this function should do nothing most runs, only when changing frame */
/* not thread safe but neither is python */
static struct {
float evaltime;
float evaltime;
/* borrowed reference to the 'self' in 'bpy_pydriver_Dict'
* keep for as long as the same self is used. */
PyObject *self;
/* borrowed reference to the 'self' in 'bpy_pydriver_Dict'
* keep for as long as the same self is used. */
PyObject *self;
} g_pydriver_state_prev = {
.evaltime = FLT_MAX,
.self = NULL,
.evaltime = FLT_MAX,
.self = NULL,
};
static void bpy_pydriver_namespace_update_frame(const float evaltime)
{
if (g_pydriver_state_prev.evaltime != evaltime) {
PyObject *item = PyFloat_FromDouble(evaltime);
PyDict_SetItem(bpy_pydriver_Dict, bpy_intern_str_frame, item);
Py_DECREF(item);
if (g_pydriver_state_prev.evaltime != evaltime) {
PyObject *item = PyFloat_FromDouble(evaltime);
PyDict_SetItem(bpy_pydriver_Dict, bpy_intern_str_frame, item);
Py_DECREF(item);
g_pydriver_state_prev.evaltime = evaltime;
}
g_pydriver_state_prev.evaltime = evaltime;
}
}
static void bpy_pydriver_namespace_update_self(struct PathResolvedRNA *anim_rna)
{
if ((g_pydriver_state_prev.self == NULL) ||
(pyrna_driver_is_equal_anim_rna(anim_rna, g_pydriver_state_prev.self) == false))
{
PyObject *item = pyrna_driver_self_from_anim_rna(anim_rna);
PyDict_SetItem(bpy_pydriver_Dict, bpy_intern_str_self, item);
Py_DECREF(item);
if ((g_pydriver_state_prev.self == NULL) ||
(pyrna_driver_is_equal_anim_rna(anim_rna, g_pydriver_state_prev.self) == false)) {
PyObject *item = pyrna_driver_self_from_anim_rna(anim_rna);
PyDict_SetItem(bpy_pydriver_Dict, bpy_intern_str_self, item);
Py_DECREF(item);
g_pydriver_state_prev.self = item;
}
g_pydriver_state_prev.self = item;
}
}
static void bpy_pydriver_namespace_clear_self(void)
{
if (g_pydriver_state_prev.self) {
PyDict_DelItem(bpy_pydriver_Dict, bpy_intern_str_self);
if (g_pydriver_state_prev.self) {
PyDict_DelItem(bpy_pydriver_Dict, bpy_intern_str_self);
g_pydriver_state_prev.self = NULL;
}
g_pydriver_state_prev.self = NULL;
}
}
/* Update function, it gets rid of pydrivers global dictionary, forcing
@@ -206,171 +205,176 @@ static void bpy_pydriver_namespace_clear_self(void)
*/
void BPY_driver_reset(void)
{
PyGILState_STATE gilstate;
bool use_gil = true; /* !PyC_IsInterpreterActive(); */
PyGILState_STATE gilstate;
bool use_gil = true; /* !PyC_IsInterpreterActive(); */
if (use_gil) {
gilstate = PyGILState_Ensure();
}
if (use_gil) {
gilstate = PyGILState_Ensure();
}
if (bpy_pydriver_Dict) { /* free the global dict used by pydrivers */
PyDict_Clear(bpy_pydriver_Dict);
Py_DECREF(bpy_pydriver_Dict);
bpy_pydriver_Dict = NULL;
}
if (bpy_pydriver_Dict) { /* free the global dict used by pydrivers */
PyDict_Clear(bpy_pydriver_Dict);
Py_DECREF(bpy_pydriver_Dict);
bpy_pydriver_Dict = NULL;
}
#ifdef USE_BYTECODE_WHITELIST
if (bpy_pydriver_Dict__whitelist) {
PyDict_Clear(bpy_pydriver_Dict__whitelist);
Py_DECREF(bpy_pydriver_Dict__whitelist);
bpy_pydriver_Dict__whitelist = NULL;
}
if (bpy_pydriver_Dict__whitelist) {
PyDict_Clear(bpy_pydriver_Dict__whitelist);
Py_DECREF(bpy_pydriver_Dict__whitelist);
bpy_pydriver_Dict__whitelist = NULL;
}
#endif
g_pydriver_state_prev.evaltime = FLT_MAX;
g_pydriver_state_prev.evaltime = FLT_MAX;
/* freed when clearing driver dict */
g_pydriver_state_prev.self = NULL;
/* freed when clearing driver dict */
g_pydriver_state_prev.self = NULL;
if (use_gil) {
PyGILState_Release(gilstate);
}
if (use_gil) {
PyGILState_Release(gilstate);
}
return;
return;
}
/* error return function for BPY_eval_pydriver */
static void pydriver_error(ChannelDriver *driver)
{
driver->flag |= DRIVER_FLAG_INVALID; /* py expression failed */
fprintf(stderr, "\nError in Driver: The following Python expression failed:\n\t'%s'\n\n", driver->expression);
driver->flag |= DRIVER_FLAG_INVALID; /* py expression failed */
fprintf(stderr,
"\nError in Driver: The following Python expression failed:\n\t'%s'\n\n",
driver->expression);
// BPy_errors_to_report(NULL); // TODO - reports
PyErr_Print();
PyErr_Clear();
// BPy_errors_to_report(NULL); // TODO - reports
PyErr_Print();
PyErr_Clear();
}
#ifdef USE_BYTECODE_WHITELIST
#define OK_OP(op) [op] = 1
# define OK_OP(op) [op] = 1
static const char secure_opcodes[255] = {
OK_OP(POP_TOP),
OK_OP(ROT_TWO),
OK_OP(ROT_THREE),
OK_OP(DUP_TOP),
OK_OP(DUP_TOP_TWO),
OK_OP(NOP),
OK_OP(UNARY_POSITIVE),
OK_OP(UNARY_NEGATIVE),
OK_OP(UNARY_NOT),
OK_OP(UNARY_INVERT),
OK_OP(BINARY_MATRIX_MULTIPLY),
OK_OP(INPLACE_MATRIX_MULTIPLY),
OK_OP(BINARY_POWER),
OK_OP(BINARY_MULTIPLY),
OK_OP(BINARY_MODULO),
OK_OP(BINARY_ADD),
OK_OP(BINARY_SUBTRACT),
OK_OP(BINARY_SUBSCR),
OK_OP(BINARY_FLOOR_DIVIDE),
OK_OP(BINARY_TRUE_DIVIDE),
OK_OP(INPLACE_FLOOR_DIVIDE),
OK_OP(INPLACE_TRUE_DIVIDE),
OK_OP(INPLACE_ADD),
OK_OP(INPLACE_SUBTRACT),
OK_OP(INPLACE_MULTIPLY),
OK_OP(INPLACE_MODULO),
OK_OP(BINARY_LSHIFT),
OK_OP(BINARY_RSHIFT),
OK_OP(BINARY_AND),
OK_OP(BINARY_XOR),
OK_OP(BINARY_OR),
OK_OP(INPLACE_POWER),
OK_OP(INPLACE_LSHIFT),
OK_OP(INPLACE_RSHIFT),
OK_OP(INPLACE_AND),
OK_OP(INPLACE_XOR),
OK_OP(INPLACE_OR),
OK_OP(RETURN_VALUE),
OK_OP(BUILD_TUPLE),
OK_OP(BUILD_LIST),
OK_OP(BUILD_SET),
OK_OP(BUILD_MAP),
OK_OP(COMPARE_OP),
OK_OP(JUMP_FORWARD),
OK_OP(JUMP_IF_FALSE_OR_POP),
OK_OP(JUMP_IF_TRUE_OR_POP),
OK_OP(JUMP_ABSOLUTE),
OK_OP(POP_JUMP_IF_FALSE),
OK_OP(POP_JUMP_IF_TRUE),
OK_OP(LOAD_GLOBAL),
OK_OP(LOAD_FAST),
OK_OP(STORE_FAST),
OK_OP(DELETE_FAST),
OK_OP(LOAD_DEREF),
OK_OP(STORE_DEREF),
OK_OP(POP_TOP),
OK_OP(ROT_TWO),
OK_OP(ROT_THREE),
OK_OP(DUP_TOP),
OK_OP(DUP_TOP_TWO),
OK_OP(NOP),
OK_OP(UNARY_POSITIVE),
OK_OP(UNARY_NEGATIVE),
OK_OP(UNARY_NOT),
OK_OP(UNARY_INVERT),
OK_OP(BINARY_MATRIX_MULTIPLY),
OK_OP(INPLACE_MATRIX_MULTIPLY),
OK_OP(BINARY_POWER),
OK_OP(BINARY_MULTIPLY),
OK_OP(BINARY_MODULO),
OK_OP(BINARY_ADD),
OK_OP(BINARY_SUBTRACT),
OK_OP(BINARY_SUBSCR),
OK_OP(BINARY_FLOOR_DIVIDE),
OK_OP(BINARY_TRUE_DIVIDE),
OK_OP(INPLACE_FLOOR_DIVIDE),
OK_OP(INPLACE_TRUE_DIVIDE),
OK_OP(INPLACE_ADD),
OK_OP(INPLACE_SUBTRACT),
OK_OP(INPLACE_MULTIPLY),
OK_OP(INPLACE_MODULO),
OK_OP(BINARY_LSHIFT),
OK_OP(BINARY_RSHIFT),
OK_OP(BINARY_AND),
OK_OP(BINARY_XOR),
OK_OP(BINARY_OR),
OK_OP(INPLACE_POWER),
OK_OP(INPLACE_LSHIFT),
OK_OP(INPLACE_RSHIFT),
OK_OP(INPLACE_AND),
OK_OP(INPLACE_XOR),
OK_OP(INPLACE_OR),
OK_OP(RETURN_VALUE),
OK_OP(BUILD_TUPLE),
OK_OP(BUILD_LIST),
OK_OP(BUILD_SET),
OK_OP(BUILD_MAP),
OK_OP(COMPARE_OP),
OK_OP(JUMP_FORWARD),
OK_OP(JUMP_IF_FALSE_OR_POP),
OK_OP(JUMP_IF_TRUE_OR_POP),
OK_OP(JUMP_ABSOLUTE),
OK_OP(POP_JUMP_IF_FALSE),
OK_OP(POP_JUMP_IF_TRUE),
OK_OP(LOAD_GLOBAL),
OK_OP(LOAD_FAST),
OK_OP(STORE_FAST),
OK_OP(DELETE_FAST),
OK_OP(LOAD_DEREF),
OK_OP(STORE_DEREF),
/* special cases */
OK_OP(LOAD_CONST), /* ok because constants are accepted */
OK_OP(LOAD_NAME), /* ok, because PyCodeObject.names is checked */
OK_OP(CALL_FUNCTION), /* ok, because we check its 'name' before calling */
OK_OP(CALL_FUNCTION_KW),
OK_OP(CALL_FUNCTION_EX),
/* special cases */
OK_OP(LOAD_CONST), /* ok because constants are accepted */
OK_OP(LOAD_NAME), /* ok, because PyCodeObject.names is checked */
OK_OP(CALL_FUNCTION), /* ok, because we check its 'name' before calling */
OK_OP(CALL_FUNCTION_KW),
OK_OP(CALL_FUNCTION_EX),
};
#undef OK_OP
# undef OK_OP
static bool bpy_driver_secure_bytecode_validate(PyObject *expr_code, PyObject *dict_arr[])
{
PyCodeObject *py_code = (PyCodeObject *)expr_code;
PyCodeObject *py_code = (PyCodeObject *)expr_code;
/* Check names. */
{
for (int i = 0; i < PyTuple_GET_SIZE(py_code->co_names); i++) {
PyObject *name = PyTuple_GET_ITEM(py_code->co_names, i);
/* Check names. */
{
for (int i = 0; i < PyTuple_GET_SIZE(py_code->co_names); i++) {
PyObject *name = PyTuple_GET_ITEM(py_code->co_names, i);
bool contains_name = false;
for (int j = 0; dict_arr[j]; j++) {
if (PyDict_Contains(dict_arr[j], name)) {
contains_name = true;
break;
}
}
bool contains_name = false;
for (int j = 0; dict_arr[j]; j++) {
if (PyDict_Contains(dict_arr[j], name)) {
contains_name = true;
break;
}
}
if (contains_name == false) {
fprintf(stderr, "\tBPY_driver_eval() - restricted access disallows name '%s', "
"enable auto-execution to support\n", _PyUnicode_AsString(name));
return false;
}
}
}
if (contains_name == false) {
fprintf(stderr,
"\tBPY_driver_eval() - restricted access disallows name '%s', "
"enable auto-execution to support\n",
_PyUnicode_AsString(name));
return false;
}
}
}
/* Check opcodes. */
{
const _Py_CODEUNIT *codestr;
Py_ssize_t code_len;
/* Check opcodes. */
{
const _Py_CODEUNIT *codestr;
Py_ssize_t code_len;
PyBytes_AsStringAndSize(py_code->co_code, (char **)&codestr, &code_len);
code_len /= sizeof(*codestr);
PyBytes_AsStringAndSize(py_code->co_code, (char **)&codestr, &code_len);
code_len /= sizeof(*codestr);
for (Py_ssize_t i = 0; i < code_len; i++) {
const int opcode = _Py_OPCODE(codestr[i]);
if (secure_opcodes[opcode] == 0) {
fprintf(stderr, "\tBPY_driver_eval() - restricted access disallows opcode '%d', "
"enable auto-execution to support\n", opcode);
return false;
}
}
for (Py_ssize_t i = 0; i < code_len; i++) {
const int opcode = _Py_OPCODE(codestr[i]);
if (secure_opcodes[opcode] == 0) {
fprintf(stderr,
"\tBPY_driver_eval() - restricted access disallows opcode '%d', "
"enable auto-execution to support\n",
opcode);
return false;
}
}
#undef CODESIZE
}
# undef CODESIZE
}
return true;
return true;
}
#endif /* USE_BYTECODE_WHITELIST */
#endif /* USE_BYTECODE_WHITELIST */
/* This evals py driver expressions, 'expr' is a Python expression that
* should evaluate to a float number, which is returned.
@@ -388,231 +392,239 @@ static bool bpy_driver_secure_bytecode_validate(PyObject *expr_code, PyObject *d
* original driver, otherwise these would get freed while editing. Due to
* the GIL this is thread-safe.
*/
float BPY_driver_exec(struct PathResolvedRNA *anim_rna, ChannelDriver *driver, ChannelDriver *driver_orig, const float evaltime)
float BPY_driver_exec(struct PathResolvedRNA *anim_rna,
ChannelDriver *driver,
ChannelDriver *driver_orig,
const float evaltime)
{
PyObject *driver_vars = NULL;
PyObject *retval = NULL;
PyObject *expr_vars; /* speed up by pre-hashing string & avoids re-converting unicode strings for every execution */
PyObject *expr_code;
PyGILState_STATE gilstate;
bool use_gil;
PyObject *driver_vars = NULL;
PyObject *retval = NULL;
PyObject *
expr_vars; /* speed up by pre-hashing string & avoids re-converting unicode strings for every execution */
PyObject *expr_code;
PyGILState_STATE gilstate;
bool use_gil;
DriverVar *dvar;
double result = 0.0; /* default return */
const char *expr;
short targets_ok = 1;
int i;
DriverVar *dvar;
double result = 0.0; /* default return */
const char *expr;
short targets_ok = 1;
int i;
/* get the py expression to be evaluated */
expr = driver_orig->expression;
if (expr[0] == '\0') {
return 0.0f;
}
/* get the py expression to be evaluated */
expr = driver_orig->expression;
if (expr[0] == '\0') {
return 0.0f;
}
#ifndef USE_BYTECODE_WHITELIST
if (!(G.f & G_FLAG_SCRIPT_AUTOEXEC)) {
if (!(G.f & G_FLAG_SCRIPT_AUTOEXEC_FAIL_QUIET)) {
G.f |= G_FLAG_SCRIPT_AUTOEXEC_FAIL;
BLI_snprintf(G.autoexec_fail, sizeof(G.autoexec_fail), "Driver '%s'", expr);
if (!(G.f & G_FLAG_SCRIPT_AUTOEXEC)) {
if (!(G.f & G_FLAG_SCRIPT_AUTOEXEC_FAIL_QUIET)) {
G.f |= G_FLAG_SCRIPT_AUTOEXEC_FAIL;
BLI_snprintf(G.autoexec_fail, sizeof(G.autoexec_fail), "Driver '%s'", expr);
printf("skipping driver '%s', automatic scripts are disabled\n", expr);
}
return 0.0f;
}
printf("skipping driver '%s', automatic scripts are disabled\n", expr);
}
return 0.0f;
}
#else
bool is_recompile = false;
bool is_recompile = false;
#endif
use_gil = true; /* !PyC_IsInterpreterActive(); */
use_gil = true; /* !PyC_IsInterpreterActive(); */
if (use_gil) {
gilstate = PyGILState_Ensure();
}
if (use_gil) {
gilstate = PyGILState_Ensure();
}
/* needed since drivers are updated directly after undo where 'main' is
* re-allocated [#28807] */
BPY_update_rna_module();
/* needed since drivers are updated directly after undo where 'main' is
* re-allocated [#28807] */
BPY_update_rna_module();
/* init global dictionary for py-driver evaluation settings */
if (!bpy_pydriver_Dict) {
if (bpy_pydriver_create_dict() != 0) {
fprintf(stderr, "PyDriver error: couldn't create Python dictionary\n");
if (use_gil) {
PyGILState_Release(gilstate);
}
return 0.0f;
}
}
/* init global dictionary for py-driver evaluation settings */
if (!bpy_pydriver_Dict) {
if (bpy_pydriver_create_dict() != 0) {
fprintf(stderr, "PyDriver error: couldn't create Python dictionary\n");
if (use_gil) {
PyGILState_Release(gilstate);
}
return 0.0f;
}
}
/* update global namespace */
bpy_pydriver_namespace_update_frame(evaltime);
/* update global namespace */
bpy_pydriver_namespace_update_frame(evaltime);
if (driver_orig->flag & DRIVER_FLAG_USE_SELF) {
bpy_pydriver_namespace_update_self(anim_rna);
}
else {
bpy_pydriver_namespace_clear_self();
}
if (driver_orig->flag & DRIVER_FLAG_USE_SELF) {
bpy_pydriver_namespace_update_self(anim_rna);
}
else {
bpy_pydriver_namespace_clear_self();
}
if (driver_orig->expr_comp == NULL) {
driver_orig->flag |= DRIVER_FLAG_RECOMPILE;
}
if (driver_orig->expr_comp == NULL) {
driver_orig->flag |= DRIVER_FLAG_RECOMPILE;
}
/* compile the expression first if it hasn't been compiled or needs to be rebuilt */
if (driver_orig->flag & DRIVER_FLAG_RECOMPILE) {
Py_XDECREF(driver_orig->expr_comp);
driver_orig->expr_comp = PyTuple_New(2);
/* compile the expression first if it hasn't been compiled or needs to be rebuilt */
if (driver_orig->flag & DRIVER_FLAG_RECOMPILE) {
Py_XDECREF(driver_orig->expr_comp);
driver_orig->expr_comp = PyTuple_New(2);
expr_code = Py_CompileString(expr, "<bpy driver>", Py_eval_input);
PyTuple_SET_ITEM(((PyObject *)driver_orig->expr_comp), 0, expr_code);
expr_code = Py_CompileString(expr, "<bpy driver>", Py_eval_input);
PyTuple_SET_ITEM(((PyObject *)driver_orig->expr_comp), 0, expr_code);
driver_orig->flag &= ~DRIVER_FLAG_RECOMPILE;
driver_orig->flag |= DRIVER_FLAG_RENAMEVAR; /* maybe this can be removed but for now best keep until were sure */
driver_orig->flag &= ~DRIVER_FLAG_RECOMPILE;
driver_orig->flag |=
DRIVER_FLAG_RENAMEVAR; /* maybe this can be removed but for now best keep until were sure */
#ifdef USE_BYTECODE_WHITELIST
is_recompile = true;
is_recompile = true;
#endif
}
else {
expr_code = PyTuple_GET_ITEM(((PyObject *)driver_orig->expr_comp), 0);
}
}
else {
expr_code = PyTuple_GET_ITEM(((PyObject *)driver_orig->expr_comp), 0);
}
if (driver_orig->flag & DRIVER_FLAG_RENAMEVAR) {
/* may not be set */
expr_vars = PyTuple_GET_ITEM(((PyObject *)driver_orig->expr_comp), 1);
Py_XDECREF(expr_vars);
if (driver_orig->flag & DRIVER_FLAG_RENAMEVAR) {
/* may not be set */
expr_vars = PyTuple_GET_ITEM(((PyObject *)driver_orig->expr_comp), 1);
Py_XDECREF(expr_vars);
expr_vars = PyTuple_New(BLI_listbase_count(&driver_orig->variables));
PyTuple_SET_ITEM(((PyObject *)driver_orig->expr_comp), 1, expr_vars);
expr_vars = PyTuple_New(BLI_listbase_count(&driver_orig->variables));
PyTuple_SET_ITEM(((PyObject *)driver_orig->expr_comp), 1, expr_vars);
for (dvar = driver_orig->variables.first, i = 0; dvar; dvar = dvar->next) {
PyTuple_SET_ITEM(expr_vars, i++, PyUnicode_FromString(dvar->name));
}
for (dvar = driver_orig->variables.first, i = 0; dvar; dvar = dvar->next) {
PyTuple_SET_ITEM(expr_vars, i++, PyUnicode_FromString(dvar->name));
}
driver_orig->flag &= ~DRIVER_FLAG_RENAMEVAR;
}
else {
expr_vars = PyTuple_GET_ITEM(((PyObject *)driver_orig->expr_comp), 1);
}
driver_orig->flag &= ~DRIVER_FLAG_RENAMEVAR;
}
else {
expr_vars = PyTuple_GET_ITEM(((PyObject *)driver_orig->expr_comp), 1);
}
/* add target values to a dict that will be used as '__locals__' dict */
driver_vars = _PyDict_NewPresized(PyTuple_GET_SIZE(expr_vars));
for (dvar = driver->variables.first, i = 0; dvar; dvar = dvar->next) {
PyObject *driver_arg = NULL;
/* add target values to a dict that will be used as '__locals__' dict */
driver_vars = _PyDict_NewPresized(PyTuple_GET_SIZE(expr_vars));
for (dvar = driver->variables.first, i = 0; dvar; dvar = dvar->next) {
PyObject *driver_arg = NULL;
/* support for any RNA data */
/* support for any RNA data */
#ifdef USE_RNA_AS_PYOBJECT
if (dvar->type == DVAR_TYPE_SINGLE_PROP) {
driver_arg = pyrna_driver_get_variable_value(driver, &dvar->targets[0]);
if (dvar->type == DVAR_TYPE_SINGLE_PROP) {
driver_arg = pyrna_driver_get_variable_value(driver, &dvar->targets[0]);
if (driver_arg == NULL) {
driver_arg = PyFloat_FromDouble(0.0);
dvar->curval = 0.0f;
}
else {
/* no need to worry about overflow here, values from RNA are within limits. */
if (PyFloat_CheckExact(driver_arg)) {
dvar->curval = (float)PyFloat_AsDouble(driver_arg);
}
else if (PyLong_CheckExact(driver_arg)) {
dvar->curval = (float)PyLong_AsLong(driver_arg);
}
else if (PyBool_Check(driver_arg)) {
dvar->curval = (driver_arg == Py_True);
}
else {
dvar->curval = 0.0f;
}
}
}
else
if (driver_arg == NULL) {
driver_arg = PyFloat_FromDouble(0.0);
dvar->curval = 0.0f;
}
else {
/* no need to worry about overflow here, values from RNA are within limits. */
if (PyFloat_CheckExact(driver_arg)) {
dvar->curval = (float)PyFloat_AsDouble(driver_arg);
}
else if (PyLong_CheckExact(driver_arg)) {
dvar->curval = (float)PyLong_AsLong(driver_arg);
}
else if (PyBool_Check(driver_arg)) {
dvar->curval = (driver_arg == Py_True);
}
else {
dvar->curval = 0.0f;
}
}
}
else
#endif
{
/* try to get variable value */
float tval = driver_get_variable_value(driver, dvar);
driver_arg = PyFloat_FromDouble((double)tval);
}
{
/* try to get variable value */
float tval = driver_get_variable_value(driver, dvar);
driver_arg = PyFloat_FromDouble((double)tval);
}
/* try to add to dictionary */
/* if (PyDict_SetItemString(driver_vars, dvar->name, driver_arg)) { */
if (PyDict_SetItem(driver_vars, PyTuple_GET_ITEM(expr_vars, i++), driver_arg) != -1) {
Py_DECREF(driver_arg);
}
else {
/* this target failed - bad name */
if (targets_ok) {
/* first one - print some extra info for easier identification */
fprintf(stderr, "\nBPY_driver_eval() - Error while evaluating PyDriver:\n");
targets_ok = 0;
}
/* try to add to dictionary */
/* if (PyDict_SetItemString(driver_vars, dvar->name, driver_arg)) { */
if (PyDict_SetItem(driver_vars, PyTuple_GET_ITEM(expr_vars, i++), driver_arg) != -1) {
Py_DECREF(driver_arg);
}
else {
/* this target failed - bad name */
if (targets_ok) {
/* first one - print some extra info for easier identification */
fprintf(stderr, "\nBPY_driver_eval() - Error while evaluating PyDriver:\n");
targets_ok = 0;
}
fprintf(stderr, "\tBPY_driver_eval() - couldn't add variable '%s' to namespace\n", dvar->name);
// BPy_errors_to_report(NULL); // TODO - reports
PyErr_Print();
PyErr_Clear();
}
}
fprintf(
stderr, "\tBPY_driver_eval() - couldn't add variable '%s' to namespace\n", dvar->name);
// BPy_errors_to_report(NULL); // TODO - reports
PyErr_Print();
PyErr_Clear();
}
}
#ifdef USE_BYTECODE_WHITELIST
if (is_recompile && expr_code) {
if (!(G.f & G_FLAG_SCRIPT_AUTOEXEC)) {
if (!bpy_driver_secure_bytecode_validate(
expr_code, (PyObject *[]){
bpy_pydriver_Dict,
bpy_pydriver_Dict__whitelist,
driver_vars,
NULL,}
))
{
if (!(G.f & G_FLAG_SCRIPT_AUTOEXEC_FAIL_QUIET)) {
G.f |= G_FLAG_SCRIPT_AUTOEXEC_FAIL;
BLI_snprintf(G.autoexec_fail, sizeof(G.autoexec_fail), "Driver '%s'", expr);
}
if (is_recompile && expr_code) {
if (!(G.f & G_FLAG_SCRIPT_AUTOEXEC)) {
if (!bpy_driver_secure_bytecode_validate(expr_code,
(PyObject *[]){
bpy_pydriver_Dict,
bpy_pydriver_Dict__whitelist,
driver_vars,
NULL,
})) {
if (!(G.f & G_FLAG_SCRIPT_AUTOEXEC_FAIL_QUIET)) {
G.f |= G_FLAG_SCRIPT_AUTOEXEC_FAIL;
BLI_snprintf(G.autoexec_fail, sizeof(G.autoexec_fail), "Driver '%s'", expr);
}
Py_DECREF(expr_code);
expr_code = NULL;
PyTuple_SET_ITEM(((PyObject *)driver_orig->expr_comp), 0, NULL);
}
}
}
#endif /* USE_BYTECODE_WHITELIST */
Py_DECREF(expr_code);
expr_code = NULL;
PyTuple_SET_ITEM(((PyObject *)driver_orig->expr_comp), 0, NULL);
}
}
}
#endif /* USE_BYTECODE_WHITELIST */
#if 0 /* slow, with this can avoid all Py_CompileString above. */
/* execute expression to get a value */
retval = PyRun_String(expr, Py_eval_input, bpy_pydriver_Dict, driver_vars);
#if 0 /* slow, with this can avoid all Py_CompileString above. */
/* execute expression to get a value */
retval = PyRun_String(expr, Py_eval_input, bpy_pydriver_Dict, driver_vars);
#else
/* evaluate the compiled expression */
if (expr_code) {
retval = PyEval_EvalCode((void *)expr_code, bpy_pydriver_Dict, driver_vars);
}
/* evaluate the compiled expression */
if (expr_code) {
retval = PyEval_EvalCode((void *)expr_code, bpy_pydriver_Dict, driver_vars);
}
#endif
/* decref the driver vars first... */
Py_DECREF(driver_vars);
/* decref the driver vars first... */
Py_DECREF(driver_vars);
/* process the result */
if (retval == NULL) {
pydriver_error(driver);
}
else if ((result = PyFloat_AsDouble(retval)) == -1.0 && PyErr_Occurred()) {
pydriver_error(driver);
Py_DECREF(retval);
result = 0.0;
}
else {
/* all fine, make sure the "invalid expression" flag is cleared */
driver->flag &= ~DRIVER_FLAG_INVALID;
Py_DECREF(retval);
}
/* process the result */
if (retval == NULL) {
pydriver_error(driver);
}
else if ((result = PyFloat_AsDouble(retval)) == -1.0 && PyErr_Occurred()) {
pydriver_error(driver);
Py_DECREF(retval);
result = 0.0;
}
else {
/* all fine, make sure the "invalid expression" flag is cleared */
driver->flag &= ~DRIVER_FLAG_INVALID;
Py_DECREF(retval);
}
if (use_gil) {
PyGILState_Release(gilstate);
}
if (use_gil) {
PyGILState_Release(gilstate);
}
if (isfinite(result)) {
return (float)result;
}
else {
fprintf(stderr, "\tBPY_driver_eval() - driver '%s' evaluates to '%f'\n", driver->expression, result);
return 0.0f;
}
if (isfinite(result)) {
return (float)result;
}
else {
fprintf(stderr,
"\tBPY_driver_eval() - driver '%s' evaluates to '%f'\n",
driver->expression,
result);
return 0.0f;
}
}

View File

@@ -24,4 +24,4 @@
int bpy_pydriver_create_dict(void);
extern PyObject *bpy_pydriver_Dict;
#endif /* __BPY_DRIVER_H__ */
#endif /* __BPY_DRIVER_H__ */

View File

@@ -39,7 +39,7 @@
#include "bpy_rna.h"
#include "bpy_intern_string.h"
#include "bpy_gizmo_wrap.h" /* own include */
#include "bpy_gizmo_wrap.h" /* own include */
/* we may want to add, but not now */
@@ -47,176 +47,168 @@
/** \name Gizmo
* \{ */
static bool bpy_gizmotype_target_property_def(
wmGizmoType *gzt, PyObject *item)
static bool bpy_gizmotype_target_property_def(wmGizmoType *gzt, PyObject *item)
{
/* Note: names based on 'rna_rna.c' */
PyObject *empty_tuple = PyTuple_New(0);
/* Note: names based on 'rna_rna.c' */
PyObject *empty_tuple = PyTuple_New(0);
struct {
char *id;
char *type_id; int type;
int array_length;
} params = {
.id = NULL, /* not optional */
.type = PROP_FLOAT,
.type_id = NULL,
.array_length = 1,
};
struct {
char *id;
char *type_id;
int type;
int array_length;
} params = {
.id = NULL, /* not optional */
.type = PROP_FLOAT,
.type_id = NULL,
.array_length = 1,
};
static const char * const _keywords[] = {"id", "type", "array_length", NULL};
static _PyArg_Parser _parser = {"|$ssi:register_class", _keywords, 0};
if (!_PyArg_ParseTupleAndKeywordsFast(
empty_tuple, item,
&_parser,
&params.id,
&params.type_id,
&params.array_length))
{
goto fail;
}
static const char *const _keywords[] = {"id", "type", "array_length", NULL};
static _PyArg_Parser _parser = {"|$ssi:register_class", _keywords, 0};
if (!_PyArg_ParseTupleAndKeywordsFast(
empty_tuple, item, &_parser, &params.id, &params.type_id, &params.array_length)) {
goto fail;
}
if (params.id == NULL) {
PyErr_SetString(PyExc_ValueError, "'id' argument not given");
goto fail;
}
if (params.id == NULL) {
PyErr_SetString(PyExc_ValueError, "'id' argument not given");
goto fail;
}
if ((params.type_id != NULL) &&
pyrna_enum_value_from_id(
rna_enum_property_type_items, params.type_id, &params.type, "'type' enum value") == -1)
{
goto fail;
}
else {
params.type = rna_enum_property_type_items[params.type].value;
}
if ((params.type_id != NULL) &&
pyrna_enum_value_from_id(
rna_enum_property_type_items, params.type_id, &params.type, "'type' enum value") == -1) {
goto fail;
}
else {
params.type = rna_enum_property_type_items[params.type].value;
}
if ((params.array_length < 1 || params.array_length > RNA_MAX_ARRAY_LENGTH)) {
PyErr_SetString(PyExc_ValueError, "'array_length' out of range");
goto fail;
}
if ((params.array_length < 1 || params.array_length > RNA_MAX_ARRAY_LENGTH)) {
PyErr_SetString(PyExc_ValueError, "'array_length' out of range");
goto fail;
}
WM_gizmotype_target_property_def(gzt, params.id, params.type, params.array_length);
Py_DECREF(empty_tuple);
return true;
WM_gizmotype_target_property_def(gzt, params.id, params.type, params.array_length);
Py_DECREF(empty_tuple);
return true;
fail:
Py_DECREF(empty_tuple);
return false;
Py_DECREF(empty_tuple);
return false;
}
static void gizmo_properties_init(wmGizmoType *gzt)
{
PyTypeObject *py_class = gzt->ext.data;
RNA_struct_blender_type_set(gzt->ext.srna, gzt);
PyTypeObject *py_class = gzt->ext.data;
RNA_struct_blender_type_set(gzt->ext.srna, gzt);
/* only call this so pyrna_deferred_register_class gives a useful error
* WM_operatortype_append_ptr will call RNA_def_struct_identifier
* later */
RNA_def_struct_identifier_no_struct_map(gzt->srna, gzt->idname);
/* only call this so pyrna_deferred_register_class gives a useful error
* WM_operatortype_append_ptr will call RNA_def_struct_identifier
* later */
RNA_def_struct_identifier_no_struct_map(gzt->srna, gzt->idname);
if (pyrna_deferred_register_class(gzt->srna, py_class) != 0) {
PyErr_Print(); /* failed to register operator props */
PyErr_Clear();
}
if (pyrna_deferred_register_class(gzt->srna, py_class) != 0) {
PyErr_Print(); /* failed to register operator props */
PyErr_Clear();
}
/* Extract target property definitions from 'bl_target_properties' */
{
/* picky developers will notice that 'bl_targets' won't work with inheritance
* get direct from the dict to avoid raising a load of attribute errors (yes this isnt ideal) - campbell */
PyObject *py_class_dict = py_class->tp_dict;
PyObject *bl_target_properties = PyDict_GetItem(py_class_dict, bpy_intern_str_bl_target_properties);
/* Extract target property definitions from 'bl_target_properties' */
{
/* picky developers will notice that 'bl_targets' won't work with inheritance
* get direct from the dict to avoid raising a load of attribute errors (yes this isnt ideal) - campbell */
PyObject *py_class_dict = py_class->tp_dict;
PyObject *bl_target_properties = PyDict_GetItem(py_class_dict,
bpy_intern_str_bl_target_properties);
/* Some widgets may only exist to activate operators. */
if (bl_target_properties != NULL) {
PyObject *bl_target_properties_fast;
if (!(bl_target_properties_fast = PySequence_Fast(
bl_target_properties, "bl_target_properties sequence")))
{
/* PySequence_Fast sets the error */
PyErr_Print();
PyErr_Clear();
return;
}
/* Some widgets may only exist to activate operators. */
if (bl_target_properties != NULL) {
PyObject *bl_target_properties_fast;
if (!(bl_target_properties_fast = PySequence_Fast(bl_target_properties,
"bl_target_properties sequence"))) {
/* PySequence_Fast sets the error */
PyErr_Print();
PyErr_Clear();
return;
}
const uint items_len = PySequence_Fast_GET_SIZE(bl_target_properties_fast);
PyObject **items = PySequence_Fast_ITEMS(bl_target_properties_fast);
const uint items_len = PySequence_Fast_GET_SIZE(bl_target_properties_fast);
PyObject **items = PySequence_Fast_ITEMS(bl_target_properties_fast);
for (uint i = 0; i < items_len; i++) {
if (!bpy_gizmotype_target_property_def(gzt, items[i])) {
PyErr_Print();
PyErr_Clear();
break;
}
}
for (uint i = 0; i < items_len; i++) {
if (!bpy_gizmotype_target_property_def(gzt, items[i])) {
PyErr_Print();
PyErr_Clear();
break;
}
}
Py_DECREF(bl_target_properties_fast);
}
}
Py_DECREF(bl_target_properties_fast);
}
}
}
void BPY_RNA_gizmo_wrapper(wmGizmoType *gzt, void *userdata)
{
/* take care not to overwrite anything set in
* WM_gizmomaptype_group_link_ptr before opfunc() is called */
StructRNA *srna = gzt->srna;
*gzt = *((wmGizmoType *)userdata);
gzt->srna = srna; /* restore */
/* take care not to overwrite anything set in
* WM_gizmomaptype_group_link_ptr before opfunc() is called */
StructRNA *srna = gzt->srna;
*gzt = *((wmGizmoType *)userdata);
gzt->srna = srna; /* restore */
/* don't do translations here yet */
/* don't do translations here yet */
#if 0
/* Use i18n context from ext.srna if possible (py gizmogroups). */
if (gt->ext.srna) {
RNA_def_struct_translation_context(gt->srna, RNA_struct_translation_context(gt->ext.srna));
}
/* Use i18n context from ext.srna if possible (py gizmogroups). */
if (gt->ext.srna) {
RNA_def_struct_translation_context(gt->srna, RNA_struct_translation_context(gt->ext.srna));
}
#endif
gzt->struct_size = sizeof(wmGizmo);
gzt->struct_size = sizeof(wmGizmo);
gizmo_properties_init(gzt);
gizmo_properties_init(gzt);
}
/** \} */
/* -------------------------------------------------------------------- */
/** \name Gizmo Group
* \{ */
static void gizmogroup_properties_init(wmGizmoGroupType *gzgt)
{
PyTypeObject *py_class = gzgt->ext.data;
RNA_struct_blender_type_set(gzgt->ext.srna, gzgt);
PyTypeObject *py_class = gzgt->ext.data;
RNA_struct_blender_type_set(gzgt->ext.srna, gzgt);
/* only call this so pyrna_deferred_register_class gives a useful error
* WM_operatortype_append_ptr will call RNA_def_struct_identifier
* later */
RNA_def_struct_identifier_no_struct_map(gzgt->srna, gzgt->idname);
/* only call this so pyrna_deferred_register_class gives a useful error
* WM_operatortype_append_ptr will call RNA_def_struct_identifier
* later */
RNA_def_struct_identifier_no_struct_map(gzgt->srna, gzgt->idname);
if (pyrna_deferred_register_class(gzgt->srna, py_class) != 0) {
PyErr_Print(); /* failed to register operator props */
PyErr_Clear();
}
if (pyrna_deferred_register_class(gzgt->srna, py_class) != 0) {
PyErr_Print(); /* failed to register operator props */
PyErr_Clear();
}
}
void BPY_RNA_gizmogroup_wrapper(wmGizmoGroupType *gzgt, void *userdata)
{
/* take care not to overwrite anything set in
* WM_gizmomaptype_group_link_ptr before opfunc() is called */
StructRNA *srna = gzgt->srna;
*gzgt = *((wmGizmoGroupType *)userdata);
gzgt->srna = srna; /* restore */
/* take care not to overwrite anything set in
* WM_gizmomaptype_group_link_ptr before opfunc() is called */
StructRNA *srna = gzgt->srna;
*gzgt = *((wmGizmoGroupType *)userdata);
gzgt->srna = srna; /* restore */
/* don't do translations here yet */
/* don't do translations here yet */
#if 0
/* Use i18n context from ext.srna if possible (py gizmogroups). */
if (gzgt->ext.srna) {
RNA_def_struct_translation_context(gzgt->srna, RNA_struct_translation_context(gzgt->ext.srna));
}
/* Use i18n context from ext.srna if possible (py gizmogroups). */
if (gzgt->ext.srna) {
RNA_def_struct_translation_context(gzgt->srna, RNA_struct_translation_context(gzgt->ext.srna));
}
#endif
gizmogroup_properties_init(gzgt);
gizmogroup_properties_init(gzgt);
}
/** \} */

View File

@@ -28,4 +28,4 @@ struct wmGizmoType;
void BPY_RNA_gizmo_wrapper(struct wmGizmoType *gzt, void *userdata);
void BPY_RNA_gizmogroup_wrapper(struct wmGizmoGroupType *gzgt, void *userdata);
#endif /* __BPY_GIZMO_WRAP_H__ */
#endif /* __BPY_GIZMO_WRAP_H__ */

File diff suppressed because it is too large Load Diff

View File

@@ -22,24 +22,23 @@
* resources.
*/
#include <Python.h>
#include "BLI_utildefines.h"
#include "bpy_capi_utils.h"
#include "bpy.h" /* own include */
#include "bpy.h" /* own include */
#include "WM_api.h"
static PyObject *bpy_atexit(PyObject *UNUSED(self), PyObject *UNUSED(args), PyObject *UNUSED(kw))
{
/* close down enough of blender at least not to crash */
struct bContext *C = BPy_GetContext();
/* close down enough of blender at least not to crash */
struct bContext *C = BPy_GetContext();
WM_exit_ext(C, 0);
WM_exit_ext(C, 0);
Py_RETURN_NONE;
Py_RETURN_NONE;
}
static PyMethodDef meth_bpy_atexit = {"bpy_atexit", (PyCFunction)bpy_atexit, METH_NOARGS, NULL};
@@ -47,45 +46,45 @@ static PyObject *func_bpy_atregister = NULL; /* borrowed referebce, atexit holds
static void atexit_func_call(const char *func_name, PyObject *atexit_func_arg)
{
/* note - no error checking, if any of these fail we'll get a crash
* this is intended, but if its problematic it could be changed
* - campbell */
/* note - no error checking, if any of these fail we'll get a crash
* this is intended, but if its problematic it could be changed
* - campbell */
PyObject *atexit_mod = PyImport_ImportModuleLevel("atexit", NULL, NULL, NULL, 0);
PyObject *atexit_func = PyObject_GetAttrString(atexit_mod, func_name);
PyObject *args = PyTuple_New(1);
PyObject *ret;
PyObject *atexit_mod = PyImport_ImportModuleLevel("atexit", NULL, NULL, NULL, 0);
PyObject *atexit_func = PyObject_GetAttrString(atexit_mod, func_name);
PyObject *args = PyTuple_New(1);
PyObject *ret;
PyTuple_SET_ITEM(args, 0, atexit_func_arg);
Py_INCREF(atexit_func_arg); /* only incref so we don't dec'ref along with 'args' */
PyTuple_SET_ITEM(args, 0, atexit_func_arg);
Py_INCREF(atexit_func_arg); /* only incref so we don't dec'ref along with 'args' */
ret = PyObject_CallObject(atexit_func, args);
ret = PyObject_CallObject(atexit_func, args);
Py_DECREF(atexit_mod);
Py_DECREF(atexit_func);
Py_DECREF(args);
Py_DECREF(atexit_mod);
Py_DECREF(atexit_func);
Py_DECREF(args);
if (ret) {
Py_DECREF(ret);
}
else { /* should never happen */
PyErr_Print();
}
if (ret) {
Py_DECREF(ret);
}
else { /* should never happen */
PyErr_Print();
}
}
void BPY_atexit_register(void)
{
/* atexit module owns this new function reference */
BLI_assert(func_bpy_atregister == NULL);
/* atexit module owns this new function reference */
BLI_assert(func_bpy_atregister == NULL);
func_bpy_atregister = (PyObject *)PyCFunction_New(&meth_bpy_atexit, NULL);
atexit_func_call("register", func_bpy_atregister);
func_bpy_atregister = (PyObject *)PyCFunction_New(&meth_bpy_atexit, NULL);
atexit_func_call("register", func_bpy_atregister);
}
void BPY_atexit_unregister(void)
{
BLI_assert(func_bpy_atregister != NULL);
BLI_assert(func_bpy_atregister != NULL);
atexit_func_call("unregister", func_bpy_atregister);
func_bpy_atregister = NULL; /* don't really need to set but just in case */
atexit_func_call("unregister", func_bpy_atregister);
func_bpy_atregister = NULL; /* don't really need to set but just in case */
}

View File

@@ -49,37 +49,40 @@ PyObject *bpy_intern_str_unregister;
void bpy_intern_string_init(void)
{
unsigned int i = 0;
unsigned int i = 0;
#define BPY_INTERN_STR(var, str) \
{ var = bpy_intern_str_arr[i++] = PyUnicode_FromString(str); } (void)0
{ \
var = bpy_intern_str_arr[i++] = PyUnicode_FromString(str); \
} \
(void)0
BPY_INTERN_STR(bpy_intern_str___annotations__, "__annotations__");
BPY_INTERN_STR(bpy_intern_str___doc__, "__doc__");
BPY_INTERN_STR(bpy_intern_str___main__, "__main__");
BPY_INTERN_STR(bpy_intern_str___module__, "__module__");
BPY_INTERN_STR(bpy_intern_str___name__, "__name__");
BPY_INTERN_STR(bpy_intern_str___slots__, "__slots__");
BPY_INTERN_STR(bpy_intern_str_attr, "attr");
BPY_INTERN_STR(bpy_intern_str_bl_property, "bl_property");
BPY_INTERN_STR(bpy_intern_str_bl_rna, "bl_rna");
BPY_INTERN_STR(bpy_intern_str_bl_target_properties, "bl_target_properties");
BPY_INTERN_STR(bpy_intern_str_bpy_types, "bpy.types");
BPY_INTERN_STR(bpy_intern_str_frame, "frame");
BPY_INTERN_STR(bpy_intern_str_properties, "properties");
BPY_INTERN_STR(bpy_intern_str_register, "register");
BPY_INTERN_STR(bpy_intern_str_self, "self");
BPY_INTERN_STR(bpy_intern_str_unregister, "unregister");
BPY_INTERN_STR(bpy_intern_str___annotations__, "__annotations__");
BPY_INTERN_STR(bpy_intern_str___doc__, "__doc__");
BPY_INTERN_STR(bpy_intern_str___main__, "__main__");
BPY_INTERN_STR(bpy_intern_str___module__, "__module__");
BPY_INTERN_STR(bpy_intern_str___name__, "__name__");
BPY_INTERN_STR(bpy_intern_str___slots__, "__slots__");
BPY_INTERN_STR(bpy_intern_str_attr, "attr");
BPY_INTERN_STR(bpy_intern_str_bl_property, "bl_property");
BPY_INTERN_STR(bpy_intern_str_bl_rna, "bl_rna");
BPY_INTERN_STR(bpy_intern_str_bl_target_properties, "bl_target_properties");
BPY_INTERN_STR(bpy_intern_str_bpy_types, "bpy.types");
BPY_INTERN_STR(bpy_intern_str_frame, "frame");
BPY_INTERN_STR(bpy_intern_str_properties, "properties");
BPY_INTERN_STR(bpy_intern_str_register, "register");
BPY_INTERN_STR(bpy_intern_str_self, "self");
BPY_INTERN_STR(bpy_intern_str_unregister, "unregister");
#undef BPY_INTERN_STR
BLI_assert(i == ARRAY_SIZE(bpy_intern_str_arr));
BLI_assert(i == ARRAY_SIZE(bpy_intern_str_arr));
}
void bpy_intern_string_exit(void)
{
unsigned int i = ARRAY_SIZE(bpy_intern_str_arr);
while (i--) {
Py_DECREF(bpy_intern_str_arr[i]);
}
unsigned int i = ARRAY_SIZE(bpy_intern_str_arr);
while (i--) {
Py_DECREF(bpy_intern_str_arr[i]);
}
}

View File

@@ -41,4 +41,4 @@ extern PyObject *bpy_intern_str_register;
extern PyObject *bpy_intern_str_self;
extern PyObject *bpy_intern_str_unregister;
#endif /* __BPY_INTERN_STRING_H__ */
#endif /* __BPY_INTERN_STRING_H__ */

View File

@@ -24,4 +24,4 @@
int BPY_library_load_module(PyObject *mod_par);
int BPY_library_write_module(PyObject *mod_par);
#endif /* __BPY_LIBRARY_H__ */
#endif /* __BPY_LIBRARY_H__ */

View File

@@ -59,13 +59,13 @@
#endif
typedef struct {
PyObject_HEAD /* required python macro */
/* collection iterator specific parts */
char relpath[FILE_MAX];
char abspath[FILE_MAX]; /* absolute path */
BlendHandle *blo_handle;
int flag;
PyObject *dict;
PyObject_HEAD /* required python macro */
/* collection iterator specific parts */
char relpath[FILE_MAX];
char abspath[FILE_MAX]; /* absolute path */
BlendHandle *blo_handle;
int flag;
PyObject *dict;
} BPy_Library;
static PyObject *bpy_lib_load(PyObject *self, PyObject *args, PyObject *kwds);
@@ -74,411 +74,407 @@ static PyObject *bpy_lib_exit(BPy_Library *self, PyObject *args);
static PyObject *bpy_lib_dir(BPy_Library *self);
static PyMethodDef bpy_lib_methods[] = {
{"__enter__", (PyCFunction)bpy_lib_enter, METH_NOARGS},
{"__exit__", (PyCFunction)bpy_lib_exit, METH_VARARGS},
{"__dir__", (PyCFunction)bpy_lib_dir, METH_NOARGS},
{NULL} /* sentinel */
{"__enter__", (PyCFunction)bpy_lib_enter, METH_NOARGS},
{"__exit__", (PyCFunction)bpy_lib_exit, METH_VARARGS},
{"__dir__", (PyCFunction)bpy_lib_dir, METH_NOARGS},
{NULL} /* sentinel */
};
static void bpy_lib_dealloc(BPy_Library *self)
{
Py_XDECREF(self->dict);
Py_TYPE(self)->tp_free(self);
Py_XDECREF(self->dict);
Py_TYPE(self)->tp_free(self);
}
static PyTypeObject bpy_lib_Type = {
PyVarObject_HEAD_INIT(NULL, 0)
"bpy_lib", /* tp_name */
sizeof(BPy_Library), /* tp_basicsize */
0, /* tp_itemsize */
/* methods */
(destructor)bpy_lib_dealloc, /* tp_dealloc */
NULL, /* printfunc tp_print; */
NULL, /* getattrfunc tp_getattr; */
NULL, /* setattrfunc tp_setattr; */
NULL, /* tp_compare */ /* DEPRECATED in python 3.0! */
NULL, /* tp_repr */
PyVarObject_HEAD_INIT(NULL, 0) "bpy_lib", /* tp_name */
sizeof(BPy_Library), /* tp_basicsize */
0, /* tp_itemsize */
/* methods */
(destructor)bpy_lib_dealloc, /* tp_dealloc */
NULL, /* printfunc tp_print; */
NULL, /* getattrfunc tp_getattr; */
NULL, /* setattrfunc tp_setattr; */
NULL,
/* tp_compare */ /* DEPRECATED in python 3.0! */
NULL, /* tp_repr */
/* Method suites for standard classes */
/* Method suites for standard classes */
NULL, /* PyNumberMethods *tp_as_number; */
NULL, /* PySequenceMethods *tp_as_sequence; */
NULL, /* PyMappingMethods *tp_as_mapping; */
NULL, /* PyNumberMethods *tp_as_number; */
NULL, /* PySequenceMethods *tp_as_sequence; */
NULL, /* PyMappingMethods *tp_as_mapping; */
/* More standard operations (here for binary compatibility) */
/* More standard operations (here for binary compatibility) */
NULL, /* hashfunc tp_hash; */
NULL, /* ternaryfunc tp_call; */
NULL, /* reprfunc tp_str; */
NULL, /* hashfunc tp_hash; */
NULL, /* ternaryfunc tp_call; */
NULL, /* reprfunc tp_str; */
/* will only use these if this is a subtype of a py class */
NULL /*PyObject_GenericGetAttr is assigned later */, /* getattrofunc tp_getattro; */
NULL, /* setattrofunc tp_setattro; */
/* will only use these if this is a subtype of a py class */
NULL /*PyObject_GenericGetAttr is assigned later */, /* getattrofunc tp_getattro; */
NULL, /* setattrofunc tp_setattro; */
/* Functions to access object as input/output buffer */
NULL, /* PyBufferProcs *tp_as_buffer; */
/* Functions to access object as input/output buffer */
NULL, /* PyBufferProcs *tp_as_buffer; */
/*** Flags to define presence of optional/expanded features ***/
Py_TPFLAGS_DEFAULT, /* long tp_flags; */
/*** Flags to define presence of optional/expanded features ***/
Py_TPFLAGS_DEFAULT, /* long tp_flags; */
NULL, /* char *tp_doc; Documentation string */
/*** Assigned meaning in release 2.0 ***/
/* call function for all accessible objects */
NULL, /* traverseproc tp_traverse; */
NULL, /* char *tp_doc; Documentation string */
/*** Assigned meaning in release 2.0 ***/
/* call function for all accessible objects */
NULL, /* traverseproc tp_traverse; */
/* delete references to contained objects */
NULL, /* inquiry tp_clear; */
/* delete references to contained objects */
NULL, /* inquiry tp_clear; */
/*** Assigned meaning in release 2.1 ***/
/*** rich comparisons (subclassed) ***/
NULL, /* richcmpfunc tp_richcompare; */
/*** Assigned meaning in release 2.1 ***/
/*** rich comparisons (subclassed) ***/
NULL, /* richcmpfunc tp_richcompare; */
/*** weak reference enabler ***/
0,
/*** Added in release 2.2 ***/
/* Iterators */
NULL, /* getiterfunc tp_iter; */
NULL, /* iternextfunc tp_iternext; */
/*** weak reference enabler ***/
0,
/*** Added in release 2.2 ***/
/* Iterators */
NULL, /* getiterfunc tp_iter; */
NULL, /* iternextfunc tp_iternext; */
/*** Attribute descriptor and subclassing stuff ***/
bpy_lib_methods, /* struct PyMethodDef *tp_methods; */
NULL, /* struct PyMemberDef *tp_members; */
NULL, /* struct PyGetSetDef *tp_getset; */
NULL, /* struct _typeobject *tp_base; */
NULL, /* PyObject *tp_dict; */
NULL, /* descrgetfunc tp_descr_get; */
NULL, /* descrsetfunc tp_descr_set; */
offsetof(BPy_Library, dict), /* long tp_dictoffset; */
NULL, /* initproc tp_init; */
NULL, /* allocfunc tp_alloc; */
NULL, /* newfunc tp_new; */
/* Low-level free-memory routine */
NULL, /* freefunc tp_free; */
/* For PyObject_IS_GC */
NULL, /* inquiry tp_is_gc; */
NULL, /* PyObject *tp_bases; */
/* method resolution order */
NULL, /* PyObject *tp_mro; */
NULL, /* PyObject *tp_cache; */
NULL, /* PyObject *tp_subclasses; */
NULL, /* PyObject *tp_weaklist; */
NULL,
/*** Attribute descriptor and subclassing stuff ***/
bpy_lib_methods, /* struct PyMethodDef *tp_methods; */
NULL, /* struct PyMemberDef *tp_members; */
NULL, /* struct PyGetSetDef *tp_getset; */
NULL, /* struct _typeobject *tp_base; */
NULL, /* PyObject *tp_dict; */
NULL, /* descrgetfunc tp_descr_get; */
NULL, /* descrsetfunc tp_descr_set; */
offsetof(BPy_Library, dict), /* long tp_dictoffset; */
NULL, /* initproc tp_init; */
NULL, /* allocfunc tp_alloc; */
NULL, /* newfunc tp_new; */
/* Low-level free-memory routine */
NULL, /* freefunc tp_free; */
/* For PyObject_IS_GC */
NULL, /* inquiry tp_is_gc; */
NULL, /* PyObject *tp_bases; */
/* method resolution order */
NULL, /* PyObject *tp_mro; */
NULL, /* PyObject *tp_cache; */
NULL, /* PyObject *tp_subclasses; */
NULL, /* PyObject *tp_weaklist; */
NULL,
};
PyDoc_STRVAR(bpy_lib_load_doc,
".. method:: load(filepath, link=False, relative=False)\n"
"\n"
" Returns a context manager which exposes 2 library objects on entering.\n"
" Each object has attributes matching bpy.data which are lists of strings to be linked.\n"
"\n"
" :arg filepath: The path to a blend file.\n"
" :type filepath: string\n"
" :arg link: When False reference to the original file is lost.\n"
" :type link: bool\n"
" :arg relative: When True the path is stored relative to the open blend file.\n"
" :type relative: bool\n"
);
PyDoc_STRVAR(
bpy_lib_load_doc,
".. method:: load(filepath, link=False, relative=False)\n"
"\n"
" Returns a context manager which exposes 2 library objects on entering.\n"
" Each object has attributes matching bpy.data which are lists of strings to be linked.\n"
"\n"
" :arg filepath: The path to a blend file.\n"
" :type filepath: string\n"
" :arg link: When False reference to the original file is lost.\n"
" :type link: bool\n"
" :arg relative: When True the path is stored relative to the open blend file.\n"
" :type relative: bool\n");
static PyObject *bpy_lib_load(PyObject *UNUSED(self), PyObject *args, PyObject *kw)
{
Main *bmain = CTX_data_main(BPy_GetContext());
BPy_Library *ret;
const char *filename = NULL;
bool is_rel = false, is_link = false;
Main *bmain = CTX_data_main(BPy_GetContext());
BPy_Library *ret;
const char *filename = NULL;
bool is_rel = false, is_link = false;
static const char *_keywords[] = {"filepath", "link", "relative", NULL};
static _PyArg_Parser _parser = {"s|O&O&:load", _keywords, 0};
if (!_PyArg_ParseTupleAndKeywordsFast(
args, kw, &_parser,
&filename,
PyC_ParseBool, &is_link,
PyC_ParseBool, &is_rel))
{
return NULL;
}
static const char *_keywords[] = {"filepath", "link", "relative", NULL};
static _PyArg_Parser _parser = {"s|O&O&:load", _keywords, 0};
if (!_PyArg_ParseTupleAndKeywordsFast(
args, kw, &_parser, &filename, PyC_ParseBool, &is_link, PyC_ParseBool, &is_rel)) {
return NULL;
}
ret = PyObject_New(BPy_Library, &bpy_lib_Type);
ret = PyObject_New(BPy_Library, &bpy_lib_Type);
BLI_strncpy(ret->relpath, filename, sizeof(ret->relpath));
BLI_strncpy(ret->abspath, filename, sizeof(ret->abspath));
BLI_path_abs(ret->abspath, BKE_main_blendfile_path(bmain));
BLI_strncpy(ret->relpath, filename, sizeof(ret->relpath));
BLI_strncpy(ret->abspath, filename, sizeof(ret->abspath));
BLI_path_abs(ret->abspath, BKE_main_blendfile_path(bmain));
ret->blo_handle = NULL;
ret->flag = ((is_link ? FILE_LINK : 0) |
(is_rel ? FILE_RELPATH : 0));
ret->blo_handle = NULL;
ret->flag = ((is_link ? FILE_LINK : 0) | (is_rel ? FILE_RELPATH : 0));
ret->dict = _PyDict_NewPresized(MAX_LIBARRAY);
ret->dict = _PyDict_NewPresized(MAX_LIBARRAY);
return (PyObject *)ret;
return (PyObject *)ret;
}
static PyObject *_bpy_names(BPy_Library *self, int blocktype)
{
PyObject *list;
LinkNode *l, *names;
int totnames;
PyObject *list;
LinkNode *l, *names;
int totnames;
names = BLO_blendhandle_get_datablock_names(self->blo_handle, blocktype, &totnames);
list = PyList_New(totnames);
names = BLO_blendhandle_get_datablock_names(self->blo_handle, blocktype, &totnames);
list = PyList_New(totnames);
if (names) {
int counter = 0;
for (l = names; l; l = l->next) {
PyList_SET_ITEM(list, counter, PyUnicode_FromString((char *)l->link));
counter++;
}
BLI_linklist_free(names, free); /* free linklist *and* each node's data */
}
if (names) {
int counter = 0;
for (l = names; l; l = l->next) {
PyList_SET_ITEM(list, counter, PyUnicode_FromString((char *)l->link));
counter++;
}
BLI_linklist_free(names, free); /* free linklist *and* each node's data */
}
return list;
return list;
}
static PyObject *bpy_lib_enter(BPy_Library *self)
{
PyObject *ret;
BPy_Library *self_from;
PyObject *from_dict = _PyDict_NewPresized(MAX_LIBARRAY);
ReportList reports;
PyObject *ret;
BPy_Library *self_from;
PyObject *from_dict = _PyDict_NewPresized(MAX_LIBARRAY);
ReportList reports;
BKE_reports_init(&reports, RPT_STORE);
BKE_reports_init(&reports, RPT_STORE);
self->blo_handle = BLO_blendhandle_from_file(self->abspath, &reports);
self->blo_handle = BLO_blendhandle_from_file(self->abspath, &reports);
if (self->blo_handle == NULL) {
if (BPy_reports_to_error(&reports, PyExc_IOError, true) != -1) {
PyErr_Format(PyExc_IOError,
"load: %s failed to open blend file",
self->abspath);
}
return NULL;
}
else {
int i = 0, code;
while ((code = BKE_idcode_iter_step(&i))) {
if (BKE_idcode_is_linkable(code)) {
const char *name_plural = BKE_idcode_to_name_plural(code);
PyObject *str = PyUnicode_FromString(name_plural);
PyObject *item;
if (self->blo_handle == NULL) {
if (BPy_reports_to_error(&reports, PyExc_IOError, true) != -1) {
PyErr_Format(PyExc_IOError, "load: %s failed to open blend file", self->abspath);
}
return NULL;
}
else {
int i = 0, code;
while ((code = BKE_idcode_iter_step(&i))) {
if (BKE_idcode_is_linkable(code)) {
const char *name_plural = BKE_idcode_to_name_plural(code);
PyObject *str = PyUnicode_FromString(name_plural);
PyObject *item;
PyDict_SetItem(self->dict, str, item = PyList_New(0));
Py_DECREF(item);
PyDict_SetItem(from_dict, str, item = _bpy_names(self, code));
Py_DECREF(item);
PyDict_SetItem(self->dict, str, item = PyList_New(0));
Py_DECREF(item);
PyDict_SetItem(from_dict, str, item = _bpy_names(self, code));
Py_DECREF(item);
Py_DECREF(str);
}
}
}
Py_DECREF(str);
}
}
}
/* create a dummy */
self_from = PyObject_New(BPy_Library, &bpy_lib_Type);
BLI_strncpy(self_from->relpath, self->relpath, sizeof(self_from->relpath));
BLI_strncpy(self_from->abspath, self->abspath, sizeof(self_from->abspath));
/* create a dummy */
self_from = PyObject_New(BPy_Library, &bpy_lib_Type);
BLI_strncpy(self_from->relpath, self->relpath, sizeof(self_from->relpath));
BLI_strncpy(self_from->abspath, self->abspath, sizeof(self_from->abspath));
self_from->blo_handle = NULL;
self_from->flag = 0;
self_from->dict = from_dict; /* owns the dict */
self_from->blo_handle = NULL;
self_from->flag = 0;
self_from->dict = from_dict; /* owns the dict */
/* return pair */
ret = PyTuple_New(2);
PyTuple_SET_ITEMS(ret,
(PyObject *)self_from,
(PyObject *)self);
Py_INCREF(self);
/* return pair */
ret = PyTuple_New(2);
PyTuple_SET_ITEMS(ret, (PyObject *)self_from, (PyObject *)self);
Py_INCREF(self);
BKE_reports_clear(&reports);
BKE_reports_clear(&reports);
return ret;
return ret;
}
static void bpy_lib_exit_warn_idname(BPy_Library *self, const char *name_plural, const char *idname)
static void bpy_lib_exit_warn_idname(BPy_Library *self,
const char *name_plural,
const char *idname)
{
PyObject *exc, *val, *tb;
PyErr_Fetch(&exc, &val, &tb);
if (PyErr_WarnFormat(PyExc_UserWarning, 1,
"load: '%s' does not contain %s[\"%s\"]",
self->abspath, name_plural, idname))
{
/* Spurious errors can appear at shutdown */
if (PyErr_ExceptionMatches(PyExc_Warning)) {
PyErr_WriteUnraisable((PyObject *)self);
}
}
PyErr_Restore(exc, val, tb);
PyObject *exc, *val, *tb;
PyErr_Fetch(&exc, &val, &tb);
if (PyErr_WarnFormat(PyExc_UserWarning,
1,
"load: '%s' does not contain %s[\"%s\"]",
self->abspath,
name_plural,
idname)) {
/* Spurious errors can appear at shutdown */
if (PyErr_ExceptionMatches(PyExc_Warning)) {
PyErr_WriteUnraisable((PyObject *)self);
}
}
PyErr_Restore(exc, val, tb);
}
static void bpy_lib_exit_warn_type(BPy_Library *self, PyObject *item)
{
PyObject *exc, *val, *tb;
PyErr_Fetch(&exc, &val, &tb);
if (PyErr_WarnFormat(PyExc_UserWarning, 1,
"load: '%s' expected a string type, not a %.200s",
self->abspath, Py_TYPE(item)->tp_name))
{
/* Spurious errors can appear at shutdown */
if (PyErr_ExceptionMatches(PyExc_Warning)) {
PyErr_WriteUnraisable((PyObject *)self);
}
}
PyErr_Restore(exc, val, tb);
PyObject *exc, *val, *tb;
PyErr_Fetch(&exc, &val, &tb);
if (PyErr_WarnFormat(PyExc_UserWarning,
1,
"load: '%s' expected a string type, not a %.200s",
self->abspath,
Py_TYPE(item)->tp_name)) {
/* Spurious errors can appear at shutdown */
if (PyErr_ExceptionMatches(PyExc_Warning)) {
PyErr_WriteUnraisable((PyObject *)self);
}
}
PyErr_Restore(exc, val, tb);
}
static PyObject *bpy_lib_exit(BPy_Library *self, PyObject *UNUSED(args))
{
Main *bmain = CTX_data_main(BPy_GetContext());
Main *mainl = NULL;
int err = 0;
const bool do_append = ((self->flag & FILE_LINK) == 0);
Main *bmain = CTX_data_main(BPy_GetContext());
Main *mainl = NULL;
int err = 0;
const bool do_append = ((self->flag & FILE_LINK) == 0);
BKE_main_id_tag_all(bmain, LIB_TAG_PRE_EXISTING, true);
BKE_main_id_tag_all(bmain, LIB_TAG_PRE_EXISTING, true);
/* here appending/linking starts */
mainl = BLO_library_link_begin(bmain, &(self->blo_handle), self->relpath);
/* here appending/linking starts */
mainl = BLO_library_link_begin(bmain, &(self->blo_handle), self->relpath);
{
int idcode_step = 0, idcode;
while ((idcode = BKE_idcode_iter_step(&idcode_step))) {
if (BKE_idcode_is_linkable(idcode) && (idcode != ID_WS || do_append)) {
const char *name_plural = BKE_idcode_to_name_plural(idcode);
PyObject *ls = PyDict_GetItemString(self->dict, name_plural);
// printf("lib: %s\n", name_plural);
if (ls && PyList_Check(ls)) {
/* loop */
Py_ssize_t size = PyList_GET_SIZE(ls);
Py_ssize_t i;
{
int idcode_step = 0, idcode;
while ((idcode = BKE_idcode_iter_step(&idcode_step))) {
if (BKE_idcode_is_linkable(idcode) && (idcode != ID_WS || do_append)) {
const char *name_plural = BKE_idcode_to_name_plural(idcode);
PyObject *ls = PyDict_GetItemString(self->dict, name_plural);
// printf("lib: %s\n", name_plural);
if (ls && PyList_Check(ls)) {
/* loop */
Py_ssize_t size = PyList_GET_SIZE(ls);
Py_ssize_t i;
for (i = 0; i < size; i++) {
PyObject *item_src = PyList_GET_ITEM(ls, i);
PyObject *item_dst; /* must be set below */
const char *item_idname = _PyUnicode_AsString(item_src);
for (i = 0; i < size; i++) {
PyObject *item_src = PyList_GET_ITEM(ls, i);
PyObject *item_dst; /* must be set below */
const char *item_idname = _PyUnicode_AsString(item_src);
// printf(" %s\n", item_idname);
// printf(" %s\n", item_idname);
if (item_idname) {
ID *id = BLO_library_link_named_part(mainl, &(self->blo_handle), idcode, item_idname);
if (id) {
if (item_idname) {
ID *id = BLO_library_link_named_part(
mainl, &(self->blo_handle), idcode, item_idname);
if (id) {
#ifdef USE_RNA_DATABLOCKS
/* swap name for pointer to the id */
item_dst = PyCapsule_New((void *)id, NULL, NULL);
/* swap name for pointer to the id */
item_dst = PyCapsule_New((void *)id, NULL, NULL);
#else
/* leave as is */
continue;
/* leave as is */
continue;
#endif
}
else {
bpy_lib_exit_warn_idname(self, name_plural, item_idname);
/* just warn for now */
/* err = -1; */
item_dst = Py_INCREF_RET(Py_None);
}
}
else {
bpy_lib_exit_warn_idname(self, name_plural, item_idname);
/* just warn for now */
/* err = -1; */
item_dst = Py_INCREF_RET(Py_None);
}
/* ID or None */
}
else {
/* XXX, could complain about this */
bpy_lib_exit_warn_type(self, item_src);
PyErr_Clear();
item_dst = Py_INCREF_RET(Py_None);
}
/* ID or None */
}
else {
/* XXX, could complain about this */
bpy_lib_exit_warn_type(self, item_src);
PyErr_Clear();
item_dst = Py_INCREF_RET(Py_None);
}
/* item_dst must be new or already incref'd */
Py_DECREF(item_src);
PyList_SET_ITEM(ls, i, item_dst);
}
}
}
}
}
/* item_dst must be new or already incref'd */
Py_DECREF(item_src);
PyList_SET_ITEM(ls, i, item_dst);
}
}
}
}
}
if (err == -1) {
/* exception raised above, XXX, this leaks some memory */
BLO_blendhandle_close(self->blo_handle);
self->blo_handle = NULL;
BKE_main_id_tag_all(bmain, LIB_TAG_PRE_EXISTING, false);
return NULL;
}
else {
Library *lib = mainl->curlib; /* newly added lib, assign before append end */
BLO_library_link_end(mainl, &(self->blo_handle), self->flag, NULL, NULL, NULL, NULL);
BLO_blendhandle_close(self->blo_handle);
self->blo_handle = NULL;
if (err == -1) {
/* exception raised above, XXX, this leaks some memory */
BLO_blendhandle_close(self->blo_handle);
self->blo_handle = NULL;
BKE_main_id_tag_all(bmain, LIB_TAG_PRE_EXISTING, false);
return NULL;
}
else {
Library *lib = mainl->curlib; /* newly added lib, assign before append end */
BLO_library_link_end(mainl, &(self->blo_handle), self->flag, NULL, NULL, NULL, NULL);
BLO_blendhandle_close(self->blo_handle);
self->blo_handle = NULL;
GHash *old_to_new_ids = BLI_ghash_ptr_new(__func__);
GHash *old_to_new_ids = BLI_ghash_ptr_new(__func__);
/* copied from wm_operator.c */
{
/* mark all library linked objects to be updated */
BKE_main_lib_objects_recalc_all(bmain);
/* copied from wm_operator.c */
{
/* mark all library linked objects to be updated */
BKE_main_lib_objects_recalc_all(bmain);
/* append, rather than linking */
if (do_append) {
BKE_library_make_local(bmain, lib, old_to_new_ids, true, false);
}
}
/* append, rather than linking */
if (do_append) {
BKE_library_make_local(bmain, lib, old_to_new_ids, true, false);
}
}
BKE_main_id_tag_all(bmain, LIB_TAG_PRE_EXISTING, false);
BKE_main_id_tag_all(bmain, LIB_TAG_PRE_EXISTING, false);
/* finally swap the capsules for real bpy objects
* important since BLO_library_append_end initializes NodeTree types used by srna->refine */
/* finally swap the capsules for real bpy objects
* important since BLO_library_append_end initializes NodeTree types used by srna->refine */
#ifdef USE_RNA_DATABLOCKS
{
int idcode_step = 0, idcode;
while ((idcode = BKE_idcode_iter_step(&idcode_step))) {
if (BKE_idcode_is_linkable(idcode) && (idcode != ID_WS || do_append)) {
const char *name_plural = BKE_idcode_to_name_plural(idcode);
PyObject *ls = PyDict_GetItemString(self->dict, name_plural);
if (ls && PyList_Check(ls)) {
Py_ssize_t size = PyList_GET_SIZE(ls);
Py_ssize_t i;
PyObject *item;
{
int idcode_step = 0, idcode;
while ((idcode = BKE_idcode_iter_step(&idcode_step))) {
if (BKE_idcode_is_linkable(idcode) && (idcode != ID_WS || do_append)) {
const char *name_plural = BKE_idcode_to_name_plural(idcode);
PyObject *ls = PyDict_GetItemString(self->dict, name_plural);
if (ls && PyList_Check(ls)) {
Py_ssize_t size = PyList_GET_SIZE(ls);
Py_ssize_t i;
PyObject *item;
for (i = 0; i < size; i++) {
item = PyList_GET_ITEM(ls, i);
if (PyCapsule_CheckExact(item)) {
PointerRNA id_ptr;
ID *id;
for (i = 0; i < size; i++) {
item = PyList_GET_ITEM(ls, i);
if (PyCapsule_CheckExact(item)) {
PointerRNA id_ptr;
ID *id;
id = PyCapsule_GetPointer(item, NULL);
id = BLI_ghash_lookup_default(old_to_new_ids, id, id);
Py_DECREF(item);
id = PyCapsule_GetPointer(item, NULL);
id = BLI_ghash_lookup_default(old_to_new_ids, id, id);
Py_DECREF(item);
RNA_id_pointer_create(id, &id_ptr);
item = pyrna_struct_CreatePyObject(&id_ptr);
PyList_SET_ITEM(ls, i, item);
}
}
}
}
}
}
#endif /* USE_RNA_DATABLOCKS */
RNA_id_pointer_create(id, &id_ptr);
item = pyrna_struct_CreatePyObject(&id_ptr);
PyList_SET_ITEM(ls, i, item);
}
}
}
}
}
}
#endif /* USE_RNA_DATABLOCKS */
BLI_ghash_free(old_to_new_ids, NULL, NULL);
Py_RETURN_NONE;
}
BLI_ghash_free(old_to_new_ids, NULL, NULL);
Py_RETURN_NONE;
}
}
static PyObject *bpy_lib_dir(BPy_Library *self)
{
return PyDict_Keys(self->dict);
return PyDict_Keys(self->dict);
}
int BPY_library_load_module(PyObject *mod_par)
{
static PyMethodDef load_meth = {
"load", (PyCFunction)bpy_lib_load,
METH_STATIC | METH_VARARGS | METH_KEYWORDS,
bpy_lib_load_doc,
};
PyModule_AddObject(mod_par, "_library_load", PyCFunction_New(&load_meth, NULL));
static PyMethodDef load_meth = {
"load",
(PyCFunction)bpy_lib_load,
METH_STATIC | METH_VARARGS | METH_KEYWORDS,
bpy_lib_load_doc,
};
PyModule_AddObject(mod_par, "_library_load", PyCFunction_New(&load_meth, NULL));
/* some compilers don't like accessing this directly, delay assignment */
bpy_lib_Type.tp_getattro = PyObject_GenericGetAttr;
/* some compilers don't like accessing this directly, delay assignment */
bpy_lib_Type.tp_getattro = PyObject_GenericGetAttr;
if (PyType_Ready(&bpy_lib_Type) < 0) {
return -1;
}
if (PyType_Ready(&bpy_lib_Type) < 0) {
return -1;
}
return 0;
return 0;
}

View File

@@ -43,174 +43,177 @@
#include "../generic/py_capi_utils.h"
PyDoc_STRVAR(bpy_lib_write_doc,
".. method:: write(filepath, datablocks, relative_remap=False, fake_user=False, compress=False)\n"
"\n"
" Write data-blocks into a blend file.\n"
"\n"
" .. note::\n"
"\n"
" Indirectly referenced data-blocks will be expanded and written too.\n"
"\n"
" :arg filepath: The path to write the blend-file.\n"
" :type filepath: string\n"
" :arg datablocks: set of data-blocks (:class:`bpy.types.ID` instances).\n"
" :type datablocks: set\n"
" :arg relative_remap: When True, make paths relative to the current blend-file.\n"
" :type relative_remap: bool\n"
" :arg fake_user: When True, data-blocks will be written with fake-user flag enabled.\n"
" :type fake_user: bool\n"
" :arg compress: When True, write a compressed blend file.\n"
" :type compress: bool\n"
);
PyDoc_STRVAR(
bpy_lib_write_doc,
".. method:: write(filepath, datablocks, relative_remap=False, fake_user=False, "
"compress=False)\n"
"\n"
" Write data-blocks into a blend file.\n"
"\n"
" .. note::\n"
"\n"
" Indirectly referenced data-blocks will be expanded and written too.\n"
"\n"
" :arg filepath: The path to write the blend-file.\n"
" :type filepath: string\n"
" :arg datablocks: set of data-blocks (:class:`bpy.types.ID` instances).\n"
" :type datablocks: set\n"
" :arg relative_remap: When True, make paths relative to the current blend-file.\n"
" :type relative_remap: bool\n"
" :arg fake_user: When True, data-blocks will be written with fake-user flag enabled.\n"
" :type fake_user: bool\n"
" :arg compress: When True, write a compressed blend file.\n"
" :type compress: bool\n");
static PyObject *bpy_lib_write(PyObject *UNUSED(self), PyObject *args, PyObject *kw)
{
/* args */
const char *filepath;
char filepath_abs[FILE_MAX];
PyObject *datablocks = NULL;
bool use_relative_remap = false, use_fake_user = false, use_compress = false;
/* args */
const char *filepath;
char filepath_abs[FILE_MAX];
PyObject *datablocks = NULL;
bool use_relative_remap = false, use_fake_user = false, use_compress = false;
static const char *_keywords[] = {
"filepath", "datablocks",
/* optional */
"relative_remap", "fake_user", "compress",
NULL,
};
static _PyArg_Parser _parser = {"sO!|$O&O&O&:write", _keywords, 0};
if (!_PyArg_ParseTupleAndKeywordsFast(
args, kw, &_parser,
&filepath,
&PySet_Type, &datablocks,
PyC_ParseBool, &use_relative_remap,
PyC_ParseBool, &use_fake_user,
PyC_ParseBool, &use_compress))
{
return NULL;
}
static const char *_keywords[] = {
"filepath",
"datablocks",
/* optional */
"relative_remap",
"fake_user",
"compress",
NULL,
};
static _PyArg_Parser _parser = {"sO!|$O&O&O&:write", _keywords, 0};
if (!_PyArg_ParseTupleAndKeywordsFast(args,
kw,
&_parser,
&filepath,
&PySet_Type,
&datablocks,
PyC_ParseBool,
&use_relative_remap,
PyC_ParseBool,
&use_fake_user,
PyC_ParseBool,
&use_compress)) {
return NULL;
}
Main *bmain_src = G_MAIN;
int write_flags = 0;
Main *bmain_src = G_MAIN;
int write_flags = 0;
if (use_relative_remap) {
write_flags |= G_FILE_RELATIVE_REMAP;
}
if (use_relative_remap) {
write_flags |= G_FILE_RELATIVE_REMAP;
}
if (use_compress) {
write_flags |= G_FILE_COMPRESS;
}
if (use_compress) {
write_flags |= G_FILE_COMPRESS;
}
BLI_strncpy(filepath_abs, filepath, FILE_MAX);
BLI_path_abs(filepath_abs, BKE_main_blendfile_path_from_global());
BLI_strncpy(filepath_abs, filepath, FILE_MAX);
BLI_path_abs(filepath_abs, BKE_main_blendfile_path_from_global());
BKE_blendfile_write_partial_begin(bmain_src);
BKE_blendfile_write_partial_begin(bmain_src);
/* array of ID's and backup any data we modify */
struct {
ID *id;
/* original values */
short id_flag;
short id_us;
} *id_store_array, *id_store;
int id_store_len = 0;
/* array of ID's and backup any data we modify */
struct {
ID *id;
/* original values */
short id_flag;
short id_us;
} * id_store_array, *id_store;
int id_store_len = 0;
PyObject *ret;
PyObject *ret;
/* collect all id data from the set and store in 'id_store_array' */
{
Py_ssize_t pos, hash;
PyObject *key;
/* collect all id data from the set and store in 'id_store_array' */
{
Py_ssize_t pos, hash;
PyObject *key;
id_store_array = MEM_mallocN(sizeof(*id_store_array) * PySet_Size(datablocks), __func__);
id_store = id_store_array;
id_store_array = MEM_mallocN(sizeof(*id_store_array) * PySet_Size(datablocks), __func__);
id_store = id_store_array;
pos = hash = 0;
while (_PySet_NextEntry(datablocks, &pos, &key, &hash)) {
pos = hash = 0;
while (_PySet_NextEntry(datablocks, &pos, &key, &hash)) {
if (!pyrna_id_FromPyObject(key, &id_store->id)) {
PyErr_Format(PyExc_TypeError,
"Expected an ID type, not %.200s",
Py_TYPE(key)->tp_name);
ret = NULL;
goto finally;
}
else {
id_store->id_flag = id_store->id->flag;
id_store->id_us = id_store->id->us;
if (!pyrna_id_FromPyObject(key, &id_store->id)) {
PyErr_Format(PyExc_TypeError, "Expected an ID type, not %.200s", Py_TYPE(key)->tp_name);
ret = NULL;
goto finally;
}
else {
id_store->id_flag = id_store->id->flag;
id_store->id_us = id_store->id->us;
if (use_fake_user) {
id_store->id->flag |= LIB_FAKEUSER;
}
id_store->id->us = 1;
if (use_fake_user) {
id_store->id->flag |= LIB_FAKEUSER;
}
id_store->id->us = 1;
BKE_blendfile_write_partial_tag_ID(id_store->id, true);
BKE_blendfile_write_partial_tag_ID(id_store->id, true);
id_store_len += 1;
id_store++;
}
}
}
id_store_len += 1;
id_store++;
}
}
}
/* write blend */
int retval = 0;
ReportList reports;
/* write blend */
int retval = 0;
ReportList reports;
BKE_reports_init(&reports, RPT_STORE);
BKE_reports_init(&reports, RPT_STORE);
retval = BKE_blendfile_write_partial(bmain_src, filepath_abs, write_flags, &reports);
retval = BKE_blendfile_write_partial(bmain_src, filepath_abs, write_flags, &reports);
/* cleanup state */
BKE_blendfile_write_partial_end(bmain_src);
if (retval) {
BKE_reports_print(&reports, RPT_ERROR_ALL);
BKE_reports_clear(&reports);
ret = Py_None;
Py_INCREF(ret);
}
else {
if (BPy_reports_to_error(&reports, PyExc_IOError, true) == 0) {
PyErr_SetString(PyExc_IOError, "Unknown error writing library data");
}
ret = NULL;
}
/* cleanup state */
BKE_blendfile_write_partial_end(bmain_src);
if (retval) {
BKE_reports_print(&reports, RPT_ERROR_ALL);
BKE_reports_clear(&reports);
ret = Py_None;
Py_INCREF(ret);
}
else {
if (BPy_reports_to_error(&reports, PyExc_IOError, true) == 0) {
PyErr_SetString(PyExc_IOError, "Unknown error writing library data");
}
ret = NULL;
}
finally:
/* clear all flags for ID's added to the store (may run on error too) */
id_store = id_store_array;
/* clear all flags for ID's added to the store (may run on error too) */
id_store = id_store_array;
for (int i = 0; i < id_store_len; id_store++, i++) {
for (int i = 0; i < id_store_len; id_store++, i++) {
if (use_fake_user) {
if ((id_store->id_flag & LIB_FAKEUSER) == 0) {
id_store->id->flag &= ~LIB_FAKEUSER;
}
}
if (use_fake_user) {
if ((id_store->id_flag & LIB_FAKEUSER) == 0) {
id_store->id->flag &= ~LIB_FAKEUSER;
}
}
id_store->id->us = id_store->id_us;
id_store->id->us = id_store->id_us;
BKE_blendfile_write_partial_tag_ID(id_store->id, false);
}
BKE_blendfile_write_partial_tag_ID(id_store->id, false);
}
MEM_freeN(id_store_array);
MEM_freeN(id_store_array);
return ret;
return ret;
}
int BPY_library_write_module(PyObject *mod_par)
{
static PyMethodDef write_meth = {
"write", (PyCFunction)bpy_lib_write,
METH_STATIC | METH_VARARGS | METH_KEYWORDS,
bpy_lib_write_doc,
};
static PyMethodDef write_meth = {
"write",
(PyCFunction)bpy_lib_write,
METH_STATIC | METH_VARARGS | METH_KEYWORDS,
bpy_lib_write_doc,
};
PyModule_AddObject(mod_par, "_library_write", PyCFunction_New(&write_meth, NULL));
PyModule_AddObject(mod_par, "_library_write", PyCFunction_New(&write_meth, NULL));
return 0;
return 0;
}

View File

@@ -40,24 +40,22 @@
#include "bpy_capi_utils.h"
#include "bpy_rna.h"
#include "bpy_intern_string.h"
#include "bpy_gizmo_wrap.h" /* own include */
#include "bpy_msgbus.h" /* own include */
#include "bpy_gizmo_wrap.h" /* own include */
#include "bpy_msgbus.h" /* own include */
/* -------------------------------------------------------------------- */
/** \name Internal Utils
* \{ */
#define BPY_MSGBUS_RNA_MSGKEY_DOC \
" :arg key: Represents the type of data being subscribed to\n" \
"\n" \
" Arguments include\n" \
" - :class:`bpy.types.Property` instance.\n" \
" - :class:`bpy.types.Struct` type.\n" \
" - (:class:`bpy.types.Struct`, str) type and property name.\n" \
" :type key: Muliple\n"
" :arg key: Represents the type of data being subscribed to\n" \
"\n" \
" Arguments include\n" \
" - :class:`bpy.types.Property` instance.\n" \
" - :class:`bpy.types.Struct` type.\n" \
" - (:class:`bpy.types.Struct`, str) type and property name.\n" \
" :type key: Muliple\n"
/**
* There are multiple ways we can get RNA from Python,
@@ -69,87 +67,78 @@
* \param msg_key_params: Message key with all members zeroed out.
* \return -1 on failure, 0 on success.
*/
static int py_msgbus_rna_key_from_py(
PyObject *py_sub,
wmMsgParams_RNA *msg_key_params,
const char *error_prefix)
static int py_msgbus_rna_key_from_py(PyObject *py_sub,
wmMsgParams_RNA *msg_key_params,
const char *error_prefix)
{
/* Allow common case, object rotation, location - etc. */
if (BaseMathObject_CheckExact(py_sub)) {
BaseMathObject *py_sub_math = (BaseMathObject *)py_sub;
if (py_sub_math->cb_user == NULL) {
PyErr_Format(
PyExc_TypeError,
"%s: math argument has no owner",
error_prefix);
return -1;
}
py_sub = py_sub_math->cb_user;
/* Common case will use BPy_PropertyRNA_Check below. */
}
/* Allow common case, object rotation, location - etc. */
if (BaseMathObject_CheckExact(py_sub)) {
BaseMathObject *py_sub_math = (BaseMathObject *)py_sub;
if (py_sub_math->cb_user == NULL) {
PyErr_Format(PyExc_TypeError, "%s: math argument has no owner", error_prefix);
return -1;
}
py_sub = py_sub_math->cb_user;
/* Common case will use BPy_PropertyRNA_Check below. */
}
if (BPy_PropertyRNA_Check(py_sub)) {
BPy_PropertyRNA *data_prop = (BPy_PropertyRNA *)py_sub;
PYRNA_PROP_CHECK_INT(data_prop);
msg_key_params->ptr = data_prop->ptr;
msg_key_params->prop = data_prop->prop;
}
else if (BPy_StructRNA_Check(py_sub)) {
/* note, this isn't typically used since we don't edit structs directly. */
BPy_StructRNA *data_srna = (BPy_StructRNA *)py_sub;
PYRNA_STRUCT_CHECK_INT(data_srna);
msg_key_params->ptr = data_srna->ptr;
}
/* TODO - property / type, not instance. */
else if (PyType_Check(py_sub)) {
StructRNA *data_type = pyrna_struct_as_srna(py_sub, false, error_prefix);
if (data_type == NULL) {
return -1;
}
msg_key_params->ptr.type = data_type;
}
else if (PyTuple_CheckExact(py_sub)) {
if (PyTuple_GET_SIZE(py_sub) == 2) {
PyObject *data_type_py = PyTuple_GET_ITEM(py_sub, 0);
PyObject *data_prop_py = PyTuple_GET_ITEM(py_sub, 1);
StructRNA *data_type = pyrna_struct_as_srna(data_type_py, false, error_prefix);
if (data_type == NULL) {
return -1;
}
if (!PyUnicode_CheckExact(data_prop_py)) {
PyErr_Format(
PyExc_TypeError,
"%s: expected property to be a string",
error_prefix);
return -1;
}
PointerRNA data_type_ptr = { .type = data_type, };
const char *data_prop_str = _PyUnicode_AsString(data_prop_py);
PropertyRNA *data_prop = RNA_struct_find_property(&data_type_ptr, data_prop_str);
if (BPy_PropertyRNA_Check(py_sub)) {
BPy_PropertyRNA *data_prop = (BPy_PropertyRNA *)py_sub;
PYRNA_PROP_CHECK_INT(data_prop);
msg_key_params->ptr = data_prop->ptr;
msg_key_params->prop = data_prop->prop;
}
else if (BPy_StructRNA_Check(py_sub)) {
/* note, this isn't typically used since we don't edit structs directly. */
BPy_StructRNA *data_srna = (BPy_StructRNA *)py_sub;
PYRNA_STRUCT_CHECK_INT(data_srna);
msg_key_params->ptr = data_srna->ptr;
}
/* TODO - property / type, not instance. */
else if (PyType_Check(py_sub)) {
StructRNA *data_type = pyrna_struct_as_srna(py_sub, false, error_prefix);
if (data_type == NULL) {
return -1;
}
msg_key_params->ptr.type = data_type;
}
else if (PyTuple_CheckExact(py_sub)) {
if (PyTuple_GET_SIZE(py_sub) == 2) {
PyObject *data_type_py = PyTuple_GET_ITEM(py_sub, 0);
PyObject *data_prop_py = PyTuple_GET_ITEM(py_sub, 1);
StructRNA *data_type = pyrna_struct_as_srna(data_type_py, false, error_prefix);
if (data_type == NULL) {
return -1;
}
if (!PyUnicode_CheckExact(data_prop_py)) {
PyErr_Format(PyExc_TypeError, "%s: expected property to be a string", error_prefix);
return -1;
}
PointerRNA data_type_ptr = {
.type = data_type,
};
const char *data_prop_str = _PyUnicode_AsString(data_prop_py);
PropertyRNA *data_prop = RNA_struct_find_property(&data_type_ptr, data_prop_str);
if (data_prop == NULL) {
PyErr_Format(
PyExc_TypeError,
"%s: struct %.200s does not contain property %.200s",
error_prefix,
RNA_struct_identifier(data_type),
data_prop_str);
return -1;
}
if (data_prop == NULL) {
PyErr_Format(PyExc_TypeError,
"%s: struct %.200s does not contain property %.200s",
error_prefix,
RNA_struct_identifier(data_type),
data_prop_str);
return -1;
}
msg_key_params->ptr.type = data_type;
msg_key_params->prop = data_prop;
}
else {
PyErr_Format(
PyExc_ValueError,
"%s: Expected a pair (type, property_id)",
error_prefix);
return -1;
}
}
return 0;
msg_key_params->ptr.type = data_type;
msg_key_params->prop = data_prop;
}
else {
PyErr_Format(PyExc_ValueError, "%s: Expected a pair (type, property_id)", error_prefix);
return -1;
}
}
return 0;
}
/** \} */
@@ -161,51 +150,52 @@ static int py_msgbus_rna_key_from_py(
#define BPY_MSGBUS_USER_DATA_LEN 2
/* Follow wmMsgNotifyFn spec */
static void bpy_msgbus_notify(
bContext *C, wmMsgSubscribeKey *UNUSED(msg_key), wmMsgSubscribeValue *msg_val)
static void bpy_msgbus_notify(bContext *C,
wmMsgSubscribeKey *UNUSED(msg_key),
wmMsgSubscribeValue *msg_val)
{
PyGILState_STATE gilstate;
bpy_context_set(C, &gilstate);
PyGILState_STATE gilstate;
bpy_context_set(C, &gilstate);
PyObject *user_data = msg_val->user_data;
BLI_assert(PyTuple_GET_SIZE(user_data) == BPY_MSGBUS_USER_DATA_LEN);
PyObject *user_data = msg_val->user_data;
BLI_assert(PyTuple_GET_SIZE(user_data) == BPY_MSGBUS_USER_DATA_LEN);
PyObject *callback_args = PyTuple_GET_ITEM(user_data, 0);
PyObject *callback_notify = PyTuple_GET_ITEM(user_data, 1);
PyObject *callback_args = PyTuple_GET_ITEM(user_data, 0);
PyObject *callback_notify = PyTuple_GET_ITEM(user_data, 1);
const bool is_write_ok = pyrna_write_check();
if (!is_write_ok) {
pyrna_write_set(true);
}
const bool is_write_ok = pyrna_write_check();
if (!is_write_ok) {
pyrna_write_set(true);
}
PyObject *ret = PyObject_CallObject(callback_notify, callback_args);
PyObject *ret = PyObject_CallObject(callback_notify, callback_args);
if (ret == NULL) {
PyC_Err_PrintWithFunc(callback_notify);
}
else {
if (ret != Py_None) {
PyErr_SetString(PyExc_ValueError, "the return value must be None");
PyC_Err_PrintWithFunc(callback_notify);
}
Py_DECREF(ret);
}
if (ret == NULL) {
PyC_Err_PrintWithFunc(callback_notify);
}
else {
if (ret != Py_None) {
PyErr_SetString(PyExc_ValueError, "the return value must be None");
PyC_Err_PrintWithFunc(callback_notify);
}
Py_DECREF(ret);
}
bpy_context_clear(C, &gilstate);
bpy_context_clear(C, &gilstate);
if (!is_write_ok) {
pyrna_write_set(false);
}
if (!is_write_ok) {
pyrna_write_set(false);
}
}
/* Follow wmMsgSubscribeValueFreeDataFn spec */
static void bpy_msgbus_subscribe_value_free_data(
struct wmMsgSubscribeKey *UNUSED(msg_key), struct wmMsgSubscribeValue *msg_val)
static void bpy_msgbus_subscribe_value_free_data(struct wmMsgSubscribeKey *UNUSED(msg_key),
struct wmMsgSubscribeValue *msg_val)
{
PyGILState_STATE gilstate = PyGILState_Ensure();
Py_DECREF(msg_val->owner);
Py_DECREF(msg_val->user_data);
PyGILState_Release(gilstate);
PyGILState_STATE gilstate = PyGILState_Ensure();
Py_DECREF(msg_val->owner);
Py_DECREF(msg_val->user_data);
PyGILState_Release(gilstate);
}
/** \} */
@@ -214,201 +204,196 @@ static void bpy_msgbus_subscribe_value_free_data(
/** \name Public Message Bus API
* \{ */
PyDoc_STRVAR(bpy_msgbus_subscribe_rna_doc,
".. function:: subscribe_rna(data, owner, args, notify, options=set())\n"
"\n"
BPY_MSGBUS_RNA_MSGKEY_DOC
" :arg owner: Handle for this subscription (compared by identity).\n"
" :type owner: Any type.\n"
" :arg options: Change the behavior of the subscriber.\n"
"\n"
" - ``PERSISTENT`` when set, the subscriber will be kept when remapping ID data.\n"
"\n"
" :type options: set of str.\n"
"\n"
" Returns a new vector int property definition.\n"
);
PyDoc_STRVAR(
bpy_msgbus_subscribe_rna_doc,
".. function:: subscribe_rna(data, owner, args, notify, options=set())\n"
"\n" BPY_MSGBUS_RNA_MSGKEY_DOC
" :arg owner: Handle for this subscription (compared by identity).\n"
" :type owner: Any type.\n"
" :arg options: Change the behavior of the subscriber.\n"
"\n"
" - ``PERSISTENT`` when set, the subscriber will be kept when remapping ID data.\n"
"\n"
" :type options: set of str.\n"
"\n"
" Returns a new vector int property definition.\n");
static PyObject *bpy_msgbus_subscribe_rna(PyObject *UNUSED(self), PyObject *args, PyObject *kw)
{
const char *error_prefix = "subscribe_rna";
PyObject *py_sub = NULL;
PyObject *py_owner = NULL;
PyObject *callback_args = NULL;
PyObject *callback_notify = NULL;
const char *error_prefix = "subscribe_rna";
PyObject *py_sub = NULL;
PyObject *py_owner = NULL;
PyObject *callback_args = NULL;
PyObject *callback_notify = NULL;
enum {
IS_PERSISTENT = (1 << 0),
};
PyObject *py_options = NULL;
EnumPropertyItem py_options_enum[] = {
{IS_PERSISTENT, "PERSISTENT", 0, ""},
{0, NULL, 0, NULL, NULL},
};
int options = 0;
enum {
IS_PERSISTENT = (1 << 0),
};
PyObject *py_options = NULL;
EnumPropertyItem py_options_enum[] = {
{IS_PERSISTENT, "PERSISTENT", 0, ""},
{0, NULL, 0, NULL, NULL},
};
int options = 0;
if (PyTuple_GET_SIZE(args) != 0) {
PyErr_Format(
PyExc_TypeError,
"%s: only keyword arguments are supported",
error_prefix);
return NULL;
}
static const char *_keywords[] = {
"key",
"owner",
"args",
"notify",
"options",
NULL,
};
static _PyArg_Parser _parser = {"OOO!O|O!:subscribe_rna", _keywords, 0};
if (!_PyArg_ParseTupleAndKeywordsFast(
args, kw, &_parser,
&py_sub, &py_owner,
&PyTuple_Type, &callback_args,
&callback_notify,
&PySet_Type, &py_options))
{
return NULL;
}
if (PyTuple_GET_SIZE(args) != 0) {
PyErr_Format(PyExc_TypeError, "%s: only keyword arguments are supported", error_prefix);
return NULL;
}
static const char *_keywords[] = {
"key",
"owner",
"args",
"notify",
"options",
NULL,
};
static _PyArg_Parser _parser = {"OOO!O|O!:subscribe_rna", _keywords, 0};
if (!_PyArg_ParseTupleAndKeywordsFast(args,
kw,
&_parser,
&py_sub,
&py_owner,
&PyTuple_Type,
&callback_args,
&callback_notify,
&PySet_Type,
&py_options)) {
return NULL;
}
if (py_options &&
(pyrna_set_to_enum_bitfield(py_options_enum, py_options, &options, error_prefix)) == -1)
{
return NULL;
}
if (py_options &&
(pyrna_set_to_enum_bitfield(py_options_enum, py_options, &options, error_prefix)) == -1) {
return NULL;
}
/* Note: we may want to have a way to pass this in. */
bContext *C = (bContext *)BPy_GetContext();
struct wmMsgBus *mbus = CTX_wm_message_bus(C);
wmMsgParams_RNA msg_key_params = {{{0}}};
/* Note: we may want to have a way to pass this in. */
bContext *C = (bContext *)BPy_GetContext();
struct wmMsgBus *mbus = CTX_wm_message_bus(C);
wmMsgParams_RNA msg_key_params = {{{0}}};
wmMsgSubscribeValue msg_val_params = {0};
wmMsgSubscribeValue msg_val_params = {0};
if (py_msgbus_rna_key_from_py(py_sub, &msg_key_params, error_prefix) == -1) {
return NULL;
}
if (py_msgbus_rna_key_from_py(py_sub, &msg_key_params, error_prefix) == -1) {
return NULL;
}
if (!PyFunction_Check(callback_notify)) {
PyErr_Format(
PyExc_TypeError,
"notify expects a function, found %.200s",
Py_TYPE(callback_notify)->tp_name);
return NULL;
}
if (!PyFunction_Check(callback_notify)) {
PyErr_Format(PyExc_TypeError,
"notify expects a function, found %.200s",
Py_TYPE(callback_notify)->tp_name);
return NULL;
}
if (options != 0) {
if (options & IS_PERSISTENT) {
msg_val_params.is_persistent = true;
}
}
if (options != 0) {
if (options & IS_PERSISTENT) {
msg_val_params.is_persistent = true;
}
}
/* owner can be anything. */
{
msg_val_params.owner = py_owner;
Py_INCREF(py_owner);
}
/* owner can be anything. */
{
msg_val_params.owner = py_owner;
Py_INCREF(py_owner);
}
{
PyObject *user_data = PyTuple_New(2);
PyTuple_SET_ITEMS(
user_data,
Py_INCREF_RET(callback_args),
Py_INCREF_RET(callback_notify));
msg_val_params.user_data = user_data;
}
{
PyObject *user_data = PyTuple_New(2);
PyTuple_SET_ITEMS(user_data, Py_INCREF_RET(callback_args), Py_INCREF_RET(callback_notify));
msg_val_params.user_data = user_data;
}
msg_val_params.notify = bpy_msgbus_notify;
msg_val_params.free_data = bpy_msgbus_subscribe_value_free_data;
msg_val_params.notify = bpy_msgbus_notify;
msg_val_params.free_data = bpy_msgbus_subscribe_value_free_data;
WM_msg_subscribe_rna_params(mbus, &msg_key_params, &msg_val_params, __func__);
WM_msg_subscribe_rna_params(mbus, &msg_key_params, &msg_val_params, __func__);
WM_msg_dump(mbus, __func__);
WM_msg_dump(mbus, __func__);
Py_RETURN_NONE;
Py_RETURN_NONE;
}
PyDoc_STRVAR(bpy_msgbus_publish_rna_doc,
".. function:: publish_rna(data, owner, args, notify)\n"
"\n"
BPY_MSGBUS_RNA_MSGKEY_DOC
"\n"
" Notify subscribers of changes to this property\n"
" (this typically doesn't need to be called explicitly since changes will automatically publish updates).\n"
" In some cases it may be useful to publish changes explicitly using more general keys.\n"
);
PyDoc_STRVAR(
bpy_msgbus_publish_rna_doc,
".. function:: publish_rna(data, owner, args, notify)\n"
"\n" BPY_MSGBUS_RNA_MSGKEY_DOC
"\n"
" Notify subscribers of changes to this property\n"
" (this typically doesn't need to be called explicitly since changes will automatically "
"publish updates).\n"
" In some cases it may be useful to publish changes explicitly using more general keys.\n");
static PyObject *bpy_msgbus_publish_rna(PyObject *UNUSED(self), PyObject *args, PyObject *kw)
{
const char *error_prefix = "publish_rna";
PyObject *py_sub = NULL;
const char *error_prefix = "publish_rna";
PyObject *py_sub = NULL;
if (PyTuple_GET_SIZE(args) != 0) {
PyErr_Format(
PyExc_TypeError,
"%s: only keyword arguments are supported",
error_prefix);
return NULL;
}
static const char *_keywords[] = {
"key",
NULL,
};
static _PyArg_Parser _parser = {"O:publish_rna", _keywords, 0};
if (!_PyArg_ParseTupleAndKeywordsFast(
args, kw, &_parser,
&py_sub))
{
return NULL;
}
if (PyTuple_GET_SIZE(args) != 0) {
PyErr_Format(PyExc_TypeError, "%s: only keyword arguments are supported", error_prefix);
return NULL;
}
static const char *_keywords[] = {
"key",
NULL,
};
static _PyArg_Parser _parser = {"O:publish_rna", _keywords, 0};
if (!_PyArg_ParseTupleAndKeywordsFast(args, kw, &_parser, &py_sub)) {
return NULL;
}
/* Note: we may want to have a way to pass this in. */
bContext *C = (bContext *)BPy_GetContext();
struct wmMsgBus *mbus = CTX_wm_message_bus(C);
wmMsgParams_RNA msg_key_params = {{{0}}};
/* Note: we may want to have a way to pass this in. */
bContext *C = (bContext *)BPy_GetContext();
struct wmMsgBus *mbus = CTX_wm_message_bus(C);
wmMsgParams_RNA msg_key_params = {{{0}}};
if (py_msgbus_rna_key_from_py(py_sub, &msg_key_params, error_prefix) == -1) {
return NULL;
}
if (py_msgbus_rna_key_from_py(py_sub, &msg_key_params, error_prefix) == -1) {
return NULL;
}
WM_msg_publish_rna_params(mbus, &msg_key_params);
WM_msg_publish_rna_params(mbus, &msg_key_params);
Py_RETURN_NONE;
Py_RETURN_NONE;
}
PyDoc_STRVAR(bpy_msgbus_clear_by_owner_doc,
".. function:: clear_by_owner(owner)\n"
"\n"
" Clear all subscribers using this owner.\n"
);
".. function:: clear_by_owner(owner)\n"
"\n"
" Clear all subscribers using this owner.\n");
static PyObject *bpy_msgbus_clear_by_owner(PyObject *UNUSED(self), PyObject *py_owner)
{
bContext *C = (bContext *)BPy_GetContext();
struct wmMsgBus *mbus = CTX_wm_message_bus(C);
WM_msgbus_clear_by_owner(mbus, py_owner);
Py_RETURN_NONE;
bContext *C = (bContext *)BPy_GetContext();
struct wmMsgBus *mbus = CTX_wm_message_bus(C);
WM_msgbus_clear_by_owner(mbus, py_owner);
Py_RETURN_NONE;
}
static struct PyMethodDef BPy_msgbus_methods[] = {
{"subscribe_rna", (PyCFunction)bpy_msgbus_subscribe_rna, METH_VARARGS | METH_KEYWORDS, bpy_msgbus_subscribe_rna_doc},
{"publish_rna", (PyCFunction)bpy_msgbus_publish_rna, METH_VARARGS | METH_KEYWORDS, bpy_msgbus_publish_rna_doc},
{"clear_by_owner", (PyCFunction)bpy_msgbus_clear_by_owner, METH_O, bpy_msgbus_clear_by_owner_doc},
{NULL, NULL, 0, NULL},
{"subscribe_rna",
(PyCFunction)bpy_msgbus_subscribe_rna,
METH_VARARGS | METH_KEYWORDS,
bpy_msgbus_subscribe_rna_doc},
{"publish_rna",
(PyCFunction)bpy_msgbus_publish_rna,
METH_VARARGS | METH_KEYWORDS,
bpy_msgbus_publish_rna_doc},
{"clear_by_owner",
(PyCFunction)bpy_msgbus_clear_by_owner,
METH_O,
bpy_msgbus_clear_by_owner_doc},
{NULL, NULL, 0, NULL},
};
static struct PyModuleDef _bpy_msgbus_def = {
PyModuleDef_HEAD_INIT,
.m_name = "msgbus",
.m_methods = BPy_msgbus_methods,
PyModuleDef_HEAD_INIT,
.m_name = "msgbus",
.m_methods = BPy_msgbus_methods,
};
PyObject *BPY_msgbus_module(void)
{
PyObject *submodule;
PyObject *submodule;
submodule = PyModule_Create(&_bpy_msgbus_def);
submodule = PyModule_Create(&_bpy_msgbus_def);
return submodule;
return submodule;
}
/** \} */

View File

@@ -23,4 +23,4 @@
PyObject *BPY_msgbus_module(void);
#endif /* __BPY_MSGBUS_H__ */
#endif /* __BPY_MSGBUS_H__ */

View File

@@ -59,385 +59,407 @@
static wmOperatorType *ot_lookup_from_py_string(PyObject *value, const char *py_fn_id)
{
const char *opname = _PyUnicode_AsString(value);
if (opname == NULL) {
PyErr_Format(PyExc_TypeError, "%s() expects a string argument", py_fn_id);
return NULL;
}
const char *opname = _PyUnicode_AsString(value);
if (opname == NULL) {
PyErr_Format(PyExc_TypeError, "%s() expects a string argument", py_fn_id);
return NULL;
}
wmOperatorType *ot = WM_operatortype_find(opname, true);
if (ot == NULL) {
PyErr_Format(PyExc_KeyError, "%s(\"%s\") not found", py_fn_id, opname);
return NULL;
}
return ot;
wmOperatorType *ot = WM_operatortype_find(opname, true);
if (ot == NULL) {
PyErr_Format(PyExc_KeyError, "%s(\"%s\") not found", py_fn_id, opname);
return NULL;
}
return ot;
}
static PyObject *pyop_poll(PyObject *UNUSED(self), PyObject *args)
{
wmOperatorType *ot;
const char *opname;
PyObject *context_dict = NULL; /* optional args */
PyObject *context_dict_back;
const char *context_str = NULL;
PyObject *ret;
wmOperatorType *ot;
const char *opname;
PyObject *context_dict = NULL; /* optional args */
PyObject *context_dict_back;
const char *context_str = NULL;
PyObject *ret;
int context = WM_OP_EXEC_DEFAULT;
int context = WM_OP_EXEC_DEFAULT;
/* XXX Todo, work out a better solution for passing on context,
* could make a tuple from self and pack the name and Context into it... */
bContext *C = (bContext *)BPy_GetContext();
/* XXX Todo, work out a better solution for passing on context,
* could make a tuple from self and pack the name and Context into it... */
bContext *C = (bContext *)BPy_GetContext();
if (C == NULL) {
PyErr_SetString(PyExc_RuntimeError, "Context is None, cant poll any operators");
return NULL;
}
if (C == NULL) {
PyErr_SetString(PyExc_RuntimeError, "Context is None, cant poll any operators");
return NULL;
}
if (!PyArg_ParseTuple(args, "s|Os:_bpy.ops.poll", &opname, &context_dict, &context_str)) {
return NULL;
}
if (!PyArg_ParseTuple(args, "s|Os:_bpy.ops.poll", &opname, &context_dict, &context_str)) {
return NULL;
}
ot = WM_operatortype_find(opname, true);
ot = WM_operatortype_find(opname, true);
if (ot == NULL) {
PyErr_Format(PyExc_AttributeError,
"Polling operator \"bpy.ops.%s\" error, "
"could not be found", opname);
return NULL;
}
if (ot == NULL) {
PyErr_Format(PyExc_AttributeError,
"Polling operator \"bpy.ops.%s\" error, "
"could not be found",
opname);
return NULL;
}
if (context_str) {
if (RNA_enum_value_from_id(rna_enum_operator_context_items, context_str, &context) == 0) {
char *enum_str = BPy_enum_as_string(rna_enum_operator_context_items);
PyErr_Format(PyExc_TypeError,
"Calling operator \"bpy.ops.%s.poll\" error, "
"expected a string enum in (%s)",
opname, enum_str);
MEM_freeN(enum_str);
return NULL;
}
}
if (context_str) {
if (RNA_enum_value_from_id(rna_enum_operator_context_items, context_str, &context) == 0) {
char *enum_str = BPy_enum_as_string(rna_enum_operator_context_items);
PyErr_Format(PyExc_TypeError,
"Calling operator \"bpy.ops.%s.poll\" error, "
"expected a string enum in (%s)",
opname,
enum_str);
MEM_freeN(enum_str);
return NULL;
}
}
if (context_dict == NULL || context_dict == Py_None) {
context_dict = NULL;
}
else if (!PyDict_Check(context_dict)) {
PyErr_Format(PyExc_TypeError,
"Calling operator \"bpy.ops.%s.poll\" error, "
"custom context expected a dict or None, got a %.200s",
opname, Py_TYPE(context_dict)->tp_name);
return NULL;
}
if (context_dict == NULL || context_dict == Py_None) {
context_dict = NULL;
}
else if (!PyDict_Check(context_dict)) {
PyErr_Format(PyExc_TypeError,
"Calling operator \"bpy.ops.%s.poll\" error, "
"custom context expected a dict or None, got a %.200s",
opname,
Py_TYPE(context_dict)->tp_name);
return NULL;
}
context_dict_back = CTX_py_dict_get(C);
CTX_py_dict_set(C, (void *)context_dict);
Py_XINCREF(context_dict); /* so we done loose it */
context_dict_back = CTX_py_dict_get(C);
CTX_py_dict_set(C, (void *)context_dict);
Py_XINCREF(context_dict); /* so we done loose it */
/* main purpose of this function */
ret = WM_operator_poll_context((bContext *)C, ot, context) ? Py_True : Py_False;
/* main purpose of this function */
ret = WM_operator_poll_context((bContext *)C, ot, context) ? Py_True : Py_False;
/* restore with original context dict, probably NULL but need this for nested operator calls */
Py_XDECREF(context_dict);
CTX_py_dict_set(C, (void *)context_dict_back);
/* restore with original context dict, probably NULL but need this for nested operator calls */
Py_XDECREF(context_dict);
CTX_py_dict_set(C, (void *)context_dict_back);
return Py_INCREF_RET(ret);
return Py_INCREF_RET(ret);
}
static PyObject *pyop_call(PyObject *UNUSED(self), PyObject *args)
{
wmOperatorType *ot;
int error_val = 0;
PointerRNA ptr;
int operator_ret = OPERATOR_CANCELLED;
wmOperatorType *ot;
int error_val = 0;
PointerRNA ptr;
int operator_ret = OPERATOR_CANCELLED;
const char *opname;
const char *context_str = NULL;
PyObject *kw = NULL; /* optional args */
PyObject *context_dict = NULL; /* optional args */
PyObject *context_dict_back;
const char *opname;
const char *context_str = NULL;
PyObject *kw = NULL; /* optional args */
PyObject *context_dict = NULL; /* optional args */
PyObject *context_dict_back;
/* note that context is an int, python does the conversion in this case */
int context = WM_OP_EXEC_DEFAULT;
int is_undo = false;
/* note that context is an int, python does the conversion in this case */
int context = WM_OP_EXEC_DEFAULT;
int is_undo = false;
/* XXX Todo, work out a better solution for passing on context,
* could make a tuple from self and pack the name and Context into it... */
bContext *C = (bContext *)BPy_GetContext();
/* XXX Todo, work out a better solution for passing on context,
* could make a tuple from self and pack the name and Context into it... */
bContext *C = (bContext *)BPy_GetContext();
if (C == NULL) {
PyErr_SetString(PyExc_RuntimeError, "Context is None, cant poll any operators");
return NULL;
}
if (C == NULL) {
PyErr_SetString(PyExc_RuntimeError, "Context is None, cant poll any operators");
return NULL;
}
if (!PyArg_ParseTuple(args, "sO|O!si:_bpy.ops.call",
&opname, &context_dict, &PyDict_Type, &kw, &context_str, &is_undo))
{
return NULL;
}
if (!PyArg_ParseTuple(args,
"sO|O!si:_bpy.ops.call",
&opname,
&context_dict,
&PyDict_Type,
&kw,
&context_str,
&is_undo)) {
return NULL;
}
ot = WM_operatortype_find(opname, true);
ot = WM_operatortype_find(opname, true);
if (ot == NULL) {
PyErr_Format(PyExc_AttributeError,
"Calling operator \"bpy.ops.%s\" error, "
"could not be found", opname);
return NULL;
}
if (ot == NULL) {
PyErr_Format(PyExc_AttributeError,
"Calling operator \"bpy.ops.%s\" error, "
"could not be found",
opname);
return NULL;
}
if (!pyrna_write_check()) {
PyErr_Format(PyExc_RuntimeError,
"Calling operator \"bpy.ops.%s\" error, "
"can't modify blend data in this state (drawing/rendering)",
opname);
return NULL;
}
if (!pyrna_write_check()) {
PyErr_Format(PyExc_RuntimeError,
"Calling operator \"bpy.ops.%s\" error, "
"can't modify blend data in this state (drawing/rendering)",
opname);
return NULL;
}
if (context_str) {
if (RNA_enum_value_from_id(rna_enum_operator_context_items, context_str, &context) == 0) {
char *enum_str = BPy_enum_as_string(rna_enum_operator_context_items);
PyErr_Format(PyExc_TypeError,
"Calling operator \"bpy.ops.%s\" error, "
"expected a string enum in (%s)",
opname, enum_str);
MEM_freeN(enum_str);
return NULL;
}
}
if (context_str) {
if (RNA_enum_value_from_id(rna_enum_operator_context_items, context_str, &context) == 0) {
char *enum_str = BPy_enum_as_string(rna_enum_operator_context_items);
PyErr_Format(PyExc_TypeError,
"Calling operator \"bpy.ops.%s\" error, "
"expected a string enum in (%s)",
opname,
enum_str);
MEM_freeN(enum_str);
return NULL;
}
}
if (context_dict == NULL || context_dict == Py_None) {
context_dict = NULL;
}
else if (!PyDict_Check(context_dict)) {
PyErr_Format(PyExc_TypeError,
"Calling operator \"bpy.ops.%s\" error, "
"custom context expected a dict or None, got a %.200s",
opname, Py_TYPE(context_dict)->tp_name);
return NULL;
}
if (context_dict == NULL || context_dict == Py_None) {
context_dict = NULL;
}
else if (!PyDict_Check(context_dict)) {
PyErr_Format(PyExc_TypeError,
"Calling operator \"bpy.ops.%s\" error, "
"custom context expected a dict or None, got a %.200s",
opname,
Py_TYPE(context_dict)->tp_name);
return NULL;
}
context_dict_back = CTX_py_dict_get(C);
context_dict_back = CTX_py_dict_get(C);
CTX_py_dict_set(C, (void *)context_dict);
Py_XINCREF(context_dict); /* so we done loose it */
CTX_py_dict_set(C, (void *)context_dict);
Py_XINCREF(context_dict); /* so we done loose it */
if (WM_operator_poll_context((bContext *)C, ot, context) == false) {
const char *msg = CTX_wm_operator_poll_msg_get(C);
PyErr_Format(PyExc_RuntimeError,
"Operator bpy.ops.%.200s.poll() %.200s",
opname, msg ? msg : "failed, context is incorrect");
CTX_wm_operator_poll_msg_set(C, NULL); /* better set to NULL else it could be used again */
error_val = -1;
}
else {
WM_operator_properties_create_ptr(&ptr, ot);
WM_operator_properties_sanitize(&ptr, 0);
if (WM_operator_poll_context((bContext *)C, ot, context) == false) {
const char *msg = CTX_wm_operator_poll_msg_get(C);
PyErr_Format(PyExc_RuntimeError,
"Operator bpy.ops.%.200s.poll() %.200s",
opname,
msg ? msg : "failed, context is incorrect");
CTX_wm_operator_poll_msg_set(C, NULL); /* better set to NULL else it could be used again */
error_val = -1;
}
else {
WM_operator_properties_create_ptr(&ptr, ot);
WM_operator_properties_sanitize(&ptr, 0);
if (kw && PyDict_Size(kw)) {
error_val = pyrna_pydict_to_props(&ptr, kw, false, "Converting py args to operator properties: ");
}
if (kw && PyDict_Size(kw)) {
error_val = pyrna_pydict_to_props(
&ptr, kw, false, "Converting py args to operator properties: ");
}
if (error_val == 0) {
ReportList *reports;
if (error_val == 0) {
ReportList *reports;
reports = MEM_mallocN(sizeof(ReportList), "wmOperatorReportList");
BKE_reports_init(reports, RPT_STORE | RPT_OP_HOLD); /* own so these don't move into global reports */
reports = MEM_mallocN(sizeof(ReportList), "wmOperatorReportList");
BKE_reports_init(reports,
RPT_STORE | RPT_OP_HOLD); /* own so these don't move into global reports */
#ifdef BPY_RELEASE_GIL
/* release GIL, since a thread could be started from an operator
* that updates a driver */
/* note: I have not seen any examples of code that does this
* so it may not be officially supported but seems to work ok. */
{
PyThreadState *ts = PyEval_SaveThread();
/* release GIL, since a thread could be started from an operator
* that updates a driver */
/* note: I have not seen any examples of code that does this
* so it may not be officially supported but seems to work ok. */
{
PyThreadState *ts = PyEval_SaveThread();
#endif
operator_ret = WM_operator_call_py(C, ot, context, &ptr, reports, is_undo);
operator_ret = WM_operator_call_py(C, ot, context, &ptr, reports, is_undo);
#ifdef BPY_RELEASE_GIL
/* regain GIL */
PyEval_RestoreThread(ts);
}
/* regain GIL */
PyEval_RestoreThread(ts);
}
#endif
error_val = BPy_reports_to_error(reports, PyExc_RuntimeError, false);
error_val = BPy_reports_to_error(reports, PyExc_RuntimeError, false);
/* operator output is nice to have in the terminal/console too */
if (!BLI_listbase_is_empty(&reports->list)) {
BPy_reports_write_stdout(reports, NULL);
}
/* operator output is nice to have in the terminal/console too */
if (!BLI_listbase_is_empty(&reports->list)) {
BPy_reports_write_stdout(reports, NULL);
}
BKE_reports_clear(reports);
if ((reports->flag & RPT_FREE) == 0) {
MEM_freeN(reports);
}
else {
/* The WM is now responsible for running the modal operator,
* show reports in the info window. */
reports->flag &= ~RPT_OP_HOLD;
}
}
BKE_reports_clear(reports);
if ((reports->flag & RPT_FREE) == 0) {
MEM_freeN(reports);
}
else {
/* The WM is now responsible for running the modal operator,
* show reports in the info window. */
reports->flag &= ~RPT_OP_HOLD;
}
}
WM_operator_properties_free(&ptr);
WM_operator_properties_free(&ptr);
#if 0
/* if there is some way to know an operator takes args we should use this */
{
/* no props */
if (kw != NULL) {
PyErr_Format(PyExc_AttributeError,
"Operator \"%s\" does not take any args",
opname);
return NULL;
}
/* if there is some way to know an operator takes args we should use this */
{
/* no props */
if (kw != NULL) {
PyErr_Format(PyExc_AttributeError,
"Operator \"%s\" does not take any args",
opname);
return NULL;
}
WM_operator_name_call(C, opname, WM_OP_EXEC_DEFAULT, NULL);
}
WM_operator_name_call(C, opname, WM_OP_EXEC_DEFAULT, NULL);
}
#endif
}
}
/* restore with original context dict, probably NULL but need this for nested operator calls */
Py_XDECREF(context_dict);
CTX_py_dict_set(C, (void *)context_dict_back);
/* restore with original context dict, probably NULL but need this for nested operator calls */
Py_XDECREF(context_dict);
CTX_py_dict_set(C, (void *)context_dict_back);
if (error_val == -1) {
return NULL;
}
if (error_val == -1) {
return NULL;
}
/* when calling bpy.ops.wm.read_factory_settings() bpy.data's main pointer is freed by clear_globals(),
* further access will crash blender. setting context is not needed in this case, only calling because this
* function corrects bpy.data (internal Main pointer) */
BPY_modules_update(C);
/* when calling bpy.ops.wm.read_factory_settings() bpy.data's main pointer is freed by clear_globals(),
* further access will crash blender. setting context is not needed in this case, only calling because this
* function corrects bpy.data (internal Main pointer) */
BPY_modules_update(C);
/* needed for when WM_OT_read_factory_settings us called from within a script */
bpy_import_main_set(CTX_data_main(C));
/* return operator_ret as a bpy enum */
return pyrna_enum_bitfield_to_py(rna_enum_operator_return_items, operator_ret);
/* needed for when WM_OT_read_factory_settings us called from within a script */
bpy_import_main_set(CTX_data_main(C));
/* return operator_ret as a bpy enum */
return pyrna_enum_bitfield_to_py(rna_enum_operator_return_items, operator_ret);
}
static PyObject *pyop_as_string(PyObject *UNUSED(self), PyObject *args)
{
wmOperatorType *ot;
PointerRNA ptr;
wmOperatorType *ot;
PointerRNA ptr;
const char *opname;
PyObject *kw = NULL; /* optional args */
bool all_args = true;
bool macro_args = true;
int error_val = 0;
const char *opname;
PyObject *kw = NULL; /* optional args */
bool all_args = true;
bool macro_args = true;
int error_val = 0;
char *buf = NULL;
PyObject *pybuf;
char *buf = NULL;
PyObject *pybuf;
bContext *C = (bContext *)BPy_GetContext();
bContext *C = (bContext *)BPy_GetContext();
if (C == NULL) {
PyErr_SetString(PyExc_RuntimeError, "Context is None, cant get the string representation of this object.");
return NULL;
}
if (C == NULL) {
PyErr_SetString(PyExc_RuntimeError,
"Context is None, cant get the string representation of this object.");
return NULL;
}
if (!PyArg_ParseTuple(
args, "s|O!O&O&:_bpy.ops.as_string",
&opname, &PyDict_Type, &kw,
PyC_ParseBool, &all_args,
PyC_ParseBool, &macro_args))
{
return NULL;
}
if (!PyArg_ParseTuple(args,
"s|O!O&O&:_bpy.ops.as_string",
&opname,
&PyDict_Type,
&kw,
PyC_ParseBool,
&all_args,
PyC_ParseBool,
&macro_args)) {
return NULL;
}
ot = WM_operatortype_find(opname, true);
ot = WM_operatortype_find(opname, true);
if (ot == NULL) {
PyErr_Format(PyExc_AttributeError,
"_bpy.ops.as_string: operator \"%.200s\" "
"could not be found", opname);
return NULL;
}
if (ot == NULL) {
PyErr_Format(PyExc_AttributeError,
"_bpy.ops.as_string: operator \"%.200s\" "
"could not be found",
opname);
return NULL;
}
/* WM_operator_properties_create(&ptr, opname); */
/* Save another lookup */
RNA_pointer_create(NULL, ot->srna, NULL, &ptr);
/* WM_operator_properties_create(&ptr, opname); */
/* Save another lookup */
RNA_pointer_create(NULL, ot->srna, NULL, &ptr);
if (kw && PyDict_Size(kw)) {
error_val = pyrna_pydict_to_props(&ptr, kw, false, "Converting py args to operator properties: ");
}
if (kw && PyDict_Size(kw)) {
error_val = pyrna_pydict_to_props(
&ptr, kw, false, "Converting py args to operator properties: ");
}
if (error_val == 0) {
buf = WM_operator_pystring_ex(C, NULL, all_args, macro_args, ot, &ptr);
}
if (error_val == 0) {
buf = WM_operator_pystring_ex(C, NULL, all_args, macro_args, ot, &ptr);
}
WM_operator_properties_free(&ptr);
WM_operator_properties_free(&ptr);
if (error_val == -1) {
return NULL;
}
if (error_val == -1) {
return NULL;
}
if (buf) {
pybuf = PyUnicode_FromString(buf);
MEM_freeN(buf);
}
else {
pybuf = PyUnicode_FromString("");
}
if (buf) {
pybuf = PyUnicode_FromString(buf);
MEM_freeN(buf);
}
else {
pybuf = PyUnicode_FromString("");
}
return pybuf;
return pybuf;
}
static PyObject *pyop_dir(PyObject *UNUSED(self))
{
GHashIterator iter;
PyObject *list;
int i;
GHashIterator iter;
PyObject *list;
int i;
WM_operatortype_iter(&iter);
list = PyList_New(BLI_ghash_len(iter.gh));
WM_operatortype_iter(&iter);
list = PyList_New(BLI_ghash_len(iter.gh));
for (i = 0; !BLI_ghashIterator_done(&iter); BLI_ghashIterator_step(&iter), i++) {
wmOperatorType *ot = BLI_ghashIterator_getValue(&iter);
PyList_SET_ITEM(list, i, PyUnicode_FromString(ot->idname));
}
for (i = 0; !BLI_ghashIterator_done(&iter); BLI_ghashIterator_step(&iter), i++) {
wmOperatorType *ot = BLI_ghashIterator_getValue(&iter);
PyList_SET_ITEM(list, i, PyUnicode_FromString(ot->idname));
}
return list;
return list;
}
static PyObject *pyop_getrna_type(PyObject *UNUSED(self), PyObject *value)
{
wmOperatorType *ot;
if ((ot = ot_lookup_from_py_string(value, "get_rna_type")) == NULL) {
return NULL;
}
wmOperatorType *ot;
if ((ot = ot_lookup_from_py_string(value, "get_rna_type")) == NULL) {
return NULL;
}
PointerRNA ptr;
RNA_pointer_create(NULL, &RNA_Struct, ot->srna, &ptr);
BPy_StructRNA *pyrna = (BPy_StructRNA *)pyrna_struct_CreatePyObject(&ptr);
return (PyObject *)pyrna;
PointerRNA ptr;
RNA_pointer_create(NULL, &RNA_Struct, ot->srna, &ptr);
BPy_StructRNA *pyrna = (BPy_StructRNA *)pyrna_struct_CreatePyObject(&ptr);
return (PyObject *)pyrna;
}
static struct PyMethodDef bpy_ops_methods[] = {
{"poll", (PyCFunction) pyop_poll, METH_VARARGS, NULL},
{"call", (PyCFunction) pyop_call, METH_VARARGS, NULL},
{"as_string", (PyCFunction) pyop_as_string, METH_VARARGS, NULL},
{"dir", (PyCFunction) pyop_dir, METH_NOARGS, NULL},
{"get_rna_type", (PyCFunction) pyop_getrna_type, METH_O, NULL},
{"macro_define", (PyCFunction) PYOP_wrap_macro_define, METH_VARARGS, NULL},
{NULL, NULL, 0, NULL},
{"poll", (PyCFunction)pyop_poll, METH_VARARGS, NULL},
{"call", (PyCFunction)pyop_call, METH_VARARGS, NULL},
{"as_string", (PyCFunction)pyop_as_string, METH_VARARGS, NULL},
{"dir", (PyCFunction)pyop_dir, METH_NOARGS, NULL},
{"get_rna_type", (PyCFunction)pyop_getrna_type, METH_O, NULL},
{"macro_define", (PyCFunction)PYOP_wrap_macro_define, METH_VARARGS, NULL},
{NULL, NULL, 0, NULL},
};
static struct PyModuleDef bpy_ops_module = {
PyModuleDef_HEAD_INIT,
"_bpy.ops",
NULL,
-1, /* multiple "initialization" just copies the module dict. */
bpy_ops_methods,
NULL, NULL, NULL, NULL,
PyModuleDef_HEAD_INIT,
"_bpy.ops",
NULL,
-1, /* multiple "initialization" just copies the module dict. */
bpy_ops_methods,
NULL,
NULL,
NULL,
NULL,
};
PyObject *BPY_operator_module(void)
{
PyObject *submodule;
PyObject *submodule;
submodule = PyModule_Create(&bpy_ops_module);
submodule = PyModule_Create(&bpy_ops_module);
return submodule;
return submodule;
}

View File

@@ -23,10 +23,10 @@
extern PyTypeObject pyop_base_Type;
#define BPy_OperatorBase_Check(v) (PyObject_TypeCheck(v, &pyop_base_Type))
#define BPy_OperatorBase_Check(v) (PyObject_TypeCheck(v, &pyop_base_Type))
typedef struct {
PyObject_HEAD /* required python macro */
PyObject_HEAD /* required python macro */
} BPy_OperatorBase;
PyObject *BPY_operator_module(void);

View File

@@ -35,163 +35,158 @@
#include "bpy_rna.h"
#include "bpy_intern_string.h"
#include "bpy_operator_wrap.h" /* own include */
#include "bpy_operator_wrap.h" /* own include */
static void operator_properties_init(wmOperatorType *ot)
{
PyTypeObject *py_class = ot->ext.data;
RNA_struct_blender_type_set(ot->ext.srna, ot);
PyTypeObject *py_class = ot->ext.data;
RNA_struct_blender_type_set(ot->ext.srna, ot);
/* Only call this so pyrna_deferred_register_class gives a useful error
* WM_operatortype_append_ptr will call RNA_def_struct_identifier later.
*
* Note the 'no_struct_map' function is used since the actual struct name is already used by the operator.
*/
RNA_def_struct_identifier_no_struct_map(ot->srna, ot->idname);
/* Only call this so pyrna_deferred_register_class gives a useful error
* WM_operatortype_append_ptr will call RNA_def_struct_identifier later.
*
* Note the 'no_struct_map' function is used since the actual struct name is already used by the operator.
*/
RNA_def_struct_identifier_no_struct_map(ot->srna, ot->idname);
if (pyrna_deferred_register_class(ot->srna, py_class) != 0) {
PyErr_Print(); /* failed to register operator props */
PyErr_Clear();
}
if (pyrna_deferred_register_class(ot->srna, py_class) != 0) {
PyErr_Print(); /* failed to register operator props */
PyErr_Clear();
}
/* set the default property: ot->prop */
{
/* picky developers will notice that 'bl_property' won't work with inheritance
* get direct from the dict to avoid raising a load of attribute errors (yes this isnt ideal) - campbell */
PyObject *py_class_dict = py_class->tp_dict;
PyObject *bl_property = PyDict_GetItem(py_class_dict, bpy_intern_str_bl_property);
const char *prop_id;
bool prop_raise_error;
/* set the default property: ot->prop */
{
/* picky developers will notice that 'bl_property' won't work with inheritance
* get direct from the dict to avoid raising a load of attribute errors (yes this isnt ideal) - campbell */
PyObject *py_class_dict = py_class->tp_dict;
PyObject *bl_property = PyDict_GetItem(py_class_dict, bpy_intern_str_bl_property);
const char *prop_id;
bool prop_raise_error;
if (bl_property) {
if (PyUnicode_Check(bl_property)) {
/* since the property is explicitly given, raise an error if its not found */
prop_id = _PyUnicode_AsString(bl_property);
prop_raise_error = true;
}
else {
PyErr_Format(PyExc_ValueError,
"%.200s.bl_property should be a string, not %.200s",
ot->idname, Py_TYPE(bl_property)->tp_name);
if (bl_property) {
if (PyUnicode_Check(bl_property)) {
/* since the property is explicitly given, raise an error if its not found */
prop_id = _PyUnicode_AsString(bl_property);
prop_raise_error = true;
}
else {
PyErr_Format(PyExc_ValueError,
"%.200s.bl_property should be a string, not %.200s",
ot->idname,
Py_TYPE(bl_property)->tp_name);
/* this could be done cleaner, for now its OK */
PyErr_Print();
PyErr_Clear();
/* this could be done cleaner, for now its OK */
PyErr_Print();
PyErr_Clear();
prop_id = NULL;
prop_raise_error = false;
}
}
else {
/* fallback to hard-coded string (pre 2.66, could be deprecated) */
prop_id = "type";
prop_raise_error = false;
}
prop_id = NULL;
prop_raise_error = false;
}
}
else {
/* fallback to hard-coded string (pre 2.66, could be deprecated) */
prop_id = "type";
prop_raise_error = false;
}
if (prop_id) {
PointerRNA ptr;
PropertyRNA *prop;
if (prop_id) {
PointerRNA ptr;
PropertyRNA *prop;
RNA_pointer_create(NULL, ot->srna, NULL, &ptr);
prop = RNA_struct_find_property(&ptr, prop_id);
if (prop) {
ot->prop = prop;
}
else {
if (prop_raise_error) {
PyErr_Format(PyExc_ValueError,
"%.200s.bl_property '%.200s' not found",
ot->idname, prop_id);
/* this could be done cleaner, for now its OK */
PyErr_Print();
PyErr_Clear();
}
}
}
}
/* end 'ot->prop' assignment */
RNA_pointer_create(NULL, ot->srna, NULL, &ptr);
prop = RNA_struct_find_property(&ptr, prop_id);
if (prop) {
ot->prop = prop;
}
else {
if (prop_raise_error) {
PyErr_Format(
PyExc_ValueError, "%.200s.bl_property '%.200s' not found", ot->idname, prop_id);
/* this could be done cleaner, for now its OK */
PyErr_Print();
PyErr_Clear();
}
}
}
}
/* end 'ot->prop' assignment */
}
void BPY_RNA_operator_wrapper(wmOperatorType *ot, void *userdata)
{
/* take care not to overwrite anything set in
* WM_operatortype_append_ptr before opfunc() is called */
StructRNA *srna = ot->srna;
*ot = *((wmOperatorType *)userdata);
ot->srna = srna; /* restore */
/* take care not to overwrite anything set in
* WM_operatortype_append_ptr before opfunc() is called */
StructRNA *srna = ot->srna;
*ot = *((wmOperatorType *)userdata);
ot->srna = srna; /* restore */
/* Use i18n context from ext.srna if possible (py operators). */
if (ot->ext.srna) {
RNA_def_struct_translation_context(ot->srna, RNA_struct_translation_context(ot->ext.srna));
}
/* Use i18n context from ext.srna if possible (py operators). */
if (ot->ext.srna) {
RNA_def_struct_translation_context(ot->srna, RNA_struct_translation_context(ot->ext.srna));
}
operator_properties_init(ot);
operator_properties_init(ot);
}
void BPY_RNA_operator_macro_wrapper(wmOperatorType *ot, void *userdata)
{
wmOperatorType *data = (wmOperatorType *)userdata;
wmOperatorType *data = (wmOperatorType *)userdata;
/* only copy a couple of things, the rest is set by the macro registration */
ot->name = data->name;
ot->idname = data->idname;
ot->description = data->description;
ot->flag |= data->flag; /* append flags to the one set by registration */
ot->pyop_poll = data->pyop_poll;
ot->ui = data->ui;
ot->ext = data->ext;
/* only copy a couple of things, the rest is set by the macro registration */
ot->name = data->name;
ot->idname = data->idname;
ot->description = data->description;
ot->flag |= data->flag; /* append flags to the one set by registration */
ot->pyop_poll = data->pyop_poll;
ot->ui = data->ui;
ot->ext = data->ext;
/* Use i18n context from ext.srna if possible (py operators). */
if (ot->ext.srna) {
RNA_def_struct_translation_context(ot->srna, RNA_struct_translation_context(ot->ext.srna));
}
/* Use i18n context from ext.srna if possible (py operators). */
if (ot->ext.srna) {
RNA_def_struct_translation_context(ot->srna, RNA_struct_translation_context(ot->ext.srna));
}
operator_properties_init(ot);
operator_properties_init(ot);
}
PyObject *PYOP_wrap_macro_define(PyObject *UNUSED(self), PyObject *args)
{
wmOperatorType *ot;
wmOperatorTypeMacro *otmacro;
PyObject *macro;
PointerRNA ptr_otmacro;
StructRNA *srna;
wmOperatorType *ot;
wmOperatorTypeMacro *otmacro;
PyObject *macro;
PointerRNA ptr_otmacro;
StructRNA *srna;
const char *opname;
const char *macroname;
const char *opname;
const char *macroname;
if (!PyArg_ParseTuple(args, "Os:_bpy.ops.macro_define", &macro, &opname)) {
return NULL;
}
if (!PyArg_ParseTuple(args, "Os:_bpy.ops.macro_define", &macro, &opname)) {
return NULL;
}
if (WM_operatortype_find(opname, true) == NULL) {
PyErr_Format(PyExc_ValueError,
"Macro Define: '%s' is not a valid operator id",
opname);
return NULL;
}
if (WM_operatortype_find(opname, true) == NULL) {
PyErr_Format(PyExc_ValueError, "Macro Define: '%s' is not a valid operator id", opname);
return NULL;
}
/* identifiers */
srna = pyrna_struct_as_srna((PyObject *)macro, false, "Macro Define:");
if (srna == NULL) {
return NULL;
}
/* identifiers */
srna = pyrna_struct_as_srna((PyObject *)macro, false, "Macro Define:");
if (srna == NULL) {
return NULL;
}
macroname = RNA_struct_identifier(srna);
ot = WM_operatortype_find(macroname, true);
macroname = RNA_struct_identifier(srna);
ot = WM_operatortype_find(macroname, true);
if (!ot) {
PyErr_Format(PyExc_ValueError,
"Macro Define: '%s' is not a valid macro",
macroname);
return NULL;
}
if (!ot) {
PyErr_Format(PyExc_ValueError, "Macro Define: '%s' is not a valid macro", macroname);
return NULL;
}
otmacro = WM_operatortype_macro_define(ot, opname);
otmacro = WM_operatortype_macro_define(ot, opname);
RNA_pointer_create(NULL, &RNA_OperatorMacro, otmacro, &ptr_otmacro);
RNA_pointer_create(NULL, &RNA_OperatorMacro, otmacro, &ptr_otmacro);
return pyrna_struct_CreatePyObject(&ptr_otmacro);
return pyrna_struct_CreatePyObject(&ptr_otmacro);
}

View File

@@ -35,26 +35,26 @@ extern const char *imb_ext_audio[];
/*----------------------------MODULE INIT-------------------------*/
static struct PyModuleDef _bpy_path_module_def = {
PyModuleDef_HEAD_INIT,
"_bpy_path", /* m_name */
NULL, /* m_doc */
0, /* m_size */
NULL, /* m_methods */
NULL, /* m_reload */
NULL, /* m_traverse */
NULL, /* m_clear */
NULL, /* m_free */
PyModuleDef_HEAD_INIT,
"_bpy_path", /* m_name */
NULL, /* m_doc */
0, /* m_size */
NULL, /* m_methods */
NULL, /* m_reload */
NULL, /* m_traverse */
NULL, /* m_clear */
NULL, /* m_free */
};
PyObject *BPyInit__bpy_path(void)
{
PyObject *submodule;
PyObject *submodule;
submodule = PyModule_Create(&_bpy_path_module_def);
submodule = PyModule_Create(&_bpy_path_module_def);
PyModule_AddObject(submodule, "extensions_image", PyC_FrozenSetFromStrings(imb_ext_image));
PyModule_AddObject(submodule, "extensions_movie", PyC_FrozenSetFromStrings(imb_ext_movie));
PyModule_AddObject(submodule, "extensions_audio", PyC_FrozenSetFromStrings(imb_ext_audio));
PyModule_AddObject(submodule, "extensions_image", PyC_FrozenSetFromStrings(imb_ext_image));
PyModule_AddObject(submodule, "extensions_movie", PyC_FrozenSetFromStrings(imb_ext_movie));
PyModule_AddObject(submodule, "extensions_audio", PyC_FrozenSetFromStrings(imb_ext_audio));
return submodule;
return submodule;
}

View File

@@ -18,7 +18,6 @@
* \ingroup pythonintern
*/
#ifndef __BPY_PATH_H__
#define __BPY_PATH_H__

File diff suppressed because it is too large Load Diff

View File

@@ -18,7 +18,6 @@
* \ingroup pythonintern
*/
#ifndef __BPY_PROPS_H__
#define __BPY_PROPS_H__

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