Welcome to mirror list, hosted at ThFree Co, Russian Federation.

git.blender.org/blender.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
Diffstat (limited to 'source/blender/python')
-rw-r--r--source/blender/python/BPY_extern.h3
-rw-r--r--source/blender/python/CMakeLists.txt1
-rw-r--r--source/blender/python/bmesh/CMakeLists.txt1
-rw-r--r--source/blender/python/bmesh/bmesh_py_api.c23
-rw-r--r--source/blender/python/bmesh/bmesh_py_ops.c25
-rw-r--r--source/blender/python/bmesh/bmesh_py_ops_call.c46
-rw-r--r--source/blender/python/bmesh/bmesh_py_types.c92
-rw-r--r--source/blender/python/bmesh/bmesh_py_types_customdata.c21
-rw-r--r--source/blender/python/bmesh/bmesh_py_types_meshdata.c92
-rw-r--r--source/blender/python/bmesh/bmesh_py_types_meshdata.h4
-rw-r--r--source/blender/python/generic/bgl.c1695
-rw-r--r--source/blender/python/generic/blf_py_api.c39
-rw-r--r--source/blender/python/generic/bpy_internal_import.c12
-rw-r--r--source/blender/python/generic/bpy_internal_import.h5
-rw-r--r--source/blender/python/generic/idprop_py_api.c28
-rw-r--r--source/blender/python/generic/py_capi_utils.c106
-rw-r--r--source/blender/python/generic/py_capi_utils.h12
-rw-r--r--source/blender/python/gpu/CMakeLists.txt62
-rw-r--r--source/blender/python/gpu/gpu_py_api.c165
-rw-r--r--source/blender/python/gpu/gpu_py_api.h37
-rw-r--r--source/blender/python/gpu/gpu_py_batch.c386
-rw-r--r--source/blender/python/gpu/gpu_py_batch.h48
-rw-r--r--source/blender/python/gpu/gpu_py_element.c244
-rw-r--r--source/blender/python/gpu/gpu_py_element.h39
-rw-r--r--source/blender/python/gpu/gpu_py_matrix.c575
-rw-r--r--source/blender/python/gpu/gpu_py_matrix.h30
-rw-r--r--source/blender/python/gpu/gpu_py_offscreen.c374
-rw-r--r--source/blender/python/gpu/gpu_py_offscreen.h42
-rw-r--r--source/blender/python/gpu/gpu_py_select.c95
-rw-r--r--source/blender/python/gpu/gpu_py_select.h30
-rw-r--r--source/blender/python/gpu/gpu_py_shader.c839
-rw-r--r--source/blender/python/gpu/gpu_py_shader.h41
-rw-r--r--source/blender/python/gpu/gpu_py_types.c80
-rw-r--r--source/blender/python/gpu/gpu_py_types.h37
-rw-r--r--source/blender/python/gpu/gpu_py_vertex_buffer.c352
-rw-r--r--source/blender/python/gpu/gpu_py_vertex_buffer.h42
-rw-r--r--source/blender/python/gpu/gpu_py_vertex_format.c263
-rw-r--r--source/blender/python/gpu/gpu_py_vertex_format.h41
-rw-r--r--source/blender/python/intern/CMakeLists.txt25
-rw-r--r--source/blender/python/intern/bpy.c8
-rw-r--r--source/blender/python/intern/bpy_app.c48
-rw-r--r--source/blender/python/intern/bpy_app_build_options.c21
-rw-r--r--source/blender/python/intern/bpy_app_handlers.c49
-rw-r--r--source/blender/python/intern/bpy_app_icons.c187
-rw-r--r--source/blender/python/intern/bpy_app_icons.h30
-rw-r--r--source/blender/python/intern/bpy_app_timers.c199
-rw-r--r--source/blender/python/intern/bpy_app_timers.h30
-rw-r--r--source/blender/python/intern/bpy_driver.c50
-rw-r--r--source/blender/python/intern/bpy_driver.h7
-rw-r--r--source/blender/python/intern/bpy_gizmo_wrap.c228
-rw-r--r--source/blender/python/intern/bpy_gizmo_wrap.h35
-rw-r--r--source/blender/python/intern/bpy_interface.c11
-rw-r--r--source/blender/python/intern/bpy_intern_string.c48
-rw-r--r--source/blender/python/intern/bpy_intern_string.h23
-rw-r--r--source/blender/python/intern/bpy_library_load.c19
-rw-r--r--source/blender/python/intern/bpy_library_write.c3
-rw-r--r--source/blender/python/intern/bpy_msgbus.c399
-rw-r--r--source/blender/python/intern/bpy_msgbus.h30
-rw-r--r--source/blender/python/intern/bpy_props.c14
-rw-r--r--source/blender/python/intern/bpy_props.h2
-rw-r--r--source/blender/python/intern/bpy_rna.c302
-rw-r--r--source/blender/python/intern/bpy_rna.h4
-rw-r--r--source/blender/python/intern/bpy_rna_anim.c188
-rw-r--r--source/blender/python/intern/bpy_rna_callback.c197
-rw-r--r--source/blender/python/intern/bpy_rna_gizmo.c564
-rw-r--r--source/blender/python/intern/bpy_rna_gizmo.h (renamed from source/blender/python/intern/gpu.h)21
-rw-r--r--source/blender/python/intern/bpy_rna_id_collection.c84
-rw-r--r--source/blender/python/intern/bpy_utils_units.c1
-rw-r--r--source/blender/python/intern/gpu.c342
-rw-r--r--source/blender/python/intern/gpu_offscreen.c408
-rw-r--r--source/blender/python/mathutils/CMakeLists.txt1
-rw-r--r--source/blender/python/mathutils/mathutils.c5
-rw-r--r--source/blender/python/mathutils/mathutils.h2
-rw-r--r--source/blender/python/mathutils/mathutils_Matrix.c187
-rw-r--r--source/blender/python/mathutils/mathutils_Quaternion.c135
-rw-r--r--source/blender/python/mathutils/mathutils_Vector.c164
-rw-r--r--source/blender/python/mathutils/mathutils_bvhtree.c95
-rw-r--r--source/blender/python/mathutils/mathutils_noise.c565
-rw-r--r--source/blender/python/mathutils/mathutils_noise.h2
-rw-r--r--source/blender/python/simple_enum_gen.py2
80 files changed, 7715 insertions, 3047 deletions
diff --git a/source/blender/python/BPY_extern.h b/source/blender/python/BPY_extern.h
index 955b1c4e4ed..5a2f15405c1 100644
--- a/source/blender/python/BPY_extern.h
+++ b/source/blender/python/BPY_extern.h
@@ -90,7 +90,8 @@ void BPY_modules_load_user(struct bContext *C);
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, const float evaltime);
+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);
diff --git a/source/blender/python/CMakeLists.txt b/source/blender/python/CMakeLists.txt
index e855f3a3756..030576fefd1 100644
--- a/source/blender/python/CMakeLists.txt
+++ b/source/blender/python/CMakeLists.txt
@@ -18,5 +18,6 @@
add_subdirectory(intern)
add_subdirectory(generic)
+add_subdirectory(gpu)
add_subdirectory(mathutils)
add_subdirectory(bmesh)
diff --git a/source/blender/python/bmesh/CMakeLists.txt b/source/blender/python/bmesh/CMakeLists.txt
index 3b38fead7b9..48213b7eed5 100644
--- a/source/blender/python/bmesh/CMakeLists.txt
+++ b/source/blender/python/bmesh/CMakeLists.txt
@@ -23,6 +23,7 @@ set(INC
../../bmesh
../../blenkernel
../../blenlib
+ ../../depsgraph
../../makesdna
../../../../intern/guardedalloc
)
diff --git a/source/blender/python/bmesh/bmesh_py_api.c b/source/blender/python/bmesh/bmesh_py_api.c
index 5819d7ce2bb..012f7b1232d 100644
--- a/source/blender/python/bmesh/bmesh_py_api.c
+++ b/source/blender/python/bmesh/bmesh_py_api.c
@@ -113,30 +113,30 @@ static PyObject *bpy_bm_from_edit_mesh(PyObject *UNUSED(self), PyObject *value)
}
PyDoc_STRVAR(bpy_bm_update_edit_mesh_doc,
-".. method:: update_edit_mesh(mesh, tessface=True, destructive=True)\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 tessface: Option to recalculate n-gon tessellation.\n"
-" :type tessface: boolean\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", "tessface", "destructive", NULL};
+ static const char *kwlist[] = {"mesh", "loop_triangles", "destructive", NULL};
PyObject *py_me;
Mesh *me;
- bool do_tessface = true;
+ 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_tessface,
+ PyC_ParseBool, &do_loop_triangles,
PyC_ParseBool, &is_destructive))
{
return NULL;
@@ -156,13 +156,8 @@ static PyObject *bpy_bm_update_edit_mesh(PyObject *UNUSED(self), PyObject *args,
{
extern void EDBM_update_generic(BMEditMesh *em, const bool do_tessface, const bool is_destructive);
- BMEditMesh *em = me->edit_btmesh;
- BMesh *bm = em->bm;
- /* python won't ensure matching uv/mtex */
- BM_mesh_cd_validate(bm);
-
- EDBM_update_generic(me->edit_btmesh, do_tessface, is_destructive);
+ EDBM_update_generic(me->edit_btmesh, do_loop_triangles, is_destructive);
}
Py_RETURN_NONE;
@@ -208,21 +203,17 @@ PyObject *BPyInit_bmesh(void)
/* bmesh.types */
PyModule_AddObject(mod, "types", (submodule = BPyInit_bmesh_types()));
PyDict_SetItem(sys_modules, PyModule_GetNameObject(submodule), submodule);
- Py_INCREF(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 */
- Py_INCREF(submodule);
PyModule_AddObject(mod, "utils", (submodule = BPyInit_bmesh_utils()));
PyDict_SetItem(sys_modules, PyModule_GetNameObject(submodule), submodule);
- Py_INCREF(submodule);
PyModule_AddObject(mod, "geometry", (submodule = BPyInit_bmesh_geometry()));
PyDict_SetItem(sys_modules, PyModule_GetNameObject(submodule), submodule);
- Py_INCREF(submodule);
return mod;
}
diff --git a/source/blender/python/bmesh/bmesh_py_ops.c b/source/blender/python/bmesh/bmesh_py_ops.c
index ee96c859858..49e71da3bc3 100644
--- a/source/blender/python/bmesh/bmesh_py_ops.c
+++ b/source/blender/python/bmesh/bmesh_py_ops.c
@@ -75,10 +75,14 @@ static char *bmp_slots_as_args(const BMOSlotType slot_types[BMO_OP_MAX_SLOTS], c
{
DynStr *dyn_str = BLI_dynstr_new();
char *ret;
+ bool quoted;
+ bool set;
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) :
@@ -86,7 +90,19 @@ static char *bmp_slots_as_args(const BMOSlotType slot_types[BMO_OP_MAX_SLOTS], c
const char *value = "<Unknown>";
switch (slot_types[i].type) {
case BMO_OP_SLOT_BOOL: value = "False"; break;
- case BMO_OP_SLOT_INT: value = "0"; 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;
@@ -95,7 +111,12 @@ static char *bmp_slots_as_args(const BMOSlotType slot_types[BMO_OP_MAX_SLOTS], c
(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", name_len, slot_types[i].name, value);
+ 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++;
}
diff --git a/source/blender/python/bmesh/bmesh_py_ops_call.c b/source/blender/python/bmesh/bmesh_py_ops_call.c
index 14e14cd5fe3..ac328e852ac 100644
--- a/source/blender/python/bmesh/bmesh_py_ops_call.c
+++ b/source/blender/python/bmesh/bmesh_py_ops_call.c
@@ -46,6 +46,8 @@
#include "../generic/python_utildefines.h"
#include "../generic/py_capi_utils.h"
+BLI_STATIC_ASSERT(sizeof(PyC_FlagSet) == sizeof(BMO_FlagSet), "size mismatch");
+
static int bpy_bm_op_as_py_error(BMesh *bm)
{
if (BMO_error_occurred(bm)) {
@@ -169,16 +171,46 @@ static int bpy_slot_from_py(
}
case BMO_OP_SLOT_INT:
{
- const int param = PyC_Long_AsI32(value);
+ if (slot->slot_subtype.intg == BMO_OP_SLOT_SUBTYPE_INT_ENUM) {
+ int enum_val = -1;
+ PyC_FlagSet *items = (PyC_FlagSet *)slot->data.enum_flags;
+ const char *enum_str = _PyUnicode_AsString(value);
- if (param == -1 && PyErr_Occurred()) {
- PyErr_Format(PyExc_TypeError,
- "%.200s: keyword \"%.200s\" expected an int, not %.200s",
- opname, slot_name, Py_TYPE(value)->tp_name);
- return -1;
+ if (enum_str == NULL) {
+ PyErr_Format(PyExc_TypeError,
+ "%.200s: keyword \"%.200s\" expected a string, not %.200s",
+ opname, slot_name, Py_TYPE(value)->tp_name);
+ return -1;
+ }
+
+ if (PyC_FlagSet_ValueFromID(items, enum_str, &enum_val, slot_name) == -1) {
+ return -1;
+ }
+
+ BMO_SLOT_AS_INT(slot) = enum_val;
+ }
+ else if (slot->slot_subtype.intg == BMO_OP_SLOT_SUBTYPE_INT_FLAG) {
+ int flag = 0;
+ PyC_FlagSet *items = (PyC_FlagSet *)slot->data.enum_flags;
+
+ if (PyC_FlagSet_ToBitfield(items, value, &flag, slot_name) == -1) {
+ return -1;
+ }
+
+ BMO_SLOT_AS_INT(slot) = flag;
}
else {
- BMO_SLOT_AS_INT(slot) = param;
+ const int param = PyC_Long_AsI32(value);
+
+ if (param == -1 && PyErr_Occurred()) {
+ PyErr_Format(PyExc_TypeError,
+ "%.200s: keyword \"%.200s\" expected an int, not %.200s",
+ opname, slot_name, Py_TYPE(value)->tp_name);
+ return -1;
+ }
+ else {
+ BMO_SLOT_AS_INT(slot) = param;
+ }
}
break;
}
diff --git a/source/blender/python/bmesh/bmesh_py_types.c b/source/blender/python/bmesh/bmesh_py_types.c
index 21239f7494a..d18f660197d 100644
--- a/source/blender/python/bmesh/bmesh_py_types.c
+++ b/source/blender/python/bmesh/bmesh_py_types.c
@@ -34,11 +34,13 @@
#include "DNA_object_types.h"
#include "DNA_material_types.h"
-#include "BKE_depsgraph.h"
#include "BKE_customdata.h"
-#include "BKE_DerivedMesh.h"
#include "BKE_global.h"
#include "BKE_library.h"
+#include "BKE_mesh_runtime.h"
+
+#include "DEG_depsgraph.h"
+#include "DEG_depsgraph_query.h"
#include "bmesh.h"
@@ -903,10 +905,7 @@ static PyObject *bpy_bmesh_to_mesh(BPy_BMesh *self, PyObject *args)
bm = self->bm;
- /* python won't ensure matching uv/mtex */
- BM_mesh_cd_validate(bm);
-
- BLI_assert(BKE_id_is_in_gobal_main(&me->id));
+ BLI_assert(BKE_id_is_in_global_main(&me->id));
BM_mesh_bm_to_me(
G_MAIN, /* XXX UGLY! */
bm, me,
@@ -916,13 +915,13 @@ static PyObject *bpy_bmesh_to_mesh(BPy_BMesh *self, PyObject *args)
/* we could have the user do this but if they forget blender can easy crash
* since the references arrays for the objects derived meshes are now invalid */
- DAG_id_tag_update(&me->id, OB_RECALC_DATA);
+ DEG_id_tag_update(&me->id, ID_RECALC_GEOMETRY);
Py_RETURN_NONE;
}
PyDoc_STRVAR(bpy_bmesh_from_object_doc,
-".. method:: from_object(object, scene, deform=True, render=False, cage=False, face_normals=True)\n"
+".. method:: from_object(object, depsgraph, deform=True, cage=False, face_normals=True)\n"
"\n"
" Initialize this bmesh from existing object datablock (currently only meshes are supported).\n"
"\n"
@@ -930,8 +929,6 @@ PyDoc_STRVAR(bpy_bmesh_from_object_doc,
" :type object: :class:`Object`\n"
" :arg deform: Apply deformation modifiers.\n"
" :type deform: boolean\n"
-" :arg render: Use render settings.\n"
-" :type render: boolean\n"
" :arg cage: Get the mesh as a deformed cage.\n"
" :type cage: boolean\n"
" :arg face_normals: Calculate face normals.\n"
@@ -939,30 +936,29 @@ PyDoc_STRVAR(bpy_bmesh_from_object_doc,
);
static PyObject *bpy_bmesh_from_object(BPy_BMesh *self, PyObject *args, PyObject *kw)
{
- static const char *kwlist[] = {"object", "scene", "deform", "render", "cage", "face_normals", NULL};
+ static const char *kwlist[] = {"object", "depsgraph", "deform", "cage", "face_normals", NULL};
PyObject *py_object;
- PyObject *py_scene;
- Object *ob;
- struct Scene *scene;
+ PyObject *py_depsgraph;
+ Object *ob, *ob_eval;
+ struct Depsgraph *depsgraph;
+ struct Scene *scene_eval;
+ Mesh *me_eval;
BMesh *bm;
bool use_deform = true;
- bool use_render = false;
bool use_cage = false;
bool use_fnorm = true;
- DerivedMesh *dm;
const int mask = CD_MASK_BMESH;
BPY_BM_CHECK_OBJ(self);
if (!PyArg_ParseTupleAndKeywords(
- args, kw, "OO|O&O&O&O&:from_object", (char **)kwlist,
- &py_object, &py_scene,
+ args, kw, "OO|O&O&O&:from_object", (char **)kwlist,
+ &py_object, &py_depsgraph,
PyC_ParseBool, &use_deform,
- PyC_ParseBool, &use_render,
PyC_ParseBool, &use_cage,
PyC_ParseBool, &use_fnorm) ||
- !(ob = PyC_RNA_AsPointer(py_object, "Object")) ||
- !(scene = PyC_RNA_AsPointer(py_scene, "Scene")))
+ !(ob = PyC_RNA_AsPointer(py_object, "Object")) ||
+ !(depsgraph = PyC_RNA_AsPointer(py_depsgraph, "Depsgraph")))
{
return NULL;
}
@@ -973,52 +969,47 @@ static PyObject *bpy_bmesh_from_object(BPy_BMesh *self, PyObject *args, PyObject
return NULL;
}
+ const bool use_render = DEG_get_mode(depsgraph) == DAG_EVAL_RENDER;
+ scene_eval = DEG_get_evaluated_scene(depsgraph);
+ ob_eval = DEG_get_evaluated_object(depsgraph, ob);
+
/* Write the display mesh into the dummy mesh */
if (use_deform) {
if (use_render) {
if (use_cage) {
PyErr_SetString(PyExc_ValueError,
- "from_object(...): cage arg is unsupported when (render=True)");
+ "from_object(...): cage arg is unsupported when dependency graph evaluation mode is RENDER");
return NULL;
}
else {
- dm = mesh_create_derived_render(scene, ob, mask);
+ me_eval = mesh_create_eval_final_render(depsgraph, scene_eval, ob_eval, mask);
}
}
else {
if (use_cage) {
- dm = mesh_get_derived_deform(scene, ob, mask); /* ob->derivedDeform */
+ me_eval = mesh_get_eval_deform(depsgraph, scene_eval, ob_eval, mask);
}
else {
- dm = mesh_get_derived_final(scene, ob, mask); /* ob->derivedFinal */
+ me_eval = mesh_get_eval_final(depsgraph, scene_eval, ob_eval, mask);
}
}
}
else {
/* !use_deform */
- if (use_render) {
- if (use_cage) {
- PyErr_SetString(PyExc_ValueError,
- "from_object(...): cage arg is unsupported when (render=True)");
- return NULL;
- }
- else {
- dm = mesh_create_derived_no_deform_render(scene, ob, NULL, mask);
- }
+ if (use_cage) {
+ PyErr_SetString(PyExc_ValueError,
+ "from_object(...): cage arg is unsupported when deform=False");
+ return NULL;
+ }
+ else if (use_render) {
+ me_eval = mesh_create_eval_no_deform_render(depsgraph, scene_eval, ob, NULL, mask);
}
else {
- if (use_cage) {
- PyErr_SetString(PyExc_ValueError,
- "from_object(...): cage arg is unsupported when (deform=False, render=False)");
- return NULL;
- }
- else {
- dm = mesh_create_derived_no_deform(scene, ob, NULL, mask);
- }
+ me_eval = mesh_create_eval_no_deform(depsgraph, scene_eval, ob, NULL, mask);
}
}
- if (dm == NULL) {
+ if (me_eval == NULL) {
PyErr_Format(PyExc_ValueError,
"from_object(...): Object '%s' has no usable mesh data", ob->id.name + 2);
return NULL;
@@ -1026,9 +1017,10 @@ static PyObject *bpy_bmesh_from_object(BPy_BMesh *self, PyObject *args, PyObject
bm = self->bm;
- DM_to_bmesh_ex(dm, bm, use_fnorm);
-
- dm->release(dm);
+ BM_mesh_bm_from_me(
+ bm, me_eval, (&(struct BMeshFromMeshParams){
+ .calc_face_normal = use_fnorm,
+ }));
Py_RETURN_NONE;
}
@@ -1243,15 +1235,15 @@ static PyObject *bpy_bmesh_calc_volume(BPy_BMElem *self, PyObject *args, PyObjec
}
}
-PyDoc_STRVAR(bpy_bmesh_calc_tessface_doc,
-".. method:: calc_tessface()\n"
+PyDoc_STRVAR(bpy_bmesh_calc_loop_triangles_doc,
+".. method:: calc_loop_triangles()\n"
"\n"
" Calculate triangle tessellation from quads/ngons.\n"
"\n"
" :return: The triangulated faces.\n"
" :rtype: list of :class:`BMLoop` tuples\n"
);
-static PyObject *bpy_bmesh_calc_tessface(BPy_BMElem *self)
+static PyObject *bpy_bmesh_calc_loop_triangles(BPy_BMElem *self)
{
BMesh *bm;
@@ -2730,7 +2722,7 @@ static struct PyMethodDef bpy_bmesh_methods[] = {
/* calculations */
{"calc_volume", (PyCFunction)bpy_bmesh_calc_volume, METH_VARARGS | METH_KEYWORDS, bpy_bmesh_calc_volume_doc},
- {"calc_tessface", (PyCFunction)bpy_bmesh_calc_tessface, METH_NOARGS, bpy_bmesh_calc_tessface_doc},
+ {"calc_loop_triangles", (PyCFunction)bpy_bmesh_calc_loop_triangles, METH_NOARGS, bpy_bmesh_calc_loop_triangles_doc},
{NULL, NULL, 0, NULL}
};
diff --git a/source/blender/python/bmesh/bmesh_py_types_customdata.c b/source/blender/python/bmesh/bmesh_py_types_customdata.c
index ecf5cce8bd2..f49766c93ab 100644
--- a/source/blender/python/bmesh/bmesh_py_types_customdata.c
+++ b/source/blender/python/bmesh/bmesh_py_types_customdata.c
@@ -105,9 +105,6 @@ PyDoc_STRVAR(bpy_bmlayeraccess_collection__bevel_weight_doc,
PyDoc_STRVAR(bpy_bmlayeraccess_collection__crease_doc,
"Edge crease for subsurf - float in [0 - 1].\n\n:type: :class:`BMLayerCollection`"
);
-PyDoc_STRVAR(bpy_bmlayeraccess_collection__tex_doc,
-"Accessor for :class:`BMTexPoly` layer (TODO).\n\ntype: :class:`BMLayerCollection`" // TYPE DOESN'T EXIST YET
-);
PyDoc_STRVAR(bpy_bmlayeraccess_collection__uv_doc,
"Accessor for :class:`BMLoopUV` UV (as a 2D Vector).\n\ntype: :class:`BMLayerCollection`"
);
@@ -120,6 +117,9 @@ PyDoc_STRVAR(bpy_bmlayeraccess_collection__skin_doc,
PyDoc_STRVAR(bpy_bmlayeraccess_collection__paint_mask_doc,
"Accessor for paint mask layer.\n\ntype: :class:`BMLayerCollection`"
);
+PyDoc_STRVAR(bpy_bmlayeraccess_collection__face_map_doc,
+"FaceMap custom-data layer.\n\ntype: :class:`BMLayerCollection`"
+);
#ifdef WITH_FREESTYLE
PyDoc_STRVAR(bpy_bmlayeraccess_collection__freestyle_edge_doc,
"Accessor for Freestyle edge layer.\n\ntype: :class:`BMLayerCollection`"
@@ -222,8 +222,7 @@ static PyGetSetDef bpy_bmlayeraccess_face_getseters[] = {
{(char *)"float", (getter)bpy_bmlayeraccess_collection_get, (setter)NULL, (char *)bpy_bmlayeraccess_collection__float_doc, (void *)CD_PROP_FLT},
{(char *)"int", (getter)bpy_bmlayeraccess_collection_get, (setter)NULL, (char *)bpy_bmlayeraccess_collection__int_doc, (void *)CD_PROP_INT},
{(char *)"string", (getter)bpy_bmlayeraccess_collection_get, (setter)NULL, (char *)bpy_bmlayeraccess_collection__string_doc, (void *)CD_PROP_STR},
-
- {(char *)"tex", (getter)bpy_bmlayeraccess_collection_get, (setter)NULL, (char *)bpy_bmlayeraccess_collection__tex_doc, (void *)CD_MTEXPOLY},
+ {(char *)"face_map", (getter)bpy_bmlayeraccess_collection_get, (setter)NULL, (char *)bpy_bmlayeraccess_collection__face_map_doc, (void *)CD_FACEMAP},
#ifdef WITH_FREESTYLE
{(char *)"freestyle", (getter)bpy_bmlayeraccess_collection_get, (setter)NULL, (char *)bpy_bmlayeraccess_collection__freestyle_face_doc, (void *)CD_FREESTYLE_FACE},
@@ -989,6 +988,7 @@ PyObject *BPy_BMLayerItem_GetItem(BPy_BMElem *py_ele, BPy_BMLayerItem *py_layer)
break;
}
case CD_PROP_INT:
+ case CD_FACEMAP:
{
ret = PyLong_FromLong(*(int *)value);
break;
@@ -999,11 +999,6 @@ PyObject *BPy_BMLayerItem_GetItem(BPy_BMElem *py_ele, BPy_BMLayerItem *py_layer)
ret = PyBytes_FromStringAndSize(mstring->s, mstring->s_len);
break;
}
- case CD_MTEXPOLY:
- {
- ret = BPy_BMTexPoly_CreatePyObject(value);
- break;
- }
case CD_MLOOPUV:
{
ret = BPy_BMLoopUV_CreatePyObject(value);
@@ -1074,6 +1069,7 @@ int BPy_BMLayerItem_SetItem(BPy_BMElem *py_ele, BPy_BMLayerItem *py_layer, PyObj
break;
}
case CD_PROP_INT:
+ case CD_FACEMAP:
{
int tmp_val = PyC_Long_AsI32(py_value);
if (UNLIKELY(tmp_val == -1 && PyErr_Occurred())) {
@@ -1102,11 +1098,6 @@ int BPy_BMLayerItem_SetItem(BPy_BMElem *py_ele, BPy_BMLayerItem *py_layer, PyObj
}
break;
}
- case CD_MTEXPOLY:
- {
- ret = BPy_BMTexPoly_AssignPyObject(value, py_value);
- break;
- }
case CD_MLOOPUV:
{
ret = BPy_BMLoopUV_AssignPyObject(value, py_value);
diff --git a/source/blender/python/bmesh/bmesh_py_types_meshdata.c b/source/blender/python/bmesh/bmesh_py_types_meshdata.c
index d2ea87dd03f..2a0f3817f35 100644
--- a/source/blender/python/bmesh/bmesh_py_types_meshdata.c
+++ b/source/blender/python/bmesh/bmesh_py_types_meshdata.c
@@ -42,103 +42,12 @@
#include "BLI_math_vector.h"
#include "BKE_deform.h"
-#include "BKE_library.h"
#include "bmesh_py_types_meshdata.h"
#include "../generic/py_capi_utils.h"
#include "../generic/python_utildefines.h"
-
-/* Mesh BMTexPoly
- * ************** */
-
-#define BPy_BMTexPoly_Check(v) (Py_TYPE(v) == &BPy_BMTexPoly_Type)
-
-typedef struct BPy_BMTexPoly {
- PyObject_VAR_HEAD
- MTexPoly *data;
-} BPy_BMTexPoly;
-
-extern PyObject *pyrna_id_CreatePyObject(ID *id);
-extern bool pyrna_id_FromPyObject(PyObject *obj, ID **id);
-
-PyDoc_STRVAR(bpy_bmtexpoly_image_doc,
-"Image or None.\n\n:type: :class:`bpy.types.Image`"
-);
-static PyObject *bpy_bmtexpoly_image_get(BPy_BMTexPoly *self, void *UNUSED(closure))
-{
- return pyrna_id_CreatePyObject((ID *)self->data->tpage);
-}
-
-static int bpy_bmtexpoly_image_set(BPy_BMTexPoly *self, PyObject *value, void *UNUSED(closure))
-{
- ID *id;
-
- if (value == Py_None) {
- id = NULL;
- }
- else if (pyrna_id_FromPyObject(value, &id) && id && GS(id->name) == ID_IM) {
- /* pass */
- }
- else {
- PyErr_Format(PyExc_KeyError, "BMTexPoly.image = x"
- "expected an image or None, not '%.200s'",
- Py_TYPE(value)->tp_name);
- return -1;
- }
-
- id_lib_extern(id);
- self->data->tpage = (struct Image *)id;
-
- return 0;
-}
-
-static PyGetSetDef bpy_bmtexpoly_getseters[] = {
- /* attributes match rna_def_mtpoly */
- {(char *)"image", (getter)bpy_bmtexpoly_image_get, (setter)bpy_bmtexpoly_image_set, (char *)bpy_bmtexpoly_image_doc, NULL},
-
- {NULL, NULL, NULL, NULL, NULL} /* Sentinel */
-};
-
-static PyTypeObject BPy_BMTexPoly_Type; /* bm.loops.layers.uv.active */
-
-static void bm_init_types_bmtexpoly(void)
-{
- BPy_BMTexPoly_Type.tp_basicsize = sizeof(BPy_BMTexPoly);
-
- BPy_BMTexPoly_Type.tp_name = "BMTexPoly";
-
- BPy_BMTexPoly_Type.tp_doc = NULL; // todo
-
- BPy_BMTexPoly_Type.tp_getset = bpy_bmtexpoly_getseters;
-
- BPy_BMTexPoly_Type.tp_flags = Py_TPFLAGS_DEFAULT;
-
- PyType_Ready(&BPy_BMTexPoly_Type);
-}
-
-int BPy_BMTexPoly_AssignPyObject(struct MTexPoly *mtpoly, PyObject *value)
-{
- if (UNLIKELY(!BPy_BMTexPoly_Check(value))) {
- PyErr_Format(PyExc_TypeError, "expected BMTexPoly, not a %.200s", Py_TYPE(value)->tp_name);
- return -1;
- }
- else {
- *((MTexPoly *)mtpoly) = *(((BPy_BMTexPoly *)value)->data);
- return 0;
- }
-}
-
-PyObject *BPy_BMTexPoly_CreatePyObject(struct MTexPoly *mtpoly)
-{
- BPy_BMTexPoly *self = PyObject_New(BPy_BMTexPoly, &BPy_BMTexPoly_Type);
- self->data = mtpoly;
- return (PyObject *)self;
-}
-
-/* --- End Mesh BMTexPoly --- */
-
/* Mesh Loop UV
* ************ */
@@ -797,7 +706,6 @@ PyObject *BPy_BMDeformVert_CreatePyObject(struct MDeformVert *dvert)
/* call to init all types */
void BPy_BM_init_types_meshdata(void)
{
- bm_init_types_bmtexpoly();
bm_init_types_bmloopuv();
bm_init_types_bmloopcol();
bm_init_types_bmdvert();
diff --git a/source/blender/python/bmesh/bmesh_py_types_meshdata.h b/source/blender/python/bmesh/bmesh_py_types_meshdata.h
index 07d8a46cc65..c8ae2596f99 100644
--- a/source/blender/python/bmesh/bmesh_py_types_meshdata.h
+++ b/source/blender/python/bmesh/bmesh_py_types_meshdata.h
@@ -40,15 +40,11 @@ typedef struct BPy_BMGenericMeshData {
void *data;
} BPy_BMGenericMeshData;
-struct MTexPoly;
struct MLoopUV;
struct MLoopCol;
struct MDeformVert;
struct MVertSkin;
-int BPy_BMTexPoly_AssignPyObject(struct MTexPoly *mloopuv, PyObject *value);
-PyObject *BPy_BMTexPoly_CreatePyObject(struct MTexPoly *mloopuv);
-
int BPy_BMLoopUV_AssignPyObject(struct MLoopUV *data, PyObject *value);
PyObject *BPy_BMLoopUV_CreatePyObject(struct MLoopUV *data);
diff --git a/source/blender/python/generic/bgl.c b/source/blender/python/generic/bgl.c
index 7b9292827b0..07c0f81b7ca 100644
--- a/source/blender/python/generic/bgl.c
+++ b/source/blender/python/generic/bgl.c
@@ -37,6 +37,8 @@
#include "GPU_glew.h"
#include "MEM_guardedalloc.h"
+#include "../generic/py_capi_utils.h"
+
#include "bgl.h"
@@ -185,11 +187,13 @@
#define GLbitfield_ref(num) &bgl_var##num
#define GLbitfield_def(num) /* unsigned */ int GLbitfield_var(num)
+#if 0
/* typedef signed char GLbyte; */
#define GLbyte_str "b"
#define GLbyte_var(num) bgl_var##num
#define GLbyte_ref(num) &bgl_var##num
#define GLbyte_def(num) signed char GLbyte_var(num)
+#endif
/* typedef short GLshort; */
#define GLshort_str "h"
@@ -227,11 +231,13 @@
#define GLubyte_ref(num) &bgl_var##num
#define GLubyte_def(num) /* unsigned */ char GLubyte_var(num)
+#if 0
/* typedef unsigned short GLushort; */
#define GLushort_str "H"
#define GLushort_var(num) bgl_var##num
#define GLushort_ref(num) &bgl_var##num
#define GLushort_def(num) /* unsigned */ short GLushort_var(num)
+#endif
/* typedef unsigned int GLuint; */
#define GLuint_str "I"
@@ -474,29 +480,21 @@ int BGL_typeSize(int type)
static int gl_buffer_type_from_py_buffer(Py_buffer *pybuffer)
{
- char *typestr = pybuffer->format;
+ const char format = PyC_StructFmt_type_from_str(pybuffer->format);
Py_ssize_t itemsize = pybuffer->itemsize;
- if (ELEM(typestr[0], '<', '>', '|')) {
- typestr += 1;
+ if (PyC_StructFmt_type_is_float_any(format)) {
+ if (itemsize == 4) return GL_FLOAT;
+ if (itemsize == 8) return GL_DOUBLE;
}
-
- switch (typestr[0]) {
- case 't':
- case 'b':
- case 'h':
- case 'i':
- case 'l':
- if (itemsize == 1) return GL_BYTE;
- if (itemsize == 2) return GL_SHORT;
- if (itemsize == 4) return GL_INT;
- break;
- case 'f':
- case 'd':
- if (itemsize == 4) return GL_FLOAT;
- if (itemsize == 8) return GL_DOUBLE;
- break;
+ if (PyC_StructFmt_type_is_byte(format) ||
+ PyC_StructFmt_type_is_int_any(format))
+ {
+ if (itemsize == 1) return GL_BYTE;
+ if (itemsize == 2) return GL_SHORT;
+ if (itemsize == 4) return GL_INT;
}
+
return -1; /* UNKNOWN */
}
@@ -1073,616 +1071,266 @@ static PyObject *Method_##funcname (PyObject *UNUSED(self), PyObject *args) \
ret_ret_##ret; \
}
-#define BGLU_Wrap(funcname, ret, arg_list) \
-static PyObject *Method_##funcname (PyObject *UNUSED(self), PyObject *args) \
-{ \
- arg_def arg_list; \
- ret_def_##ret; \
- if (!PyArg_ParseTuple(args, arg_str arg_list, arg_ref arg_list)) { \
- return NULL; \
- } \
- ret_set_##ret glu##funcname (arg_var arg_list); \
- ret_ret_##ret; \
-}
-
/* GL_VERSION_1_0 */
-BGL_Wrap(Accum, void, (GLenum, GLfloat))
-BGL_Wrap(AlphaFunc, void, (GLenum, GLfloat))
-BGL_Wrap(Begin, void, (GLenum))
-BGL_Wrap(Bitmap, void, (GLsizei, GLsizei, GLfloat, GLfloat, GLfloat, GLfloat, GLubyteP))
-BGL_Wrap(BlendFunc, void, (GLenum, GLenum))
-BGL_Wrap(CallList, void, (GLuint))
-BGL_Wrap(CallLists, void, (GLsizei, GLenum, GLvoidP))
-BGL_Wrap(Clear, void, (GLbitfield))
-BGL_Wrap(ClearAccum, void, (GLfloat, GLfloat, GLfloat, GLfloat))
-BGL_Wrap(ClearColor, void, (GLfloat, GLfloat, GLfloat, GLfloat))
-BGL_Wrap(ClearDepth, void, (GLdouble))
-BGL_Wrap(ClearIndex, void, (GLfloat))
-BGL_Wrap(ClearStencil, void, (GLint))
-BGL_Wrap(ClipPlane, void, (GLenum, GLdoubleP))
-BGL_Wrap(Color3b, void, (GLbyte, GLbyte, GLbyte))
-BGL_Wrap(Color3bv, void, (GLbyteP))
-BGL_Wrap(Color3d, void, (GLdouble, GLdouble, GLdouble))
-BGL_Wrap(Color3dv, void, (GLdoubleP))
-BGL_Wrap(Color3f, void, (GLfloat, GLfloat, GLfloat))
-BGL_Wrap(Color3fv, void, (GLfloatP))
-BGL_Wrap(Color3i, void, (GLint, GLint, GLint))
-BGL_Wrap(Color3iv, void, (GLintP))
-BGL_Wrap(Color3s, void, (GLshort, GLshort, GLshort))
-BGL_Wrap(Color3sv, void, (GLshortP))
-BGL_Wrap(Color3ub, void, (GLubyte, GLubyte, GLubyte))
-BGL_Wrap(Color3ubv, void, (GLubyteP))
-BGL_Wrap(Color3ui, void, (GLuint, GLuint, GLuint))
-BGL_Wrap(Color3uiv, void, (GLuintP))
-BGL_Wrap(Color3us, void, (GLushort, GLushort, GLushort))
-BGL_Wrap(Color3usv, void, (GLushortP))
-BGL_Wrap(Color4b, void, (GLbyte, GLbyte, GLbyte, GLbyte))
-BGL_Wrap(Color4bv, void, (GLbyteP))
-BGL_Wrap(Color4d, void, (GLdouble, GLdouble, GLdouble, GLdouble))
-BGL_Wrap(Color4dv, void, (GLdoubleP))
-BGL_Wrap(Color4f, void, (GLfloat, GLfloat, GLfloat, GLfloat))
-BGL_Wrap(Color4fv, void, (GLfloatP))
-BGL_Wrap(Color4i, void, (GLint, GLint, GLint, GLint))
-BGL_Wrap(Color4iv, void, (GLintP))
-BGL_Wrap(Color4s, void, (GLshort, GLshort, GLshort, GLshort))
-BGL_Wrap(Color4sv, void, (GLshortP))
-BGL_Wrap(Color4ub, void, (GLubyte, GLubyte, GLubyte, GLubyte))
-BGL_Wrap(Color4ubv, void, (GLubyteP))
-BGL_Wrap(Color4ui, void, (GLuint, GLuint, GLuint, GLuint))
-BGL_Wrap(Color4uiv, void, (GLuintP))
-BGL_Wrap(Color4us, void, (GLushort, GLushort, GLushort, GLushort))
-BGL_Wrap(Color4usv, void, (GLushortP))
-BGL_Wrap(ColorMask, void, (GLboolean, GLboolean, GLboolean, GLboolean))
-BGL_Wrap(ColorMaterial, void, (GLenum, GLenum))
-BGL_Wrap(CopyPixels, void, (GLint, GLint, GLsizei, GLsizei, GLenum))
-BGL_Wrap(CullFace, void, (GLenum))
-BGL_Wrap(DeleteLists, void, (GLuint, GLsizei))
-BGL_Wrap(DepthFunc, void, (GLenum))
-BGL_Wrap(DepthMask, void, (GLboolean))
-BGL_Wrap(DepthRange, void, (GLdouble, GLdouble))
-BGL_Wrap(Disable, void, (GLenum))
-BGL_Wrap(DrawBuffer, void, (GLenum))
-BGL_Wrap(DrawPixels, void, (GLsizei, GLsizei, GLenum, GLenum, GLvoidP))
-BGL_Wrap(EdgeFlag, void, (GLboolean))
-BGL_Wrap(EdgeFlagv, void, (GLbooleanP))
-BGL_Wrap(Enable, void, (GLenum))
-BGL_Wrap(End, void, (void))
-BGL_Wrap(EndList, void, (void))
-BGL_Wrap(EvalCoord1d, void, (GLdouble))
-BGL_Wrap(EvalCoord1dv, void, (GLdoubleP))
-BGL_Wrap(EvalCoord1f, void, (GLfloat))
-BGL_Wrap(EvalCoord1fv, void, (GLfloatP))
-BGL_Wrap(EvalCoord2d, void, (GLdouble, GLdouble))
-BGL_Wrap(EvalCoord2dv, void, (GLdoubleP))
-BGL_Wrap(EvalCoord2f, void, (GLfloat, GLfloat))
-BGL_Wrap(EvalCoord2fv, void, (GLfloatP))
-BGL_Wrap(EvalMesh1, void, (GLenum, GLint, GLint))
-BGL_Wrap(EvalMesh2, void, (GLenum, GLint, GLint, GLint, GLint))
-BGL_Wrap(EvalPoint1, void, (GLint))
-BGL_Wrap(EvalPoint2, void, (GLint, GLint))
-BGL_Wrap(FeedbackBuffer, void, (GLsizei, GLenum, GLfloatP))
-BGL_Wrap(Finish, void, (void))
-BGL_Wrap(Flush, void, (void))
-BGL_Wrap(Fogf, void, (GLenum, GLfloat))
-BGL_Wrap(Fogfv, void, (GLenum, GLfloatP))
-BGL_Wrap(Fogi, void, (GLenum, GLint))
-BGL_Wrap(Fogiv, void, (GLenum, GLintP))
-BGL_Wrap(FrontFace, void, (GLenum))
-BGL_Wrap(Frustum, void, (GLdouble, GLdouble, GLdouble, GLdouble, GLdouble, GLdouble))
-BGL_Wrap(GenLists, GLuint, (GLsizei))
-BGL_Wrap(GetBooleanv, void, (GLenum, GLbooleanP))
-BGL_Wrap(GetClipPlane, void, (GLenum, GLdoubleP))
-BGL_Wrap(GetDoublev, void, (GLenum, GLdoubleP))
-BGL_Wrap(GetError, GLenum, (void))
-BGL_Wrap(GetFloatv, void, (GLenum, GLfloatP))
-BGL_Wrap(GetIntegerv, void, (GLenum, GLintP))
-BGL_Wrap(GetLightfv, void, (GLenum, GLenum, GLfloatP))
-BGL_Wrap(GetLightiv, void, (GLenum, GLenum, GLintP))
-BGL_Wrap(GetMapdv, void, (GLenum, GLenum, GLdoubleP))
-BGL_Wrap(GetMapfv, void, (GLenum, GLenum, GLfloatP))
-BGL_Wrap(GetMapiv, void, (GLenum, GLenum, GLintP))
-BGL_Wrap(GetMaterialfv, void, (GLenum, GLenum, GLfloatP))
-BGL_Wrap(GetMaterialiv, void, (GLenum, GLenum, GLintP))
-BGL_Wrap(GetPixelMapfv, void, (GLenum, GLfloatP))
-BGL_Wrap(GetPixelMapuiv, void, (GLenum, GLuintP))
-BGL_Wrap(GetPixelMapusv, void, (GLenum, GLushortP))
-BGL_Wrap(GetPolygonStipple, void, (GLubyteP))
-BGL_Wrap(GetString, GLstring, (GLenum))
-BGL_Wrap(GetTexEnvfv, void, (GLenum, GLenum, GLfloatP))
-BGL_Wrap(GetTexEnviv, void, (GLenum, GLenum, GLintP))
-BGL_Wrap(GetTexGendv, void, (GLenum, GLenum, GLdoubleP))
-BGL_Wrap(GetTexGenfv, void, (GLenum, GLenum, GLfloatP))
-BGL_Wrap(GetTexGeniv, void, (GLenum, GLenum, GLintP))
-BGL_Wrap(GetTexImage, void, (GLenum, GLint, GLenum, GLenum, GLvoidP))
-BGL_Wrap(GetTexLevelParameterfv, void, (GLenum, GLint, GLenum, GLfloatP))
-BGL_Wrap(GetTexLevelParameteriv, void, (GLenum, GLint, GLenum, GLintP))
-BGL_Wrap(GetTexParameterfv, void, (GLenum, GLenum, GLfloatP))
-BGL_Wrap(GetTexParameteriv, void, (GLenum, GLenum, GLintP))
-BGL_Wrap(Hint, void, (GLenum, GLenum))
-BGL_Wrap(IndexMask, void, (GLuint))
-BGL_Wrap(Indexd, void, (GLdouble))
-BGL_Wrap(Indexdv, void, (GLdoubleP))
-BGL_Wrap(Indexf, void, (GLfloat))
-BGL_Wrap(Indexfv, void, (GLfloatP))
-BGL_Wrap(Indexi, void, (GLint))
-BGL_Wrap(Indexiv, void, (GLintP))
-BGL_Wrap(Indexs, void, (GLshort))
-BGL_Wrap(Indexsv, void, (GLshortP))
-BGL_Wrap(InitNames, void, (void))
-BGL_Wrap(IsEnabled, GLboolean, (GLenum))
-BGL_Wrap(IsList, GLboolean, (GLuint))
-BGL_Wrap(LightModelf, void, (GLenum, GLfloat))
-BGL_Wrap(LightModelfv, void, (GLenum, GLfloatP))
-BGL_Wrap(LightModeli, void, (GLenum, GLint))
-BGL_Wrap(LightModeliv, void, (GLenum, GLintP))
-BGL_Wrap(Lightf, void, (GLenum, GLenum, GLfloat))
-BGL_Wrap(Lightfv, void, (GLenum, GLenum, GLfloatP))
-BGL_Wrap(Lighti, void, (GLenum, GLenum, GLint))
-BGL_Wrap(Lightiv, void, (GLenum, GLenum, GLintP))
-BGL_Wrap(LineStipple, void, (GLint, GLushort))
-BGL_Wrap(LineWidth, void, (GLfloat))
-BGL_Wrap(ListBase, void, (GLuint))
-BGL_Wrap(LoadIdentity, void, (void))
-BGL_Wrap(LoadMatrixd, void, (GLdoubleP))
-BGL_Wrap(LoadMatrixf, void, (GLfloatP))
-BGL_Wrap(LoadName, void, (GLuint))
-BGL_Wrap(LogicOp, void, (GLenum))
-BGL_Wrap(Map1d, void, (GLenum, GLdouble, GLdouble, GLint, GLint, GLdoubleP))
-BGL_Wrap(Map1f, void, (GLenum, GLfloat, GLfloat, GLint, GLint, GLfloatP))
-BGL_Wrap(Map2d, void, (GLenum, GLdouble, GLdouble, GLint, GLint, GLdouble, GLdouble, GLint, GLint, GLdoubleP))
-BGL_Wrap(Map2f, void, (GLenum, GLfloat, GLfloat, GLint, GLint, GLfloat, GLfloat, GLint, GLint, GLfloatP))
-BGL_Wrap(MapGrid1d, void, (GLint, GLdouble, GLdouble))
-BGL_Wrap(MapGrid1f, void, (GLint, GLfloat, GLfloat))
-BGL_Wrap(MapGrid2d, void, (GLint, GLdouble, GLdouble, GLint, GLdouble, GLdouble))
-BGL_Wrap(MapGrid2f, void, (GLint, GLfloat, GLfloat, GLint, GLfloat, GLfloat))
-BGL_Wrap(Materialf, void, (GLenum, GLenum, GLfloat))
-BGL_Wrap(Materialfv, void, (GLenum, GLenum, GLfloatP))
-BGL_Wrap(Materiali, void, (GLenum, GLenum, GLint))
-BGL_Wrap(Materialiv, void, (GLenum, GLenum, GLintP))
-BGL_Wrap(MatrixMode, void, (GLenum))
-BGL_Wrap(MultMatrixd, void, (GLdoubleP))
-BGL_Wrap(MultMatrixf, void, (GLfloatP))
-BGL_Wrap(NewList, void, (GLuint, GLenum))
-BGL_Wrap(Normal3b, void, (GLbyte, GLbyte, GLbyte))
-BGL_Wrap(Normal3bv, void, (GLbyteP))
-BGL_Wrap(Normal3d, void, (GLdouble, GLdouble, GLdouble))
-BGL_Wrap(Normal3dv, void, (GLdoubleP))
-BGL_Wrap(Normal3f, void, (GLfloat, GLfloat, GLfloat))
-BGL_Wrap(Normal3fv, void, (GLfloatP))
-BGL_Wrap(Normal3i, void, (GLint, GLint, GLint))
-BGL_Wrap(Normal3iv, void, (GLintP))
-BGL_Wrap(Normal3s, void, (GLshort, GLshort, GLshort))
-BGL_Wrap(Normal3sv, void, (GLshortP))
-BGL_Wrap(Ortho, void, (GLdouble, GLdouble, GLdouble, GLdouble, GLdouble, GLdouble))
-BGL_Wrap(PassThrough, void, (GLfloat))
-BGL_Wrap(PixelMapfv, void, (GLenum, GLsizei, GLfloatP))
-BGL_Wrap(PixelMapuiv, void, (GLenum, GLsizei, GLuintP))
-BGL_Wrap(PixelMapusv, void, (GLenum, GLsizei, GLushortP))
-BGL_Wrap(PixelStoref, void, (GLenum, GLfloat))
-BGL_Wrap(PixelStorei, void, (GLenum, GLint))
-BGL_Wrap(PixelTransferf, void, (GLenum, GLfloat))
-BGL_Wrap(PixelTransferi, void, (GLenum, GLint))
-BGL_Wrap(PixelZoom, void, (GLfloat, GLfloat))
-BGL_Wrap(PointSize, void, (GLfloat))
-BGL_Wrap(PolygonMode, void, (GLenum, GLenum))
-BGL_Wrap(PolygonStipple, void, (GLubyteP))
-BGL_Wrap(PopAttrib, void, (void))
-BGL_Wrap(PopMatrix, void, (void))
-BGL_Wrap(PopName, void, (void))
-BGL_Wrap(PushAttrib, void, (GLbitfield))
-BGL_Wrap(PushMatrix, void, (void))
-BGL_Wrap(PushName, void, (GLuint))
-BGL_Wrap(RasterPos2d, void, (GLdouble, GLdouble))
-BGL_Wrap(RasterPos2dv, void, (GLdoubleP))
-BGL_Wrap(RasterPos2f, void, (GLfloat, GLfloat))
-BGL_Wrap(RasterPos2fv, void, (GLfloatP))
-BGL_Wrap(RasterPos2i, void, (GLint, GLint))
-BGL_Wrap(RasterPos2iv, void, (GLintP))
-BGL_Wrap(RasterPos2s, void, (GLshort, GLshort))
-BGL_Wrap(RasterPos2sv, void, (GLshortP))
-BGL_Wrap(RasterPos3d, void, (GLdouble, GLdouble, GLdouble))
-BGL_Wrap(RasterPos3dv, void, (GLdoubleP))
-BGL_Wrap(RasterPos3f, void, (GLfloat, GLfloat, GLfloat))
-BGL_Wrap(RasterPos3fv, void, (GLfloatP))
-BGL_Wrap(RasterPos3i, void, (GLint, GLint, GLint))
-BGL_Wrap(RasterPos3iv, void, (GLintP))
-BGL_Wrap(RasterPos3s, void, (GLshort, GLshort, GLshort))
-BGL_Wrap(RasterPos3sv, void, (GLshortP))
-BGL_Wrap(RasterPos4d, void, (GLdouble, GLdouble, GLdouble, GLdouble))
-BGL_Wrap(RasterPos4dv, void, (GLdoubleP))
-BGL_Wrap(RasterPos4f, void, (GLfloat, GLfloat, GLfloat, GLfloat))
-BGL_Wrap(RasterPos4fv, void, (GLfloatP))
-BGL_Wrap(RasterPos4i, void, (GLint, GLint, GLint, GLint))
-BGL_Wrap(RasterPos4iv, void, (GLintP))
-BGL_Wrap(RasterPos4s, void, (GLshort, GLshort, GLshort, GLshort))
-BGL_Wrap(RasterPos4sv, void, (GLshortP))
-BGL_Wrap(ReadBuffer, void, (GLenum))
-BGL_Wrap(ReadPixels, void, (GLint, GLint, GLsizei, GLsizei, GLenum, GLenum, GLvoidP))
-BGL_Wrap(Rectd, void, (GLdouble, GLdouble, GLdouble, GLdouble))
-BGL_Wrap(Rectdv, void, (GLdoubleP, GLdoubleP))
-BGL_Wrap(Rectf, void, (GLfloat, GLfloat, GLfloat, GLfloat))
-BGL_Wrap(Rectfv, void, (GLfloatP, GLfloatP))
-BGL_Wrap(Recti, void, (GLint, GLint, GLint, GLint))
-BGL_Wrap(Rectiv, void, (GLintP, GLintP))
-BGL_Wrap(Rects, void, (GLshort, GLshort, GLshort, GLshort))
-BGL_Wrap(Rectsv, void, (GLshortP, GLshortP))
-BGL_Wrap(RenderMode, GLint, (GLenum))
-BGL_Wrap(Rotated, void, (GLdouble, GLdouble, GLdouble, GLdouble))
-BGL_Wrap(Rotatef, void, (GLfloat, GLfloat, GLfloat, GLfloat))
-BGL_Wrap(Scaled, void, (GLdouble, GLdouble, GLdouble))
-BGL_Wrap(Scalef, void, (GLfloat, GLfloat, GLfloat))
-BGL_Wrap(Scissor, void, (GLint, GLint, GLsizei, GLsizei))
-BGL_Wrap(SelectBuffer, void, (GLsizei, GLuintP))
-BGL_Wrap(ShadeModel, void, (GLenum))
-BGL_Wrap(StencilFunc, void, (GLenum, GLint, GLuint))
-BGL_Wrap(StencilMask, void, (GLuint))
-BGL_Wrap(StencilOp, void, (GLenum, GLenum, GLenum))
-BGL_Wrap(TexCoord1d, void, (GLdouble))
-BGL_Wrap(TexCoord1dv, void, (GLdoubleP))
-BGL_Wrap(TexCoord1f, void, (GLfloat))
-BGL_Wrap(TexCoord1fv, void, (GLfloatP))
-BGL_Wrap(TexCoord1i, void, (GLint))
-BGL_Wrap(TexCoord1iv, void, (GLintP))
-BGL_Wrap(TexCoord1s, void, (GLshort))
-BGL_Wrap(TexCoord1sv, void, (GLshortP))
-BGL_Wrap(TexCoord2d, void, (GLdouble, GLdouble))
-BGL_Wrap(TexCoord2dv, void, (GLdoubleP))
-BGL_Wrap(TexCoord2f, void, (GLfloat, GLfloat))
-BGL_Wrap(TexCoord2fv, void, (GLfloatP))
-BGL_Wrap(TexCoord2i, void, (GLint, GLint))
-BGL_Wrap(TexCoord2iv, void, (GLintP))
-BGL_Wrap(TexCoord2s, void, (GLshort, GLshort))
-BGL_Wrap(TexCoord2sv, void, (GLshortP))
-BGL_Wrap(TexCoord3d, void, (GLdouble, GLdouble, GLdouble))
-BGL_Wrap(TexCoord3dv, void, (GLdoubleP))
-BGL_Wrap(TexCoord3f, void, (GLfloat, GLfloat, GLfloat))
-BGL_Wrap(TexCoord3fv, void, (GLfloatP))
-BGL_Wrap(TexCoord3i, void, (GLint, GLint, GLint))
-BGL_Wrap(TexCoord3iv, void, (GLintP))
-BGL_Wrap(TexCoord3s, void, (GLshort, GLshort, GLshort))
-BGL_Wrap(TexCoord3sv, void, (GLshortP))
-BGL_Wrap(TexCoord4d, void, (GLdouble, GLdouble, GLdouble, GLdouble))
-BGL_Wrap(TexCoord4dv, void, (GLdoubleP))
-BGL_Wrap(TexCoord4f, void, (GLfloat, GLfloat, GLfloat, GLfloat))
-BGL_Wrap(TexCoord4fv, void, (GLfloatP))
-BGL_Wrap(TexCoord4i, void, (GLint, GLint, GLint, GLint))
-BGL_Wrap(TexCoord4iv, void, (GLintP))
-BGL_Wrap(TexCoord4s, void, (GLshort, GLshort, GLshort, GLshort))
-BGL_Wrap(TexCoord4sv, void, (GLshortP))
-BGL_Wrap(TexEnvf, void, (GLenum, GLenum, GLfloat))
-BGL_Wrap(TexEnvfv, void, (GLenum, GLenum, GLfloatP))
-BGL_Wrap(TexEnvi, void, (GLenum, GLenum, GLint))
-BGL_Wrap(TexEnviv, void, (GLenum, GLenum, GLintP))
-BGL_Wrap(TexGend, void, (GLenum, GLenum, GLdouble))
-BGL_Wrap(TexGendv, void, (GLenum, GLenum, GLdoubleP))
-BGL_Wrap(TexGenf, void, (GLenum, GLenum, GLfloat))
-BGL_Wrap(TexGenfv, void, (GLenum, GLenum, GLfloatP))
-BGL_Wrap(TexGeni, void, (GLenum, GLenum, GLint))
-BGL_Wrap(TexGeniv, void, (GLenum, GLenum, GLintP))
-BGL_Wrap(TexImage1D, void, (GLenum, GLint, GLint, GLsizei, GLint, GLenum, GLenum, GLvoidP))
-BGL_Wrap(TexImage2D, void, (GLenum, GLint, GLint, GLsizei, GLsizei, GLint, GLenum, GLenum, GLvoidP))
-BGL_Wrap(TexParameterf, void, (GLenum, GLenum, GLfloat))
-BGL_Wrap(TexParameterfv, void, (GLenum, GLenum, GLfloatP))
-BGL_Wrap(TexParameteri, void, (GLenum, GLenum, GLint))
-BGL_Wrap(TexParameteriv, void, (GLenum, GLenum, GLintP))
-BGL_Wrap(Translated, void, (GLdouble, GLdouble, GLdouble))
-BGL_Wrap(Translatef, void, (GLfloat, GLfloat, GLfloat))
-BGL_Wrap(Vertex2d, void, (GLdouble, GLdouble))
-BGL_Wrap(Vertex2dv, void, (GLdoubleP))
-BGL_Wrap(Vertex2f, void, (GLfloat, GLfloat))
-BGL_Wrap(Vertex2fv, void, (GLfloatP))
-BGL_Wrap(Vertex2i, void, (GLint, GLint))
-BGL_Wrap(Vertex2iv, void, (GLintP))
-BGL_Wrap(Vertex2s, void, (GLshort, GLshort))
-BGL_Wrap(Vertex2sv, void, (GLshortP))
-BGL_Wrap(Vertex3d, void, (GLdouble, GLdouble, GLdouble))
-BGL_Wrap(Vertex3dv, void, (GLdoubleP))
-BGL_Wrap(Vertex3f, void, (GLfloat, GLfloat, GLfloat))
-BGL_Wrap(Vertex3fv, void, (GLfloatP))
-BGL_Wrap(Vertex3i, void, (GLint, GLint, GLint))
-BGL_Wrap(Vertex3iv, void, (GLintP))
-BGL_Wrap(Vertex3s, void, (GLshort, GLshort, GLshort))
-BGL_Wrap(Vertex3sv, void, (GLshortP))
-BGL_Wrap(Vertex4d, void, (GLdouble, GLdouble, GLdouble, GLdouble))
-BGL_Wrap(Vertex4dv, void, (GLdoubleP))
-BGL_Wrap(Vertex4f, void, (GLfloat, GLfloat, GLfloat, GLfloat))
-BGL_Wrap(Vertex4fv, void, (GLfloatP))
-BGL_Wrap(Vertex4i, void, (GLint, GLint, GLint, GLint))
-BGL_Wrap(Vertex4iv, void, (GLintP))
-BGL_Wrap(Vertex4s, void, (GLshort, GLshort, GLshort, GLshort))
-BGL_Wrap(Vertex4sv, void, (GLshortP))
-BGL_Wrap(Viewport, void, (GLint, GLint, GLsizei, GLsizei))
+BGL_Wrap(BlendFunc, void, (GLenum, GLenum));
+BGL_Wrap(Clear, void, (GLbitfield));
+BGL_Wrap(ClearColor, void, (GLfloat, GLfloat, GLfloat, GLfloat));
+BGL_Wrap(ClearDepth, void, (GLdouble));
+BGL_Wrap(ClearStencil, void, (GLint));
+BGL_Wrap(ColorMask, void, (GLboolean, GLboolean, GLboolean, GLboolean));
+BGL_Wrap(CullFace, void, (GLenum));
+BGL_Wrap(DepthFunc, void, (GLenum));
+BGL_Wrap(DepthMask, void, (GLboolean));
+BGL_Wrap(DepthRange, void, (GLdouble, GLdouble));
+BGL_Wrap(Disable, void, (GLenum));
+BGL_Wrap(DrawBuffer, void, (GLenum));
+BGL_Wrap(Enable, void, (GLenum));
+BGL_Wrap(Finish, void, (void));
+BGL_Wrap(Flush, void, (void));
+BGL_Wrap(FrontFace, void, (GLenum));
+BGL_Wrap(GetBooleanv, void, (GLenum, GLbooleanP));
+BGL_Wrap(GetDoublev, void, (GLenum, GLdoubleP));
+BGL_Wrap(GetError, GLenum, (void));
+BGL_Wrap(GetFloatv, void, (GLenum, GLfloatP));
+BGL_Wrap(GetIntegerv, void, (GLenum, GLintP));
+BGL_Wrap(GetString, GLstring, (GLenum));
+BGL_Wrap(GetTexImage, void, (GLenum, GLint, GLenum, GLenum, GLvoidP));
+BGL_Wrap(GetTexLevelParameterfv, void, (GLenum, GLint, GLenum, GLfloatP));
+BGL_Wrap(GetTexLevelParameteriv, void, (GLenum, GLint, GLenum, GLintP));
+BGL_Wrap(GetTexParameterfv, void, (GLenum, GLenum, GLfloatP));
+BGL_Wrap(GetTexParameteriv, void, (GLenum, GLenum, GLintP));
+BGL_Wrap(Hint, void, (GLenum, GLenum));
+BGL_Wrap(IsEnabled, GLboolean, (GLenum));
+BGL_Wrap(LineWidth, void, (GLfloat));
+BGL_Wrap(LogicOp, void, (GLenum));
+BGL_Wrap(PixelStoref, void, (GLenum, GLfloat));
+BGL_Wrap(PixelStorei, void, (GLenum, GLint));
+BGL_Wrap(PointSize, void, (GLfloat));
+BGL_Wrap(PolygonMode, void, (GLenum, GLenum));
+BGL_Wrap(ReadBuffer, void, (GLenum));
+BGL_Wrap(ReadPixels, void, (GLint, GLint, GLsizei, GLsizei, GLenum, GLenum, GLvoidP));
+BGL_Wrap(Scissor, void, (GLint, GLint, GLsizei, GLsizei));
+BGL_Wrap(StencilFunc, void, (GLenum, GLint, GLuint));
+BGL_Wrap(StencilMask, void, (GLuint));
+BGL_Wrap(StencilOp, void, (GLenum, GLenum, GLenum));
+BGL_Wrap(TexImage1D, void, (GLenum, GLint, GLint, GLsizei, GLint, GLenum, GLenum, GLvoidP));
+BGL_Wrap(TexImage2D, void, (GLenum, GLint, GLint, GLsizei, GLsizei, GLint, GLenum, GLenum, GLvoidP));
+BGL_Wrap(TexParameterf, void, (GLenum, GLenum, GLfloat));
+BGL_Wrap(TexParameterfv, void, (GLenum, GLenum, GLfloatP));
+BGL_Wrap(TexParameteri, void, (GLenum, GLenum, GLint));
+BGL_Wrap(TexParameteriv, void, (GLenum, GLenum, GLintP));
+BGL_Wrap(Viewport, void, (GLint, GLint, GLsizei, GLsizei));
/* GL_VERSION_1_1 */
-BGL_Wrap(AreTexturesResident, GLboolean, (GLsizei, GLuintP, GLbooleanP))
-BGL_Wrap(ArrayElement, void, (GLint))
-BGL_Wrap(BindTexture, void, (GLenum, GLuint))
-BGL_Wrap(ColorPointer, void, (GLint, GLenum, GLsizei, GLvoidP))
-BGL_Wrap(CopyTexImage1D, void, (GLenum, GLint, GLenum, GLint, GLint, GLsizei, GLint))
-BGL_Wrap(CopyTexImage2D, void, (GLenum, GLint, GLenum, GLint, GLint, GLsizei, GLsizei, GLint))
-BGL_Wrap(CopyTexSubImage1D, void, (GLenum, GLint, GLint, GLint, GLint, GLsizei))
-BGL_Wrap(CopyTexSubImage2D, void, (GLenum, GLint, GLint, GLint, GLint, GLint, GLsizei, GLsizei))
-BGL_Wrap(DeleteTextures, void, (GLsizei, GLuintP))
-BGL_Wrap(DisableClientState, void, (GLenum))
-BGL_Wrap(DrawArrays, void, (GLenum, GLint, GLsizei))
-BGL_Wrap(DrawElements, void, (GLenum, GLsizei, GLenum, GLvoidP))
-BGL_Wrap(EdgeFlagPointer, void, (GLsizei, GLvoidP))
-BGL_Wrap(EnableClientState, void, (GLenum))
-BGL_Wrap(GenTextures, void, (GLsizei, GLuintP))
-BGL_Wrap(GetPointerv, void, (GLenum, GLvoidP))
-BGL_Wrap(IndexPointer, void, (GLenum, GLsizei, GLvoidP))
-BGL_Wrap(Indexub, void, (GLubyte))
-BGL_Wrap(Indexubv, void, (GLubyteP))
-BGL_Wrap(InterleavedArrays, void, (GLenum, GLsizei, GLvoidP))
-BGL_Wrap(IsTexture, GLboolean, (GLuint))
-BGL_Wrap(NormalPointer, void, (GLenum, GLsizei, GLvoidP))
-BGL_Wrap(PolygonOffset, void, (GLfloat, GLfloat))
-BGL_Wrap(PopClientAttrib, void, (void))
-BGL_Wrap(PrioritizeTextures, void, (GLsizei, GLuintP, GLfloatP))
-BGL_Wrap(PushClientAttrib, void, (GLbitfield))
-BGL_Wrap(TexCoordPointer, void, (GLint, GLenum, GLsizei, GLvoidP))
-BGL_Wrap(TexSubImage1D, void, (GLenum, GLint, GLint, GLsizei, GLenum, GLenum, GLvoidP))
-BGL_Wrap(TexSubImage2D, void, (GLenum, GLint, GLint, GLint, GLsizei, GLsizei, GLenum, GLenum, GLvoidP))
-BGL_Wrap(VertexPointer, void, (GLint, GLenum, GLsizei, GLvoidP))
+BGL_Wrap(BindTexture, void, (GLenum, GLuint));
+BGL_Wrap(CopyTexImage1D, void, (GLenum, GLint, GLenum, GLint, GLint, GLsizei, GLint));
+BGL_Wrap(CopyTexImage2D, void, (GLenum, GLint, GLenum, GLint, GLint, GLsizei, GLsizei, GLint));
+BGL_Wrap(CopyTexSubImage1D, void, (GLenum, GLint, GLint, GLint, GLint, GLsizei));
+BGL_Wrap(CopyTexSubImage2D, void, (GLenum, GLint, GLint, GLint, GLint, GLint, GLsizei, GLsizei));
+BGL_Wrap(DeleteTextures, void, (GLsizei, GLuintP));
+BGL_Wrap(DrawArrays, void, (GLenum, GLint, GLsizei));
+BGL_Wrap(DrawElements, void, (GLenum, GLsizei, GLenum, GLvoidP));
+BGL_Wrap(GenTextures, void, (GLsizei, GLuintP));
+BGL_Wrap(IsTexture, GLboolean, (GLuint));
+BGL_Wrap(PolygonOffset, void, (GLfloat, GLfloat));
+BGL_Wrap(TexSubImage1D, void, (GLenum, GLint, GLint, GLsizei, GLenum, GLenum, GLvoidP));
+BGL_Wrap(TexSubImage2D, void, (GLenum, GLint, GLint, GLint, GLsizei, GLsizei, GLenum, GLenum, GLvoidP));
/* GL_VERSION_1_2 */
-BGL_Wrap(CopyTexSubImage3D, void, (GLenum, GLint, GLint, GLint, GLint, GLint, GLint, GLsizei, GLsizei))
-BGL_Wrap(DrawRangeElements, void, (GLenum, GLuint, GLuint, GLsizei, GLenum, GLvoidP))
-BGL_Wrap(TexImage3D, void, (GLenum, GLint, GLint, GLsizei, GLsizei, GLsizei, GLint, GLenum, GLenum, GLvoidP))
-BGL_Wrap(TexSubImage3D, void, (GLenum, GLint, GLint, GLint, GLint, GLsizei, GLsizei, GLsizei, GLenum, GLenum, GLvoidP))
+BGL_Wrap(CopyTexSubImage3D, void, (GLenum, GLint, GLint, GLint, GLint, GLint, GLint, GLsizei, GLsizei));
+BGL_Wrap(DrawRangeElements, void, (GLenum, GLuint, GLuint, GLsizei, GLenum, GLvoidP));
+BGL_Wrap(TexImage3D, void, (GLenum, GLint, GLint, GLsizei, GLsizei, GLsizei, GLint, GLenum, GLenum, GLvoidP));
+BGL_Wrap(TexSubImage3D, void, (GLenum, GLint, GLint, GLint, GLint, GLsizei, GLsizei, GLsizei, GLenum, GLenum, GLvoidP));
/* GL_VERSION_1_3 */
-BGL_Wrap(ActiveTexture, void, (GLenum))
-BGL_Wrap(ClientActiveTexture, void, (GLenum))
-BGL_Wrap(CompressedTexImage1D, void, (GLenum, GLint, GLenum, GLsizei, GLint, GLsizei, GLvoidP))
-BGL_Wrap(CompressedTexImage2D, void, (GLenum, GLint, GLenum, GLsizei, GLsizei, GLint, GLsizei, GLvoidP))
-BGL_Wrap(CompressedTexImage3D, void, (GLenum, GLint, GLenum, GLsizei, GLsizei, GLsizei, GLint, GLsizei, GLvoidP))
-BGL_Wrap(CompressedTexSubImage1D, void, (GLenum, GLint, GLint, GLsizei, GLenum, GLsizei, GLvoidP))
-BGL_Wrap(CompressedTexSubImage2D, void, (GLenum, GLint, GLint, GLint, GLsizei, GLsizei, GLenum, GLsizei, GLvoidP))
-BGL_Wrap(CompressedTexSubImage3D, void, (GLenum, GLint, GLint, GLint, GLint, GLsizei, GLsizei, GLsizei, GLenum, GLsizei, GLvoidP))
-BGL_Wrap(GetCompressedTexImage, void, (GLenum, GLint, GLvoidP))
-BGL_Wrap(LoadTransposeMatrixd, void, (GLdoubleP))
-BGL_Wrap(LoadTransposeMatrixf, void, (GLfloatP))
-BGL_Wrap(MultTransposeMatrixd, void, (GLdoubleP))
-BGL_Wrap(MultTransposeMatrixf, void, (GLfloatP))
-BGL_Wrap(MultiTexCoord1d, void, (GLenum, GLdouble))
-BGL_Wrap(MultiTexCoord1dv, void, (GLenum, GLdoubleP))
-BGL_Wrap(MultiTexCoord1f, void, (GLenum, GLfloat))
-BGL_Wrap(MultiTexCoord1fv, void, (GLenum, GLfloatP))
-BGL_Wrap(MultiTexCoord1i, void, (GLenum, GLint))
-BGL_Wrap(MultiTexCoord1iv, void, (GLenum, GLintP))
-BGL_Wrap(MultiTexCoord1s, void, (GLenum, GLshort))
-BGL_Wrap(MultiTexCoord1sv, void, (GLenum, GLshortP))
-BGL_Wrap(MultiTexCoord2d, void, (GLenum, GLdouble, GLdouble))
-BGL_Wrap(MultiTexCoord2dv, void, (GLenum, GLdoubleP))
-BGL_Wrap(MultiTexCoord2f, void, (GLenum, GLfloat, GLfloat))
-BGL_Wrap(MultiTexCoord2fv, void, (GLenum, GLfloatP))
-BGL_Wrap(MultiTexCoord2i, void, (GLenum, GLint, GLint))
-BGL_Wrap(MultiTexCoord2iv, void, (GLenum, GLintP))
-BGL_Wrap(MultiTexCoord2s, void, (GLenum, GLshort, GLshort))
-BGL_Wrap(MultiTexCoord2sv, void, (GLenum, GLshortP))
-BGL_Wrap(MultiTexCoord3d, void, (GLenum, GLdouble, GLdouble, GLdouble))
-BGL_Wrap(MultiTexCoord3dv, void, (GLenum, GLdoubleP))
-BGL_Wrap(MultiTexCoord3f, void, (GLenum, GLfloat, GLfloat, GLfloat))
-BGL_Wrap(MultiTexCoord3fv, void, (GLenum, GLfloatP))
-BGL_Wrap(MultiTexCoord3i, void, (GLenum, GLint, GLint, GLint))
-BGL_Wrap(MultiTexCoord3iv, void, (GLenum, GLintP))
-BGL_Wrap(MultiTexCoord3s, void, (GLenum, GLshort, GLshort, GLshort))
-BGL_Wrap(MultiTexCoord3sv, void, (GLenum, GLshortP))
-BGL_Wrap(MultiTexCoord4d, void, (GLenum, GLdouble, GLdouble, GLdouble, GLdouble))
-BGL_Wrap(MultiTexCoord4dv, void, (GLenum, GLdoubleP))
-BGL_Wrap(MultiTexCoord4f, void, (GLenum, GLfloat, GLfloat, GLfloat, GLfloat))
-BGL_Wrap(MultiTexCoord4fv, void, (GLenum, GLfloatP))
-BGL_Wrap(MultiTexCoord4i, void, (GLenum, GLint, GLint, GLint, GLint))
-BGL_Wrap(MultiTexCoord4iv, void, (GLenum, GLintP))
-BGL_Wrap(MultiTexCoord4s, void, (GLenum, GLshort, GLshort, GLshort, GLshort))
-BGL_Wrap(MultiTexCoord4sv, void, (GLenum, GLshortP))
-BGL_Wrap(SampleCoverage, void, (GLfloat, GLboolean))
+BGL_Wrap(ActiveTexture, void, (GLenum));
+BGL_Wrap(CompressedTexImage1D, void, (GLenum, GLint, GLenum, GLsizei, GLint, GLsizei, GLvoidP));
+BGL_Wrap(CompressedTexImage2D, void, (GLenum, GLint, GLenum, GLsizei, GLsizei, GLint, GLsizei, GLvoidP));
+BGL_Wrap(CompressedTexImage3D, void, (GLenum, GLint, GLenum, GLsizei, GLsizei, GLsizei, GLint, GLsizei, GLvoidP));
+BGL_Wrap(CompressedTexSubImage1D, void, (GLenum, GLint, GLint, GLsizei, GLenum, GLsizei, GLvoidP));
+BGL_Wrap(CompressedTexSubImage2D, void, (GLenum, GLint, GLint, GLint, GLsizei, GLsizei, GLenum, GLsizei, GLvoidP));
+BGL_Wrap(CompressedTexSubImage3D, void, (GLenum, GLint, GLint, GLint, GLint, GLsizei, GLsizei, GLsizei, GLenum, GLsizei, GLvoidP));
+BGL_Wrap(GetCompressedTexImage, void, (GLenum, GLint, GLvoidP));
+BGL_Wrap(SampleCoverage, void, (GLfloat, GLboolean));
/* GL_VERSION_1_4 */
-BGL_Wrap(BlendColor, void, (GLfloat, GLfloat, GLfloat, GLfloat))
-BGL_Wrap(BlendEquation, void, (GLenum))
+BGL_Wrap(BlendColor, void, (GLfloat, GLfloat, GLfloat, GLfloat));
+BGL_Wrap(BlendEquation, void, (GLenum));
/* GL_VERSION_1_5 */
-BGL_Wrap(BeginQuery, void, (GLenum, GLuint))
-BGL_Wrap(BindBuffer, void, (GLenum, GLuint))
-BGL_Wrap(BufferData, void, (GLenum, GLsizeiptr, GLvoidP, GLenum))
-BGL_Wrap(BufferSubData, void, (GLenum, GLintptr, GLsizeiptr, GLvoidP))
-BGL_Wrap(DeleteBuffers, void, (GLsizei, GLuintP))
-BGL_Wrap(DeleteQueries, void, (GLsizei, GLuintP))
-BGL_Wrap(EndQuery, void, (GLenum))
-BGL_Wrap(GenBuffers, void, (GLsizei, GLuintP))
-BGL_Wrap(GenQueries, void, (GLsizei, GLuintP))
-BGL_Wrap(GetBufferParameteriv, void, (GLenum, GLenum, GLintP))
-BGL_Wrap(GetBufferPointerv, void, (GLenum, GLenum, GLvoidP))
-BGL_Wrap(GetBufferSubData, void, (GLenum, GLintptr, GLsizeiptr, GLvoidP))
-BGL_Wrap(GetQueryObjectiv, void, (GLuint, GLenum, GLintP))
-BGL_Wrap(GetQueryObjectuiv, void, (GLuint, GLenum, GLuintP))
-BGL_Wrap(GetQueryiv, void, (GLenum, GLenum, GLintP))
-BGL_Wrap(IsBuffer, GLboolean, (GLuint))
-BGL_Wrap(IsQuery, GLboolean, (GLuint))
-BGL_Wrap(MapBuffer, void, (GLenum, GLenum))
-BGL_Wrap(UnmapBuffer, GLboolean, (GLenum))
+BGL_Wrap(BeginQuery, void, (GLenum, GLuint));
+BGL_Wrap(BindBuffer, void, (GLenum, GLuint));
+BGL_Wrap(BufferData, void, (GLenum, GLsizeiptr, GLvoidP, GLenum));
+BGL_Wrap(BufferSubData, void, (GLenum, GLintptr, GLsizeiptr, GLvoidP));
+BGL_Wrap(DeleteBuffers, void, (GLsizei, GLuintP));
+BGL_Wrap(DeleteQueries, void, (GLsizei, GLuintP));
+BGL_Wrap(EndQuery, void, (GLenum));
+BGL_Wrap(GenBuffers, void, (GLsizei, GLuintP));
+BGL_Wrap(GenQueries, void, (GLsizei, GLuintP));
+BGL_Wrap(GetBufferParameteriv, void, (GLenum, GLenum, GLintP));
+BGL_Wrap(GetBufferPointerv, void, (GLenum, GLenum, GLvoidP));
+BGL_Wrap(GetBufferSubData, void, (GLenum, GLintptr, GLsizeiptr, GLvoidP));
+BGL_Wrap(GetQueryObjectiv, void, (GLuint, GLenum, GLintP));
+BGL_Wrap(GetQueryObjectuiv, void, (GLuint, GLenum, GLuintP));
+BGL_Wrap(GetQueryiv, void, (GLenum, GLenum, GLintP));
+BGL_Wrap(IsBuffer, GLboolean, (GLuint));
+BGL_Wrap(IsQuery, GLboolean, (GLuint));
+BGL_Wrap(MapBuffer, void, (GLenum, GLenum));
+BGL_Wrap(UnmapBuffer, GLboolean, (GLenum));
/* GL_VERSION_2_0 */
-BGL_Wrap(AttachShader, void, (GLuint, GLuint))
-BGL_Wrap(BindAttribLocation, void, (GLuint, GLuint, GLstring))
-BGL_Wrap(BlendEquationSeparate, void, (GLenum, GLenum))
-BGL_Wrap(CompileShader, void, (GLuint))
-BGL_Wrap(CreateProgram, GLuint, (void))
-BGL_Wrap(CreateShader, GLuint, (GLenum))
-BGL_Wrap(DeleteProgram, void, (GLuint))
-BGL_Wrap(DeleteShader, void, (GLuint))
-BGL_Wrap(DetachShader, void, (GLuint, GLuint))
-BGL_Wrap(DisableVertexAttribArray, void, (GLuint))
-BGL_Wrap(DrawBuffers, void, (GLsizei, GLenumP))
-BGL_Wrap(EnableVertexAttribArray, void, (GLuint))
-BGL_Wrap(GetActiveAttrib, void, (GLuint, GLuint, GLsizei, GLsizeiP, GLintP, GLenumP, GLcharP))
-BGL_Wrap(GetActiveUniform, void, (GLuint, GLuint, GLsizei, GLsizeiP, GLintP, GLenumP, GLcharP))
-BGL_Wrap(GetAttachedShaders, void, (GLuint, GLsizei, GLsizeiP, GLuintP))
-BGL_Wrap(GetAttribLocation, GLint, (GLuint, GLstring))
-BGL_Wrap(GetProgramInfoLog, void, (GLuint, GLsizei, GLsizeiP, GLcharP))
-BGL_Wrap(GetProgramiv, void, (GLuint, GLenum, GLintP))
-BGL_Wrap(GetShaderInfoLog, void, (GLuint, GLsizei, GLsizeiP, GLcharP))
-BGL_Wrap(GetShaderSource, void, (GLuint, GLsizei, GLsizeiP, GLcharP))
-BGL_Wrap(GetShaderiv, void, (GLuint, GLenum, GLintP))
-BGL_Wrap(GetUniformLocation, GLint, (GLuint, GLstring))
-BGL_Wrap(GetUniformfv, void, (GLuint, GLint, GLfloatP))
-BGL_Wrap(GetUniformiv, void, (GLuint, GLint, GLintP))
-BGL_Wrap(GetVertexAttribPointerv, void, (GLuint, GLenum, GLvoidP))
-BGL_Wrap(GetVertexAttribdv, void, (GLuint, GLenum, GLdoubleP))
-BGL_Wrap(GetVertexAttribfv, void, (GLuint, GLenum, GLfloatP))
-BGL_Wrap(GetVertexAttribiv, void, (GLuint, GLenum, GLintP))
-BGL_Wrap(IsProgram, GLboolean, (GLuint))
-BGL_Wrap(IsShader, GLboolean, (GLuint))
-BGL_Wrap(LinkProgram, void, (GLuint))
-BGL_Wrap(StencilFuncSeparate, void, (GLenum, GLenum, GLint, GLuint))
-BGL_Wrap(StencilMaskSeparate, void, (GLenum, GLuint))
-BGL_Wrap(StencilOpSeparate, void, (GLenum, GLenum, GLenum, GLenum))
-BGL_Wrap(Uniform1f, void, (GLint, GLfloat))
-BGL_Wrap(Uniform1fv, void, (GLint, GLsizei, GLfloatP))
-BGL_Wrap(Uniform1i, void, (GLint, GLint))
-BGL_Wrap(Uniform1iv, void, (GLint, GLsizei, GLintP))
-BGL_Wrap(Uniform2f, void, (GLint, GLfloat, GLfloat))
-BGL_Wrap(Uniform2fv, void, (GLint, GLsizei, GLfloatP))
-BGL_Wrap(Uniform2i, void, (GLint, GLint, GLint))
-BGL_Wrap(Uniform2iv, void, (GLint, GLsizei, GLintP))
-BGL_Wrap(Uniform3f, void, (GLint, GLfloat, GLfloat, GLfloat))
-BGL_Wrap(Uniform3fv, void, (GLint, GLsizei, GLfloatP))
-BGL_Wrap(Uniform3i, void, (GLint, GLint, GLint, GLint))
-BGL_Wrap(Uniform3iv, void, (GLint, GLsizei, GLintP))
-BGL_Wrap(Uniform4f, void, (GLint, GLfloat, GLfloat, GLfloat, GLfloat))
-BGL_Wrap(Uniform4fv, void, (GLint, GLsizei, GLfloatP))
-BGL_Wrap(Uniform4i, void, (GLint, GLint, GLint, GLint, GLint))
-BGL_Wrap(Uniform4iv, void, (GLint, GLsizei, GLintP))
-BGL_Wrap(UniformMatrix2fv, void, (GLint, GLsizei, GLboolean, GLfloatP))
-BGL_Wrap(UniformMatrix3fv, void, (GLint, GLsizei, GLboolean, GLfloatP))
-BGL_Wrap(UniformMatrix4fv, void, (GLint, GLsizei, GLboolean, GLfloatP))
-BGL_Wrap(UseProgram, void, (GLuint))
-BGL_Wrap(ValidateProgram, void, (GLuint))
-BGL_Wrap(VertexAttrib1d, void, (GLuint, GLdouble))
-BGL_Wrap(VertexAttrib1dv, void, (GLuint, GLdoubleP))
-BGL_Wrap(VertexAttrib1f, void, (GLuint, GLfloat))
-BGL_Wrap(VertexAttrib1fv, void, (GLuint, GLfloatP))
-BGL_Wrap(VertexAttrib1s, void, (GLuint, GLshort))
-BGL_Wrap(VertexAttrib1sv, void, (GLuint, GLshortP))
-BGL_Wrap(VertexAttrib2d, void, (GLuint, GLdouble, GLdouble))
-BGL_Wrap(VertexAttrib2dv, void, (GLuint, GLdoubleP))
-BGL_Wrap(VertexAttrib2f, void, (GLuint, GLfloat, GLfloat))
-BGL_Wrap(VertexAttrib2fv, void, (GLuint, GLfloatP))
-BGL_Wrap(VertexAttrib2s, void, (GLuint, GLshort, GLshort))
-BGL_Wrap(VertexAttrib2sv, void, (GLuint, GLshortP))
-BGL_Wrap(VertexAttrib3d, void, (GLuint, GLdouble, GLdouble, GLdouble))
-BGL_Wrap(VertexAttrib3dv, void, (GLuint, GLdoubleP))
-BGL_Wrap(VertexAttrib3f, void, (GLuint, GLfloat, GLfloat, GLfloat))
-BGL_Wrap(VertexAttrib3fv, void, (GLuint, GLfloatP))
-BGL_Wrap(VertexAttrib3s, void, (GLuint, GLshort, GLshort, GLshort))
-BGL_Wrap(VertexAttrib3sv, void, (GLuint, GLshortP))
-BGL_Wrap(VertexAttrib4Nbv, void, (GLuint, GLbyteP))
-BGL_Wrap(VertexAttrib4Niv, void, (GLuint, GLintP))
-BGL_Wrap(VertexAttrib4Nsv, void, (GLuint, GLshortP))
-BGL_Wrap(VertexAttrib4Nub, void, (GLuint, GLubyte, GLubyte, GLubyte, GLubyte))
-BGL_Wrap(VertexAttrib4Nubv, void, (GLuint, GLubyteP))
-BGL_Wrap(VertexAttrib4Nuiv, void, (GLuint, GLuintP))
-BGL_Wrap(VertexAttrib4Nusv, void, (GLuint, GLushortP))
-BGL_Wrap(VertexAttrib4bv, void, (GLuint, GLbyteP))
-BGL_Wrap(VertexAttrib4d, void, (GLuint, GLdouble, GLdouble, GLdouble, GLdouble))
-BGL_Wrap(VertexAttrib4dv, void, (GLuint, GLdoubleP))
-BGL_Wrap(VertexAttrib4f, void, (GLuint, GLfloat, GLfloat, GLfloat, GLfloat))
-BGL_Wrap(VertexAttrib4fv, void, (GLuint, GLfloatP))
-BGL_Wrap(VertexAttrib4iv, void, (GLuint, GLintP))
-BGL_Wrap(VertexAttrib4s, void, (GLuint, GLshort, GLshort, GLshort, GLshort))
-BGL_Wrap(VertexAttrib4sv, void, (GLuint, GLshortP))
-BGL_Wrap(VertexAttrib4ubv, void, (GLuint, GLubyteP))
-BGL_Wrap(VertexAttrib4uiv, void, (GLuint, GLuintP))
-BGL_Wrap(VertexAttrib4usv, void, (GLuint, GLushortP))
-BGL_Wrap(VertexAttribPointer, void, (GLuint, GLint, GLenum, GLboolean, GLsizei, GLvoidP))
+BGL_Wrap(AttachShader, void, (GLuint, GLuint));
+BGL_Wrap(BindAttribLocation, void, (GLuint, GLuint, GLstring));
+BGL_Wrap(BlendEquationSeparate, void, (GLenum, GLenum));
+BGL_Wrap(CompileShader, void, (GLuint));
+BGL_Wrap(CreateProgram, GLuint, (void));
+BGL_Wrap(CreateShader, GLuint, (GLenum));
+BGL_Wrap(DeleteProgram, void, (GLuint));
+BGL_Wrap(DeleteShader, void, (GLuint));
+BGL_Wrap(DetachShader, void, (GLuint, GLuint));
+BGL_Wrap(DisableVertexAttribArray, void, (GLuint));
+BGL_Wrap(DrawBuffers, void, (GLsizei, GLenumP));
+BGL_Wrap(EnableVertexAttribArray, void, (GLuint));
+BGL_Wrap(GetActiveAttrib, void, (GLuint, GLuint, GLsizei, GLsizeiP, GLintP, GLenumP, GLcharP));
+BGL_Wrap(GetActiveUniform, void, (GLuint, GLuint, GLsizei, GLsizeiP, GLintP, GLenumP, GLcharP));
+BGL_Wrap(GetAttachedShaders, void, (GLuint, GLsizei, GLsizeiP, GLuintP));
+BGL_Wrap(GetAttribLocation, GLint, (GLuint, GLstring));
+BGL_Wrap(GetProgramInfoLog, void, (GLuint, GLsizei, GLsizeiP, GLcharP));
+BGL_Wrap(GetProgramiv, void, (GLuint, GLenum, GLintP));
+BGL_Wrap(GetShaderInfoLog, void, (GLuint, GLsizei, GLsizeiP, GLcharP));
+BGL_Wrap(GetShaderSource, void, (GLuint, GLsizei, GLsizeiP, GLcharP));
+BGL_Wrap(GetShaderiv, void, (GLuint, GLenum, GLintP));
+BGL_Wrap(GetUniformLocation, GLint, (GLuint, GLstring));
+BGL_Wrap(GetUniformfv, void, (GLuint, GLint, GLfloatP));
+BGL_Wrap(GetUniformiv, void, (GLuint, GLint, GLintP));
+BGL_Wrap(GetVertexAttribPointerv, void, (GLuint, GLenum, GLvoidP));
+BGL_Wrap(GetVertexAttribdv, void, (GLuint, GLenum, GLdoubleP));
+BGL_Wrap(GetVertexAttribfv, void, (GLuint, GLenum, GLfloatP));
+BGL_Wrap(GetVertexAttribiv, void, (GLuint, GLenum, GLintP));
+BGL_Wrap(IsProgram, GLboolean, (GLuint));
+BGL_Wrap(IsShader, GLboolean, (GLuint));
+BGL_Wrap(LinkProgram, void, (GLuint));
+BGL_Wrap(StencilFuncSeparate, void, (GLenum, GLenum, GLint, GLuint));
+BGL_Wrap(StencilMaskSeparate, void, (GLenum, GLuint));
+BGL_Wrap(StencilOpSeparate, void, (GLenum, GLenum, GLenum, GLenum));
+BGL_Wrap(Uniform1f, void, (GLint, GLfloat));
+BGL_Wrap(Uniform1fv, void, (GLint, GLsizei, GLfloatP));
+BGL_Wrap(Uniform1i, void, (GLint, GLint));
+BGL_Wrap(Uniform1iv, void, (GLint, GLsizei, GLintP));
+BGL_Wrap(Uniform2f, void, (GLint, GLfloat, GLfloat));
+BGL_Wrap(Uniform2fv, void, (GLint, GLsizei, GLfloatP));
+BGL_Wrap(Uniform2i, void, (GLint, GLint, GLint));
+BGL_Wrap(Uniform2iv, void, (GLint, GLsizei, GLintP));
+BGL_Wrap(Uniform3f, void, (GLint, GLfloat, GLfloat, GLfloat));
+BGL_Wrap(Uniform3fv, void, (GLint, GLsizei, GLfloatP));
+BGL_Wrap(Uniform3i, void, (GLint, GLint, GLint, GLint));
+BGL_Wrap(Uniform3iv, void, (GLint, GLsizei, GLintP));
+BGL_Wrap(Uniform4f, void, (GLint, GLfloat, GLfloat, GLfloat, GLfloat));
+BGL_Wrap(Uniform4fv, void, (GLint, GLsizei, GLfloatP));
+BGL_Wrap(Uniform4i, void, (GLint, GLint, GLint, GLint, GLint));
+BGL_Wrap(Uniform4iv, void, (GLint, GLsizei, GLintP));
+BGL_Wrap(UniformMatrix2fv, void, (GLint, GLsizei, GLboolean, GLfloatP));
+BGL_Wrap(UniformMatrix3fv, void, (GLint, GLsizei, GLboolean, GLfloatP));
+BGL_Wrap(UniformMatrix4fv, void, (GLint, GLsizei, GLboolean, GLfloatP));
+BGL_Wrap(UseProgram, void, (GLuint));
+BGL_Wrap(ValidateProgram, void, (GLuint));
+BGL_Wrap(VertexAttrib1d, void, (GLuint, GLdouble));
+BGL_Wrap(VertexAttrib1dv, void, (GLuint, GLdoubleP));
+BGL_Wrap(VertexAttrib1f, void, (GLuint, GLfloat));
+BGL_Wrap(VertexAttrib1fv, void, (GLuint, GLfloatP));
+BGL_Wrap(VertexAttrib1s, void, (GLuint, GLshort));
+BGL_Wrap(VertexAttrib1sv, void, (GLuint, GLshortP));
+BGL_Wrap(VertexAttrib2d, void, (GLuint, GLdouble, GLdouble));
+BGL_Wrap(VertexAttrib2dv, void, (GLuint, GLdoubleP));
+BGL_Wrap(VertexAttrib2f, void, (GLuint, GLfloat, GLfloat));
+BGL_Wrap(VertexAttrib2fv, void, (GLuint, GLfloatP));
+BGL_Wrap(VertexAttrib2s, void, (GLuint, GLshort, GLshort));
+BGL_Wrap(VertexAttrib2sv, void, (GLuint, GLshortP));
+BGL_Wrap(VertexAttrib3d, void, (GLuint, GLdouble, GLdouble, GLdouble));
+BGL_Wrap(VertexAttrib3dv, void, (GLuint, GLdoubleP));
+BGL_Wrap(VertexAttrib3f, void, (GLuint, GLfloat, GLfloat, GLfloat));
+BGL_Wrap(VertexAttrib3fv, void, (GLuint, GLfloatP));
+BGL_Wrap(VertexAttrib3s, void, (GLuint, GLshort, GLshort, GLshort));
+BGL_Wrap(VertexAttrib3sv, void, (GLuint, GLshortP));
+BGL_Wrap(VertexAttrib4Nbv, void, (GLuint, GLbyteP));
+BGL_Wrap(VertexAttrib4Niv, void, (GLuint, GLintP));
+BGL_Wrap(VertexAttrib4Nsv, void, (GLuint, GLshortP));
+BGL_Wrap(VertexAttrib4Nub, void, (GLuint, GLubyte, GLubyte, GLubyte, GLubyte));
+BGL_Wrap(VertexAttrib4Nubv, void, (GLuint, GLubyteP));
+BGL_Wrap(VertexAttrib4Nuiv, void, (GLuint, GLuintP));
+BGL_Wrap(VertexAttrib4Nusv, void, (GLuint, GLushortP));
+BGL_Wrap(VertexAttrib4bv, void, (GLuint, GLbyteP));
+BGL_Wrap(VertexAttrib4d, void, (GLuint, GLdouble, GLdouble, GLdouble, GLdouble));
+BGL_Wrap(VertexAttrib4dv, void, (GLuint, GLdoubleP));
+BGL_Wrap(VertexAttrib4f, void, (GLuint, GLfloat, GLfloat, GLfloat, GLfloat));
+BGL_Wrap(VertexAttrib4fv, void, (GLuint, GLfloatP));
+BGL_Wrap(VertexAttrib4iv, void, (GLuint, GLintP));
+BGL_Wrap(VertexAttrib4s, void, (GLuint, GLshort, GLshort, GLshort, GLshort));
+BGL_Wrap(VertexAttrib4sv, void, (GLuint, GLshortP));
+BGL_Wrap(VertexAttrib4ubv, void, (GLuint, GLubyteP));
+BGL_Wrap(VertexAttrib4uiv, void, (GLuint, GLuintP));
+BGL_Wrap(VertexAttrib4usv, void, (GLuint, GLushortP));
+BGL_Wrap(VertexAttribPointer, void, (GLuint, GLint, GLenum, GLboolean, GLsizei, GLvoidP));
/* GL_VERSION_2_1 */
-BGL_Wrap(UniformMatrix2x3fv, void, (GLint, GLsizei, GLboolean, GLfloatP))
-BGL_Wrap(UniformMatrix2x4fv, void, (GLint, GLsizei, GLboolean, GLfloatP))
-BGL_Wrap(UniformMatrix3x2fv, void, (GLint, GLsizei, GLboolean, GLfloatP))
-BGL_Wrap(UniformMatrix3x4fv, void, (GLint, GLsizei, GLboolean, GLfloatP))
-BGL_Wrap(UniformMatrix4x2fv, void, (GLint, GLsizei, GLboolean, GLfloatP))
-BGL_Wrap(UniformMatrix4x3fv, void, (GLint, GLsizei, GLboolean, GLfloatP))
+BGL_Wrap(UniformMatrix2x3fv, void, (GLint, GLsizei, GLboolean, GLfloatP));
+BGL_Wrap(UniformMatrix2x4fv, void, (GLint, GLsizei, GLboolean, GLfloatP));
+BGL_Wrap(UniformMatrix3x2fv, void, (GLint, GLsizei, GLboolean, GLfloatP));
+BGL_Wrap(UniformMatrix3x4fv, void, (GLint, GLsizei, GLboolean, GLfloatP));
+BGL_Wrap(UniformMatrix4x2fv, void, (GLint, GLsizei, GLboolean, GLfloatP));
+BGL_Wrap(UniformMatrix4x3fv, void, (GLint, GLsizei, GLboolean, GLfloatP));
/* GL_VERSION_3_0 */
-BGL_Wrap(BindVertexArray, void, (GLuint))
-BGL_Wrap(DeleteVertexArrays, void, (GLsizei, GLuintP))
-BGL_Wrap(GenVertexArrays, void, (GLsizei, GLuintP))
-BGL_Wrap(IsVertexArray, GLboolean, (GLuint))
+BGL_Wrap(BindFramebuffer, void, (GLenum, GLuint));
+BGL_Wrap(BindRenderbuffer, void, (GLenum, GLuint));
+BGL_Wrap(BindVertexArray, void, (GLuint));
+BGL_Wrap(BlitFramebuffer, void, (GLint, GLint, GLint, GLint, GLint, GLint, GLint, GLint, GLbitfield, GLenum));
+BGL_Wrap(CheckFramebufferStatus, GLenum, (GLenum));
+BGL_Wrap(DeleteFramebuffers, void, (GLsizei, GLuintP));
+BGL_Wrap(DeleteRenderbuffers, void, (GLsizei, GLuintP));
+BGL_Wrap(DeleteVertexArrays, void, (GLsizei, GLuintP));
+BGL_Wrap(FramebufferRenderbuffer, void, (GLenum, GLenum, GLenum, GLuint));
+BGL_Wrap(GenFramebuffers, void, (GLsizei, GLuintP));
+BGL_Wrap(GenRenderbuffers, void, (GLsizei, GLuintP));
+BGL_Wrap(GenVertexArrays, void, (GLsizei, GLuintP));
+BGL_Wrap(GetStringi, GLstring, (GLenum, GLuint));
+BGL_Wrap(IsVertexArray, GLboolean, (GLuint));
+BGL_Wrap(RenderbufferStorage, void, (GLenum, GLenum, GLsizei, GLsizei));
/* GL_VERSION_3_1 */
-BGL_Wrap(BindBufferBase, void, (GLenum, GLuint, GLuint))
-BGL_Wrap(BindBufferRange, void, (GLenum, GLuint, GLuint, GLintptr, GLsizeiptr))
-BGL_Wrap(GetActiveUniformBlockName, void, (GLuint, GLuint, GLsizei, GLsizeiP, GLcharP))
-BGL_Wrap(GetActiveUniformBlockiv, void, (GLuint, GLuint, GLenum, GLintP))
-BGL_Wrap(GetActiveUniformName, void, (GLuint, GLuint, GLsizei, GLsizeiP, GLcharP))
-BGL_Wrap(GetActiveUniformsiv, void, (GLuint, GLsizei, GLuintP, GLenum, GLintP))
-BGL_Wrap(GetIntegeri_v, void, (GLenum, GLuint, GLintP))
-BGL_Wrap(GetUniformBlockIndex, GLuint, (GLuint, GLstring))
-BGL_Wrap(GetUniformIndices, void, (GLuint, GLsizei, GLcharP, GLuintP))
-BGL_Wrap(UniformBlockBinding, void, (GLuint, GLuint, GLuint))
+BGL_Wrap(BindBufferBase, void, (GLenum, GLuint, GLuint));
+BGL_Wrap(BindBufferRange, void, (GLenum, GLuint, GLuint, GLintptr, GLsizeiptr));
+BGL_Wrap(GetActiveUniformBlockName, void, (GLuint, GLuint, GLsizei, GLsizeiP, GLcharP));
+BGL_Wrap(GetActiveUniformBlockiv, void, (GLuint, GLuint, GLenum, GLintP));
+BGL_Wrap(GetActiveUniformName, void, (GLuint, GLuint, GLsizei, GLsizeiP, GLcharP));
+BGL_Wrap(GetActiveUniformsiv, void, (GLuint, GLsizei, GLuintP, GLenum, GLintP));
+BGL_Wrap(GetIntegeri_v, void, (GLenum, GLuint, GLintP));
+BGL_Wrap(GetUniformBlockIndex, GLuint, (GLuint, GLstring));
+BGL_Wrap(GetUniformIndices, void, (GLuint, GLsizei, GLcharP, GLuintP));
+BGL_Wrap(UniformBlockBinding, void, (GLuint, GLuint, GLuint));
/* GL_VERSION_3_2 */
-BGL_Wrap(FramebufferTexture, void, (GLenum, GLenum, GLuint, GLint))
-BGL_Wrap(GetBufferParameteri64v, void, (GLenum, GLenum, GLint64P))
-BGL_Wrap(GetInteger64i_v, void, (GLenum, GLuint, GLint64P))
-BGL_Wrap(GetMultisamplefv, void, (GLenum, GLuint, GLfloatP))
-BGL_Wrap(SampleMaski, void, (GLuint, GLbitfield))
-BGL_Wrap(TexImage2DMultisample, void, (GLenum, GLsizei, GLenum, GLsizei, GLsizei, GLboolean))
-BGL_Wrap(TexImage3DMultisample, void, (GLenum, GLsizei, GLenum, GLsizei, GLsizei, GLsizei, GLboolean))
+BGL_Wrap(FramebufferTexture, void, (GLenum, GLenum, GLuint, GLint));
+BGL_Wrap(GetBufferParameteri64v, void, (GLenum, GLenum, GLint64P));
+BGL_Wrap(GetInteger64i_v, void, (GLenum, GLuint, GLint64P));
+BGL_Wrap(GetMultisamplefv, void, (GLenum, GLuint, GLfloatP));
+BGL_Wrap(SampleMaski, void, (GLuint, GLbitfield));
+BGL_Wrap(TexImage2DMultisample, void, (GLenum, GLsizei, GLenum, GLsizei, GLsizei, GLboolean));
+BGL_Wrap(TexImage3DMultisample, void, (GLenum, GLsizei, GLenum, GLsizei, GLsizei, GLsizei, GLboolean));
/* GL_VERSION_3_3 */
-BGL_Wrap(ColorP3ui, void, (GLenum, GLuint))
-BGL_Wrap(ColorP3uiv, void, (GLenum, GLuintP))
-BGL_Wrap(ColorP4ui, void, (GLenum, GLuint))
-BGL_Wrap(ColorP4uiv, void, (GLenum, GLuintP))
-BGL_Wrap(MultiTexCoordP1ui, void, (GLenum, GLenum, GLuint))
-BGL_Wrap(MultiTexCoordP1uiv, void, (GLenum, GLenum, GLuintP))
-BGL_Wrap(MultiTexCoordP2ui, void, (GLenum, GLenum, GLuint))
-BGL_Wrap(MultiTexCoordP2uiv, void, (GLenum, GLenum, GLuintP))
-BGL_Wrap(MultiTexCoordP3ui, void, (GLenum, GLenum, GLuint))
-BGL_Wrap(MultiTexCoordP3uiv, void, (GLenum, GLenum, GLuintP))
-BGL_Wrap(MultiTexCoordP4ui, void, (GLenum, GLenum, GLuint))
-BGL_Wrap(MultiTexCoordP4uiv, void, (GLenum, GLenum, GLuintP))
-BGL_Wrap(NormalP3ui, void, (GLenum, GLuint))
-BGL_Wrap(NormalP3uiv, void, (GLenum, GLuintP))
-BGL_Wrap(SecondaryColorP3ui, void, (GLenum, GLuint))
-BGL_Wrap(SecondaryColorP3uiv, void, (GLenum, GLuintP))
-BGL_Wrap(TexCoordP1ui, void, (GLenum, GLuint))
-BGL_Wrap(TexCoordP1uiv, void, (GLenum, GLuintP))
-BGL_Wrap(TexCoordP2ui, void, (GLenum, GLuint))
-BGL_Wrap(TexCoordP2uiv, void, (GLenum, GLuintP))
-BGL_Wrap(TexCoordP3ui, void, (GLenum, GLuint))
-BGL_Wrap(TexCoordP3uiv, void, (GLenum, GLuintP))
-BGL_Wrap(TexCoordP4ui, void, (GLenum, GLuint))
-BGL_Wrap(TexCoordP4uiv, void, (GLenum, GLuintP))
-BGL_Wrap(VertexP2ui, void, (GLenum, GLuint))
-BGL_Wrap(VertexP2uiv, void, (GLenum, GLuintP))
-BGL_Wrap(VertexP3ui, void, (GLenum, GLuint))
-BGL_Wrap(VertexP3uiv, void, (GLenum, GLuintP))
-BGL_Wrap(VertexP4ui, void, (GLenum, GLuint))
-BGL_Wrap(VertexP4uiv, void, (GLenum, GLuintP))
-
-
-BGLU_Wrap(Perspective, void, (GLdouble, GLdouble, GLdouble, GLdouble))
-BGLU_Wrap(LookAt, void, (GLdouble, GLdouble, GLdouble, GLdouble, GLdouble, GLdouble, GLdouble, GLdouble, GLdouble))
-BGLU_Wrap(Ortho2D, void, (GLdouble, GLdouble, GLdouble, GLdouble))
-BGLU_Wrap(PickMatrix, void, (GLdouble, GLdouble, GLdouble, GLdouble, GLintP))
-BGLU_Wrap(Project, GLint, (GLdouble, GLdouble, GLdouble, GLdoubleP, GLdoubleP, GLintP, GLdoubleP, GLdoubleP, GLdoubleP))
-BGLU_Wrap(UnProject, GLint, (GLdouble, GLdouble, GLdouble, GLdoubleP, GLdoubleP, GLintP, GLdoubleP, GLdoubleP, GLdoubleP))
+/* no new functions besides packed immediate mode (not part of core profile) */
/** \} */
@@ -1692,26 +1340,12 @@ BGLU_Wrap(UnProject, GLint, (GLdouble, GLdouble, GLdouble, GLdouble
/** \name Module Definition
* \{ */
-#define MethodDefu(func) {"glu"#func, Method_##func, METH_VARARGS, NULL}
-
-static struct PyMethodDef BGL_methods[] = {
- MethodDefu(Perspective),
- MethodDefu(LookAt),
- MethodDefu(Ortho2D),
- MethodDefu(PickMatrix),
- MethodDefu(Project),
- MethodDefu(UnProject),
- {NULL, NULL, 0, NULL}
-};
-
-#undef MethodDefu
-
static struct PyModuleDef BGL_module_def = {
PyModuleDef_HEAD_INIT,
"bgl", /* m_name */
NULL, /* m_doc */
0, /* m_size */
- BGL_methods, /* m_methods */
+ NULL, /* m_methods */
NULL, /* m_reload */
NULL, /* m_traverse */
NULL, /* m_clear */
@@ -1745,9 +1379,6 @@ static void py_module_dict_add_method(PyObject *submodule, PyObject *dict, PyMet
}
}
-/* TODO, expose to users */
-static bool use_deprecated = true;
-
PyObject *BPyInit_bgl(void)
{
PyObject *submodule, *dict;
@@ -1822,268 +1453,6 @@ PyObject *BPyInit_bgl(void)
PY_MOD_ADD_METHOD(TexParameteriv);
PY_MOD_ADD_METHOD(Viewport);
}
- /* adding in GL_VERSION_1_0 removed from core profile */
- if (use_deprecated == true) {
- PY_MOD_ADD_METHOD(Accum);
- PY_MOD_ADD_METHOD(AlphaFunc);
- PY_MOD_ADD_METHOD(Begin);
- PY_MOD_ADD_METHOD(Bitmap);
- PY_MOD_ADD_METHOD(CallList);
- PY_MOD_ADD_METHOD(CallLists);
- PY_MOD_ADD_METHOD(ClearAccum);
- PY_MOD_ADD_METHOD(ClearIndex);
- PY_MOD_ADD_METHOD(ClipPlane);
- PY_MOD_ADD_METHOD(Color3b);
- PY_MOD_ADD_METHOD(Color3bv);
- PY_MOD_ADD_METHOD(Color3d);
- PY_MOD_ADD_METHOD(Color3dv);
- PY_MOD_ADD_METHOD(Color3f);
- PY_MOD_ADD_METHOD(Color3fv);
- PY_MOD_ADD_METHOD(Color3i);
- PY_MOD_ADD_METHOD(Color3iv);
- PY_MOD_ADD_METHOD(Color3s);
- PY_MOD_ADD_METHOD(Color3sv);
- PY_MOD_ADD_METHOD(Color3ub);
- PY_MOD_ADD_METHOD(Color3ubv);
- PY_MOD_ADD_METHOD(Color3ui);
- PY_MOD_ADD_METHOD(Color3uiv);
- PY_MOD_ADD_METHOD(Color3us);
- PY_MOD_ADD_METHOD(Color3usv);
- PY_MOD_ADD_METHOD(Color4b);
- PY_MOD_ADD_METHOD(Color4bv);
- PY_MOD_ADD_METHOD(Color4d);
- PY_MOD_ADD_METHOD(Color4dv);
- PY_MOD_ADD_METHOD(Color4f);
- PY_MOD_ADD_METHOD(Color4fv);
- PY_MOD_ADD_METHOD(Color4i);
- PY_MOD_ADD_METHOD(Color4iv);
- PY_MOD_ADD_METHOD(Color4s);
- PY_MOD_ADD_METHOD(Color4sv);
- PY_MOD_ADD_METHOD(Color4ub);
- PY_MOD_ADD_METHOD(Color4ubv);
- PY_MOD_ADD_METHOD(Color4ui);
- PY_MOD_ADD_METHOD(Color4uiv);
- PY_MOD_ADD_METHOD(Color4us);
- PY_MOD_ADD_METHOD(Color4usv);
- PY_MOD_ADD_METHOD(ColorMaterial);
- PY_MOD_ADD_METHOD(CopyPixels);
- PY_MOD_ADD_METHOD(DeleteLists);
- PY_MOD_ADD_METHOD(DrawPixels);
- PY_MOD_ADD_METHOD(EdgeFlag);
- PY_MOD_ADD_METHOD(EdgeFlagv);
- PY_MOD_ADD_METHOD(End);
- PY_MOD_ADD_METHOD(EndList);
- PY_MOD_ADD_METHOD(EvalCoord1d);
- PY_MOD_ADD_METHOD(EvalCoord1dv);
- PY_MOD_ADD_METHOD(EvalCoord1f);
- PY_MOD_ADD_METHOD(EvalCoord1fv);
- PY_MOD_ADD_METHOD(EvalCoord2d);
- PY_MOD_ADD_METHOD(EvalCoord2dv);
- PY_MOD_ADD_METHOD(EvalCoord2f);
- PY_MOD_ADD_METHOD(EvalCoord2fv);
- PY_MOD_ADD_METHOD(EvalMesh1);
- PY_MOD_ADD_METHOD(EvalMesh2);
- PY_MOD_ADD_METHOD(EvalPoint1);
- PY_MOD_ADD_METHOD(EvalPoint2);
- PY_MOD_ADD_METHOD(FeedbackBuffer);
- PY_MOD_ADD_METHOD(Fogf);
- PY_MOD_ADD_METHOD(Fogfv);
- PY_MOD_ADD_METHOD(Fogi);
- PY_MOD_ADD_METHOD(Fogiv);
- PY_MOD_ADD_METHOD(Frustum);
- PY_MOD_ADD_METHOD(GenLists);
- PY_MOD_ADD_METHOD(GetClipPlane);
- PY_MOD_ADD_METHOD(GetLightfv);
- PY_MOD_ADD_METHOD(GetLightiv);
- PY_MOD_ADD_METHOD(GetMapdv);
- PY_MOD_ADD_METHOD(GetMapfv);
- PY_MOD_ADD_METHOD(GetMapiv);
- PY_MOD_ADD_METHOD(GetMaterialfv);
- PY_MOD_ADD_METHOD(GetMaterialiv);
- PY_MOD_ADD_METHOD(GetPixelMapfv);
- PY_MOD_ADD_METHOD(GetPixelMapuiv);
- PY_MOD_ADD_METHOD(GetPixelMapusv);
- PY_MOD_ADD_METHOD(GetPolygonStipple);
- PY_MOD_ADD_METHOD(GetTexEnvfv);
- PY_MOD_ADD_METHOD(GetTexEnviv);
- PY_MOD_ADD_METHOD(GetTexGendv);
- PY_MOD_ADD_METHOD(GetTexGenfv);
- PY_MOD_ADD_METHOD(GetTexGeniv);
- PY_MOD_ADD_METHOD(IndexMask);
- PY_MOD_ADD_METHOD(Indexd);
- PY_MOD_ADD_METHOD(Indexdv);
- PY_MOD_ADD_METHOD(Indexf);
- PY_MOD_ADD_METHOD(Indexfv);
- PY_MOD_ADD_METHOD(Indexi);
- PY_MOD_ADD_METHOD(Indexiv);
- PY_MOD_ADD_METHOD(Indexs);
- PY_MOD_ADD_METHOD(Indexsv);
- PY_MOD_ADD_METHOD(InitNames);
- PY_MOD_ADD_METHOD(IsList);
- PY_MOD_ADD_METHOD(LightModelf);
- PY_MOD_ADD_METHOD(LightModelfv);
- PY_MOD_ADD_METHOD(LightModeli);
- PY_MOD_ADD_METHOD(LightModeliv);
- PY_MOD_ADD_METHOD(Lightf);
- PY_MOD_ADD_METHOD(Lightfv);
- PY_MOD_ADD_METHOD(Lighti);
- PY_MOD_ADD_METHOD(Lightiv);
- PY_MOD_ADD_METHOD(LineStipple);
- PY_MOD_ADD_METHOD(ListBase);
- PY_MOD_ADD_METHOD(LoadIdentity);
- PY_MOD_ADD_METHOD(LoadMatrixd);
- PY_MOD_ADD_METHOD(LoadMatrixf);
- PY_MOD_ADD_METHOD(LoadName);
- PY_MOD_ADD_METHOD(Map1d);
- PY_MOD_ADD_METHOD(Map1f);
- PY_MOD_ADD_METHOD(Map2d);
- PY_MOD_ADD_METHOD(Map2f);
- PY_MOD_ADD_METHOD(MapGrid1d);
- PY_MOD_ADD_METHOD(MapGrid1f);
- PY_MOD_ADD_METHOD(MapGrid2d);
- PY_MOD_ADD_METHOD(MapGrid2f);
- PY_MOD_ADD_METHOD(Materialf);
- PY_MOD_ADD_METHOD(Materialfv);
- PY_MOD_ADD_METHOD(Materiali);
- PY_MOD_ADD_METHOD(Materialiv);
- PY_MOD_ADD_METHOD(MatrixMode);
- PY_MOD_ADD_METHOD(MultMatrixd);
- PY_MOD_ADD_METHOD(MultMatrixf);
- PY_MOD_ADD_METHOD(NewList);
- PY_MOD_ADD_METHOD(Normal3b);
- PY_MOD_ADD_METHOD(Normal3bv);
- PY_MOD_ADD_METHOD(Normal3d);
- PY_MOD_ADD_METHOD(Normal3dv);
- PY_MOD_ADD_METHOD(Normal3f);
- PY_MOD_ADD_METHOD(Normal3fv);
- PY_MOD_ADD_METHOD(Normal3i);
- PY_MOD_ADD_METHOD(Normal3iv);
- PY_MOD_ADD_METHOD(Normal3s);
- PY_MOD_ADD_METHOD(Normal3sv);
- PY_MOD_ADD_METHOD(Ortho);
- PY_MOD_ADD_METHOD(PassThrough);
- PY_MOD_ADD_METHOD(PixelMapfv);
- PY_MOD_ADD_METHOD(PixelMapuiv);
- PY_MOD_ADD_METHOD(PixelMapusv);
- PY_MOD_ADD_METHOD(PixelTransferf);
- PY_MOD_ADD_METHOD(PixelTransferi);
- PY_MOD_ADD_METHOD(PixelZoom);
- PY_MOD_ADD_METHOD(PolygonStipple);
- PY_MOD_ADD_METHOD(PopAttrib);
- PY_MOD_ADD_METHOD(PopMatrix);
- PY_MOD_ADD_METHOD(PopName);
- PY_MOD_ADD_METHOD(PushAttrib);
- PY_MOD_ADD_METHOD(PushMatrix);
- PY_MOD_ADD_METHOD(PushName);
- PY_MOD_ADD_METHOD(RasterPos2d);
- PY_MOD_ADD_METHOD(RasterPos2dv);
- PY_MOD_ADD_METHOD(RasterPos2f);
- PY_MOD_ADD_METHOD(RasterPos2fv);
- PY_MOD_ADD_METHOD(RasterPos2i);
- PY_MOD_ADD_METHOD(RasterPos2iv);
- PY_MOD_ADD_METHOD(RasterPos2s);
- PY_MOD_ADD_METHOD(RasterPos2sv);
- PY_MOD_ADD_METHOD(RasterPos3d);
- PY_MOD_ADD_METHOD(RasterPos3dv);
- PY_MOD_ADD_METHOD(RasterPos3f);
- PY_MOD_ADD_METHOD(RasterPos3fv);
- PY_MOD_ADD_METHOD(RasterPos3i);
- PY_MOD_ADD_METHOD(RasterPos3iv);
- PY_MOD_ADD_METHOD(RasterPos3s);
- PY_MOD_ADD_METHOD(RasterPos3sv);
- PY_MOD_ADD_METHOD(RasterPos4d);
- PY_MOD_ADD_METHOD(RasterPos4dv);
- PY_MOD_ADD_METHOD(RasterPos4f);
- PY_MOD_ADD_METHOD(RasterPos4fv);
- PY_MOD_ADD_METHOD(RasterPos4i);
- PY_MOD_ADD_METHOD(RasterPos4iv);
- PY_MOD_ADD_METHOD(RasterPos4s);
- PY_MOD_ADD_METHOD(RasterPos4sv);
- PY_MOD_ADD_METHOD(Rectd);
- PY_MOD_ADD_METHOD(Rectdv);
- PY_MOD_ADD_METHOD(Rectf);
- PY_MOD_ADD_METHOD(Rectfv);
- PY_MOD_ADD_METHOD(Recti);
- PY_MOD_ADD_METHOD(Rectiv);
- PY_MOD_ADD_METHOD(Rects);
- PY_MOD_ADD_METHOD(Rectsv);
- PY_MOD_ADD_METHOD(RenderMode);
- PY_MOD_ADD_METHOD(Rotated);
- PY_MOD_ADD_METHOD(Rotatef);
- PY_MOD_ADD_METHOD(Scaled);
- PY_MOD_ADD_METHOD(Scalef);
- PY_MOD_ADD_METHOD(SelectBuffer);
- PY_MOD_ADD_METHOD(ShadeModel);
- PY_MOD_ADD_METHOD(TexCoord1d);
- PY_MOD_ADD_METHOD(TexCoord1dv);
- PY_MOD_ADD_METHOD(TexCoord1f);
- PY_MOD_ADD_METHOD(TexCoord1fv);
- PY_MOD_ADD_METHOD(TexCoord1i);
- PY_MOD_ADD_METHOD(TexCoord1iv);
- PY_MOD_ADD_METHOD(TexCoord1s);
- PY_MOD_ADD_METHOD(TexCoord1sv);
- PY_MOD_ADD_METHOD(TexCoord2d);
- PY_MOD_ADD_METHOD(TexCoord2dv);
- PY_MOD_ADD_METHOD(TexCoord2f);
- PY_MOD_ADD_METHOD(TexCoord2fv);
- PY_MOD_ADD_METHOD(TexCoord2i);
- PY_MOD_ADD_METHOD(TexCoord2iv);
- PY_MOD_ADD_METHOD(TexCoord2s);
- PY_MOD_ADD_METHOD(TexCoord2sv);
- PY_MOD_ADD_METHOD(TexCoord3d);
- PY_MOD_ADD_METHOD(TexCoord3dv);
- PY_MOD_ADD_METHOD(TexCoord3f);
- PY_MOD_ADD_METHOD(TexCoord3fv);
- PY_MOD_ADD_METHOD(TexCoord3i);
- PY_MOD_ADD_METHOD(TexCoord3iv);
- PY_MOD_ADD_METHOD(TexCoord3s);
- PY_MOD_ADD_METHOD(TexCoord3sv);
- PY_MOD_ADD_METHOD(TexCoord4d);
- PY_MOD_ADD_METHOD(TexCoord4dv);
- PY_MOD_ADD_METHOD(TexCoord4f);
- PY_MOD_ADD_METHOD(TexCoord4fv);
- PY_MOD_ADD_METHOD(TexCoord4i);
- PY_MOD_ADD_METHOD(TexCoord4iv);
- PY_MOD_ADD_METHOD(TexCoord4s);
- PY_MOD_ADD_METHOD(TexCoord4sv);
- PY_MOD_ADD_METHOD(TexEnvf);
- PY_MOD_ADD_METHOD(TexEnvfv);
- PY_MOD_ADD_METHOD(TexEnvi);
- PY_MOD_ADD_METHOD(TexEnviv);
- PY_MOD_ADD_METHOD(TexGend);
- PY_MOD_ADD_METHOD(TexGendv);
- PY_MOD_ADD_METHOD(TexGenf);
- PY_MOD_ADD_METHOD(TexGenfv);
- PY_MOD_ADD_METHOD(TexGeni);
- PY_MOD_ADD_METHOD(TexGeniv);
- PY_MOD_ADD_METHOD(Translated);
- PY_MOD_ADD_METHOD(Translatef);
- PY_MOD_ADD_METHOD(Vertex2d);
- PY_MOD_ADD_METHOD(Vertex2dv);
- PY_MOD_ADD_METHOD(Vertex2f);
- PY_MOD_ADD_METHOD(Vertex2fv);
- PY_MOD_ADD_METHOD(Vertex2i);
- PY_MOD_ADD_METHOD(Vertex2iv);
- PY_MOD_ADD_METHOD(Vertex2s);
- PY_MOD_ADD_METHOD(Vertex2sv);
- PY_MOD_ADD_METHOD(Vertex3d);
- PY_MOD_ADD_METHOD(Vertex3dv);
- PY_MOD_ADD_METHOD(Vertex3f);
- PY_MOD_ADD_METHOD(Vertex3fv);
- PY_MOD_ADD_METHOD(Vertex3i);
- PY_MOD_ADD_METHOD(Vertex3iv);
- PY_MOD_ADD_METHOD(Vertex3s);
- PY_MOD_ADD_METHOD(Vertex3sv);
- PY_MOD_ADD_METHOD(Vertex4d);
- PY_MOD_ADD_METHOD(Vertex4dv);
- PY_MOD_ADD_METHOD(Vertex4f);
- PY_MOD_ADD_METHOD(Vertex4fv);
- PY_MOD_ADD_METHOD(Vertex4i);
- PY_MOD_ADD_METHOD(Vertex4iv);
- PY_MOD_ADD_METHOD(Vertex4s);
- PY_MOD_ADD_METHOD(Vertex4sv);
- }
-
/* GL_VERSION_1_1 */
{
@@ -2101,27 +1470,6 @@ PyObject *BPyInit_bgl(void)
PY_MOD_ADD_METHOD(TexSubImage1D);
PY_MOD_ADD_METHOD(TexSubImage2D);
}
- /* adding in GL_VERSION_1_1 removed from core profile */
- if (use_deprecated == true) {
- PY_MOD_ADD_METHOD(AreTexturesResident);
- PY_MOD_ADD_METHOD(ArrayElement);
- PY_MOD_ADD_METHOD(ColorPointer);
- PY_MOD_ADD_METHOD(DisableClientState);
- PY_MOD_ADD_METHOD(EdgeFlagPointer);
- PY_MOD_ADD_METHOD(EnableClientState);
- PY_MOD_ADD_METHOD(GetPointerv);
- PY_MOD_ADD_METHOD(IndexPointer);
- PY_MOD_ADD_METHOD(Indexub);
- PY_MOD_ADD_METHOD(Indexubv);
- PY_MOD_ADD_METHOD(InterleavedArrays);
- PY_MOD_ADD_METHOD(NormalPointer);
- PY_MOD_ADD_METHOD(PopClientAttrib);
- PY_MOD_ADD_METHOD(PrioritizeTextures);
- PY_MOD_ADD_METHOD(PushClientAttrib);
- PY_MOD_ADD_METHOD(TexCoordPointer);
- PY_MOD_ADD_METHOD(VertexPointer);
- }
-
/* GL_VERSION_1_2 */
{
@@ -2131,7 +1479,6 @@ PyObject *BPyInit_bgl(void)
PY_MOD_ADD_METHOD(TexSubImage3D);
}
-
/* GL_VERSION_1_3 */
{
PY_MOD_ADD_METHOD(ActiveTexture);
@@ -2144,47 +1491,6 @@ PyObject *BPyInit_bgl(void)
PY_MOD_ADD_METHOD(GetCompressedTexImage);
PY_MOD_ADD_METHOD(SampleCoverage);
}
- /* adding in GL_VERSION_1_3 removed from core profile */
- if (use_deprecated == true) {
- PY_MOD_ADD_METHOD(ClientActiveTexture);
- PY_MOD_ADD_METHOD(LoadTransposeMatrixd);
- PY_MOD_ADD_METHOD(LoadTransposeMatrixf);
- PY_MOD_ADD_METHOD(MultTransposeMatrixd);
- PY_MOD_ADD_METHOD(MultTransposeMatrixf);
- PY_MOD_ADD_METHOD(MultiTexCoord1d);
- PY_MOD_ADD_METHOD(MultiTexCoord1dv);
- PY_MOD_ADD_METHOD(MultiTexCoord1f);
- PY_MOD_ADD_METHOD(MultiTexCoord1fv);
- PY_MOD_ADD_METHOD(MultiTexCoord1i);
- PY_MOD_ADD_METHOD(MultiTexCoord1iv);
- PY_MOD_ADD_METHOD(MultiTexCoord1s);
- PY_MOD_ADD_METHOD(MultiTexCoord1sv);
- PY_MOD_ADD_METHOD(MultiTexCoord2d);
- PY_MOD_ADD_METHOD(MultiTexCoord2dv);
- PY_MOD_ADD_METHOD(MultiTexCoord2f);
- PY_MOD_ADD_METHOD(MultiTexCoord2fv);
- PY_MOD_ADD_METHOD(MultiTexCoord2i);
- PY_MOD_ADD_METHOD(MultiTexCoord2iv);
- PY_MOD_ADD_METHOD(MultiTexCoord2s);
- PY_MOD_ADD_METHOD(MultiTexCoord2sv);
- PY_MOD_ADD_METHOD(MultiTexCoord3d);
- PY_MOD_ADD_METHOD(MultiTexCoord3dv);
- PY_MOD_ADD_METHOD(MultiTexCoord3f);
- PY_MOD_ADD_METHOD(MultiTexCoord3fv);
- PY_MOD_ADD_METHOD(MultiTexCoord3i);
- PY_MOD_ADD_METHOD(MultiTexCoord3iv);
- PY_MOD_ADD_METHOD(MultiTexCoord3s);
- PY_MOD_ADD_METHOD(MultiTexCoord3sv);
- PY_MOD_ADD_METHOD(MultiTexCoord4d);
- PY_MOD_ADD_METHOD(MultiTexCoord4dv);
- PY_MOD_ADD_METHOD(MultiTexCoord4f);
- PY_MOD_ADD_METHOD(MultiTexCoord4fv);
- PY_MOD_ADD_METHOD(MultiTexCoord4i);
- PY_MOD_ADD_METHOD(MultiTexCoord4iv);
- PY_MOD_ADD_METHOD(MultiTexCoord4s);
- PY_MOD_ADD_METHOD(MultiTexCoord4sv);
- }
-
/* GL_VERSION_1_4 */
{
@@ -2192,7 +1498,6 @@ PyObject *BPyInit_bgl(void)
PY_MOD_ADD_METHOD(BlendEquation);
}
-
/* GL_VERSION_1_5 */
{
PY_MOD_ADD_METHOD(BeginQuery);
@@ -2216,7 +1521,6 @@ PyObject *BPyInit_bgl(void)
PY_MOD_ADD_METHOD(UnmapBuffer);
}
-
/* GL_VERSION_2_0 */
{
PY_MOD_ADD_METHOD(AttachShader);
@@ -2314,7 +1618,6 @@ PyObject *BPyInit_bgl(void)
PY_MOD_ADD_METHOD(VertexAttribPointer);
}
-
/* GL_VERSION_2_1 */
{
PY_MOD_ADD_METHOD(UniformMatrix2x3fv);
@@ -2325,16 +1628,25 @@ PyObject *BPyInit_bgl(void)
PY_MOD_ADD_METHOD(UniformMatrix4x3fv);
}
-
/* GL_VERSION_3_0 */
{
+ PY_MOD_ADD_METHOD(BindFramebuffer);
+ PY_MOD_ADD_METHOD(BindRenderbuffer);
PY_MOD_ADD_METHOD(BindVertexArray);
+ PY_MOD_ADD_METHOD(BlitFramebuffer);
+ PY_MOD_ADD_METHOD(CheckFramebufferStatus);
+ PY_MOD_ADD_METHOD(DeleteFramebuffers);
+ PY_MOD_ADD_METHOD(DeleteRenderbuffers);
PY_MOD_ADD_METHOD(DeleteVertexArrays);
+ PY_MOD_ADD_METHOD(FramebufferRenderbuffer);
+ PY_MOD_ADD_METHOD(GenFramebuffers);
+ PY_MOD_ADD_METHOD(GenRenderbuffers);
PY_MOD_ADD_METHOD(GenVertexArrays);
+ PY_MOD_ADD_METHOD(GetStringi);
PY_MOD_ADD_METHOD(IsVertexArray);
+ PY_MOD_ADD_METHOD(RenderbufferStorage);
}
-
/* GL_VERSION_3_1 */
{
PY_MOD_ADD_METHOD(BindBufferBase);
@@ -2349,7 +1661,6 @@ PyObject *BPyInit_bgl(void)
PY_MOD_ADD_METHOD(UniformBlockBinding);
}
-
/* GL_VERSION_3_2 */
{
PY_MOD_ADD_METHOD(FramebufferTexture);
@@ -2361,39 +1672,8 @@ PyObject *BPyInit_bgl(void)
PY_MOD_ADD_METHOD(TexImage3DMultisample);
}
-
/* GL_VERSION_3_3 */
{
- PY_MOD_ADD_METHOD(ColorP3ui);
- PY_MOD_ADD_METHOD(ColorP3uiv);
- PY_MOD_ADD_METHOD(ColorP4ui);
- PY_MOD_ADD_METHOD(ColorP4uiv);
- PY_MOD_ADD_METHOD(MultiTexCoordP1ui);
- PY_MOD_ADD_METHOD(MultiTexCoordP1uiv);
- PY_MOD_ADD_METHOD(MultiTexCoordP2ui);
- PY_MOD_ADD_METHOD(MultiTexCoordP2uiv);
- PY_MOD_ADD_METHOD(MultiTexCoordP3ui);
- PY_MOD_ADD_METHOD(MultiTexCoordP3uiv);
- PY_MOD_ADD_METHOD(MultiTexCoordP4ui);
- PY_MOD_ADD_METHOD(MultiTexCoordP4uiv);
- PY_MOD_ADD_METHOD(NormalP3ui);
- PY_MOD_ADD_METHOD(NormalP3uiv);
- PY_MOD_ADD_METHOD(SecondaryColorP3ui);
- PY_MOD_ADD_METHOD(SecondaryColorP3uiv);
- PY_MOD_ADD_METHOD(TexCoordP1ui);
- PY_MOD_ADD_METHOD(TexCoordP1uiv);
- PY_MOD_ADD_METHOD(TexCoordP2ui);
- PY_MOD_ADD_METHOD(TexCoordP2uiv);
- PY_MOD_ADD_METHOD(TexCoordP3ui);
- PY_MOD_ADD_METHOD(TexCoordP3uiv);
- PY_MOD_ADD_METHOD(TexCoordP4ui);
- PY_MOD_ADD_METHOD(TexCoordP4uiv);
- PY_MOD_ADD_METHOD(VertexP2ui);
- PY_MOD_ADD_METHOD(VertexP2uiv);
- PY_MOD_ADD_METHOD(VertexP3ui);
- PY_MOD_ADD_METHOD(VertexP3uiv);
- PY_MOD_ADD_METHOD(VertexP4ui);
- PY_MOD_ADD_METHOD(VertexP4uiv);
}
#define PY_DICT_ADD_INT(x) py_module_dict_add_int(dict, #x, x)
@@ -2511,8 +1791,6 @@ PyObject *BPyInit_bgl(void)
PY_DICT_ADD_INT(GL_POINT);
PY_DICT_ADD_INT(GL_POINTS);
PY_DICT_ADD_INT(GL_POINT_SIZE);
- PY_DICT_ADD_INT(GL_POINT_SIZE_GRANULARITY);
- PY_DICT_ADD_INT(GL_POINT_SIZE_RANGE);
PY_DICT_ADD_INT(GL_POLYGON_MODE);
PY_DICT_ADD_INT(GL_POLYGON_OFFSET_FACTOR);
PY_DICT_ADD_INT(GL_POLYGON_OFFSET_FILL);
@@ -2602,338 +1880,6 @@ PyObject *BPyInit_bgl(void)
PY_DICT_ADD_INT(GL_XOR);
PY_DICT_ADD_INT(GL_ZERO);
}
- /* adding in GL_VERSION_1_1 removed from core profile */
- if (use_deprecated == true) {
- PY_DICT_ADD_INT(GL_2D);
- PY_DICT_ADD_INT(GL_2_BYTES);
- PY_DICT_ADD_INT(GL_3D);
- PY_DICT_ADD_INT(GL_3D_COLOR);
- PY_DICT_ADD_INT(GL_3D_COLOR_TEXTURE);
- PY_DICT_ADD_INT(GL_3_BYTES);
- PY_DICT_ADD_INT(GL_4D_COLOR_TEXTURE);
- PY_DICT_ADD_INT(GL_4_BYTES);
- PY_DICT_ADD_INT(GL_ACCUM);
- PY_DICT_ADD_INT(GL_ACCUM_ALPHA_BITS);
- PY_DICT_ADD_INT(GL_ACCUM_BLUE_BITS);
- PY_DICT_ADD_INT(GL_ACCUM_BUFFER_BIT);
- PY_DICT_ADD_INT(GL_ACCUM_CLEAR_VALUE);
- PY_DICT_ADD_INT(GL_ACCUM_GREEN_BITS);
- PY_DICT_ADD_INT(GL_ACCUM_RED_BITS);
- PY_DICT_ADD_INT(GL_ADD);
- PY_DICT_ADD_INT(GL_ALL_ATTRIB_BITS);
- PY_DICT_ADD_INT(GL_ALPHA12);
- PY_DICT_ADD_INT(GL_ALPHA16);
- PY_DICT_ADD_INT(GL_ALPHA4);
- PY_DICT_ADD_INT(GL_ALPHA8);
- PY_DICT_ADD_INT(GL_ALPHA_BIAS);
- PY_DICT_ADD_INT(GL_ALPHA_BITS);
- PY_DICT_ADD_INT(GL_ALPHA_SCALE);
- PY_DICT_ADD_INT(GL_ALPHA_TEST);
- PY_DICT_ADD_INT(GL_ALPHA_TEST_FUNC);
- PY_DICT_ADD_INT(GL_ALPHA_TEST_REF);
- PY_DICT_ADD_INT(GL_AMBIENT);
- PY_DICT_ADD_INT(GL_AMBIENT_AND_DIFFUSE);
- PY_DICT_ADD_INT(GL_ATTRIB_STACK_DEPTH);
- PY_DICT_ADD_INT(GL_AUTO_NORMAL);
- PY_DICT_ADD_INT(GL_AUX0);
- PY_DICT_ADD_INT(GL_AUX1);
- PY_DICT_ADD_INT(GL_AUX2);
- PY_DICT_ADD_INT(GL_AUX3);
- PY_DICT_ADD_INT(GL_AUX_BUFFERS);
- PY_DICT_ADD_INT(GL_BITMAP);
- PY_DICT_ADD_INT(GL_BITMAP_TOKEN);
- PY_DICT_ADD_INT(GL_BLUE_BIAS);
- PY_DICT_ADD_INT(GL_BLUE_BITS);
- PY_DICT_ADD_INT(GL_BLUE_SCALE);
- PY_DICT_ADD_INT(GL_C3F_V3F);
- PY_DICT_ADD_INT(GL_C4F_N3F_V3F);
- PY_DICT_ADD_INT(GL_C4UB_V2F);
- PY_DICT_ADD_INT(GL_C4UB_V3F);
- PY_DICT_ADD_INT(GL_CLAMP);
- PY_DICT_ADD_INT(GL_CLIENT_ALL_ATTRIB_BITS);
- PY_DICT_ADD_INT(GL_CLIENT_ATTRIB_STACK_DEPTH);
- PY_DICT_ADD_INT(GL_CLIENT_PIXEL_STORE_BIT);
- PY_DICT_ADD_INT(GL_CLIENT_VERTEX_ARRAY_BIT);
- PY_DICT_ADD_INT(GL_CLIP_PLANE0);
- PY_DICT_ADD_INT(GL_CLIP_PLANE1);
- PY_DICT_ADD_INT(GL_CLIP_PLANE2);
- PY_DICT_ADD_INT(GL_CLIP_PLANE3);
- PY_DICT_ADD_INT(GL_CLIP_PLANE4);
- PY_DICT_ADD_INT(GL_CLIP_PLANE5);
- PY_DICT_ADD_INT(GL_COEFF);
- PY_DICT_ADD_INT(GL_COLOR_ARRAY);
- PY_DICT_ADD_INT(GL_COLOR_ARRAY_POINTER);
- PY_DICT_ADD_INT(GL_COLOR_ARRAY_SIZE);
- PY_DICT_ADD_INT(GL_COLOR_ARRAY_STRIDE);
- PY_DICT_ADD_INT(GL_COLOR_ARRAY_TYPE);
- PY_DICT_ADD_INT(GL_COLOR_INDEX);
- PY_DICT_ADD_INT(GL_COLOR_INDEXES);
- PY_DICT_ADD_INT(GL_COLOR_MATERIAL);
- PY_DICT_ADD_INT(GL_COLOR_MATERIAL_FACE);
- PY_DICT_ADD_INT(GL_COLOR_MATERIAL_PARAMETER);
- PY_DICT_ADD_INT(GL_COMPILE);
- PY_DICT_ADD_INT(GL_COMPILE_AND_EXECUTE);
- PY_DICT_ADD_INT(GL_CONSTANT_ATTENUATION);
- PY_DICT_ADD_INT(GL_COPY_PIXEL_TOKEN);
- PY_DICT_ADD_INT(GL_CURRENT_BIT);
- PY_DICT_ADD_INT(GL_CURRENT_COLOR);
- PY_DICT_ADD_INT(GL_CURRENT_INDEX);
- PY_DICT_ADD_INT(GL_CURRENT_NORMAL);
- PY_DICT_ADD_INT(GL_CURRENT_RASTER_COLOR);
- PY_DICT_ADD_INT(GL_CURRENT_RASTER_DISTANCE);
- PY_DICT_ADD_INT(GL_CURRENT_RASTER_INDEX);
- PY_DICT_ADD_INT(GL_CURRENT_RASTER_POSITION);
- PY_DICT_ADD_INT(GL_CURRENT_RASTER_POSITION_VALID);
- PY_DICT_ADD_INT(GL_CURRENT_RASTER_TEXTURE_COORDS);
- PY_DICT_ADD_INT(GL_CURRENT_TEXTURE_COORDS);
- PY_DICT_ADD_INT(GL_DECAL);
- PY_DICT_ADD_INT(GL_DEPTH_BIAS);
- PY_DICT_ADD_INT(GL_DEPTH_BITS);
- PY_DICT_ADD_INT(GL_DEPTH_SCALE);
- PY_DICT_ADD_INT(GL_DIFFUSE);
- PY_DICT_ADD_INT(GL_DOMAIN);
- PY_DICT_ADD_INT(GL_DRAW_PIXEL_TOKEN);
- PY_DICT_ADD_INT(GL_EDGE_FLAG);
- PY_DICT_ADD_INT(GL_EDGE_FLAG_ARRAY);
- PY_DICT_ADD_INT(GL_EDGE_FLAG_ARRAY_POINTER);
- PY_DICT_ADD_INT(GL_EDGE_FLAG_ARRAY_STRIDE);
- PY_DICT_ADD_INT(GL_EMISSION);
- PY_DICT_ADD_INT(GL_ENABLE_BIT);
- PY_DICT_ADD_INT(GL_EVAL_BIT);
- PY_DICT_ADD_INT(GL_EXP);
- PY_DICT_ADD_INT(GL_EXP2);
- PY_DICT_ADD_INT(GL_EYE_LINEAR);
- PY_DICT_ADD_INT(GL_EYE_PLANE);
- PY_DICT_ADD_INT(GL_FEEDBACK);
- PY_DICT_ADD_INT(GL_FEEDBACK_BUFFER_POINTER);
- PY_DICT_ADD_INT(GL_FEEDBACK_BUFFER_SIZE);
- PY_DICT_ADD_INT(GL_FEEDBACK_BUFFER_TYPE);
- PY_DICT_ADD_INT(GL_FLAT);
- PY_DICT_ADD_INT(GL_FOG);
- PY_DICT_ADD_INT(GL_FOG_BIT);
- PY_DICT_ADD_INT(GL_FOG_COLOR);
- PY_DICT_ADD_INT(GL_FOG_DENSITY);
- PY_DICT_ADD_INT(GL_FOG_END);
- PY_DICT_ADD_INT(GL_FOG_HINT);
- PY_DICT_ADD_INT(GL_FOG_INDEX);
- PY_DICT_ADD_INT(GL_FOG_MODE);
- PY_DICT_ADD_INT(GL_FOG_START);
- PY_DICT_ADD_INT(GL_GREEN_BIAS);
- PY_DICT_ADD_INT(GL_GREEN_BITS);
- PY_DICT_ADD_INT(GL_GREEN_SCALE);
- PY_DICT_ADD_INT(GL_HINT_BIT);
- PY_DICT_ADD_INT(GL_INDEX_ARRAY);
- PY_DICT_ADD_INT(GL_INDEX_ARRAY_POINTER);
- PY_DICT_ADD_INT(GL_INDEX_ARRAY_STRIDE);
- PY_DICT_ADD_INT(GL_INDEX_ARRAY_TYPE);
- PY_DICT_ADD_INT(GL_INDEX_BITS);
- PY_DICT_ADD_INT(GL_INDEX_CLEAR_VALUE);
- PY_DICT_ADD_INT(GL_INDEX_LOGIC_OP);
- PY_DICT_ADD_INT(GL_INDEX_MODE);
- PY_DICT_ADD_INT(GL_INDEX_OFFSET);
- PY_DICT_ADD_INT(GL_INDEX_SHIFT);
- PY_DICT_ADD_INT(GL_INDEX_WRITEMASK);
- PY_DICT_ADD_INT(GL_INTENSITY);
- PY_DICT_ADD_INT(GL_INTENSITY12);
- PY_DICT_ADD_INT(GL_INTENSITY16);
- PY_DICT_ADD_INT(GL_INTENSITY4);
- PY_DICT_ADD_INT(GL_INTENSITY8);
- PY_DICT_ADD_INT(GL_LIGHT0);
- PY_DICT_ADD_INT(GL_LIGHT1);
- PY_DICT_ADD_INT(GL_LIGHT2);
- PY_DICT_ADD_INT(GL_LIGHT3);
- PY_DICT_ADD_INT(GL_LIGHT4);
- PY_DICT_ADD_INT(GL_LIGHT5);
- PY_DICT_ADD_INT(GL_LIGHT6);
- PY_DICT_ADD_INT(GL_LIGHT7);
- PY_DICT_ADD_INT(GL_LIGHTING);
- PY_DICT_ADD_INT(GL_LIGHTING_BIT);
- PY_DICT_ADD_INT(GL_LIGHT_MODEL_AMBIENT);
- PY_DICT_ADD_INT(GL_LIGHT_MODEL_LOCAL_VIEWER);
- PY_DICT_ADD_INT(GL_LIGHT_MODEL_TWO_SIDE);
- PY_DICT_ADD_INT(GL_LINEAR_ATTENUATION);
- PY_DICT_ADD_INT(GL_LINE_BIT);
- PY_DICT_ADD_INT(GL_LINE_RESET_TOKEN);
- PY_DICT_ADD_INT(GL_LINE_STIPPLE);
- PY_DICT_ADD_INT(GL_LINE_STIPPLE_PATTERN);
- PY_DICT_ADD_INT(GL_LINE_STIPPLE_REPEAT);
- PY_DICT_ADD_INT(GL_LINE_TOKEN);
- PY_DICT_ADD_INT(GL_LIST_BASE);
- PY_DICT_ADD_INT(GL_LIST_BIT);
- PY_DICT_ADD_INT(GL_LIST_INDEX);
- PY_DICT_ADD_INT(GL_LIST_MODE);
- PY_DICT_ADD_INT(GL_LOAD);
- PY_DICT_ADD_INT(GL_LOGIC_OP);
- PY_DICT_ADD_INT(GL_LUMINANCE);
- PY_DICT_ADD_INT(GL_LUMINANCE12);
- PY_DICT_ADD_INT(GL_LUMINANCE12_ALPHA12);
- PY_DICT_ADD_INT(GL_LUMINANCE12_ALPHA4);
- PY_DICT_ADD_INT(GL_LUMINANCE16);
- PY_DICT_ADD_INT(GL_LUMINANCE16_ALPHA16);
- PY_DICT_ADD_INT(GL_LUMINANCE4);
- PY_DICT_ADD_INT(GL_LUMINANCE4_ALPHA4);
- PY_DICT_ADD_INT(GL_LUMINANCE6_ALPHA2);
- PY_DICT_ADD_INT(GL_LUMINANCE8);
- PY_DICT_ADD_INT(GL_LUMINANCE8_ALPHA8);
- PY_DICT_ADD_INT(GL_LUMINANCE_ALPHA);
- PY_DICT_ADD_INT(GL_MAP1_COLOR_4);
- PY_DICT_ADD_INT(GL_MAP1_GRID_DOMAIN);
- PY_DICT_ADD_INT(GL_MAP1_GRID_SEGMENTS);
- PY_DICT_ADD_INT(GL_MAP1_INDEX);
- PY_DICT_ADD_INT(GL_MAP1_NORMAL);
- PY_DICT_ADD_INT(GL_MAP1_TEXTURE_COORD_1);
- PY_DICT_ADD_INT(GL_MAP1_TEXTURE_COORD_2);
- PY_DICT_ADD_INT(GL_MAP1_TEXTURE_COORD_3);
- PY_DICT_ADD_INT(GL_MAP1_TEXTURE_COORD_4);
- PY_DICT_ADD_INT(GL_MAP1_VERTEX_3);
- PY_DICT_ADD_INT(GL_MAP1_VERTEX_4);
- PY_DICT_ADD_INT(GL_MAP2_COLOR_4);
- PY_DICT_ADD_INT(GL_MAP2_GRID_DOMAIN);
- PY_DICT_ADD_INT(GL_MAP2_GRID_SEGMENTS);
- PY_DICT_ADD_INT(GL_MAP2_INDEX);
- PY_DICT_ADD_INT(GL_MAP2_NORMAL);
- PY_DICT_ADD_INT(GL_MAP2_TEXTURE_COORD_1);
- PY_DICT_ADD_INT(GL_MAP2_TEXTURE_COORD_2);
- PY_DICT_ADD_INT(GL_MAP2_TEXTURE_COORD_3);
- PY_DICT_ADD_INT(GL_MAP2_TEXTURE_COORD_4);
- PY_DICT_ADD_INT(GL_MAP2_VERTEX_3);
- PY_DICT_ADD_INT(GL_MAP2_VERTEX_4);
- PY_DICT_ADD_INT(GL_MAP_COLOR);
- PY_DICT_ADD_INT(GL_MAP_STENCIL);
- PY_DICT_ADD_INT(GL_MATRIX_MODE);
- PY_DICT_ADD_INT(GL_MAX_ATTRIB_STACK_DEPTH);
- PY_DICT_ADD_INT(GL_MAX_CLIENT_ATTRIB_STACK_DEPTH);
- PY_DICT_ADD_INT(GL_MAX_CLIP_PLANES);
- PY_DICT_ADD_INT(GL_MAX_EVAL_ORDER);
- PY_DICT_ADD_INT(GL_MAX_LIGHTS);
- PY_DICT_ADD_INT(GL_MAX_LIST_NESTING);
- PY_DICT_ADD_INT(GL_MAX_MODELVIEW_STACK_DEPTH);
- PY_DICT_ADD_INT(GL_MAX_NAME_STACK_DEPTH);
- PY_DICT_ADD_INT(GL_MAX_PIXEL_MAP_TABLE);
- PY_DICT_ADD_INT(GL_MAX_PROJECTION_STACK_DEPTH);
- PY_DICT_ADD_INT(GL_MAX_TEXTURE_STACK_DEPTH);
- PY_DICT_ADD_INT(GL_MODELVIEW);
- PY_DICT_ADD_INT(GL_MODELVIEW_MATRIX);
- PY_DICT_ADD_INT(GL_MODELVIEW_STACK_DEPTH);
- PY_DICT_ADD_INT(GL_MODULATE);
- PY_DICT_ADD_INT(GL_MULT);
- PY_DICT_ADD_INT(GL_N3F_V3F);
- PY_DICT_ADD_INT(GL_NAME_STACK_DEPTH);
- PY_DICT_ADD_INT(GL_NORMALIZE);
- PY_DICT_ADD_INT(GL_NORMAL_ARRAY);
- PY_DICT_ADD_INT(GL_NORMAL_ARRAY_POINTER);
- PY_DICT_ADD_INT(GL_NORMAL_ARRAY_STRIDE);
- PY_DICT_ADD_INT(GL_NORMAL_ARRAY_TYPE);
- PY_DICT_ADD_INT(GL_OBJECT_LINEAR);
- PY_DICT_ADD_INT(GL_OBJECT_PLANE);
- PY_DICT_ADD_INT(GL_ORDER);
- PY_DICT_ADD_INT(GL_PASS_THROUGH_TOKEN);
- PY_DICT_ADD_INT(GL_PERSPECTIVE_CORRECTION_HINT);
- PY_DICT_ADD_INT(GL_PIXEL_MAP_A_TO_A);
- PY_DICT_ADD_INT(GL_PIXEL_MAP_A_TO_A_SIZE);
- PY_DICT_ADD_INT(GL_PIXEL_MAP_B_TO_B);
- PY_DICT_ADD_INT(GL_PIXEL_MAP_B_TO_B_SIZE);
- PY_DICT_ADD_INT(GL_PIXEL_MAP_G_TO_G);
- PY_DICT_ADD_INT(GL_PIXEL_MAP_G_TO_G_SIZE);
- PY_DICT_ADD_INT(GL_PIXEL_MAP_I_TO_A);
- PY_DICT_ADD_INT(GL_PIXEL_MAP_I_TO_A_SIZE);
- PY_DICT_ADD_INT(GL_PIXEL_MAP_I_TO_B);
- PY_DICT_ADD_INT(GL_PIXEL_MAP_I_TO_B_SIZE);
- PY_DICT_ADD_INT(GL_PIXEL_MAP_I_TO_G);
- PY_DICT_ADD_INT(GL_PIXEL_MAP_I_TO_G_SIZE);
- PY_DICT_ADD_INT(GL_PIXEL_MAP_I_TO_I);
- PY_DICT_ADD_INT(GL_PIXEL_MAP_I_TO_I_SIZE);
- PY_DICT_ADD_INT(GL_PIXEL_MAP_I_TO_R);
- PY_DICT_ADD_INT(GL_PIXEL_MAP_I_TO_R_SIZE);
- PY_DICT_ADD_INT(GL_PIXEL_MAP_R_TO_R);
- PY_DICT_ADD_INT(GL_PIXEL_MAP_R_TO_R_SIZE);
- PY_DICT_ADD_INT(GL_PIXEL_MAP_S_TO_S);
- PY_DICT_ADD_INT(GL_PIXEL_MAP_S_TO_S_SIZE);
- PY_DICT_ADD_INT(GL_PIXEL_MODE_BIT);
- PY_DICT_ADD_INT(GL_POINT_BIT);
- PY_DICT_ADD_INT(GL_POINT_SMOOTH);
- PY_DICT_ADD_INT(GL_POINT_SMOOTH_HINT);
- PY_DICT_ADD_INT(GL_POINT_TOKEN);
- PY_DICT_ADD_INT(GL_POLYGON);
- PY_DICT_ADD_INT(GL_POLYGON_BIT);
- PY_DICT_ADD_INT(GL_POLYGON_STIPPLE);
- PY_DICT_ADD_INT(GL_POLYGON_STIPPLE_BIT);
- PY_DICT_ADD_INT(GL_POLYGON_TOKEN);
- PY_DICT_ADD_INT(GL_POSITION);
- PY_DICT_ADD_INT(GL_PROJECTION);
- PY_DICT_ADD_INT(GL_PROJECTION_MATRIX);
- PY_DICT_ADD_INT(GL_PROJECTION_STACK_DEPTH);
- PY_DICT_ADD_INT(GL_Q);
- PY_DICT_ADD_INT(GL_QUADRATIC_ATTENUATION);
- PY_DICT_ADD_INT(GL_QUADS);
- PY_DICT_ADD_INT(GL_QUAD_STRIP);
- PY_DICT_ADD_INT(GL_R);
- PY_DICT_ADD_INT(GL_RED_BIAS);
- PY_DICT_ADD_INT(GL_RED_BITS);
- PY_DICT_ADD_INT(GL_RED_SCALE);
- PY_DICT_ADD_INT(GL_RENDER);
- PY_DICT_ADD_INT(GL_RENDER_MODE);
- PY_DICT_ADD_INT(GL_RETURN);
- PY_DICT_ADD_INT(GL_RGBA_MODE);
- PY_DICT_ADD_INT(GL_S);
- PY_DICT_ADD_INT(GL_SCISSOR_BIT);
- PY_DICT_ADD_INT(GL_SELECT);
- PY_DICT_ADD_INT(GL_SELECTION_BUFFER_POINTER);
- PY_DICT_ADD_INT(GL_SELECTION_BUFFER_SIZE);
- PY_DICT_ADD_INT(GL_SHADE_MODEL);
- PY_DICT_ADD_INT(GL_SHININESS);
- PY_DICT_ADD_INT(GL_SMOOTH);
- PY_DICT_ADD_INT(GL_SPECULAR);
- PY_DICT_ADD_INT(GL_SPHERE_MAP);
- PY_DICT_ADD_INT(GL_SPOT_CUTOFF);
- PY_DICT_ADD_INT(GL_SPOT_DIRECTION);
- PY_DICT_ADD_INT(GL_SPOT_EXPONENT);
- PY_DICT_ADD_INT(GL_STACK_OVERFLOW);
- PY_DICT_ADD_INT(GL_STACK_UNDERFLOW);
- PY_DICT_ADD_INT(GL_STENCIL_BITS);
- PY_DICT_ADD_INT(GL_T);
- PY_DICT_ADD_INT(GL_T2F_C3F_V3F);
- PY_DICT_ADD_INT(GL_T2F_C4F_N3F_V3F);
- PY_DICT_ADD_INT(GL_T2F_C4UB_V3F);
- PY_DICT_ADD_INT(GL_T2F_N3F_V3F);
- PY_DICT_ADD_INT(GL_T2F_V3F);
- PY_DICT_ADD_INT(GL_T4F_C4F_N3F_V4F);
- PY_DICT_ADD_INT(GL_T4F_V4F);
- PY_DICT_ADD_INT(GL_TEXTURE_BIT);
- PY_DICT_ADD_INT(GL_TEXTURE_BORDER);
- PY_DICT_ADD_INT(GL_TEXTURE_COMPONENTS);
- PY_DICT_ADD_INT(GL_TEXTURE_COORD_ARRAY);
- PY_DICT_ADD_INT(GL_TEXTURE_COORD_ARRAY_POINTER);
- PY_DICT_ADD_INT(GL_TEXTURE_COORD_ARRAY_SIZE);
- PY_DICT_ADD_INT(GL_TEXTURE_COORD_ARRAY_STRIDE);
- PY_DICT_ADD_INT(GL_TEXTURE_COORD_ARRAY_TYPE);
- PY_DICT_ADD_INT(GL_TEXTURE_ENV);
- PY_DICT_ADD_INT(GL_TEXTURE_ENV_COLOR);
- PY_DICT_ADD_INT(GL_TEXTURE_ENV_MODE);
- PY_DICT_ADD_INT(GL_TEXTURE_GEN_MODE);
- PY_DICT_ADD_INT(GL_TEXTURE_GEN_Q);
- PY_DICT_ADD_INT(GL_TEXTURE_GEN_R);
- PY_DICT_ADD_INT(GL_TEXTURE_GEN_S);
- PY_DICT_ADD_INT(GL_TEXTURE_GEN_T);
- PY_DICT_ADD_INT(GL_TEXTURE_INTENSITY_SIZE);
- PY_DICT_ADD_INT(GL_TEXTURE_LUMINANCE_SIZE);
- PY_DICT_ADD_INT(GL_TEXTURE_MATRIX);
- PY_DICT_ADD_INT(GL_TEXTURE_PRIORITY);
- PY_DICT_ADD_INT(GL_TEXTURE_RESIDENT);
- PY_DICT_ADD_INT(GL_TEXTURE_STACK_DEPTH);
- PY_DICT_ADD_INT(GL_TRANSFORM_BIT);
- PY_DICT_ADD_INT(GL_V2F);
- PY_DICT_ADD_INT(GL_V3F);
- PY_DICT_ADD_INT(GL_VERTEX_ARRAY);
- PY_DICT_ADD_INT(GL_VERTEX_ARRAY_POINTER);
- PY_DICT_ADD_INT(GL_VERTEX_ARRAY_SIZE);
- PY_DICT_ADD_INT(GL_VERTEX_ARRAY_STRIDE);
- PY_DICT_ADD_INT(GL_VERTEX_ARRAY_TYPE);
- PY_DICT_ADD_INT(GL_VIEWPORT_BIT);
- PY_DICT_ADD_INT(GL_ZOOM_X);
- PY_DICT_ADD_INT(GL_ZOOM_Y);
- }
-
/* GL_VERSION_1_2 */
{
@@ -2974,15 +1920,6 @@ PyObject *BPyInit_bgl(void)
PY_DICT_ADD_INT(GL_UNSIGNED_SHORT_5_6_5);
PY_DICT_ADD_INT(GL_UNSIGNED_SHORT_5_6_5_REV);
}
- /* adding in GL_VERSION_1_2 removed from core profile */
- if (use_deprecated == true) {
- PY_DICT_ADD_INT(GL_ALIASED_POINT_SIZE_RANGE);
- PY_DICT_ADD_INT(GL_LIGHT_MODEL_COLOR_CONTROL);
- PY_DICT_ADD_INT(GL_RESCALE_NORMAL);
- PY_DICT_ADD_INT(GL_SEPARATE_SPECULAR_COLOR);
- PY_DICT_ADD_INT(GL_SINGLE_COLOR);
- }
-
/* GL_VERSION_1_3 */
{
@@ -3046,47 +1983,6 @@ PyObject *BPyInit_bgl(void)
PY_DICT_ADD_INT(GL_TEXTURE_CUBE_MAP_POSITIVE_Y);
PY_DICT_ADD_INT(GL_TEXTURE_CUBE_MAP_POSITIVE_Z);
}
- /* adding in GL_VERSION_1_3 removed from core profile */
- if (use_deprecated == true) {
- PY_DICT_ADD_INT(GL_ADD_SIGNED);
- PY_DICT_ADD_INT(GL_CLIENT_ACTIVE_TEXTURE);
- PY_DICT_ADD_INT(GL_COMBINE);
- PY_DICT_ADD_INT(GL_COMBINE_ALPHA);
- PY_DICT_ADD_INT(GL_COMBINE_RGB);
- PY_DICT_ADD_INT(GL_COMPRESSED_ALPHA);
- PY_DICT_ADD_INT(GL_COMPRESSED_INTENSITY);
- PY_DICT_ADD_INT(GL_COMPRESSED_LUMINANCE);
- PY_DICT_ADD_INT(GL_COMPRESSED_LUMINANCE_ALPHA);
- PY_DICT_ADD_INT(GL_CONSTANT);
- PY_DICT_ADD_INT(GL_DOT3_RGB);
- PY_DICT_ADD_INT(GL_DOT3_RGBA);
- PY_DICT_ADD_INT(GL_INTERPOLATE);
- PY_DICT_ADD_INT(GL_MAX_TEXTURE_UNITS);
- PY_DICT_ADD_INT(GL_MULTISAMPLE_BIT);
- PY_DICT_ADD_INT(GL_NORMAL_MAP);
- PY_DICT_ADD_INT(GL_OPERAND0_ALPHA);
- PY_DICT_ADD_INT(GL_OPERAND0_RGB);
- PY_DICT_ADD_INT(GL_OPERAND1_ALPHA);
- PY_DICT_ADD_INT(GL_OPERAND1_RGB);
- PY_DICT_ADD_INT(GL_OPERAND2_ALPHA);
- PY_DICT_ADD_INT(GL_OPERAND2_RGB);
- PY_DICT_ADD_INT(GL_PREVIOUS);
- PY_DICT_ADD_INT(GL_PRIMARY_COLOR);
- PY_DICT_ADD_INT(GL_REFLECTION_MAP);
- PY_DICT_ADD_INT(GL_RGB_SCALE);
- PY_DICT_ADD_INT(GL_SOURCE0_ALPHA);
- PY_DICT_ADD_INT(GL_SOURCE0_RGB);
- PY_DICT_ADD_INT(GL_SOURCE1_ALPHA);
- PY_DICT_ADD_INT(GL_SOURCE1_RGB);
- PY_DICT_ADD_INT(GL_SOURCE2_ALPHA);
- PY_DICT_ADD_INT(GL_SOURCE2_RGB);
- PY_DICT_ADD_INT(GL_SUBTRACT);
- PY_DICT_ADD_INT(GL_TRANSPOSE_COLOR_MATRIX);
- PY_DICT_ADD_INT(GL_TRANSPOSE_MODELVIEW_MATRIX);
- PY_DICT_ADD_INT(GL_TRANSPOSE_PROJECTION_MATRIX);
- PY_DICT_ADD_INT(GL_TRANSPOSE_TEXTURE_MATRIX);
- }
-
/* GL_VERSION_1_4 */
{
@@ -3116,33 +2012,6 @@ PyObject *BPyInit_bgl(void)
PY_DICT_ADD_INT(GL_TEXTURE_DEPTH_SIZE);
PY_DICT_ADD_INT(GL_TEXTURE_LOD_BIAS);
}
- /* adding in GL_VERSION_1_4 removed from core profile */
- if (use_deprecated == true) {
- PY_DICT_ADD_INT(GL_COLOR_SUM);
- PY_DICT_ADD_INT(GL_COMPARE_R_TO_TEXTURE);
- PY_DICT_ADD_INT(GL_CURRENT_FOG_COORDINATE);
- PY_DICT_ADD_INT(GL_CURRENT_SECONDARY_COLOR);
- PY_DICT_ADD_INT(GL_DEPTH_TEXTURE_MODE);
- PY_DICT_ADD_INT(GL_FOG_COORDINATE);
- PY_DICT_ADD_INT(GL_FOG_COORDINATE_ARRAY);
- PY_DICT_ADD_INT(GL_FOG_COORDINATE_ARRAY_POINTER);
- PY_DICT_ADD_INT(GL_FOG_COORDINATE_ARRAY_STRIDE);
- PY_DICT_ADD_INT(GL_FOG_COORDINATE_ARRAY_TYPE);
- PY_DICT_ADD_INT(GL_FOG_COORDINATE_SOURCE);
- PY_DICT_ADD_INT(GL_FRAGMENT_DEPTH);
- PY_DICT_ADD_INT(GL_GENERATE_MIPMAP);
- PY_DICT_ADD_INT(GL_GENERATE_MIPMAP_HINT);
- PY_DICT_ADD_INT(GL_POINT_DISTANCE_ATTENUATION);
- PY_DICT_ADD_INT(GL_POINT_SIZE_MAX);
- PY_DICT_ADD_INT(GL_POINT_SIZE_MIN);
- PY_DICT_ADD_INT(GL_SECONDARY_COLOR_ARRAY);
- PY_DICT_ADD_INT(GL_SECONDARY_COLOR_ARRAY_POINTER);
- PY_DICT_ADD_INT(GL_SECONDARY_COLOR_ARRAY_SIZE);
- PY_DICT_ADD_INT(GL_SECONDARY_COLOR_ARRAY_STRIDE);
- PY_DICT_ADD_INT(GL_SECONDARY_COLOR_ARRAY_TYPE);
- PY_DICT_ADD_INT(GL_TEXTURE_FILTER_CONTROL);
- }
-
/* GL_VERSION_1_5 */
{
@@ -3165,7 +2034,6 @@ PyObject *BPyInit_bgl(void)
PY_DICT_ADD_INT(GL_READ_ONLY);
PY_DICT_ADD_INT(GL_READ_WRITE);
PY_DICT_ADD_INT(GL_SAMPLES_PASSED);
- PY_DICT_ADD_INT(GL_SRC1_ALPHA);
PY_DICT_ADD_INT(GL_STATIC_COPY);
PY_DICT_ADD_INT(GL_STATIC_DRAW);
PY_DICT_ADD_INT(GL_STATIC_READ);
@@ -3175,32 +2043,6 @@ PyObject *BPyInit_bgl(void)
PY_DICT_ADD_INT(GL_VERTEX_ATTRIB_ARRAY_BUFFER_BINDING);
PY_DICT_ADD_INT(GL_WRITE_ONLY);
}
- /* adding in GL_VERSION_1_5 removed from core profile */
- if (use_deprecated == true) {
- PY_DICT_ADD_INT(GL_COLOR_ARRAY_BUFFER_BINDING);
- PY_DICT_ADD_INT(GL_CURRENT_FOG_COORD);
- PY_DICT_ADD_INT(GL_EDGE_FLAG_ARRAY_BUFFER_BINDING);
- PY_DICT_ADD_INT(GL_FOG_COORD);
- PY_DICT_ADD_INT(GL_FOG_COORDINATE_ARRAY_BUFFER_BINDING);
- PY_DICT_ADD_INT(GL_FOG_COORD_ARRAY);
- PY_DICT_ADD_INT(GL_FOG_COORD_ARRAY_BUFFER_BINDING);
- PY_DICT_ADD_INT(GL_FOG_COORD_ARRAY_POINTER);
- PY_DICT_ADD_INT(GL_FOG_COORD_ARRAY_STRIDE);
- PY_DICT_ADD_INT(GL_FOG_COORD_ARRAY_TYPE);
- PY_DICT_ADD_INT(GL_FOG_COORD_SRC);
- PY_DICT_ADD_INT(GL_INDEX_ARRAY_BUFFER_BINDING);
- PY_DICT_ADD_INT(GL_NORMAL_ARRAY_BUFFER_BINDING);
- PY_DICT_ADD_INT(GL_SECONDARY_COLOR_ARRAY_BUFFER_BINDING);
- PY_DICT_ADD_INT(GL_SRC0_ALPHA);
- PY_DICT_ADD_INT(GL_SRC0_RGB);
- PY_DICT_ADD_INT(GL_SRC1_RGB);
- PY_DICT_ADD_INT(GL_SRC2_ALPHA);
- PY_DICT_ADD_INT(GL_SRC2_RGB);
- PY_DICT_ADD_INT(GL_TEXTURE_COORD_ARRAY_BUFFER_BINDING);
- PY_DICT_ADD_INT(GL_VERTEX_ARRAY_BUFFER_BINDING);
- PY_DICT_ADD_INT(GL_WEIGHT_ARRAY_BUFFER_BINDING);
- }
-
/* GL_VERSION_2_0 */
{
@@ -3285,14 +2127,6 @@ PyObject *BPyInit_bgl(void)
PY_DICT_ADD_INT(GL_VERTEX_PROGRAM_POINT_SIZE);
PY_DICT_ADD_INT(GL_VERTEX_SHADER);
}
- /* adding in GL_VERSION_2_0 removed from core profile */
- if (use_deprecated == true) {
- PY_DICT_ADD_INT(GL_COORD_REPLACE);
- PY_DICT_ADD_INT(GL_MAX_TEXTURE_COORDS);
- PY_DICT_ADD_INT(GL_POINT_SPRITE);
- PY_DICT_ADD_INT(GL_VERTEX_PROGRAM_TWO_SIDE);
- }
-
/* GL_VERSION_2_1 */
{
@@ -3313,16 +2147,6 @@ PyObject *BPyInit_bgl(void)
PY_DICT_ADD_INT(GL_SRGB8_ALPHA8);
PY_DICT_ADD_INT(GL_SRGB_ALPHA);
}
- /* adding in GL_VERSION_2_1 removed from core profile */
- if (use_deprecated == true) {
- PY_DICT_ADD_INT(GL_COMPRESSED_SLUMINANCE);
- PY_DICT_ADD_INT(GL_COMPRESSED_SLUMINANCE_ALPHA);
- PY_DICT_ADD_INT(GL_CURRENT_RASTER_SECONDARY_COLOR);
- PY_DICT_ADD_INT(GL_SLUMINANCE);
- PY_DICT_ADD_INT(GL_SLUMINANCE8);
- PY_DICT_ADD_INT(GL_SLUMINANCE8_ALPHA8);
- PY_DICT_ADD_INT(GL_SLUMINANCE_ALPHA);
- }
/* GL_VERSION_3_0 */
{
@@ -3563,14 +2387,6 @@ PyObject *BPyInit_bgl(void)
PY_DICT_ADD_INT(GL_VERTEX_ARRAY_BINDING);
PY_DICT_ADD_INT(GL_VERTEX_ATTRIB_ARRAY_INTEGER);
}
- /* adding in GL_VERSION_3_0 removed from core profile */
- if (use_deprecated == true) {
- PY_DICT_ADD_INT(GL_ALPHA_INTEGER);
- PY_DICT_ADD_INT(GL_CLAMP_FRAGMENT_COLOR);
- PY_DICT_ADD_INT(GL_CLAMP_VERTEX_COLOR);
- PY_DICT_ADD_INT(GL_TEXTURE_INTENSITY_TYPE);
- PY_DICT_ADD_INT(GL_TEXTURE_LUMINANCE_TYPE);
- }
/* GL_VERSION_3_1 */
{
@@ -3637,7 +2453,6 @@ PyObject *BPyInit_bgl(void)
PY_DICT_ADD_INT(GL_UNSIGNED_INT_SAMPLER_BUFFER);
}
-
/* GL_VERSION_3_2 */
{
PY_DICT_ADD_INT(GL_ALREADY_SIGNALED);
diff --git a/source/blender/python/generic/blf_py_api.c b/source/blender/python/generic/blf_py_api.c
index 7d124966334..7337706639f 100644
--- a/source/blender/python/generic/blf_py_api.c
+++ b/source/blender/python/generic/blf_py_api.c
@@ -114,6 +114,41 @@ static PyObject *py_blf_aspect(PyObject *UNUSED(self), PyObject *args)
}
+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"
+);
+static PyObject *py_blf_color(PyObject *UNUSED(self), PyObject *args)
+{
+ int fontid;
+ float rgba[4];
+
+ if (!PyArg_ParseTuple(
+ args, "iffff:blf.color",
+ &fontid, &rgba[0], &rgba[1], &rgba[2], &rgba[3]))
+ {
+ return NULL;
+ }
+
+ BLF_color4fv(fontid, rgba);
+
+ Py_RETURN_NONE;
+}
+
+
+#if BLF_BLUR_ENABLE
PyDoc_STRVAR(py_blf_blur_doc,
".. function:: blur(fontid, radius)\n"
"\n"
@@ -135,6 +170,7 @@ static PyObject *py_blf_blur(PyObject *UNUSED(self), PyObject *args)
Py_RETURN_NONE;
}
+#endif
PyDoc_STRVAR(py_blf_draw_doc,
@@ -418,7 +454,9 @@ static PyObject *py_blf_unload(PyObject *UNUSED(self), PyObject *args)
/*----------------------------MODULE INIT-------------------------*/
static PyMethodDef BLF_methods[] = {
{"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},
+#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},
@@ -430,6 +468,7 @@ static PyMethodDef BLF_methods[] = {
{"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}
diff --git a/source/blender/python/generic/bpy_internal_import.c b/source/blender/python/generic/bpy_internal_import.c
index 553f7e43e45..926de79d0ff 100644
--- a/source/blender/python/generic/bpy_internal_import.c
+++ b/source/blender/python/generic/bpy_internal_import.c
@@ -43,9 +43,9 @@
#include "BLI_string.h"
#include "BLI_utildefines.h"
+#include "BKE_main.h"
/* UNUSED */
#include "BKE_text.h" /* txt_to_buf */
-#include "BKE_main.h"
#include "py_capi_utils.h"
@@ -116,16 +116,6 @@ void bpy_import_main_set(struct Main *maggie)
bpy_import_main = maggie;
}
-void bpy_import_main_extra_add(struct Main *maggie)
-{
- BLI_addhead(&bpy_import_main_list, maggie);
-}
-
-void bpy_import_main_extra_remove(struct Main *maggie)
-{
- BLI_remlink_safe(&bpy_import_main_list, 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)
{
diff --git a/source/blender/python/generic/bpy_internal_import.h b/source/blender/python/generic/bpy_internal_import.h
index 29b11fbe8ff..8de1436ed48 100644
--- a/source/blender/python/generic/bpy_internal_import.h
+++ b/source/blender/python/generic/bpy_internal_import.h
@@ -51,12 +51,7 @@ PyObject *bpy_text_reimport(PyObject *module, int *found);
void bpy_text_filename_get(char *fn, size_t fn_len, struct Text *text);
-/* The game engine has its own Main struct, if this is set search this rather than G_MAIN */
struct Main *bpy_import_main_get(void);
void bpy_import_main_set(struct Main *maggie);
-/* This is used for importing text from dynamically loaded libraries in the game engine */
-void bpy_import_main_extra_add(struct Main *maggie);
-void bpy_import_main_extra_remove(struct Main *maggie);
-
#endif /* __BPY_INTERNAL_IMPORT_H__ */
diff --git a/source/blender/python/generic/idprop_py_api.c b/source/blender/python/generic/idprop_py_api.c
index 918ec8fa018..072c11b14e5 100644
--- a/source/blender/python/generic/idprop_py_api.c
+++ b/source/blender/python/generic/idprop_py_api.c
@@ -422,11 +422,18 @@ static IDProperty *idp_from_PyBytes(const char *name, PyObject *ob)
return IDP_New(IDP_STRING, &val, name);
}
-static int idp_array_type_from_format_char(char format)
+static int idp_array_type_from_formatstr_and_size(const char *typestr, Py_ssize_t itemsize)
{
- if (format == 'i') return IDP_INT;
- if (format == 'f') return IDP_FLOAT;
- if (format == 'd') return IDP_DOUBLE;
+ char format = PyC_StructFmt_type_from_str(typestr);
+
+ if (PyC_StructFmt_type_is_float_any(format)) {
+ if (itemsize == 4) return IDP_FLOAT;
+ if (itemsize == 8) return IDP_DOUBLE;
+ }
+ if (PyC_StructFmt_type_is_int_any(format)) {
+ if (itemsize == 4) return IDP_INT;
+ }
+
return -1;
}
@@ -443,13 +450,13 @@ static IDProperty *idp_from_PySequence_Buffer(const char *name, Py_buffer *buffe
IDProperty *prop;
IDPropertyTemplate val = {0};
- int format = idp_array_type_from_format_char(*buffer->format);
- if (format == -1) {
+ int id_type = idp_array_type_from_formatstr_and_size(buffer->format, buffer->itemsize);
+ if (id_type == -1) {
/* should never happen as the type has been checked before */
return NULL;
}
else {
- val.array.type = format;
+ val.array.type = id_type;
val.array.len = buffer->len / buffer->itemsize;
}
prop = IDP_New(IDP_ARRAY, &val, name);
@@ -533,8 +540,10 @@ static IDProperty *idp_from_PySequence(const char *name, PyObject *ob)
if (PyObject_CheckBuffer(ob)) {
PyObject_GetBuffer(ob, &buffer, PyBUF_SIMPLE | PyBUF_FORMAT);
- char format = *buffer.format;
- if (ELEM(format, 'i', 'f', 'd')) {
+ char format = PyC_StructFmt_type_from_str(buffer.format);
+ if (PyC_StructFmt_type_is_float_any(format) ||
+ (PyC_StructFmt_type_is_int_any(format) && buffer.itemsize == 4))
+ {
use_buffer = true;
}
else {
@@ -1802,7 +1811,6 @@ PyObject *BPyInit_idprop(void)
/* idprop.types */
PyModule_AddObject(mod, "types", (submodule = BPyInit_idprop_types()));
PyDict_SetItem(sys_modules, PyModule_GetNameObject(submodule), submodule);
- Py_INCREF(submodule);
return mod;
}
diff --git a/source/blender/python/generic/py_capi_utils.c b/source/blender/python/generic/py_capi_utils.c
index 62b24618d3f..d158c92baae 100644
--- a/source/blender/python/generic/py_capi_utils.c
+++ b/source/blender/python/generic/py_capi_utils.c
@@ -436,17 +436,24 @@ PyObject *PyC_Err_Format_Prefix(PyObject *exception_type_prefix, const char *for
if (PyErr_Occurred()) {
PyObject *error_type, *error_value, *error_traceback;
PyErr_Fetch(&error_type, &error_value, &error_traceback);
- PyErr_Format(exception_type_prefix,
- "%S, %.200s(%S)",
- error_value_prefix,
- Py_TYPE(error_value)->tp_name,
- error_value
- );
+
+ if (PyUnicode_Check(error_value)) {
+ PyErr_Format(exception_type_prefix,
+ "%S, %S",
+ error_value_prefix,
+ error_value);
+ }
+ else {
+ PyErr_Format(exception_type_prefix,
+ "%S, %.200s(%S)",
+ error_value_prefix,
+ Py_TYPE(error_value)->tp_name,
+ error_value);
+ }
}
else {
PyErr_SetObject(exception_type_prefix,
- error_value_prefix
- );
+ error_value_prefix);
}
Py_XDECREF(error_value_prefix);
@@ -455,6 +462,11 @@ PyObject *PyC_Err_Format_Prefix(PyObject *exception_type_prefix, const char *for
return NULL;
}
+PyObject *PyC_Err_SetString_Prefix(PyObject *exception_type_prefix, const char *str)
+{
+ return PyC_Err_Format_Prefix(exception_type_prefix, "%s", str);
+}
+
/**
* Use for Python callbacks run directly from C,
* when we can't use normal methods of raising exceptions.
@@ -1327,6 +1339,84 @@ uint32_t PyC_Long_AsU32(PyObject *value)
* PyC_Long_AsU64
*/
+/* -------------------------------------------------------------------- */
+
+/** \name Py_buffer Utils
+ *
+ * \{ */
+
+char PyC_StructFmt_type_from_str(const char *typestr)
+{
+ switch (typestr[0]) {
+ case '!':
+ case '<':
+ case '=':
+ case '>':
+ case '@':
+ return typestr[1];
+ default:
+ return typestr[0];
+ }
+}
+
+bool PyC_StructFmt_type_is_float_any(char format)
+{
+ switch (format) {
+ case 'f':
+ case 'd':
+ case 'e':
+ return true;
+ default:
+ return false;
+ }
+}
+
+bool PyC_StructFmt_type_is_int_any(char format)
+{
+ switch (format) {
+ case 'i':
+ case 'I':
+ case 'l':
+ case 'L':
+ case 'h':
+ case 'H':
+ case 'b':
+ case 'B':
+ case 'q':
+ case 'Q':
+ case 'n':
+ case 'N':
+ case 'P':
+ return true;
+ default:
+ return false;
+ }
+}
+
+bool PyC_StructFmt_type_is_byte(char format)
+{
+ switch (format) {
+ case 'c':
+ case 's':
+ case 'p':
+ return true;
+ default:
+ return false;
+ }
+}
+
+bool PyC_StructFmt_type_is_bool(char format)
+{
+ switch (format) {
+ case '?':
+ return true;
+ default:
+ return false;
+ }
+}
+
+/** \} */
+
#ifdef __GNUC__
# pragma warning(pop)
#endif
diff --git a/source/blender/python/generic/py_capi_utils.h b/source/blender/python/generic/py_capi_utils.h
index 4cf6d6b26de..43e397153ff 100644
--- a/source/blender/python/generic/py_capi_utils.h
+++ b/source/blender/python/generic/py_capi_utils.h
@@ -38,7 +38,10 @@ PyObject *PyC_ExceptionBuffer(void);
PyObject *PyC_ExceptionBuffer_Simple(void);
PyObject *PyC_Object_GetAttrStringArgs(PyObject *o, Py_ssize_t n, ...);
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_FileAndNum(const char **filename, int *lineno);
@@ -76,7 +79,7 @@ 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);
-/* name namespace function for bpy & bge */
+/* name namespace function for bpy */
PyObject *PyC_DefaultNameSpace(const char *filename);
void PyC_RunQuicky(const char *filepath, int n, ...);
bool PyC_NameSpace_ImportArray(PyObject *py_dict, const char *imports[]);
@@ -131,4 +134,11 @@ Py_LOCAL_INLINE(int32_t) PyC_Long_AsI32(PyObject *value) { return (int32_t)_PyL
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);
+bool PyC_StructFmt_type_is_float_any(char format);
+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__ */
diff --git a/source/blender/python/gpu/CMakeLists.txt b/source/blender/python/gpu/CMakeLists.txt
new file mode 100644
index 00000000000..fcb0b828ffb
--- /dev/null
+++ b/source/blender/python/gpu/CMakeLists.txt
@@ -0,0 +1,62 @@
+# ***** BEGIN GPL LICENSE BLOCK *****
+#
+# This program is free software; you can redistribute it and/or
+# modify it under the terms of the GNU General Public License
+# as published by the Free Software Foundation; either version 2
+# of the License, or (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program; if not, write to the Free Software Foundation,
+# Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+#
+# Contributor(s): Campbell Barton
+#
+# ***** END GPL LICENSE BLOCK *****
+
+set(INC
+ .
+ ../../blenkernel
+ ../../blenlib
+ ../../gpu
+ ../../makesdna
+ ../../../../intern/guardedalloc
+ ../../../../intern/glew-mx
+)
+
+set(INC_SYS
+ ${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.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
+)
+
+add_definitions(${GL_DEFINITIONS})
+
+blender_add_lib(bf_python_gpu "${SRC}" "${INC}" "${INC_SYS}")
diff --git a/source/blender/python/gpu/gpu_py_api.c b/source/blender/python/gpu/gpu_py_api.c
new file mode 100644
index 00000000000..7e999bdcc2d
--- /dev/null
+++ b/source/blender/python/gpu/gpu_py_api.c
@@ -0,0 +1,165 @@
+/*
+ * ***** BEGIN GPL LICENSE BLOCK *****
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ * ***** END GPL LICENSE BLOCK *****
+ */
+
+/** \file blender/python/gpu/gpu_py_api.c
+ * \ingroup bpygpu
+ *
+ * Experimental Python API, not considered public yet (called '_gpu'),
+ * we may re-expose as public later.
+ *
+ * - Use ``bpygpu_`` for local API.
+ * - Use ``BPyGPU`` for public API.
+ */
+
+#include <Python.h>
+
+#include "BLI_utildefines.h"
+
+#include "../generic/python_utildefines.h"
+
+#include "GPU_init_exit.h"
+#include "GPU_primitive.h"
+
+#include "gpu_py_matrix.h"
+#include "gpu_py_select.h"
+#include "gpu_py_types.h"
+
+#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");
+
+ return false;
+ }
+
+ 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;
+ }
+#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)
+
+ 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;
+
+success:
+ (*(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"
+);
+static struct PyModuleDef GPU_module_def = {
+ PyModuleDef_HEAD_INIT,
+ .m_name = "gpu",
+ .m_doc = GPU_doc,
+};
+
+PyObject *BPyInit_gpu(void)
+{
+ PyObject *sys_modules = PyImport_GetModuleDict();
+ PyObject *submodule;
+ PyObject *mod;
+
+ 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, "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, "shader", (submodule = BPyInit_gpu_shader()));
+ PyDict_SetItem(sys_modules, PyModule_GetNameObject(submodule), submodule);
+
+ return mod;
+}
+
+/** \} */
diff --git a/source/blender/python/gpu/gpu_py_api.h b/source/blender/python/gpu/gpu_py_api.h
new file mode 100644
index 00000000000..af08881b723
--- /dev/null
+++ b/source/blender/python/gpu/gpu_py_api.h
@@ -0,0 +1,37 @@
+/*
+ * ***** BEGIN GPL LICENSE BLOCK *****
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ * ***** END GPL LICENSE BLOCK *****
+ */
+
+/** \file blender/python/gpu/gpu_py_api.h
+ * \ingroup bpygpu
+ */
+
+#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)
+
+#endif /* __GPU_PY_API_H__ */
diff --git a/source/blender/python/gpu/gpu_py_batch.c b/source/blender/python/gpu/gpu_py_batch.c
new file mode 100644
index 00000000000..a50ea32b5dd
--- /dev/null
+++ b/source/blender/python/gpu/gpu_py_batch.c
@@ -0,0 +1,386 @@
+/*
+ * ***** BEGIN GPL LICENSE BLOCK *****
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ * Copyright 2015, Blender Foundation.
+ *
+ * ***** END GPL LICENSE BLOCK *****
+ */
+
+/** \file blender/python/gpu/gpu_py_batch.c
+ * \ingroup bpygpu
+ *
+ * This file defines the offscreen functionalities of the 'gpu' module
+ * used for off-screen OpenGL rendering.
+ *
+ * - Use ``bpygpu_`` for local API.
+ * - Use ``BPyGPU`` for public API.
+ */
+
+#include <Python.h>
+
+#include "MEM_guardedalloc.h"
+
+#include "BLI_utildefines.h"
+
+#include "BKE_global.h"
+
+#include "GPU_batch.h"
+
+#include "../mathutils/mathutils.h"
+
+#include "../generic/py_capi_utils.h"
+
+#include "gpu_py_api.h"
+#include "gpu_py_shader.h"
+#include "gpu_py_vertex_buffer.h"
+#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;
+}
+
+/** \} */
+
+
+/* -------------------------------------------------------------------- */
+/** \name GPUBatch Type
+ * \{ */
+
+static PyObject *bpygpu_Batch_new(PyTypeObject *UNUSED(type), PyObject *args, PyObject *kwds)
+{
+ BPYGPU_IS_INIT_OR_ERROR_OBJ;
+
+ 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};
+
+ 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.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);
+
+ 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);
+
+ if (params.py_indexbuf != NULL) {
+ PyList_SET_ITEM(ret->references, 1, (PyObject *)params.py_indexbuf);
+ Py_INCREF(params.py_indexbuf);
+ }
+
+ PyObject_GC_Track(ret);
+#endif
+
+ return (PyObject *)ret;
+}
+
+PyDoc_STRVAR(bpygpu_Batch_vertbuf_add_doc,
+".. method:: vertbuf_add(buf)\n"
+"\n"
+" Add another vertex buffer to the Batch.\n"
+" It is not possible to add more vertices to the batch using this method.\n"
+" Instead it can be used to add more attributes to the existing vertices.\n"
+" A good use case would be when you have a separate vertex buffer for vertex positions and vertex normals.\n"
+" Current a batch can have at most " STRINGIFY(GPU_BATCH_VBO_MAX_LEN) " vertex buffers.\n"
+"\n"
+" :param buf: The vertex buffer that will be added to the batch.\n"
+" :type buf: :class:`gpu.types.GPUVertBuf`\n"
+);
+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 (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;
+ }
+
+#ifdef USE_GPU_PY_REFERENCES
+ /* Hold user */
+ PyList_Append(self->references, (PyObject *)py_buf);
+#endif
+
+ 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"
+);
+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;
+ }
+
+ 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);
+ }
+#endif
+
+ 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"
+);
+static PyObject *bpygpu_Batch_draw(BPyGPUBatch *self, PyObject *args)
+{
+ 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));
+ }
+
+ 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;
+}
+
+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;
+}
+
+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}
+};
+
+#ifdef USE_GPU_PY_REFERENCES
+
+static int bpygpu_Batch_traverse(BPyGPUBatch *self, visitproc visit, void *arg)
+{
+ Py_VISIT(self->references);
+ return 0;
+}
+
+static int bpygpu_Batch_clear(BPyGPUBatch *self)
+{
+ Py_CLEAR(self->references);
+ return 0;
+}
+
+#endif
+
+static void bpygpu_Batch_dealloc(BPyGPUBatch *self)
+{
+ 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);
+ }
+#endif
+
+ 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"
+);
+PyTypeObject BPyGPUBatch_Type = {
+ 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,
+#else
+ .tp_flags = Py_TPFLAGS_DEFAULT,
+#endif
+ .tp_methods = bpygpu_Batch_methods,
+ .tp_new = bpygpu_Batch_new,
+};
+
+/** \} */
+
+
+/* -------------------------------------------------------------------- */
+/** \name Public API
+* \{ */
+
+PyObject *BPyGPUBatch_CreatePyObject(GPUBatch *batch)
+{
+ BPyGPUBatch *self;
+
+#ifdef USE_GPU_PY_REFERENCES
+ self = (BPyGPUBatch *)_PyObject_GC_New(&BPyGPUBatch_Type);
+ self->references = NULL;
+#else
+ self = PyObject_New(BPyGPUBatch, &BPyGPUBatch_Type);
+#endif
+
+ self->batch = batch;
+
+ return (PyObject *)self;
+}
+
+/** \} */
+
+#undef BPY_GPU_BATCH_CHECK_OBJ
diff --git a/source/blender/python/gpu/gpu_py_batch.h b/source/blender/python/gpu/gpu_py_batch.h
new file mode 100644
index 00000000000..c77574428db
--- /dev/null
+++ b/source/blender/python/gpu/gpu_py_batch.h
@@ -0,0 +1,48 @@
+/*
+ * ***** BEGIN GPL LICENSE BLOCK *****
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ * ***** END GPL LICENSE BLOCK *****
+ */
+
+/** \file blender/python/gpu/gpu_py_batch.h
+ * \ingroup bpygpu
+ */
+
+#ifndef __GPU_PY_BATCH_H__
+#define __GPU_PY_BATCH_H__
+
+#include "BLI_compiler_attrs.h"
+
+#define USE_GPU_PY_REFERENCES
+
+extern PyTypeObject 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;
+#ifdef USE_GPU_PY_REFERENCES
+ /* Just to keep a user to prevent freeing buf's we're using */
+ PyObject *references;
+#endif
+} BPyGPUBatch;
+
+PyObject *BPyGPUBatch_CreatePyObject(struct GPUBatch *batch) ATTR_NONNULL(1);
+
+#endif /* __GPU_PY_BATCH_H__ */
diff --git a/source/blender/python/gpu/gpu_py_element.c b/source/blender/python/gpu/gpu_py_element.c
new file mode 100644
index 00000000000..2faf57ac55c
--- /dev/null
+++ b/source/blender/python/gpu/gpu_py_element.c
@@ -0,0 +1,244 @@
+/*
+ * ***** BEGIN GPL LICENSE BLOCK *****
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ * ***** END GPL LICENSE BLOCK *****
+ */
+
+/** \file blender/python/gpu/gpu_py_element.c
+ * \ingroup bpygpu
+ *
+ * - Use ``bpygpu_`` for local API.
+ * - Use ``BPyGPU`` for public API.
+ */
+
+#include <Python.h>
+
+#include "GPU_element.h"
+
+#include "BLI_math.h"
+
+#include "MEM_guardedalloc.h"
+
+#include "../generic/py_capi_utils.h"
+#include "../generic/python_utildefines.h"
+
+#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;
+
+ const char *error_prefix = "IndexBuf.__new__";
+ bool ok = true;
+
+ struct {
+ GPUPrimType type_id;
+ PyObject *seq;
+ } params;
+
+ 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;
+ }
+
+ 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_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.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];
+ }
+
+ /* 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);
+ }
+#else
+ 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);
+
+ if (seq_fast == NULL) {
+ return false;
+ }
+
+ const uint seq_len = PySequence_Fast_GET_SIZE(seq_fast);
+
+ PyObject **seq_items = PySequence_Fast_ITEMS(seq_fast);
+
+ 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);
+
+ 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;
+
+ 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;
+ }
+
+finally:
+
+ Py_DECREF(seq_fast);
+ }
+
+ if (ok == false) {
+ MEM_freeN(builder.data);
+ return NULL;
+ }
+
+ 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);
+}
+
+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"
+);
+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,
+};
+
+/** \} */
+
+
+/* -------------------------------------------------------------------- */
+
+/** \name Public API
+ * \{ */
+
+PyObject *BPyGPUIndexBuf_CreatePyObject(GPUIndexBuf *elem)
+{
+ BPyGPUIndexBuf *self;
+
+ self = PyObject_New(BPyGPUIndexBuf, &BPyGPUIndexBuf_Type);
+ self->elem = elem;
+
+ return (PyObject *)self;
+}
+
+/** \} */
diff --git a/source/blender/python/gpu/gpu_py_element.h b/source/blender/python/gpu/gpu_py_element.h
new file mode 100644
index 00000000000..e201a767582
--- /dev/null
+++ b/source/blender/python/gpu/gpu_py_element.h
@@ -0,0 +1,39 @@
+/*
+ * ***** BEGIN GPL LICENSE BLOCK *****
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ * ***** END GPL LICENSE BLOCK *****
+ */
+
+/** \file blender/python/gpu/gpu_py_element.h
+ * \ingroup bpygpu
+ */
+
+#ifndef __GPU_PY_ELEMENT_H__
+#define __GPU_PY_ELEMENT_H__
+
+extern PyTypeObject BPyGPUIndexBuf_Type;
+
+#define BPyGPUIndexBuf_Check(v) (Py_TYPE(v) == &BPyGPUIndexBuf_Type)
+
+typedef struct BPyGPUIndexBuf {
+ PyObject_VAR_HEAD
+ struct GPUIndexBuf *elem;
+} BPyGPUIndexBuf;
+
+PyObject *BPyGPUIndexBuf_CreatePyObject(struct GPUIndexBuf *elem);
+
+#endif /* __GPU_PY_ELEMENT_H__ */
diff --git a/source/blender/python/gpu/gpu_py_matrix.c b/source/blender/python/gpu/gpu_py_matrix.c
new file mode 100644
index 00000000000..6c77f2ee02b
--- /dev/null
+++ b/source/blender/python/gpu/gpu_py_matrix.c
@@ -0,0 +1,575 @@
+/*
+ * ***** BEGIN GPL LICENSE BLOCK *****
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ * ***** END GPL LICENSE BLOCK *****
+ */
+
+/** \file blender/python/gpu/gpu_py_matrix.c
+ * \ingroup bpygpu
+ *
+ * This file defines the gpu.matrix stack API.
+ *
+ * \warning While these functions attempt to ensure correct stack usage.
+ * Mixing Python and C functions may still crash on invalid use.
+ *
+ * - Use ``bpygpu_`` for local API.
+ * - Use ``BPyGPU`` for public API.
+ */
+
+#include <Python.h>
+
+
+#include "BLI_utildefines.h"
+
+#include "../mathutils/mathutils.h"
+
+#include "../generic/py_capi_utils.h"
+
+#define USE_GPU_PY_MATRIX_API
+#include "GPU_matrix.h"
+#undef USE_GPU_PY_MATRIX_API
+
+#include "gpu_py_matrix.h" /* own include */
+
+/* -------------------------------------------------------------------- */
+/** \name Helper Functions
+ * \{ */
+
+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;
+}
+
+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;
+}
+
+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;
+}
+
+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;
+}
+
+/** \} */
+
+/* -------------------------------------------------------------------- */
+/** \name Manage Stack
+ * \{ */
+
+PyDoc_STRVAR(bpygpu_matrix_push_doc,
+".. 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;
+}
+
+PyDoc_STRVAR(bpygpu_matrix_pop_doc,
+".. 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;
+}
+
+PyDoc_STRVAR(bpygpu_matrix_push_projection_doc,
+".. 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;
+}
+
+PyDoc_STRVAR(bpygpu_matrix_pop_projection_doc,
+".. 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;
+}
+
+/** \} */
+
+/* -------------------------------------------------------------------- */
+/** \name Stack (Context Manager)
+ *
+ * Safer alternative to ensure balanced push/pop calls.
+ *
+ * \{ */
+
+typedef struct {
+ PyObject_HEAD /* required python macro */
+ int type;
+ int level;
+} BPyGPU_MatrixStackContext;
+
+enum {
+ 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}
+};
+
+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,
+};
+
+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;
+ }
+
+ 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))
+{
+ /* 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);
+ }
+finally:
+ 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;
+}
+
+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);
+}
+
+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);
+}
+
+/** \} */
+
+/* -------------------------------------------------------------------- */
+/** \name Manipulate State
+ * \{ */
+
+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"
+);
+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;
+}
+
+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"
+);
+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;
+}
+
+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"
+);
+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;
+}
+
+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"
+);
+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;
+}
+
+/** \} */
+
+/* -------------------------------------------------------------------- */
+/** \name Write State
+ * \{ */
+
+PyDoc_STRVAR(bpygpu_matrix_reset_doc,
+".. 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;
+}
+
+PyDoc_STRVAR(bpygpu_matrix_load_identity_doc,
+".. 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;
+}
+
+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"
+);
+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;
+}
+
+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"
+);
+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;
+}
+
+/** \} */
+
+/* -------------------------------------------------------------------- */
+/** \name Read State
+ * \{ */
+
+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"
+);
+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);
+}
+
+
+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"
+);
+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);
+}
+
+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"
+);
+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);
+}
+
+/** \} */
+
+/* -------------------------------------------------------------------- */
+/** \name Module
+ * \{ */
+
+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},
+
+ {"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},
+
+ /* 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 */
+#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},
+#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},
+
+ /* 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}
+};
+
+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,
+};
+
+PyObject *BPyInit_gpu_matrix(void)
+{
+ PyObject *submodule;
+
+ submodule = PyModule_Create(&BPyGPU_matrix_module_def);
+
+ if (PyType_Ready(&BPyGPU_matrix_stack_context_Type) < 0) {
+ return NULL;
+ }
+
+ return submodule;
+}
+
+/** \} */
diff --git a/source/blender/python/gpu/gpu_py_matrix.h b/source/blender/python/gpu/gpu_py_matrix.h
new file mode 100644
index 00000000000..7bd6318611d
--- /dev/null
+++ b/source/blender/python/gpu/gpu_py_matrix.h
@@ -0,0 +1,30 @@
+/*
+ * ***** BEGIN GPL LICENSE BLOCK *****
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ * ***** END GPL LICENSE BLOCK *****
+ */
+
+/** \file blender/python/gpu/gpu_py_matrix.h
+ * \ingroup bpygpu
+ */
+
+#ifndef __GPU_PY_MATRIX_H__
+#define __GPU_PY_MATRIX_H__
+
+PyObject *BPyInit_gpu_matrix(void);
+
+#endif /* __GPU_PY_MATRIX_H__ */
diff --git a/source/blender/python/gpu/gpu_py_offscreen.c b/source/blender/python/gpu/gpu_py_offscreen.c
new file mode 100644
index 00000000000..5dc6e36ca56
--- /dev/null
+++ b/source/blender/python/gpu/gpu_py_offscreen.c
@@ -0,0 +1,374 @@
+/*
+ * ***** BEGIN GPL LICENSE BLOCK *****
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ * Copyright 2015, Blender Foundation.
+ *
+ * ***** END GPL LICENSE BLOCK *****
+ */
+
+/** \file blender/python/gpu/gpu_py_offscreen.c
+ * \ingroup bpygpu
+ *
+ * This file defines the offscreen functionalities of the 'gpu' module
+ * used for off-screen OpenGL rendering.
+ *
+ * - Use ``bpygpu_`` for local API.
+ * - Use ``BPyGPU`` for public API.
+ */
+
+#include <Python.h>
+
+#include "MEM_guardedalloc.h"
+
+#include "BLI_utildefines.h"
+
+#include "BKE_global.h"
+#include "BKE_library.h"
+#include "BKE_scene.h"
+
+#include "DNA_screen_types.h"
+#include "DNA_scene_types.h"
+#include "DNA_view3d_types.h"
+
+#include "GPU_framebuffer.h"
+#include "GPU_texture.h"
+
+#include "../editors/include/ED_view3d.h"
+
+#include "../mathutils/mathutils.h"
+
+#include "../generic/py_capi_utils.h"
+
+#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;
+}
+
+#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;
+
+ 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;
+ }
+
+ 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;
+ }
+
+ 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));
+}
+
+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));
+}
+
+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));
+}
+
+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;
+
+ 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);
+
+ self->is_saved = save;
+ Py_INCREF(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"
+);
+static PyObject *bpygpu_offscreen_unbind(BPyGPUOffScreen *self, PyObject *args, PyObject *kwds)
+{
+ bool restore = true;
+
+ 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;
+ }
+
+ 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)
+{
+ 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;
+
+ BPY_GPU_OFFSCREEN_CHECK_OBJ(self);
+
+ 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;
+ }
+
+ BLI_assert(BKE_id_is_in_global_main(&scene->id));
+
+ depsgraph = BKE_scene_get_depsgraph(scene, view_layer, true);
+
+ rv3d_mats = ED_view3d_mats_rv3d_backup(ar->regiondata);
+
+ 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,
+ self->ofs,
+ NULL);
+
+ GPU_offscreen_unbind(self->ofs, true);
+
+ ED_view3d_mats_rv3d_restore(ar->regiondata, rv3d_mats);
+ MEM_freeN(rv3d_mats);
+
+ 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"
+);
+static PyObject *bpygpu_offscreen_free(BPyGPUOffScreen *self)
+{
+ BPY_GPU_OFFSCREEN_CHECK_OBJ(self);
+
+ GPU_offscreen_free(self->ofs);
+ self->ofs = NULL;
+ Py_RETURN_NONE;
+}
+
+static PyObject *bpygpu_offscreen_bind_context_enter(BPyGPUOffScreen *UNUSED(self))
+{
+ 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;
+}
+
+static void BPyGPUOffScreen__tp_dealloc(BPyGPUOffScreen *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 */
+};
+
+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}
+};
+
+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"
+);
+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,
+};
+
+/** \} */
+
+
+/* -------------------------------------------------------------------- */
+
+/** \name Public API
+ * \{ */
+
+PyObject *BPyGPUOffScreen_CreatePyObject(GPUOffScreen *ofs)
+{
+ BPyGPUOffScreen *self;
+
+ self = PyObject_New(BPyGPUOffScreen, &BPyGPUOffScreen_Type);
+ self->ofs = ofs;
+
+ return (PyObject *)self;
+}
+
+/** \} */
+
+#undef BPY_GPU_OFFSCREEN_CHECK_OBJ
diff --git a/source/blender/python/gpu/gpu_py_offscreen.h b/source/blender/python/gpu/gpu_py_offscreen.h
new file mode 100644
index 00000000000..c4a2d02a694
--- /dev/null
+++ b/source/blender/python/gpu/gpu_py_offscreen.h
@@ -0,0 +1,42 @@
+/*
+ * ***** BEGIN GPL LICENSE BLOCK *****
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ * ***** END GPL LICENSE BLOCK *****
+ */
+
+/** \file blender/python/gpu/gpu_py_offscreen.h
+ * \ingroup bpygpu
+ */
+
+#ifndef __GPU_PY_OFFSCREEN_H__
+#define __GPU_PY_OFFSCREEN_H__
+
+#include "BLI_compiler_attrs.h"
+
+extern PyTypeObject BPyGPUOffScreen_Type;
+
+#define BPyGPUOffScreen_Check(v) (Py_TYPE(v) == &BPyGPUOffScreen_Type)
+
+typedef struct BPyGPUOffScreen {
+ PyObject_HEAD
+ struct GPUOffScreen *ofs;
+ bool is_saved;
+} BPyGPUOffScreen;
+
+PyObject *BPyGPUOffScreen_CreatePyObject(struct GPUOffScreen *ofs) ATTR_NONNULL(1);
+
+#endif /* __GPU_PY_OFFSCREEN_H__ */
diff --git a/source/blender/python/gpu/gpu_py_select.c b/source/blender/python/gpu/gpu_py_select.c
new file mode 100644
index 00000000000..56b8b904464
--- /dev/null
+++ b/source/blender/python/gpu/gpu_py_select.c
@@ -0,0 +1,95 @@
+/*
+ * ***** BEGIN GPL LICENSE BLOCK *****
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ * ***** END GPL LICENSE BLOCK *****
+ */
+
+/** \file blender/python/gpu/gpu_py_select.c
+ * \ingroup bpygpu
+ *
+ * This file defines the gpu.select API.
+ *
+ * \note Currently only used for gizmo selection,
+ * will need to add begin/end and a way to access the hits.
+ *
+ * - Use ``bpygpu_`` for local API.
+ * - Use ``BPyGPU`` for public API.
+ */
+
+#include <Python.h>
+
+#include "BLI_utildefines.h"
+
+#include "../generic/py_capi_utils.h"
+
+#include "GPU_select.h"
+
+#include "gpu_py_select.h" /* own include */
+
+/* -------------------------------------------------------------------- */
+/** \name Methods
+ * \{ */
+
+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"
+);
+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;
+}
+/** \} */
+
+/* -------------------------------------------------------------------- */
+/** \name Module
+ * \{ */
+
+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}
+};
+
+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,
+};
+
+PyObject *BPyInit_gpu_select(void)
+{
+ PyObject *submodule;
+
+ submodule = PyModule_Create(&BPyGPU_select_module_def);
+
+ return submodule;
+}
+
+/** \} */
diff --git a/source/blender/python/gpu/gpu_py_select.h b/source/blender/python/gpu/gpu_py_select.h
new file mode 100644
index 00000000000..11daf2ade64
--- /dev/null
+++ b/source/blender/python/gpu/gpu_py_select.h
@@ -0,0 +1,30 @@
+/*
+ * ***** BEGIN GPL LICENSE BLOCK *****
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ * ***** END GPL LICENSE BLOCK *****
+ */
+
+/** \file blender/python/gpu/gpu_py_select.h
+ * \ingroup bpygpu
+ */
+
+#ifndef __GPU_PY_SELECT_H__
+#define __GPU_PY_SELECT_H__
+
+PyObject *BPyInit_gpu_select(void);
+
+#endif /* __GPU_PY_SELECT_H__ */
diff --git a/source/blender/python/gpu/gpu_py_shader.c b/source/blender/python/gpu/gpu_py_shader.c
new file mode 100644
index 00000000000..31e1ccf6f8c
--- /dev/null
+++ b/source/blender/python/gpu/gpu_py_shader.c
@@ -0,0 +1,839 @@
+/*
+ * ***** BEGIN GPL LICENSE BLOCK *****
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ * ***** END GPL LICENSE BLOCK *****
+ */
+
+/** \file blender/python/gpu/gpu_py_shader.c
+ * \ingroup bpygpu
+ *
+ * - Use ``bpygpu_`` for local API.
+ * - Use ``BPyGPU`` for public API.
+ */
+
+#include <Python.h>
+
+#include "BLI_utildefines.h"
+
+#include "GPU_shader.h"
+#include "GPU_shader_interface.h"
+
+#include "../generic/py_capi_utils.h"
+#include "../generic/python_utildefines.h"
+#include "../mathutils/mathutils.h"
+
+#include "gpu_py_api.h"
+#include "gpu_py_shader.h" /* own include */
+#include "gpu_py_vertex_format.h"
+
+
+ /* -------------------------------------------------------------------- */
+
+ /** \name Enum Conversion.
+ * \{ */
+
+static int bpygpu_ParseBultinShaderEnum(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;
+ }
+#define MATCH_ID(id) \
+ if (mode_id_len == (Py_ssize_t)strlen(STRINGIFY(id))) { \
+ if (STREQ(mode_id, STRINGIFY(id))) { \
+ mode = GPU_SHADER_##id; \
+ goto success; \
+ } \
+ } ((void)0)
+
+ GPUBuiltinShader mode;
+ MATCH_ID(2D_UNIFORM_COLOR);
+ MATCH_ID(2D_FLAT_COLOR);
+ MATCH_ID(2D_SMOOTH_COLOR);
+ MATCH_ID(2D_IMAGE);
+ MATCH_ID(3D_UNIFORM_COLOR);
+ MATCH_ID(3D_FLAT_COLOR);
+ MATCH_ID(3D_SMOOTH_COLOR);
+
+#undef MATCH_ID
+ PyErr_Format(PyExc_ValueError,
+ "unknown type literal: '%s'",
+ mode_id);
+ return 0;
+
+success:
+ (*(GPUBuiltinShader *)p) = mode;
+ return 1;
+}
+
+static int bpygpu_uniform_location_get(GPUShader *shader, const char *name, const char *error_prefix)
+{
+ int uniform = GPU_shader_get_uniform_ensure(shader, name);
+
+ if (uniform == -1) {
+ PyErr_Format(PyExc_ValueError, "%s: uniform %.32s %.32s not found", error_prefix, name);
+ }
+
+ return uniform;
+}
+
+/** \} */
+
+
+/* -------------------------------------------------------------------- */
+
+/** \name Shader Type
+ * \{ */
+
+static PyObject *bpygpu_shader_new(PyTypeObject *UNUSED(type), PyObject *args, PyObject *kwds)
+{
+ BPYGPU_IS_INIT_OR_ERROR_OBJ;
+
+ struct {
+ const char *vertexcode;
+ const char *fragcode;
+ const char *geocode;
+ const char *libcode;
+ const char *defines;
+ } params = {0};
+
+ static const char *_keywords[] = {
+ "vertexcode", "fragcode", "geocode",
+ "libcode", "defines", NULL};
+
+ static _PyArg_Parser _parser = {"ss|$sss:GPUShader.__new__", _keywords, 0};
+ if (!_PyArg_ParseTupleAndKeywordsFast(
+ args, kwds, &_parser,
+ &params.vertexcode, &params.fragcode, &params.geocode,
+ &params.libcode, &params.defines))
+ {
+ return NULL;
+ }
+
+ GPUShader *shader = GPU_shader_create(
+ params.vertexcode,
+ params.fragcode,
+ params.geocode,
+ params.libcode,
+ params.defines,
+ NULL);
+
+ if (shader == NULL) {
+ PyErr_SetString(PyExc_Exception,
+ "Shader Compile Error, see console for more details");
+ return NULL;
+ }
+
+ return BPyGPUShader_CreatePyObject(shader, false);
+}
+
+PyDoc_STRVAR(bpygpu_shader_bind_doc,
+".. method:: bind()\n"
+"\n"
+" Bind the shader object. Required to be able to change uniforms of this shader.\n"
+);
+static PyObject *bpygpu_shader_bind(BPyGPUShader *self)
+{
+ GPU_shader_bind(self->shader);
+ Py_RETURN_NONE;
+}
+
+PyDoc_STRVAR(bpygpu_shader_uniform_from_name_doc,
+".. method:: uniform_from_name(name)\n"
+"\n"
+" Get uniform location by name.\n"
+"\n"
+" :param name: Name of the uniform variable whose location is to be queried.\n"
+" :type name: `str`\n"
+" :return: Location of the uniform variable.\n"
+" :rtype: `int`\n"
+);
+static PyObject *bpygpu_shader_uniform_from_name(
+ BPyGPUShader *self, PyObject *arg)
+{
+ const char *name = PyUnicode_AsUTF8(arg);
+ if (name == NULL) {
+ return NULL;
+ }
+
+ int uniform = bpygpu_uniform_location_get(
+ self->shader, name, "GPUShader.get_uniform");
+
+ if (uniform == -1) {
+ return NULL;
+ }
+
+ return PyLong_FromLong(uniform);
+}
+
+PyDoc_STRVAR(bpygpu_shader_uniform_block_from_name_doc,
+".. method:: uniform_block_from_name(name)\n"
+"\n"
+" Get uniform block location by name.\n"
+"\n"
+" :param name: Name of the uniform block variable whose location is to be queried.\n"
+" :type name: `str`\n"
+" :return: The location of the uniform block variable.\n"
+" :rtype: `int`\n"
+);
+static PyObject *bpygpu_shader_uniform_block_from_name(
+ BPyGPUShader *self, PyObject *arg)
+{
+ const char *name = PyUnicode_AsUTF8(arg);
+ if (name == NULL) {
+ return NULL;
+ }
+
+ int uniform = GPU_shader_get_uniform_block(self->shader, name);
+
+ if (uniform == -1) {
+ PyErr_Format(PyExc_ValueError,
+ "GPUShader.get_uniform_block: uniform %.32s not found", name);
+ return NULL;
+ }
+
+ return PyLong_FromLong(uniform);
+}
+
+static bool bpygpu_shader_uniform_vector_imp(
+ PyObject *args, int elem_size,
+ int *r_location, int *r_length, int *r_count, Py_buffer *r_pybuffer)
+{
+ PyObject *buffer;
+
+ *r_count = 1;
+ if (!PyArg_ParseTuple(
+ args, "iOi|i:GPUShader.uniform_vector_*",
+ r_location, &buffer, r_length, r_count))
+ {
+ return false;
+ }
+
+ if (PyObject_GetBuffer(buffer, r_pybuffer, PyBUF_SIMPLE) == -1) {
+ /* PyObject_GetBuffer raise a PyExc_BufferError */
+ return false;
+ }
+
+ if (r_pybuffer->len != (*r_length * *r_count * elem_size)) {
+ PyErr_SetString(
+ PyExc_BufferError,
+ "GPUShader.uniform_vector_*: buffer size does not match.");
+ return false;
+ }
+
+ return true;
+}
+
+PyDoc_STRVAR(bpygpu_shader_uniform_vector_float_doc,
+".. method:: uniform_vector_float(location, buffer, length, count)\n"
+"\n"
+" Set the buffer to fill the uniform.\n"
+"\n"
+" :param location: Location of the uniform variable to be modified.\n"
+" :type location: int\n"
+" :param buffer: The data that should be set. Can support the buffer protocol.\n"
+" :type buffer: sequence of floats\n"
+" :param length: Size of the uniform data type:\n"
+"\n"
+" - 1: float\n"
+" - 2: vec2 or float[2]\n"
+" - 3: vec3 or float[3]\n"
+" - 4: vec4 or float[4]\n"
+" - 9: mat3\n"
+" - 16: mat4\n"
+"\n"
+" :type length: int\n"
+" :param count: Specifies the number of elements, vector or matrices that are to be modified.\n"
+" :type count: int\n"
+);
+static PyObject *bpygpu_shader_uniform_vector_float(
+ BPyGPUShader *self, PyObject *args)
+{
+ int location, length, count;
+
+ Py_buffer pybuffer;
+
+ if (!bpygpu_shader_uniform_vector_imp(
+ args, sizeof(float),
+ &location, &length, &count, &pybuffer))
+ {
+ return NULL;
+ }
+
+ GPU_shader_uniform_vector(
+ self->shader, location, length,
+ count, pybuffer.buf);
+
+ PyBuffer_Release(&pybuffer);
+
+ Py_RETURN_NONE;
+}
+
+PyDoc_STRVAR(bpygpu_shader_uniform_vector_int_doc,
+".. method:: uniform_vector_int(location, buffer, length, count)\n"
+"\n"
+" See GPUShader.uniform_vector_float(...) description.\n"
+);
+static PyObject *bpygpu_shader_uniform_vector_int(
+ BPyGPUShader *self, PyObject *args)
+{
+ int location, length, count;
+
+ Py_buffer pybuffer;
+
+ if (!bpygpu_shader_uniform_vector_imp(
+ args, sizeof(int),
+ &location, &length, &count, &pybuffer))
+ {
+ return NULL;
+ }
+
+ GPU_shader_uniform_vector_int(
+ self->shader, location, length,
+ count, pybuffer.buf);
+
+ PyBuffer_Release(&pybuffer);
+
+ Py_RETURN_NONE;
+}
+
+PyDoc_STRVAR(bpygpu_shader_uniform_bool_doc,
+".. method:: uniform_bool(name, seq)\n"
+"\n"
+" Specify the value of a uniform variable for the current program object.\n"
+"\n"
+" :param name: Name of the uniform variable whose value is to be changed.\n"
+" :type name: str\n"
+" :param seq: Value that will be used to update the specified uniform variable.\n"
+" :type seq: sequence of bools\n"
+);
+static PyObject *bpygpu_shader_uniform_bool(
+ BPyGPUShader *self, PyObject *args)
+{
+ const char *error_prefix = "GPUShader.uniform_bool";
+
+ struct {
+ const char *id;
+ PyObject *seq;
+ } params;
+
+ if (!PyArg_ParseTuple(
+ args, "sO:GPUShader.uniform_bool",
+ &params.id, &params.seq))
+ {
+ return NULL;
+ }
+
+ int values[4];
+ int length;
+ int ret;
+ {
+ PyObject *seq_fast = PySequence_Fast(params.seq, error_prefix);
+ if (seq_fast == NULL) {
+ PyErr_Format(PyExc_TypeError,
+ "%s: expected a sequence, got %s",
+ error_prefix, Py_TYPE(params.seq)->tp_name);
+ ret = -1;
+ }
+ else {
+ length = PySequence_Fast_GET_SIZE(seq_fast);
+ if (length == 0 || length > 4) {
+ PyErr_Format(PyExc_TypeError,
+ "%s: invalid sequence length. expected 1..4, got %d",
+ error_prefix, length);
+ ret = -1;
+ }
+ else {
+ ret = PyC_AsArray_FAST(
+ values, seq_fast, length, &PyLong_Type,
+ false, error_prefix);
+ }
+ Py_DECREF(seq_fast);
+ }
+ }
+ if (ret == -1) {
+ return NULL;
+ }
+
+ const int location = bpygpu_uniform_location_get(
+ self->shader, params.id, error_prefix);
+
+ if (location == -1) {
+ return NULL;
+ }
+
+ GPU_shader_uniform_vector_int(self->shader, location, length, 1, values);
+
+ Py_RETURN_NONE;
+}
+
+PyDoc_STRVAR(bpygpu_shader_uniform_float_doc,
+".. method:: uniform_float(name, value)\n"
+"\n"
+" Specify the value of a uniform variable for the current program object.\n"
+"\n"
+" :param name: Name of the uniform variable whose value is to be changed.\n"
+" :type name: str\n"
+" :param value: Value that will be used to update the specified uniform variable.\n"
+" :type value: single number or sequence of numbers\n"
+);
+static PyObject *bpygpu_shader_uniform_float(
+ BPyGPUShader *self, PyObject *args)
+{
+ const char *error_prefix = "GPUShader.uniform_float";
+
+ struct {
+ const char *id;
+ PyObject *seq;
+ } params;
+
+ if (!PyArg_ParseTuple(
+ args, "sO:GPUShader.uniform_float",
+ &params.id, &params.seq))
+ {
+ return NULL;
+ }
+
+ float values[16];
+ int length;
+
+ if (PyFloat_Check(params.seq)) {
+ values[0] = (float)PyFloat_AsDouble(params.seq);
+ length = 1;
+ }
+ else if (PyLong_Check(params.seq)) {
+ values[0] = (float)PyLong_AsDouble(params.seq);
+ length = 1;
+ }
+ else if (MatrixObject_Check(params.seq)) {
+ MatrixObject *mat = (MatrixObject *)params.seq;
+ if (BaseMath_ReadCallback(mat) == -1) {
+ return NULL;
+ }
+ if ((mat->num_row != mat->num_col) || !ELEM(mat->num_row, 3, 4)) {
+ PyErr_SetString(PyExc_ValueError,
+ "Expected 3x3 or 4x4 matrix");
+ return NULL;
+ }
+ length = mat->num_row * mat->num_col;
+ memcpy(values, mat->matrix, sizeof(float) * length);
+ }
+ else {
+ length = mathutils_array_parse(values, 2, 16, params.seq, "");
+ if (length == -1) {
+ return NULL;
+ }
+ }
+
+ if (!ELEM(length, 1, 2, 3, 4, 9, 16)) {
+ PyErr_SetString(PyExc_TypeError,
+ "Expected a single float or a sequence of floats of length 1..4, 9 or 16.");
+ return NULL;
+ }
+
+ const int location = bpygpu_uniform_location_get(
+ self->shader, params.id, error_prefix);
+
+ if (location == -1) {
+ return NULL;
+ }
+
+ GPU_shader_uniform_vector(self->shader, location, length, 1, values);
+
+ Py_RETURN_NONE;
+}
+
+PyDoc_STRVAR(bpygpu_shader_uniform_int_doc,
+".. method:: uniform_int(name, seq)\n"
+"\n"
+" Specify the value of a uniform variable for the current program object.\n"
+"\n"
+" :param name: name of the uniform variable whose value is to be changed.\n"
+" :type name: str\n"
+" :param seq: Value that will be used to update the specified uniform variable.\n"
+" :type seq: sequence of numbers\n"
+);
+static PyObject *bpygpu_shader_uniform_int(
+ BPyGPUShader *self, PyObject *args)
+{
+ const char *error_prefix = "GPUShader.uniform_int";
+
+ struct {
+ const char *id;
+ PyObject *seq;
+ } params;
+
+ if (!PyArg_ParseTuple(
+ args, "sO:GPUShader.uniform_int",
+ &params.id, &params.seq))
+ {
+ return NULL;
+ }
+
+ int values[4];
+ int length;
+ int ret;
+
+ if (PyLong_Check(params.seq)) {
+ values[0] = PyC_Long_AsI32(params.seq);
+ length = 1;
+ ret = 0;
+ }
+ else {
+ PyObject *seq_fast = PySequence_Fast(params.seq, error_prefix);
+ if (seq_fast == NULL) {
+ PyErr_Format(PyExc_TypeError,
+ "%s: expected a sequence, got %s",
+ error_prefix, Py_TYPE(params.seq)->tp_name);
+ ret = -1;
+ }
+ else {
+ length = PySequence_Fast_GET_SIZE(seq_fast);
+ if (length == 0 || length > 4) {
+ PyErr_Format(PyExc_TypeError,
+ "%s: invalid sequence length. expected 1..4, got %d",
+ error_prefix, length);
+ ret = -1;
+ }
+ else {
+ ret = PyC_AsArray_FAST(
+ values, seq_fast, length, &PyLong_Type,
+ false, error_prefix);
+ }
+ Py_DECREF(seq_fast);
+ }
+ }
+ if (ret == -1) {
+ return NULL;
+ }
+
+ const int location = bpygpu_uniform_location_get(
+ self->shader, params.id, error_prefix);
+
+ if (location == -1) {
+ return NULL;
+ }
+
+ GPU_shader_uniform_vector_int(self->shader, location, length, 1, values);
+
+ Py_RETURN_NONE;
+}
+
+PyDoc_STRVAR(bpygpu_shader_attr_from_name_doc,
+".. method:: attr_from_name(name)\n"
+"\n"
+" Get attribute location by name.\n"
+"\n"
+" :param name: The name of the attribute variable whose location is to be queried.\n"
+" :type name: str\n"
+" :return: The location of an attribute variable.\n"
+" :rtype: int\n"
+);
+static PyObject *bpygpu_shader_attr_from_name(
+ BPyGPUShader *self, PyObject *arg)
+{
+ const char *name = PyUnicode_AsUTF8(arg);
+ if (name == NULL) {
+ return NULL;
+ }
+
+ int attr = GPU_shader_get_attribute(self->shader, name);
+
+ if (attr == -1) {
+ PyErr_Format(PyExc_ValueError,
+ "GPUShader.attr_from_name: attribute %.32s not found", name);
+ return NULL;
+ }
+
+ return PyLong_FromLong(attr);
+}
+
+PyDoc_STRVAR(bpygpu_shader_calc_format_doc,
+".. method:: calc_format()\n"
+"\n"
+" Build a new format based on the attributes of the shader.\n"
+"\n"
+" :return: vertex attribute format for the shader\n"
+" :rtype: GPUVertFormat\n"
+);
+static PyObject *bpygpu_shader_calc_format(BPyGPUShader *self, PyObject *UNUSED(arg))
+{
+ BPyGPUVertFormat *ret = (BPyGPUVertFormat *)BPyGPUVertFormat_CreatePyObject(NULL);
+ GPU_vertformat_from_interface(&ret->fmt, GPU_shader_get_interface(self->shader));
+ return (PyObject *)ret;
+}
+
+static struct PyMethodDef bpygpu_shader_methods[] = {
+ {"bind", (PyCFunction)bpygpu_shader_bind,
+ METH_NOARGS, bpygpu_shader_bind_doc},
+ {"uniform_from_name",
+ (PyCFunction)bpygpu_shader_uniform_from_name,
+ METH_O, bpygpu_shader_uniform_from_name_doc},
+ {"uniform_block_from_name",
+ (PyCFunction)bpygpu_shader_uniform_block_from_name,
+ METH_O, bpygpu_shader_uniform_block_from_name_doc},
+ {"uniform_vector_float",
+ (PyCFunction)bpygpu_shader_uniform_vector_float,
+ METH_VARARGS, bpygpu_shader_uniform_vector_float_doc},
+ {"uniform_vector_int",
+ (PyCFunction)bpygpu_shader_uniform_vector_int,
+ METH_VARARGS, bpygpu_shader_uniform_vector_int_doc},
+ {"uniform_bool",
+ (PyCFunction)bpygpu_shader_uniform_bool,
+ METH_VARARGS, bpygpu_shader_uniform_bool_doc},
+ {"uniform_float",
+ (PyCFunction)bpygpu_shader_uniform_float,
+ METH_VARARGS, bpygpu_shader_uniform_float_doc},
+ {"uniform_int",
+ (PyCFunction)bpygpu_shader_uniform_int,
+ METH_VARARGS, bpygpu_shader_uniform_int_doc},
+ {"attr_from_name",
+ (PyCFunction)bpygpu_shader_attr_from_name,
+ METH_O, bpygpu_shader_attr_from_name_doc},
+ {"format_calc",
+ (PyCFunction)bpygpu_shader_calc_format,
+ METH_NOARGS, bpygpu_shader_calc_format_doc},
+ {NULL, NULL, 0, NULL}
+};
+
+PyDoc_STRVAR(bpygpu_shader_program_doc,
+"The name of the program object for use by the OpenGL API (read-only).\n\n:type: int"
+);
+static PyObject *bpygpu_shader_program_get(BPyGPUShader *self, void *UNUSED(closure))
+{
+ return PyLong_FromLong(GPU_shader_get_program(self->shader));
+}
+
+static PyGetSetDef bpygpu_shader_getseters[] = {
+ {(char *)"program",
+ (getter)bpygpu_shader_program_get, (setter)NULL,
+ bpygpu_shader_program_doc, NULL},
+ {NULL, NULL, NULL, NULL, NULL} /* Sentinel */
+};
+
+
+static void bpygpu_shader_dealloc(BPyGPUShader *self)
+{
+ if (self->is_builtin == false) {
+ GPU_shader_free(self->shader);
+ }
+ Py_TYPE(self)->tp_free((PyObject *)self);
+}
+
+
+PyDoc_STRVAR(bpygpu_shader_doc,
+".. class:: GPUShader(vertexcode, fragcode, geocode=None, libcode=None, defines=None)\n"
+"\n"
+" GPUShader combines multiple GLSL shaders into a program used for drawing.\n"
+" It must contain a vertex and fragment shaders, with an optional geometry shader.\n"
+"\n"
+" The GLSL #version directive is automatically included at the top of shaders, and set to 330.\n"
+" Some preprocessor directives are automatically added according to the Operating System or availability:\n"
+" ``GPU_ATI``, ``GPU_NVIDIA`` and ``GPU_INTEL``.\n"
+"\n"
+" The following extensions are enabled by default if supported by the GPU:\n"
+" ``GL_ARB_texture_gather`` and ``GL_ARB_texture_query_lod``.\n"
+"\n"
+" To debug shaders, use the --debug-gpu-shaders command line option"
+" to see full GLSL shader compilation and linking errors.\n"
+"\n"
+" :param vertexcode: Vertex shader code.\n"
+" :type vertexcode: str\n"
+" :param fragcode: Fragment shader code.\n"
+" :type value: str\n"
+" :param geocode: Geometry shader code.\n"
+" :type value: str\n"
+" :param libcode: Code with functions and presets to be shared between shaders.\n"
+" :type value: str\n"
+" :param defines: Preprocessor directives.\n"
+" :type value: str\n"
+);
+PyTypeObject BPyGPUShader_Type = {
+ PyVarObject_HEAD_INIT(NULL, 0)
+ .tp_name = "GPUShader",
+ .tp_basicsize = sizeof(BPyGPUShader),
+ .tp_dealloc = (destructor)bpygpu_shader_dealloc,
+ .tp_flags = Py_TPFLAGS_DEFAULT,
+ .tp_doc = bpygpu_shader_doc,
+ .tp_methods = bpygpu_shader_methods,
+ .tp_getset = bpygpu_shader_getseters,
+ .tp_new = bpygpu_shader_new,
+};
+
+/** \} */
+
+
+/* -------------------------------------------------------------------- */
+
+/** \name gpu.shader Module API
+ * \{ */
+
+PyDoc_STRVAR(bpygpu_shader_unbind_doc,
+".. function:: unbind()\n"
+"\n"
+" Unbind the bound shader object.\n"
+);
+static PyObject *bpygpu_shader_unbind(BPyGPUShader *UNUSED(self))
+{
+ GPU_shader_unbind();
+ Py_RETURN_NONE;
+}
+
+PyDoc_STRVAR(bpygpu_shader_from_builtin_doc,
+".. function:: from_builtin(shader_name)\n"
+"\n"
+" Shaders that are embedded in the blender internal code.\n"
+" They all read the uniform 'mat4 ModelViewProjectionMatrix', which can be edited by the 'gpu.matrix' module.\n"
+" For more details, you can check the shader code with the function 'gpu.shader.code_from_builtin';\n"
+"\n"
+" :param shader_name: One of these builtin shader names: {\n"
+" '2D_UNIFORM_COLOR',\n"
+" '2D_FLAT_COLOR',\n"
+" '2D_SMOOTH_COLOR',\n"
+" '2D_IMAGE',\n"
+" '3D_UNIFORM_COLOR',\n"
+" '3D_FLAT_COLOR',\n"
+" '3D_SMOOTH_COLOR'}\n"
+" :type shader_name: str\n"
+" :return: Shader object corresponding to the given name.\n"
+" :rtype: :class:`bpy.types.GPUShader`\n"
+);
+static PyObject *bpygpu_shader_from_builtin(PyObject *UNUSED(self), PyObject *arg)
+{
+ BPYGPU_IS_INIT_OR_ERROR_OBJ;
+
+ GPUBuiltinShader shader_id;
+
+ if (!bpygpu_ParseBultinShaderEnum(arg, &shader_id)) {
+ return NULL;
+ }
+
+ GPUShader *shader = GPU_shader_get_builtin_shader(shader_id);
+
+ return BPyGPUShader_CreatePyObject(shader, true);
+}
+
+PyDoc_STRVAR(bpygpu_shader_code_from_builtin_doc,
+".. function:: code_from_builtin(shader_name)\n"
+"\n"
+" Exposes the internal shader code for query.\n"
+"\n"
+" :param shader_name: One of these builtin shader names: {\n"
+" '2D_UNIFORM_COLOR',\n"
+" '2D_FLAT_COLOR',\n"
+" '2D_SMOOTH_COLOR',\n"
+" '2D_IMAGE',\n"
+" '3D_UNIFORM_COLOR',\n"
+" '3D_FLAT_COLOR',\n"
+" '3D_SMOOTH_COLOR'}\n"
+" :type shader_name: str\n"
+" :return: Vertex, fragment and geometry shader codes.\n"
+" :rtype: dict\n"
+);
+static PyObject *bpygpu_shader_code_from_builtin(BPyGPUShader *UNUSED(self), PyObject *arg)
+{
+ GPUBuiltinShader shader_id;
+
+ const char *vert;
+ const char *frag;
+ const char *geom;
+ const char *defines;
+
+ PyObject *item, *r_dict;
+
+ if (!bpygpu_ParseBultinShaderEnum(arg, &shader_id)) {
+ return NULL;
+ }
+
+ GPU_shader_get_builtin_shader_code(
+ shader_id, &vert, &frag, &geom, &defines);
+
+ r_dict = PyDict_New();
+
+ PyDict_SetItemString(r_dict, "vertex_shader", item = PyUnicode_FromString(vert));
+ Py_DECREF(item);
+
+ PyDict_SetItemString(r_dict, "fragment_shader", item = PyUnicode_FromString(frag));
+ Py_DECREF(item);
+
+ if (geom) {
+ PyDict_SetItemString(r_dict, "geometry_shader", item = PyUnicode_FromString(geom));
+ Py_DECREF(item);
+ }
+ if (defines) {
+ PyDict_SetItemString(r_dict, "defines", item = PyUnicode_FromString(defines));
+ Py_DECREF(item);
+ }
+ return r_dict;
+}
+
+static struct PyMethodDef bpygpu_shader_module_methods[] = {
+ {"unbind",
+ (PyCFunction)bpygpu_shader_unbind,
+ METH_NOARGS, bpygpu_shader_unbind_doc},
+ {"from_builtin",
+ (PyCFunction)bpygpu_shader_from_builtin,
+ METH_O, bpygpu_shader_from_builtin_doc},
+ {"code_from_builtin",
+ (PyCFunction)bpygpu_shader_code_from_builtin,
+ METH_O, bpygpu_shader_code_from_builtin_doc},
+ {NULL, NULL, 0, NULL}
+};
+
+PyDoc_STRVAR(bpygpu_shader_module_doc,
+"This module provides access to GPUShader internal functions."
+);
+static PyModuleDef BPyGPU_shader_module_def = {
+ PyModuleDef_HEAD_INIT,
+ .m_name = "gpu.shader",
+ .m_doc = bpygpu_shader_module_doc,
+ .m_methods = bpygpu_shader_module_methods,
+};
+
+/** \} */
+
+
+/* -------------------------------------------------------------------- */
+
+/** \name Public API
+ * \{ */
+
+PyObject *BPyGPUShader_CreatePyObject(GPUShader *shader, bool is_builtin)
+{
+ BPyGPUShader *self;
+
+ self = PyObject_New(BPyGPUShader, &BPyGPUShader_Type);
+ self->shader = shader;
+ self->is_builtin = is_builtin;
+
+ return (PyObject *)self;
+}
+
+PyObject *BPyInit_gpu_shader(void)
+{
+ PyObject *submodule;
+
+ submodule = PyModule_Create(&BPyGPU_shader_module_def);
+
+ return submodule;
+}
+
+/** \} */
diff --git a/source/blender/python/gpu/gpu_py_shader.h b/source/blender/python/gpu/gpu_py_shader.h
new file mode 100644
index 00000000000..c038cf63e40
--- /dev/null
+++ b/source/blender/python/gpu/gpu_py_shader.h
@@ -0,0 +1,41 @@
+/*
+ * ***** BEGIN GPL LICENSE BLOCK *****
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ * ***** END GPL LICENSE BLOCK *****
+ */
+
+/** \file blender/python/gpu/gpu_py_shader.h
+ * \ingroup bpygpu
+ */
+
+#ifndef __GPU_PY_SHADER_H__
+#define __GPU_PY_SHADER_H__
+
+extern PyTypeObject BPyGPUShader_Type;
+
+#define BPyGPUShader_Check(v) (Py_TYPE(v) == &BPyGPUShader_Type)
+
+typedef struct BPyGPUShader {
+ PyObject_VAR_HEAD
+ struct GPUShader *shader;
+ bool is_builtin;
+} BPyGPUShader;
+
+PyObject *BPyGPUShader_CreatePyObject(struct GPUShader *shader, bool is_builtin);
+PyObject *BPyInit_gpu_shader(void);
+
+#endif /* __GPU_PY_SHADER_H__ */
diff --git a/source/blender/python/gpu/gpu_py_types.c b/source/blender/python/gpu/gpu_py_types.c
new file mode 100644
index 00000000000..d9ef0736f8e
--- /dev/null
+++ b/source/blender/python/gpu/gpu_py_types.c
@@ -0,0 +1,80 @@
+/*
+ * ***** BEGIN GPL LICENSE BLOCK *****
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ * ***** END GPL LICENSE BLOCK *****
+ */
+
+/** \file blender/python/gpu/gpu_py_types.c
+ * \ingroup bpygpu
+ *
+ * - Use ``bpygpu_`` for local API.
+ * - Use ``BPyGPU`` for public API.
+ */
+
+#include <Python.h>
+
+#include "../generic/py_capi_utils.h"
+#include "../generic/python_utildefines.h"
+
+#include "gpu_py_types.h" /* own include */
+
+/* -------------------------------------------------------------------- */
+
+
+/** \name GPU Types Module
+ * \{ */
+
+static struct PyModuleDef BPyGPU_types_module_def = {
+ PyModuleDef_HEAD_INIT,
+ .m_name = "gpu.types",
+};
+
+PyObject *BPyInit_gpu_types(void)
+{
+ PyObject *submodule;
+
+ 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;
+
+#define MODULE_TYPE_ADD(s, 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);
+
+#undef MODULE_TYPE_ADD
+
+ return submodule;
+}
+
+/** \} */
diff --git a/source/blender/python/gpu/gpu_py_types.h b/source/blender/python/gpu/gpu_py_types.h
new file mode 100644
index 00000000000..dc91c579aaf
--- /dev/null
+++ b/source/blender/python/gpu/gpu_py_types.h
@@ -0,0 +1,37 @@
+/*
+ * ***** BEGIN GPL LICENSE BLOCK *****
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ * ***** END GPL LICENSE BLOCK *****
+ */
+
+/** \file blender/python/gpu/gpu_py_types.h
+ * \ingroup bpygpu
+ */
+
+#ifndef __GPU_PY_TYPES_H__
+#define __GPU_PY_TYPES_H__
+
+#include "gpu_py_vertex_format.h"
+#include "gpu_py_vertex_buffer.h"
+#include "gpu_py_element.h"
+#include "gpu_py_batch.h"
+#include "gpu_py_offscreen.h"
+#include "gpu_py_shader.h"
+
+PyObject *BPyInit_gpu_types(void);
+
+#endif /* __GPU_PY_TYPES_H__ */
diff --git a/source/blender/python/gpu/gpu_py_vertex_buffer.c b/source/blender/python/gpu/gpu_py_vertex_buffer.c
new file mode 100644
index 00000000000..c13e3f2195e
--- /dev/null
+++ b/source/blender/python/gpu/gpu_py_vertex_buffer.c
@@ -0,0 +1,352 @@
+/*
+ * ***** BEGIN GPL LICENSE BLOCK *****
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ * ***** END GPL LICENSE BLOCK *****
+ */
+
+/** \file blender/python/gpu/gpu_py_vertex_buffer.c
+ * \ingroup bpygpu
+ *
+ * - Use ``bpygpu_`` for local API.
+ * - Use ``BPyGPU`` for public API.
+ */
+
+#include <Python.h>
+
+#include "GPU_vertex_buffer.h"
+
+#include "BLI_math.h"
+
+#include "MEM_guardedalloc.h"
+
+#include "../generic/py_capi_utils.h"
+#include "../generic/python_utildefines.h"
+
+#include "gpu_py_vertex_format.h"
+#include "gpu_py_vertex_buffer.h" /* own include */
+
+/* -------------------------------------------------------------------- */
+
+/** \name Utility Functions
+ * \{ */
+
+#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)
+
+/* 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)
+
+ 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)
+{
+ 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)
+
+ PY_AS_NATIVE_SWITCH(attr);
+
+#undef PY_AS_NATIVE
+}
+
+#undef PY_AS_NATIVE_SWITCH
+#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)
+{
+ const char *exc_str_size_mismatch = "Expected a %s of size %d, got %u";
+
+ bool ok = true;
+ const GPUVertAttr *attr = &vbo->format.attribs[data_id];
+
+ 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;
+ }
+
+ 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);
+ }
+
+ 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;
+ }
+
+ 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);
+ }
+
+ 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 (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);
+ }
+ }
+
+ if (PyErr_Occurred()) {
+ ok = false;
+ }
+
+finally:
+
+ Py_DECREF(seq_fast);
+ }
+ return ok;
+}
+
+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 (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;
+ }
+
+ return 1;
+}
+
+
+/** \} */
+
+
+/* -------------------------------------------------------------------- */
+
+/** \name VertBuf Type
+ * \{ */
+
+static PyObject *bpygpu_VertBuf_new(PyTypeObject *UNUSED(type), PyObject *args, PyObject *kwds)
+{
+ 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;
+ }
+
+ const GPUVertFormat *fmt = &((BPyGPUVertFormat *)params.py_fmt)->fmt;
+ GPUVertBuf *vbo = GPU_vertbuf_create_with_format(fmt);
+
+ GPU_vertbuf_data_alloc(vbo, params.len);
+
+ 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"
+);
+static PyObject *bpygpu_VertBuf_attr_fill(BPyGPUVertBuf *self, PyObject *args, PyObject *kwds)
+{
+ 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;
+ }
+
+ 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 (!bpygpu_attr_fill(self->buf, id, data, "GPUVertBuf.attr_fill")) {
+ return NULL;
+ }
+
+ 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}
+};
+
+static void bpygpu_VertBuf_dealloc(BPyGPUVertBuf *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"
+);
+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,
+};
+
+/** \} */
+
+
+/* -------------------------------------------------------------------- */
+
+/** \name Public API
+ * \{ */
+
+PyObject *BPyGPUVertBuf_CreatePyObject(GPUVertBuf *buf)
+{
+ BPyGPUVertBuf *self;
+
+ self = PyObject_New(BPyGPUVertBuf, &BPyGPUVertBuf_Type);
+ self->buf = buf;
+
+ return (PyObject *)self;
+}
+
+/** \} */
diff --git a/source/blender/python/gpu/gpu_py_vertex_buffer.h b/source/blender/python/gpu/gpu_py_vertex_buffer.h
new file mode 100644
index 00000000000..6751956298c
--- /dev/null
+++ b/source/blender/python/gpu/gpu_py_vertex_buffer.h
@@ -0,0 +1,42 @@
+/*
+ * ***** BEGIN GPL LICENSE BLOCK *****
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ * ***** END GPL LICENSE BLOCK *****
+ */
+
+/** \file blender/python/gpu/gpu_py_vertex_buffer.h
+ * \ingroup bpygpu
+ */
+
+#ifndef __GPU_PY_VERTEX_BUFFER_H__
+#define __GPU_PY_VERTEX_BUFFER_H__
+
+#include "BLI_compiler_attrs.h"
+
+extern PyTypeObject 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;
+} BPyGPUVertBuf;
+
+PyObject *BPyGPUVertBuf_CreatePyObject(struct GPUVertBuf *vbo) ATTR_NONNULL(1);
+
+#endif /* __GPU_PY_VERTEX_BUFFER_H__ */
diff --git a/source/blender/python/gpu/gpu_py_vertex_format.c b/source/blender/python/gpu/gpu_py_vertex_format.c
new file mode 100644
index 00000000000..27f3791ec15
--- /dev/null
+++ b/source/blender/python/gpu/gpu_py_vertex_format.c
@@ -0,0 +1,263 @@
+/*
+ * ***** BEGIN GPL LICENSE BLOCK *****
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ * ***** END GPL LICENSE BLOCK *****
+ */
+
+/** \file blender/python/gpu/gpu_py_vertex_format.c
+ * \ingroup bpygpu
+ *
+ * - Use ``bpygpu_`` for local API.
+ * - Use ``BPyGPU`` for public API.
+ */
+
+#include <Python.h>
+
+#include "BLI_math.h"
+
+#include "MEM_guardedalloc.h"
+
+#include "../generic/py_capi_utils.h"
+#include "../generic/python_utildefines.h"
+
+#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) )
+#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) )
+#endif
+
+/* -------------------------------------------------------------------- */
+
+/** \name Enum Conversion
+ *
+ * Use with PyArg_ParseTuple's "O&" formatting.
+ * \{ */
+
+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;
+}
+
+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)
+
+ MATCH_ID(FLOAT);
+ MATCH_ID(INT);
+ MATCH_ID(INT_TO_FLOAT_UNIT);
+ MATCH_ID(INT_TO_FLOAT);
+#undef MATCH_ID
+
+ return -1;
+}
+
+static int bpygpu_ParseVertCompType(PyObject *o, void *p)
+{
+ 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;
+ }
+
+ 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;
+}
+
+static int bpygpu_ParseVertFetchMode(PyObject *o, void *p)
+{
+ 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;
+ }
+
+ 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;
+}
+
+/** \} */
+
+
+/* -------------------------------------------------------------------- */
+
+/** \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);
+}
+
+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;
+
+ 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;
+ }
+
+ 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}
+};
+
+
+static void bpygpu_VertFormat_dealloc(BPyGPUVertFormat *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"
+);
+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,
+};
+
+/** \} */
+
+
+/* -------------------------------------------------------------------- */
+
+/** \name Public API
+ * \{ */
+
+PyObject *BPyGPUVertFormat_CreatePyObject(GPUVertFormat *fmt)
+{
+ BPyGPUVertFormat *self;
+
+ self = PyObject_New(BPyGPUVertFormat, &BPyGPUVertFormat_Type);
+ if (fmt) {
+ self->fmt = *fmt;
+ }
+ else {
+ memset(&self->fmt, 0, sizeof(self->fmt));
+ }
+
+ return (PyObject *)self;
+}
+
+/** \} */
diff --git a/source/blender/python/gpu/gpu_py_vertex_format.h b/source/blender/python/gpu/gpu_py_vertex_format.h
new file mode 100644
index 00000000000..5b0bf1addc2
--- /dev/null
+++ b/source/blender/python/gpu/gpu_py_vertex_format.h
@@ -0,0 +1,41 @@
+/*
+ * ***** BEGIN GPL LICENSE BLOCK *****
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ * ***** END GPL LICENSE BLOCK *****
+ */
+
+/** \file blender/python/gpu/gpu_py_vertex_format.h
+ * \ingroup bpygpu
+ */
+
+#ifndef __GPU_PY_VERTEX_FORMAT_H__
+#define __GPU_PY_VERTEX_FORMAT_H__
+
+#include "GPU_vertex_format.h"
+
+extern PyTypeObject BPyGPUVertFormat_Type;
+
+#define BPyGPUVertFormat_Check(v) (Py_TYPE(v) == &BPyGPUVertFormat_Type)
+
+typedef struct BPyGPUVertFormat {
+ PyObject_VAR_HEAD
+ struct GPUVertFormat fmt;
+} BPyGPUVertFormat;
+
+PyObject *BPyGPUVertFormat_CreatePyObject(struct GPUVertFormat *fmt);
+
+#endif /* __GPU_PY_VERTEX_FORMAT_H__ */
diff --git a/source/blender/python/intern/CMakeLists.txt b/source/blender/python/intern/CMakeLists.txt
index 357cb175769..bd7306cddf2 100644
--- a/source/blender/python/intern/CMakeLists.txt
+++ b/source/blender/python/intern/CMakeLists.txt
@@ -52,11 +52,13 @@ set(SRC
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
@@ -65,6 +67,8 @@ set(SRC
bpy_intern_string.c
bpy_library_load.c
bpy_library_write.c
+ bpy_gizmo_wrap.c
+ bpy_msgbus.c
bpy_operator.c
bpy_operator_wrap.c
bpy_path.c
@@ -75,11 +79,10 @@ set(SRC
bpy_rna_callback.c
bpy_rna_driver.c
bpy_rna_id_collection.c
+ bpy_rna_gizmo.c
bpy_traceback.c
bpy_utils_previews.c
bpy_utils_units.c
- gpu.c
- gpu_offscreen.c
stubs.c
bpy.h
@@ -88,16 +91,20 @@ set(SRC
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_intern_string.h
bpy_library.h
+ bpy_gizmo_wrap.h
+ bpy_msgbus.h
bpy_operator.h
bpy_operator_wrap.h
bpy_path.h
@@ -107,10 +114,10 @@ set(SRC
bpy_rna_callback.h
bpy_rna_driver.h
bpy_rna_id_collection.h
+ bpy_rna_gizmo.h
bpy_traceback.h
bpy_utils_previews.h
bpy_utils_units.h
- gpu.h
../BPY_extern.h
../BPY_extern_clog.h
)
@@ -176,10 +183,6 @@ if(WITH_FREESTYLE)
add_definitions(-DWITH_FREESTYLE)
endif()
-if(WITH_GAMEENGINE)
- add_definitions(-DWITH_GAMEENGINE)
-endif()
-
if(WITH_IMAGE_CINEON)
add_definitions(-DWITH_CINEON)
endif()
@@ -188,10 +191,6 @@ if(WITH_IMAGE_DDS)
add_definitions(-DWITH_DDS)
endif()
-if(WITH_IMAGE_FRAMESERVER)
- add_definitions(-DWITH_FRAMESERVER)
-endif()
-
if(WITH_IMAGE_HDR)
add_definitions(-DWITH_HDR)
endif()
@@ -302,10 +301,6 @@ if(WITH_OPENSUBDIV)
)
endif()
-if(WITH_PLAYER)
- add_definitions(-DWITH_PLAYER)
-endif()
-
add_definitions(${GL_DEFINITIONS})
blender_add_lib(bf_python "${SRC}" "${INC}" "${INC_SYS}")
diff --git a/source/blender/python/intern/bpy.c b/source/blender/python/intern/bpy.c
index 82f710e4acf..07ad8274f11 100644
--- a/source/blender/python/intern/bpy.c
+++ b/source/blender/python/intern/bpy.c
@@ -46,6 +46,7 @@
#include "bpy_rna.h"
#include "bpy_app.h"
#include "bpy_rna_id_collection.h"
+#include "bpy_rna_gizmo.h"
#include "bpy_props.h"
#include "bpy_library.h"
#include "bpy_operator.h"
@@ -57,6 +58,7 @@
/* external util modules */
#include "../generic/idprop_py_api.h"
+#include "bpy_msgbus.h"
#ifdef WITH_FREESTYLE
# include "BPy_Freestyle.h"
@@ -338,6 +340,8 @@ void BPy_init_modules(void)
BPY_rna_id_collection_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");
@@ -347,6 +351,7 @@ void BPy_init_modules(void)
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);
@@ -371,6 +376,9 @@ void BPy_init_modules(void)
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));
+
/* add our own modules dir, this is a python package */
bpy_package_py = bpy_import_test("bpy");
}
diff --git a/source/blender/python/intern/bpy_app.c b/source/blender/python/intern/bpy_app.c
index 928e14c09bf..fe8eb768b3a 100644
--- a/source/blender/python/intern/bpy_app.c
+++ b/source/blender/python/intern/bpy_app.c
@@ -47,11 +47,16 @@
#include "bpy_app_handlers.h"
#include "bpy_driver.h"
+/* modules */
+#include "bpy_app_icons.h"
+#include "bpy_app_timers.h"
+
#include "BLI_utildefines.h"
#include "BKE_appdir.h"
#include "BKE_blender_version.h"
#include "BKE_global.h"
+#include "BKE_library_override.h"
#include "DNA_ID.h"
@@ -117,6 +122,10 @@ static PyStructSequence_Field app_info_fields[] = {
{(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},
};
@@ -129,6 +138,8 @@ PyDoc_STRVAR(bpy_app_doc,
" :maxdepth: 1\n"
"\n"
" bpy.app.handlers.rst\n"
+" bpy.app.icons.rst\n"
+" bpy.app.timers.rst\n"
" bpy.app.translations.rst\n"
);
@@ -210,6 +221,10 @@ static PyObject *make_app_info(void)
SetObjItem(BPY_app_handlers_struct());
SetObjItem(BPY_app_translations_struct());
+ /* modules */
+ SetObjItem(BPY_app_icons_module());
+ SetObjItem(BPY_app_timers_module());
+
#undef SetIntItem
#undef SetStrItem
#undef SetBytesItem
@@ -282,7 +297,7 @@ static PyObject *bpy_app_binary_path_python_get(PyObject *self, void *UNUSED(clo
}
PyDoc_STRVAR(bpy_app_debug_value_doc,
-"Int, 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))
{
@@ -291,10 +306,12 @@ static PyObject *bpy_app_debug_value_get(PyObject *UNUSED(self), void *UNUSED(cl
static int bpy_app_debug_value_set(PyObject *UNUSED(self), PyObject *value, void *UNUSED(closure))
{
- int param = PyC_Long_AsI32(value);
+ short param = PyC_Long_AsI16(value);
if (param == -1 && PyErr_Occurred()) {
- PyErr_SetString(PyExc_TypeError, "bpy.app.debug_value can only be set to a whole number");
+ PyC_Err_SetString_Prefix(
+ PyExc_TypeError,
+ "bpy.app.debug_value can only be set to a whole number");
return -1;
}
@@ -348,6 +365,29 @@ static PyObject *bpy_app_autoexec_fail_message_get(PyObject *UNUSED(self), void
}
+PyDoc_STRVAR(bpy_app_use_static_override_doc,
+"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());
+}
+
+static int bpy_app_use_static_override_set(PyObject *UNUSED(self), PyObject *value, void *UNUSED(closure))
+{
+ 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;
+ }
+
+ BKE_override_static_enable((const bool)param);
+
+ 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},
@@ -366,6 +406,8 @@ static PyGetSetDef bpy_app_getsets[] = {
{(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 *)"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},
diff --git a/source/blender/python/intern/bpy_app_build_options.c b/source/blender/python/intern/bpy_app_build_options.c
index d5c325e4317..70c52b8860c 100644
--- a/source/blender/python/intern/bpy_app_build_options.c
+++ b/source/blender/python/intern/bpy_app_build_options.c
@@ -42,10 +42,8 @@ static PyStructSequence_Field app_builtopts_info_fields[] = {
{(char *)"cycles", NULL},
{(char *)"cycles_osl", NULL},
{(char *)"freestyle", NULL},
- {(char *)"gameengine", NULL},
{(char *)"image_cineon", NULL},
{(char *)"image_dds", NULL},
- {(char *)"image_frameserver", NULL},
{(char *)"image_hdr", NULL},
{(char *)"image_openexr", NULL},
{(char *)"image_openjpeg", NULL},
@@ -64,7 +62,6 @@ static PyStructSequence_Field app_builtopts_info_fields[] = {
{(char *)"mod_smoke", NULL},
{(char *)"collada", NULL},
{(char *)"opencolorio", NULL},
- {(char *)"player", NULL},
{(char *)"openmp", NULL},
{(char *)"openvdb", NULL},
{(char *)"alembic", NULL},
@@ -140,12 +137,6 @@ static PyObject *make_builtopts_info(void)
SetObjIncref(Py_False);
#endif
-#ifdef WITH_GAMEENGINE
- SetObjIncref(Py_True);
-#else
- SetObjIncref(Py_False);
-#endif
-
#ifdef WITH_CINEON
SetObjIncref(Py_True);
#else
@@ -158,12 +149,6 @@ static PyObject *make_builtopts_info(void)
SetObjIncref(Py_False);
#endif
-#ifdef WITH_FRAMESERVER
- SetObjIncref(Py_True);
-#else
- SetObjIncref(Py_False);
-#endif
-
#ifdef WITH_HDR
SetObjIncref(Py_True);
#else
@@ -272,12 +257,6 @@ static PyObject *make_builtopts_info(void)
SetObjIncref(Py_False);
#endif
-#ifdef WITH_PLAYER
- SetObjIncref(Py_True);
-#else
- SetObjIncref(Py_False);
-#endif
-
#ifdef _OPENMP
SetObjIncref(Py_True);
#else
diff --git a/source/blender/python/intern/bpy_app_handlers.c b/source/blender/python/intern/bpy_app_handlers.c
index 8453808d6ec..d89b3bd01f5 100644
--- a/source/blender/python/intern/bpy_app_handlers.c
+++ b/source/blender/python/intern/bpy_app_handlers.c
@@ -46,35 +46,30 @@ 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 *)"scene_update_pre", (char *)"on every scene data update. Does not imply that anything changed in the "
- "scene, just that the dependency graph is about to be reevaluated, and the "
- "scene is about to be updated by Blender's animation system."},
- {(char *)"scene_update_post", (char *)"on every scene data update. Does not imply that anything changed in the "
- "scene, just that the dependency graph was reevaluated, and the scene was "
- "possibly updated by Blender's animation system."},
- {(char *)"game_pre", (char *)"on starting the game engine"},
- {(char *)"game_post", (char *)"on ending the game engine"},
- {(char *)"version_update", (char *)"on ending the versioning code"},
+ {(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 */
-# define APP_CB_OTHER_FIELDS 1
+#define APP_CB_OTHER_FIELDS 1
{(char *)"persistent", (char *)"Function decorator for callback functions not to be removed when loading new files"},
{NULL}
diff --git a/source/blender/python/intern/bpy_app_icons.c b/source/blender/python/intern/bpy_app_icons.c
new file mode 100644
index 00000000000..12315a6e112
--- /dev/null
+++ b/source/blender/python/intern/bpy_app_icons.c
@@ -0,0 +1,187 @@
+/*
+ * ***** BEGIN GPL LICENSE BLOCK *****
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ * ***** END GPL LICENSE BLOCK *****
+ */
+
+/** \file blender/python/intern/bpy_app_icons.c
+ * \ingroup pythonintern
+ *
+ * Runtime defined icons.
+ */
+
+#include <Python.h>
+
+#include "MEM_guardedalloc.h"
+
+#include "BLI_utildefines.h"
+
+#include "BKE_icons.h"
+
+#include "../generic/py_capi_utils.h"
+
+#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"
+);
+static PyObject *bpy_app_icons_new_triangles(PyObject *UNUSED(self), PyObject *args, PyObject *kw)
+{
+ /* 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;
+ }
+
+ 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__);
+
+ 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);
+}
+
+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)
+{
+ /* 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;
+ }
+
+ 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"
+);
+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;
+ }
+
+ 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}
+};
+
+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 */
+};
+
+PyObject *BPY_app_icons_module(void)
+{
+ PyObject *sys_modules = PyImport_GetModuleDict();
+
+ PyObject *mod = PyModule_Create(&M_AppIcons_module_def);
+
+ PyDict_SetItem(sys_modules, PyModule_GetNameObject(mod), mod);
+
+ return mod;
+}
diff --git a/source/blender/python/intern/bpy_app_icons.h b/source/blender/python/intern/bpy_app_icons.h
new file mode 100644
index 00000000000..309c7ed222f
--- /dev/null
+++ b/source/blender/python/intern/bpy_app_icons.h
@@ -0,0 +1,30 @@
+/*
+ * ***** BEGIN GPL LICENSE BLOCK *****
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ * ***** END GPL LICENSE BLOCK *****
+ */
+
+/** \file blender/python/intern/bpy_app_icons.h
+ * \ingroup pythonintern
+ */
+
+#ifndef __BPY_APP_ICONS_H__
+#define __BPY_APP_ICONS_H__
+
+PyObject *BPY_app_icons_module(void);
+
+#endif /* __BPY_APP_ICONS_H__ */
diff --git a/source/blender/python/intern/bpy_app_timers.c b/source/blender/python/intern/bpy_app_timers.c
new file mode 100644
index 00000000000..cd0e57200ec
--- /dev/null
+++ b/source/blender/python/intern/bpy_app_timers.c
@@ -0,0 +1,199 @@
+/*
+ * ***** BEGIN GPL LICENSE BLOCK *****
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ * ***** END GPL LICENSE BLOCK *****
+ */
+
+/** \file blender/python/intern/bpy_app_timers.c
+ * \ingroup pythonintern
+ */
+
+#include <Python.h>
+#include "BLI_utildefines.h"
+#include "BLI_timer.h"
+#include "PIL_time.h"
+
+#include "BPY_extern.h"
+#include "bpy_app_timers.h"
+
+#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 == 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;
+ }
+
+ if (value < 0.0) {
+ value = 0.0;
+ }
+
+ return value;
+}
+
+static double py_timer_execute(uintptr_t UNUSED(uuid), void *user_data)
+{
+ PyObject *function = user_data;
+
+ PyGILState_STATE gilstate;
+ gilstate = PyGILState_Ensure();
+
+ PyObject *py_ret = PyObject_CallObject(function, NULL);
+ double ret = handle_returned_value(function, py_ret);
+
+ PyGILState_Release(gilstate);
+
+ return ret;
+}
+
+static void py_timer_free(uintptr_t UNUSED(uuid), void *user_data)
+{
+ PyObject *function = user_data;
+
+ PyGILState_STATE gilstate;
+ gilstate = PyGILState_Ensure();
+
+ Py_DECREF(function);
+
+ 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"
+);
+static PyObject *bpy_app_timers_register(PyObject *UNUSED(self), PyObject *args, PyObject *kw)
+{
+ 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;
+ }
+
+ 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;
+}
+
+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"
+);
+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;
+}
+
+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"
+);
+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);
+}
+
+
+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}
+};
+
+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 */
+};
+
+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;
+}
diff --git a/source/blender/python/intern/bpy_app_timers.h b/source/blender/python/intern/bpy_app_timers.h
new file mode 100644
index 00000000000..ddf0e258e67
--- /dev/null
+++ b/source/blender/python/intern/bpy_app_timers.h
@@ -0,0 +1,30 @@
+/*
+ * ***** BEGIN GPL LICENSE BLOCK *****
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ * ***** END GPL LICENSE BLOCK *****
+ */
+
+/** \file blender/python/intern/bpy_app_timers.h
+ * \ingroup pythonintern
+ */
+
+#ifndef __BPY_APP_TIMERS_H__
+#define __BPY_APP_TIMERS_H__
+
+PyObject *BPY_app_timers_module(void);
+
+#endif /* __BPY_APP_TIMERS_H__ */
diff --git a/source/blender/python/intern/bpy_driver.c b/source/blender/python/intern/bpy_driver.c
index e7608e93f58..f098a28d679 100644
--- a/source/blender/python/intern/bpy_driver.c
+++ b/source/blender/python/intern/bpy_driver.c
@@ -48,6 +48,8 @@
#include "bpy_driver.h"
+#include "BPY_extern.h"
+
extern void BPY_update_rna_module(void);
#define USE_RNA_AS_PYOBJECT
@@ -381,8 +383,12 @@ static bool bpy_driver_secure_bytecode_validate(PyObject *expr_code, PyObject *d
* (new)note: checking if python is running is not threadsafe [#28114]
* now release the GIL on python operator execution instead, using
* PyEval_SaveThread() / PyEval_RestoreThread() so we don't lock up blender.
+ *
+ * For copy-on-write we always cache expressions and write errors in the
+ * 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, 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;
@@ -398,7 +404,7 @@ float BPY_driver_exec(struct PathResolvedRNA *anim_rna, ChannelDriver *driver, c
int i;
/* get the py expression to be evaluated */
- expr = driver->expression;
+ expr = driver_orig->expression;
if (expr[0] == '\0')
return 0.0f;
@@ -438,50 +444,50 @@ float BPY_driver_exec(struct PathResolvedRNA *anim_rna, ChannelDriver *driver, c
/* update global namespace */
bpy_pydriver_namespace_update_frame(evaltime);
- if (driver->flag & DRIVER_FLAG_USE_SELF) {
+ if (driver_orig->flag & DRIVER_FLAG_USE_SELF) {
bpy_pydriver_namespace_update_self(anim_rna);
}
else {
bpy_pydriver_namespace_clear_self();
}
- if (driver->expr_comp == NULL)
- driver->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->flag & DRIVER_FLAG_RECOMPILE) {
- Py_XDECREF(driver->expr_comp);
- driver->expr_comp = PyTuple_New(2);
+ 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->expr_comp), 0, expr_code);
+ PyTuple_SET_ITEM(((PyObject *)driver_orig->expr_comp), 0, expr_code);
- driver->flag &= ~DRIVER_FLAG_RECOMPILE;
- driver->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;
#endif
}
else {
- expr_code = PyTuple_GET_ITEM(((PyObject *)driver->expr_comp), 0);
+ expr_code = PyTuple_GET_ITEM(((PyObject *)driver_orig->expr_comp), 0);
}
- if (driver->flag & DRIVER_FLAG_RENAMEVAR) {
+ if (driver_orig->flag & DRIVER_FLAG_RENAMEVAR) {
/* may not be set */
- expr_vars = PyTuple_GET_ITEM(((PyObject *)driver->expr_comp), 1);
+ expr_vars = PyTuple_GET_ITEM(((PyObject *)driver_orig->expr_comp), 1);
Py_XDECREF(expr_vars);
- expr_vars = PyTuple_New(BLI_listbase_count(&driver->variables));
- PyTuple_SET_ITEM(((PyObject *)driver->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->variables.first, i = 0; dvar; dvar = dvar->next) {
+ for (dvar = driver_orig->variables.first, i = 0; dvar; dvar = dvar->next) {
PyTuple_SET_ITEM(expr_vars, i++, PyUnicode_FromString(dvar->name));
}
- driver->flag &= ~DRIVER_FLAG_RENAMEVAR;
+ driver_orig->flag &= ~DRIVER_FLAG_RENAMEVAR;
}
else {
- expr_vars = PyTuple_GET_ITEM(((PyObject *)driver->expr_comp), 1);
+ expr_vars = PyTuple_GET_ITEM(((PyObject *)driver_orig->expr_comp), 1);
}
/* add target values to a dict that will be used as '__locals__' dict */
@@ -543,7 +549,7 @@ float BPY_driver_exec(struct PathResolvedRNA *anim_rna, ChannelDriver *driver, c
}
#ifdef USE_BYTECODE_WHITELIST
- if (is_recompile) {
+ if (is_recompile && expr_code) {
if (!(G.f & G_SCRIPT_AUTOEXEC)) {
if (!bpy_driver_secure_bytecode_validate(
expr_code, (PyObject *[]){
@@ -555,7 +561,7 @@ float BPY_driver_exec(struct PathResolvedRNA *anim_rna, ChannelDriver *driver, c
{
Py_DECREF(expr_code);
expr_code = NULL;
- PyTuple_SET_ITEM(((PyObject *)driver->expr_comp), 0, NULL);
+ PyTuple_SET_ITEM(((PyObject *)driver_orig->expr_comp), 0, NULL);
}
}
}
@@ -595,7 +601,7 @@ float BPY_driver_exec(struct PathResolvedRNA *anim_rna, ChannelDriver *driver, c
return (float)result;
}
else {
- fprintf(stderr, "\tBPY_driver_eval() - driver '%s' evaluates to '%f'\n", dvar->name, result);
+ fprintf(stderr, "\tBPY_driver_eval() - driver '%s' evaluates to '%f'\n", driver->expression, result);
return 0.0f;
}
}
diff --git a/source/blender/python/intern/bpy_driver.h b/source/blender/python/intern/bpy_driver.h
index 017a6fe89c5..971cbdf901f 100644
--- a/source/blender/python/intern/bpy_driver.h
+++ b/source/blender/python/intern/bpy_driver.h
@@ -27,14 +27,7 @@
#ifndef __BPY_DRIVER_H__
#define __BPY_DRIVER_H__
-struct ChannelDriver;
-struct PathResolvedRNA;
-
int bpy_pydriver_create_dict(void);
extern PyObject *bpy_pydriver_Dict;
-/* externals */
-float BPY_driver_exec(struct PathResolvedRNA *anim_rna, struct ChannelDriver *driver, const float evaltime);
-void BPY_driver_reset(void);
-
#endif /* __BPY_DRIVER_H__ */
diff --git a/source/blender/python/intern/bpy_gizmo_wrap.c b/source/blender/python/intern/bpy_gizmo_wrap.c
new file mode 100644
index 00000000000..411822ee4da
--- /dev/null
+++ b/source/blender/python/intern/bpy_gizmo_wrap.c
@@ -0,0 +1,228 @@
+/*
+ * ***** BEGIN GPL LICENSE BLOCK *****
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ * ***** END GPL LICENSE BLOCK *****
+ */
+
+/** \file blender/python/intern/bpy_gizmo_wrap.c
+ * \ingroup pythonintern
+ *
+ * This file is so Python can define widget-group's that C can call into.
+ * The generic callback functions for Python widget-group are defines in
+ * 'rna_wm.c', some calling into functions here to do python specific
+ * functionality.
+ *
+ * \note This follows 'bpy_operator_wrap.c' very closely.
+ * Keep in sync unless there is good reason not to!
+ */
+
+#include <Python.h>
+
+#include "BLI_utildefines.h"
+
+#include "WM_api.h"
+#include "WM_types.h"
+
+#include "RNA_access.h"
+#include "RNA_define.h"
+#include "RNA_enum_types.h"
+
+#include "bpy_rna.h"
+#include "bpy_intern_string.h"
+#include "bpy_gizmo_wrap.h" /* own include */
+
+/* we may want to add, but not now */
+
+/* -------------------------------------------------------------------- */
+
+/** \name Gizmo
+ * \{ */
+
+
+static bool bpy_gizmotype_target_property_def(
+ wmGizmoType *gzt, PyObject *item)
+{
+ /* 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,
+ };
+
+ 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.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;
+ }
+
+ 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;
+}
+
+static void gizmo_properties_init(wmGizmoType *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);
+
+ 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);
+
+ /* 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);
+
+ 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);
+ }
+ }
+}
+
+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 */
+
+ /* 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));
+ }
+#endif
+
+ gzt->struct_size = sizeof(wmGizmo);
+
+ 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);
+
+ /* 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();
+ }
+}
+
+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 */
+
+ /* 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));
+ }
+#endif
+
+ gizmogroup_properties_init(gzgt);
+}
+
+/** \} */
diff --git a/source/blender/python/intern/bpy_gizmo_wrap.h b/source/blender/python/intern/bpy_gizmo_wrap.h
new file mode 100644
index 00000000000..96f15312a4e
--- /dev/null
+++ b/source/blender/python/intern/bpy_gizmo_wrap.h
@@ -0,0 +1,35 @@
+/*
+ * ***** BEGIN GPL LICENSE BLOCK *****
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ * ***** END GPL LICENSE BLOCK *****
+ */
+
+/** \file blender/python/intern/bpy_gizmo_wrap.h
+ * \ingroup pythonintern
+ */
+
+#ifndef __BPY_GIZMO_WRAP_H__
+#define __BPY_GIZMO_WRAP_H__
+
+struct wmGizmoType;
+struct wmGizmoGroupType;
+
+/* exposed to rna/wm api */
+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__ */
diff --git a/source/blender/python/intern/bpy_interface.c b/source/blender/python/intern/bpy_interface.c
index 1ae3106aa76..e17e7562f2a 100644
--- a/source/blender/python/intern/bpy_interface.c
+++ b/source/blender/python/intern/bpy_interface.c
@@ -46,7 +46,6 @@
#include "RNA_types.h"
#include "bpy.h"
-#include "gpu.h"
#include "bpy_rna.h"
#include "bpy_path.h"
#include "bpy_capi_utils.h"
@@ -59,9 +58,9 @@
#include "BKE_appdir.h"
#include "BKE_context.h"
-#include "BKE_text.h"
-#include "BKE_main.h"
#include "BKE_global.h" /* only for script checking */
+#include "BKE_main.h"
+#include "BKE_text.h"
#include "CCL_api.h"
@@ -75,6 +74,7 @@
#include "../generic/blf_py_api.h"
#include "../generic/idprop_py_api.h"
#include "../generic/imbuf_py_api.h"
+#include "../gpu/gpu_py_api.h"
#include "../bmesh/bmesh_py_api.h"
#include "../mathutils/mathutils.h"
@@ -233,7 +233,7 @@ static struct _inittab bpy_internal_modules[] = {
#ifdef WITH_CYCLES
{"_cycles", CCL_initPython},
#endif
- {"gpu", GPU_initPython},
+ {"gpu", BPyInit_gpu},
{"idprop", BPyInit_idprop},
{NULL, NULL}
};
@@ -537,7 +537,8 @@ static bool python_script_exec(
if (py_dict) {
#ifdef PYMODULE_CLEAR_WORKAROUND
- PyModuleObject *mmod = (PyModuleObject *)PyDict_GetItemString(PyImport_GetModuleDict(), "__main__");
+ PyModuleObject *mmod = (PyModuleObject *)PyDict_GetItem(
+ PyImport_GetModuleDict(), bpy_intern_str___main__);
PyObject *dict_back = mmod->md_dict;
/* freeing the module will clear the namespace,
* gives problems running classes defined in this namespace being used later. */
diff --git a/source/blender/python/intern/bpy_intern_string.c b/source/blender/python/intern/bpy_intern_string.c
index ac0100fa75d..41276963fc9 100644
--- a/source/blender/python/intern/bpy_intern_string.c
+++ b/source/blender/python/intern/bpy_intern_string.c
@@ -34,21 +34,24 @@
#include "BLI_utildefines.h"
-static PyObject *bpy_intern_str_arr[13];
+static PyObject *bpy_intern_str_arr[16];
-PyObject *bpy_intern_str_register;
-PyObject *bpy_intern_str_unregister;
-PyObject *bpy_intern_str_bl_rna;
+PyObject *bpy_intern_str___annotations__;
+PyObject *bpy_intern_str___doc__;
+PyObject *bpy_intern_str___main__;
+PyObject *bpy_intern_str___module__;
+PyObject *bpy_intern_str___name__;
+PyObject *bpy_intern_str___slots__;
+PyObject *bpy_intern_str_attr;
PyObject *bpy_intern_str_bl_property;
+PyObject *bpy_intern_str_bl_rna;
+PyObject *bpy_intern_str_bl_target_properties;
PyObject *bpy_intern_str_bpy_types;
-PyObject *bpy_intern_str_order;
-PyObject *bpy_intern_str_attr;
-PyObject *bpy_intern_str_self;
PyObject *bpy_intern_str_frame;
-PyObject *bpy_intern_str___slots__;
-PyObject *bpy_intern_str___name__;
-PyObject *bpy_intern_str___doc__;
-PyObject *bpy_intern_str___module__;
+PyObject *bpy_intern_str_properties;
+PyObject *bpy_intern_str_register;
+PyObject *bpy_intern_str_self;
+PyObject *bpy_intern_str_unregister;
void bpy_intern_string_init(void)
{
@@ -57,19 +60,22 @@ void bpy_intern_string_init(void)
#define BPY_INTERN_STR(var, str) \
{ var = bpy_intern_str_arr[i++] = PyUnicode_FromString(str); } (void)0
- BPY_INTERN_STR(bpy_intern_str_register, "register");
- BPY_INTERN_STR(bpy_intern_str_unregister, "unregister");
- BPY_INTERN_STR(bpy_intern_str_bl_rna, "bl_rna");
+ 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_order, "order");
- BPY_INTERN_STR(bpy_intern_str_attr, "attr");
- BPY_INTERN_STR(bpy_intern_str_self, "self");
BPY_INTERN_STR(bpy_intern_str_frame, "frame");
- BPY_INTERN_STR(bpy_intern_str___slots__, "__slots__");
- BPY_INTERN_STR(bpy_intern_str___name__, "__name__");
- BPY_INTERN_STR(bpy_intern_str___doc__, "__doc__");
- BPY_INTERN_STR(bpy_intern_str___module__, "__module__");
+ 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
diff --git a/source/blender/python/intern/bpy_intern_string.h b/source/blender/python/intern/bpy_intern_string.h
index 394e84d89bd..41cd58f9c3d 100644
--- a/source/blender/python/intern/bpy_intern_string.h
+++ b/source/blender/python/intern/bpy_intern_string.h
@@ -30,18 +30,21 @@
void bpy_intern_string_init(void);
void bpy_intern_string_exit(void);
-extern PyObject *bpy_intern_str_register;
-extern PyObject *bpy_intern_str_unregister;
-extern PyObject *bpy_intern_str_bl_rna;
+extern PyObject *bpy_intern_str___annotations__;
+extern PyObject *bpy_intern_str___doc__;
+extern PyObject *bpy_intern_str___main__;
+extern PyObject *bpy_intern_str___module__;
+extern PyObject *bpy_intern_str___name__;
+extern PyObject *bpy_intern_str___slots__;
+extern PyObject *bpy_intern_str_attr;
extern PyObject *bpy_intern_str_bl_property;
+extern PyObject *bpy_intern_str_bl_rna;
+extern PyObject *bpy_intern_str_bl_target_properties;
extern PyObject *bpy_intern_str_bpy_types;
-extern PyObject *bpy_intern_str_order;
-extern PyObject *bpy_intern_str_attr;
-extern PyObject *bpy_intern_str_self;
extern PyObject *bpy_intern_str_frame;
-extern PyObject *bpy_intern_str___slots__;
-extern PyObject *bpy_intern_str___name__;
-extern PyObject *bpy_intern_str___doc__;
-extern PyObject *bpy_intern_str___module__;
+extern PyObject *bpy_intern_str_properties;
+extern PyObject *bpy_intern_str_register;
+extern PyObject *bpy_intern_str_self;
+extern PyObject *bpy_intern_str_unregister;
#endif /* __BPY_INTERN_STRING_H__ */
diff --git a/source/blender/python/intern/bpy_library_load.c b/source/blender/python/intern/bpy_library_load.c
index e66b4e834dc..5c64a65fb58 100644
--- a/source/blender/python/intern/bpy_library_load.c
+++ b/source/blender/python/intern/bpy_library_load.c
@@ -38,16 +38,16 @@
#include "BLI_linklist.h"
#include "BLI_path_util.h"
-#include "BLO_readfile.h"
-
-#include "BKE_main.h"
-#include "BKE_library.h"
+#include "BKE_context.h"
#include "BKE_idcode.h"
+#include "BKE_library.h"
+#include "BKE_main.h"
#include "BKE_report.h"
-#include "BKE_context.h"
#include "DNA_space_types.h" /* FILE_LINK, FILE_RELPATH */
+#include "BLO_readfile.h"
+
#include "bpy_capi_utils.h"
#include "bpy_library.h"
@@ -332,6 +332,7 @@ 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);
BKE_main_id_tag_all(bmain, LIB_TAG_PRE_EXISTING, true);
@@ -341,7 +342,7 @@ static PyObject *bpy_lib_exit(BPy_Library *self, PyObject *UNUSED(args))
{
int idcode_step = 0, idcode;
while ((idcode = BKE_idcode_iter_step(&idcode_step))) {
- if (BKE_idcode_is_linkable(idcode)) {
+ 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);
@@ -402,7 +403,7 @@ static PyObject *bpy_lib_exit(BPy_Library *self, PyObject *UNUSED(args))
}
else {
Library *lib = mainl->curlib; /* newly added lib, assign before append end */
- BLO_library_link_end(mainl, &(self->blo_handle), self->flag, NULL, NULL);
+ BLO_library_link_end(mainl, &(self->blo_handle), self->flag, NULL, NULL, NULL, NULL);
BLO_blendhandle_close(self->blo_handle);
self->blo_handle = NULL;
@@ -414,7 +415,7 @@ static PyObject *bpy_lib_exit(BPy_Library *self, PyObject *UNUSED(args))
BKE_main_lib_objects_recalc_all(bmain);
/* append, rather than linking */
- if ((self->flag & FILE_LINK) == 0) {
+ if (do_append) {
BKE_library_make_local(bmain, lib, old_to_new_ids, true, false);
}
}
@@ -427,7 +428,7 @@ static PyObject *bpy_lib_exit(BPy_Library *self, PyObject *UNUSED(args))
{
int idcode_step = 0, idcode;
while ((idcode = BKE_idcode_iter_step(&idcode_step))) {
- if (BKE_idcode_is_linkable(idcode)) {
+ 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)) {
diff --git a/source/blender/python/intern/bpy_library_write.c b/source/blender/python/intern/bpy_library_write.c
index 76b7ccf72fa..69dcfdb9455 100644
--- a/source/blender/python/intern/bpy_library_write.c
+++ b/source/blender/python/intern/bpy_library_write.c
@@ -34,7 +34,6 @@
#include "BLI_string.h"
#include "BLI_path_util.h"
-#include "BKE_library.h"
#include "BKE_blendfile.h"
#include "BKE_global.h"
#include "BKE_main.h"
@@ -135,7 +134,7 @@ static PyObject *bpy_lib_write(PyObject *UNUSED(self), PyObject *args, PyObject
if (!pyrna_id_FromPyObject(key, &id_store->id)) {
PyErr_Format(PyExc_TypeError,
- "Expected and ID type, not %.200s",
+ "Expected an ID type, not %.200s",
Py_TYPE(key)->tp_name);
ret = NULL;
goto finally;
diff --git a/source/blender/python/intern/bpy_msgbus.c b/source/blender/python/intern/bpy_msgbus.c
new file mode 100644
index 00000000000..101cc8b41a3
--- /dev/null
+++ b/source/blender/python/intern/bpy_msgbus.c
@@ -0,0 +1,399 @@
+/*
+ * ***** BEGIN GPL LICENSE BLOCK *****
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ * ***** END GPL LICENSE BLOCK *****
+ */
+
+/** \file blender/python/intern/bpy_msgbus.c
+ * \ingroup pythonintern
+ * This file defines '_bpy_msgbus' module, exposed as 'bpy.msgbus'.
+ */
+
+#include <Python.h>
+
+#include "../generic/python_utildefines.h"
+#include "../generic/py_capi_utils.h"
+#include "../mathutils/mathutils.h"
+
+#include "BLI_utildefines.h"
+
+#include "BKE_context.h"
+
+#include "WM_api.h"
+#include "WM_types.h"
+#include "WM_message.h"
+
+#include "RNA_access.h"
+#include "RNA_define.h"
+#include "RNA_enum_types.h"
+
+#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 */
+
+
+/* -------------------------------------------------------------------- */
+/** \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"
+
+/**
+ * There are multiple ways we can get RNA from Python,
+ * it's also possible to register a type instead of an instance.
+ *
+ * This function handles converting Python to RNA subscription information.
+ *
+ * \param py_sub: See #BPY_MSGBUS_RNA_MSGKEY_DOC for description.
+ * \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)
+{
+
+ /* 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 (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;
+}
+
+/** \} */
+
+/* -------------------------------------------------------------------- */
+/** \name Internal Callbacks
+ * \{ */
+
+#define BPY_MSGBUS_USER_DATA_LEN 2
+
+/* Follow wmMsgNotifyFn spec */
+static void bpy_msgbus_notify(
+ bContext *C, wmMsgSubscribeKey *UNUSED(msg_key), wmMsgSubscribeValue *msg_val)
+{
+ 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 *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);
+ }
+
+ 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);
+ }
+
+ bpy_context_clear(C, &gilstate);
+
+ 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)
+{
+ PyGILState_STATE gilstate = PyGILState_Ensure();
+ Py_DECREF(msg_val->owner);
+ Py_DECREF(msg_val->user_data);
+ PyGILState_Release(gilstate);
+}
+
+/** \} */
+
+/* -------------------------------------------------------------------- */
+/** \name Public Message Bus API
+ * \{ */
+
+PyDoc_STRVAR(bpy_msgbus_subscribe_rna_doc,
+".. function:: subscribe_rna(data, owner, args, notify)\n"
+"\n"
+BPY_MSGBUS_RNA_MSGKEY_DOC
+" :arg owner: Handle for this subscription (compared by identity).\n"
+" :type owner: Any type.\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;
+
+ 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;
+
+ static const char *_keywords[] = {
+ "key",
+ "owner",
+ "args",
+ "notify",
+ "options",
+ NULL,
+ };
+ static _PyArg_Parser _parser = {"$OOO!OO!: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;
+ }
+
+ /* 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};
+
+ 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 (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);
+ }
+
+ {
+ 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;
+
+ WM_msg_subscribe_rna_params(mbus, &msg_key_params, &msg_val_params, __func__);
+
+ WM_msg_dump(mbus, __func__);
+
+ 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"
+);
+static PyObject *bpy_msgbus_publish_rna(PyObject *UNUSED(self), PyObject *args, PyObject *kw)
+{
+ const char *error_prefix = "publish_rna";
+ PyObject *py_sub = 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}}};
+
+ 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);
+
+ 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"
+);
+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;
+}
+
+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}
+};
+
+static struct PyModuleDef _bpy_msgbus_def = {
+ PyModuleDef_HEAD_INIT,
+ .m_name = "msgbus",
+ .m_methods = BPy_msgbus_methods,
+};
+
+
+PyObject *BPY_msgbus_module(void)
+{
+ PyObject *submodule;
+
+ submodule = PyModule_Create(&_bpy_msgbus_def);
+
+ return submodule;
+}
+
+/** \} */
diff --git a/source/blender/python/intern/bpy_msgbus.h b/source/blender/python/intern/bpy_msgbus.h
new file mode 100644
index 00000000000..97b20e9b926
--- /dev/null
+++ b/source/blender/python/intern/bpy_msgbus.h
@@ -0,0 +1,30 @@
+/*
+ * ***** BEGIN GPL LICENSE BLOCK *****
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ * ***** END GPL LICENSE BLOCK *****
+ */
+
+/** \file blender/python/intern/bpy_msgbus.h
+ * \ingroup pythonintern
+ */
+
+#ifndef __BPY_MSGBUS_H__
+#define __BPY_MSGBUS_H__
+
+PyObject *BPY_msgbus_module(void);
+
+#endif /* __BPY_MSGBUS_H__ */
diff --git a/source/blender/python/intern/bpy_props.c b/source/blender/python/intern/bpy_props.c
index 0db2fc189c1..b7242680dca 100644
--- a/source/blender/python/intern/bpy_props.c
+++ b/source/blender/python/intern/bpy_props.c
@@ -1905,7 +1905,7 @@ static void bpy_prop_callback_assign_enum(struct PropertyRNA *prop, PyObject *ge
#define BPY_PROPDEF_UNIT_DOC \
" :arg unit: Enumerator in ['NONE', 'LENGTH', 'AREA', 'VOLUME', 'ROTATION', 'TIME', 'VELOCITY', 'ACCELERATION', 'MASS', 'CAMERA'].\n" \
-" :type unit: string\n" \
+" :type unit: string\n" \
#define BPY_PROPDEF_NUM_MIN_DOC \
" :arg min: Hard minimum, trying to assign a value below will silently assign this minimum instead.\n" \
@@ -3083,9 +3083,10 @@ PyObject *BPy_CollectionProperty(PyObject *self, PyObject *args, PyObject *kw)
return NULL;
if (!RNA_struct_is_a(ptype, &RNA_PropertyGroup)) {
- PyErr_Format(PyExc_TypeError,
- "CollectionProperty(...) expected an RNA type derived from %.200s",
- RNA_struct_ui_name(&RNA_ID), RNA_struct_ui_name(&RNA_PropertyGroup));
+ PyErr_Format(
+ PyExc_TypeError,
+ "CollectionProperty(...) expected an RNA type derived from %.200s",
+ RNA_struct_ui_name(&RNA_ID), RNA_struct_ui_name(&RNA_PropertyGroup));
return NULL;
}
@@ -3203,11 +3204,6 @@ PyObject *BPY_rna_props(void)
submodule = PyModule_Create(&props_module);
PyDict_SetItemString(PyImport_GetModuleDict(), props_module.m_name, submodule);
- /* INCREF since its its assumed that all these functions return the
- * module with a new ref like PyDict_New, since they are passed to
- * PyModule_AddObject which steals a ref */
- Py_INCREF(submodule);
-
/* api needs the PyObjects internally */
submodule_dict = PyModule_GetDict(submodule);
diff --git a/source/blender/python/intern/bpy_props.h b/source/blender/python/intern/bpy_props.h
index 614c1b4b708..fa2594f94d2 100644
--- a/source/blender/python/intern/bpy_props.h
+++ b/source/blender/python/intern/bpy_props.h
@@ -34,6 +34,6 @@ PyObject *BPy_PointerProperty(PyObject *self, PyObject *args, PyObject *kw);
PyObject *BPy_CollectionProperty(PyObject *self, PyObject *args, PyObject *kw);
StructRNA *pointer_type_from_py(PyObject *value, const char *error_prefix);
-#define PYRNA_STACK_ARRAY 32
+#define PYRNA_STACK_ARRAY RNA_STACK_ARRAY
#endif
diff --git a/source/blender/python/intern/bpy_rna.c b/source/blender/python/intern/bpy_rna.c
index b36a6e06651..f25f007033f 100644
--- a/source/blender/python/intern/bpy_rna.c
+++ b/source/blender/python/intern/bpy_rna.c
@@ -315,7 +315,7 @@ static bool rna_id_write_error(PointerRNA *ptr, PyObject *key)
ID *id = ptr->id.data;
if (id) {
const short idcode = GS(id->name);
- if (!ELEM(idcode, ID_WM, ID_SCR)) { /* may need more added here */
+ if (!ELEM(idcode, ID_WM, ID_SCR, ID_WS)) { /* may need more added here */
const char *idtype = BKE_idcode_to_name(idcode);
const char *pyname;
if (key && PyUnicode_Check(key)) pyname = _PyUnicode_AsString(key);
@@ -1401,53 +1401,39 @@ static PyObject *pyrna_enum_to_py(PointerRNA *ptr, PropertyRNA *prop, int val)
ret = PyUnicode_FromString(identifier);
}
else {
+ /* Static, no need to free. */
const EnumPropertyItem *enum_item;
- bool free;
+ bool free_dummy;
+ RNA_property_enum_items_ex(NULL, ptr, prop, true, &enum_item, NULL, &free_dummy);
+ BLI_assert(!free_dummy);
- /* don't throw error here, can't trust blender 100% to give the
- * right values, python code should not generate error for that */
- RNA_property_enum_items(BPy_GetContext(), ptr, prop, &enum_item, NULL, &free);
- if (enum_item && enum_item->identifier) {
- ret = PyUnicode_FromString(enum_item->identifier);
- }
- else {
- if (free) {
- MEM_freeN((void *)enum_item);
- }
- RNA_property_enum_items(NULL, ptr, prop, &enum_item, NULL, &free);
-
- /* Do not print warning in case of DummyRNA_NULL_items, this one will never match any value... */
- if (enum_item != DummyRNA_NULL_items) {
- const char *ptr_name = RNA_struct_name_get_alloc(ptr, NULL, 0, NULL);
+ /* Do not print warning in case of DummyRNA_NULL_items, this one will never match any value... */
+ if (enum_item != DummyRNA_NULL_items) {
+ const char *ptr_name = RNA_struct_name_get_alloc(ptr, NULL, 0, NULL);
- /* prefer not fail silently in case of api errors, maybe disable it later */
- CLOG_WARN(BPY_LOG_RNA,
- "current value '%d' "
- "matches no enum in '%s', '%s', '%s'",
- val, RNA_struct_identifier(ptr->type),
- ptr_name, RNA_property_identifier(prop));
+ /* prefer not fail silently in case of api errors, maybe disable it later */
+ CLOG_WARN(BPY_LOG_RNA,
+ "current value '%d' "
+ "matches no enum in '%s', '%s', '%s'",
+ val, RNA_struct_identifier(ptr->type),
+ ptr_name, RNA_property_identifier(prop));
#if 0 /* gives python decoding errors while generating docs :( */
- char error_str[256];
- BLI_snprintf(error_str, sizeof(error_str),
- "RNA Warning: Current value \"%d\" "
- "matches no enum in '%s', '%s', '%s'",
- val, RNA_struct_identifier(ptr->type),
- ptr_name, RNA_property_identifier(prop));
-
- PyErr_Warn(PyExc_RuntimeWarning, error_str);
+ char error_str[256];
+ BLI_snprintf(error_str, sizeof(error_str),
+ "RNA Warning: Current value \"%d\" "
+ "matches no enum in '%s', '%s', '%s'",
+ val, RNA_struct_identifier(ptr->type),
+ ptr_name, RNA_property_identifier(prop));
+
+ PyErr_Warn(PyExc_RuntimeWarning, error_str);
#endif
- if (ptr_name)
- MEM_freeN((void *)ptr_name);
- }
-
- ret = PyUnicode_FromString("");
+ if (ptr_name)
+ MEM_freeN((void *)ptr_name);
}
- if (free) {
- MEM_freeN((void *)enum_item);
- }
+ ret = PyUnicode_FromString("");
#if 0
PyErr_Format(PyExc_AttributeError,
"RNA Error: Current value \"%d\" matches no enum", val);
@@ -1729,7 +1715,25 @@ static int pyrna_py_to_prop(
const int subtype = RNA_property_subtype(prop);
const char *param;
- if (subtype == PROP_BYTESTRING) {
+ if (value == Py_None) {
+ if ((RNA_property_flag(prop) & PROP_NEVER_NULL) == 0) {
+ if (data) {
+ *((char **)data) = (char *)NULL;
+ }
+ else {
+ RNA_property_string_set(ptr, prop, NULL);
+ }
+ }
+ else {
+ PyC_Err_Format_Prefix(
+ PyExc_TypeError,
+ "%.200s %.200s.%.200s doesn't support None from string types",
+ error_prefix, RNA_struct_identifier(ptr->type),
+ RNA_property_identifier(prop));
+ return -1;
+ }
+ }
+ else if (subtype == PROP_BYTESTRING) {
/* Byte String */
@@ -1849,19 +1853,28 @@ static int pyrna_py_to_prop(
* class mixing if this causes problems in the future it should be removed.
*/
if ((ptr_type == &RNA_AnyType) &&
- (BPy_StructRNA_Check(value)) &&
- (RNA_struct_is_a(((BPy_StructRNA *)value)->ptr.type, &RNA_Operator)))
+ (BPy_StructRNA_Check(value)))
{
- value = PyObject_GetAttrString(value, "properties");
- value_new = value;
+ const StructRNA *base_type =
+ RNA_struct_base_child_of(((const BPy_StructRNA *)value)->ptr.type, NULL);
+ if (ELEM(base_type, &RNA_Operator, &RNA_Gizmo)) {
+ value = PyObject_GetAttr(value, bpy_intern_str_properties);
+ value_new = value;
+ }
}
-
- /* if property is an OperatorProperties pointer and value is a map,
+ /* if property is an OperatorProperties/GizmoProperties pointer and value is a map,
* forward back to pyrna_pydict_to_props */
- if (RNA_struct_is_a(ptr_type, &RNA_OperatorProperties) && PyDict_Check(value)) {
- PointerRNA opptr = RNA_property_pointer_get(ptr, prop);
- return pyrna_pydict_to_props(&opptr, value, false, error_prefix);
+ if (PyDict_Check(value)) {
+ const StructRNA *base_type = RNA_struct_base_child_of(ptr_type, NULL);
+ if (base_type == &RNA_OperatorProperties) {
+ PointerRNA opptr = RNA_property_pointer_get(ptr, prop);
+ return pyrna_pydict_to_props(&opptr, value, false, error_prefix);
+ }
+ else if (base_type == &RNA_GizmoProperties) {
+ PointerRNA opptr = RNA_property_pointer_get(ptr, prop);
+ return pyrna_pydict_to_props(&opptr, value, false, error_prefix);
+ }
}
/* another exception, allow to pass a collection as an RNA property */
@@ -3500,6 +3513,68 @@ static PyObject *pyrna_struct_is_property_readonly(BPy_StructRNA *self, PyObject
return PyBool_FromLong(!RNA_property_editable(&self->ptr, prop));
}
+
+PyDoc_STRVAR(pyrna_struct_is_property_overridable_static_doc,
+".. method:: is_property_overridable_static(property)\n"
+"\n"
+" Check if a property is statically overridable.\n"
+"\n"
+" :return: True when the property is statically overridable.\n"
+" :rtype: boolean\n"
+);
+static PyObject *pyrna_struct_is_property_overridable_static(BPy_StructRNA *self, PyObject *args)
+{
+ PropertyRNA *prop;
+ const char *name;
+
+ PYRNA_STRUCT_CHECK_OBJ(self);
+
+ if (!PyArg_ParseTuple(args, "s:is_property_overridable_static", &name)) {
+ return NULL;
+ }
+
+ if ((prop = RNA_struct_find_property(&self->ptr, name)) == NULL) {
+ PyErr_Format(PyExc_TypeError,
+ "%.200s.is_property_overridable_static(\"%.200s\") not found",
+ RNA_struct_identifier(self->ptr.type), name);
+ return NULL;
+ }
+
+ return PyBool_FromLong((long)RNA_property_overridable_get(&self->ptr, prop));
+}
+
+PyDoc_STRVAR(pyrna_struct_property_overridable_static_set_doc,
+".. method:: property_overridable_static_set(property)\n"
+"\n"
+" Define a property as statically overridable or not (only for custom properties!).\n"
+"\n"
+" :return: True when the overridable status of the property was successfully set.\n"
+" :rtype: boolean\n"
+);
+static PyObject *pyrna_struct_property_overridable_static_set(BPy_StructRNA *self, PyObject *args)
+{
+ PropertyRNA *prop;
+ const char *name;
+ int is_overridable;
+
+ PYRNA_STRUCT_CHECK_OBJ(self);
+
+ if (!PyArg_ParseTuple(args, "sp:property_overridable_static_set", &name, &is_overridable)) {
+ return NULL;
+ }
+
+ if ((prop = RNA_struct_find_property(&self->ptr, name)) == NULL) {
+ PyErr_Format(PyExc_TypeError,
+ "%.200s.property_overridable_static_set(\"%.200s\") not found",
+ RNA_struct_identifier(self->ptr.type), name);
+ return NULL;
+ }
+
+ return PyBool_FromLong((long)RNA_property_overridable_static_set(&self->ptr, prop, (bool)is_overridable));
+}
+
+
+
PyDoc_STRVAR(pyrna_struct_path_resolve_doc,
".. method:: path_resolve(path, coerce=True)\n"
"\n"
@@ -5172,6 +5247,8 @@ static struct PyMethodDef pyrna_struct_methods[] = {
{"property_unset", (PyCFunction)pyrna_struct_property_unset, METH_VARARGS, pyrna_struct_property_unset_doc},
{"is_property_hidden", (PyCFunction)pyrna_struct_is_property_hidden, METH_VARARGS, pyrna_struct_is_property_hidden_doc},
{"is_property_readonly", (PyCFunction)pyrna_struct_is_property_readonly, METH_VARARGS, pyrna_struct_is_property_readonly_doc},
+ {"is_property_overridable_static", (PyCFunction)pyrna_struct_is_property_overridable_static, METH_VARARGS, pyrna_struct_is_property_overridable_static_doc},
+ {"property_overridable_static_set", (PyCFunction)pyrna_struct_property_overridable_static_set, METH_VARARGS, pyrna_struct_property_overridable_static_set_doc},
{"path_resolve", (PyCFunction)pyrna_struct_path_resolve, METH_VARARGS, pyrna_struct_path_resolve_doc},
{"path_from_id", (PyCFunction)pyrna_struct_path_from_id, METH_VARARGS, pyrna_struct_path_from_id_doc},
{"type_recast", (PyCFunction)pyrna_struct_type_recast, METH_NOARGS, pyrna_struct_type_recast_doc},
@@ -5581,6 +5658,17 @@ static PyObject *pyrna_func_call(BPy_FunctionRNA *self, PyObject *args, PyObject
item = NULL;
if (i < pyargs_len) {
+ /* New in 2.8x, optional arguments must be keywords. */
+ if (UNLIKELY((flag_parameter & PARM_REQUIRED) == 0)) {
+ PyErr_Format(PyExc_TypeError,
+ "%.200s.%.200s(): required parameter \"%.200s\" to be a keyword argument!",
+ RNA_struct_identifier(self_ptr->type),
+ RNA_function_identifier(self_func),
+ RNA_property_identifier(parm));
+ err = -1;
+ break;
+ }
+
item = PyTuple_GET_ITEM(args, i);
kw_arg = false;
}
@@ -7353,29 +7441,40 @@ static int deferred_register_prop(StructRNA *srna, PyObject *key, PyObject *item
static int pyrna_deferred_register_props(StructRNA *srna, PyObject *class_dict)
{
+ PyObject *annotations_dict;
PyObject *item, *key;
- PyObject *order;
Py_ssize_t pos = 0;
int ret = 0;
/* in both cases PyDict_CheckExact(class_dict) will be true even
* though Operators have a metaclass dict namespace */
+ if ((annotations_dict = PyDict_GetItem(class_dict, bpy_intern_str___annotations__)) &&
+ PyDict_CheckExact(annotations_dict))
+ {
+ while (PyDict_Next(annotations_dict, &pos, &key, &item)) {
+ ret = deferred_register_prop(srna, key, item);
- if ((order = PyDict_GetItem(class_dict, bpy_intern_str_order)) && PyList_CheckExact(order)) {
- for (pos = 0; pos < PyList_GET_SIZE(order); pos++) {
- key = PyList_GET_ITEM(order, pos);
- /* however unlikely its possible
- * fails in py 3.3 beta with __qualname__ */
- if ((item = PyDict_GetItem(class_dict, key))) {
- ret = deferred_register_prop(srna, key, item);
- if (ret != 0) {
- break;
- }
+ if (ret != 0) {
+ break;
}
}
}
- else {
+
+ {
+ /* This block can be removed once 2.8x is released and annotations are in use. */
+ bool has_warning = false;
while (PyDict_Next(class_dict, &pos, &key, &item)) {
+ if (pyrna_is_deferred_prop(item)) {
+ if (!has_warning) {
+ printf("Warning: class %.200s "
+ "contains a properties which should be an annotation!\n",
+ RNA_struct_identifier(srna));
+ PyC_LineSpit();
+ has_warning = true;
+ }
+ printf(" make annotation: %.200s.%.200s\n",
+ RNA_struct_identifier(srna), _PyUnicode_AsString(key));
+ }
ret = deferred_register_prop(srna, key, item);
if (ret != 0)
@@ -7658,7 +7757,8 @@ static int bpy_class_call(bContext *C, PointerRNA *ptr, FunctionRNA *func, Param
PyGILState_STATE gilstate;
#ifdef USE_PEDANTIC_WRITE
- const bool is_readonly_init = !RNA_struct_is_a(ptr->type, &RNA_Operator);
+ const bool is_readonly_init = !(RNA_struct_is_a(ptr->type, &RNA_Operator) ||
+ RNA_struct_is_a(ptr->type, &RNA_Gizmo));
// const char *func_id = RNA_function_identifier(func); /* UNUSED */
/* testing, for correctness, not operator and not draw function */
const bool is_readonly = !(RNA_function_flag(func) & FUNC_ALLOW_WRITE);
@@ -8316,6 +8416,43 @@ static PyObject *pyrna_unregister_class(PyObject *UNUSED(self), PyObject *py_cla
Py_RETURN_NONE;
}
+/* Access to 'owner_id' internal global. */
+
+static PyObject *pyrna_bl_owner_id_get(PyObject *UNUSED(self))
+{
+ const char *name = RNA_struct_state_owner_get();
+ if (name) {
+ return PyUnicode_FromString(name);
+ }
+ Py_RETURN_NONE;
+}
+
+static PyObject *pyrna_bl_owner_id_set(PyObject *UNUSED(self), PyObject *value)
+{
+ const char *name;
+ if (value == Py_None) {
+ name = NULL;
+ }
+ else if (PyUnicode_Check(value)) {
+ name = _PyUnicode_AsString(value);
+ }
+ else {
+ PyErr_Format(PyExc_ValueError,
+ "owner_set(...): "
+ "expected None or a string, not '%.200s'", Py_TYPE(value)->tp_name);
+ return NULL;
+ }
+ RNA_struct_state_owner_set(name);
+ Py_RETURN_NONE;
+}
+
+PyMethodDef meth_bpy_owner_id_get = {
+ "_bl_owner_id_get", (PyCFunction)pyrna_bl_owner_id_get, METH_NOARGS, NULL,
+};
+PyMethodDef meth_bpy_owner_id_set = {
+ "_bl_owner_id_set", (PyCFunction)pyrna_bl_owner_id_set, METH_O, NULL,
+};
+
/* currently this is fairly limited, we would need to make some way to split up
* pyrna_callback_classmethod_... if we want more than one callback per type */
typedef struct BPyRNA_CallBack {
@@ -8323,9 +8460,46 @@ typedef struct BPyRNA_CallBack {
StructRNA *bpy_srna;
} PyRNA_CallBack;
+PyDoc_STRVAR(pyrna_draw_handler_add_doc,
+".. method:: draw_handler_add(callback, args, region_type, draw_type)\n"
+"\n"
+" Add a new draw handler to this space type.\n"
+" It will be called every time the specified region in the space type will be drawn.\n"
+" Note: All arguments are positional only for now.\n"
+"\n"
+" :param callback:\n"
+" A function that will be called when the region is drawn.\n"
+" It gets the specified arguments as input.\n"
+" :type callback: function\n"
+" :param args: Arguments that will be passed to the callback.\n"
+" :type args: tuple\n"
+" :param region_type: The region type the callback draws in; usually `'WINDOW'`. (:class:`bpy.types.Region.type`)\n"
+" :type region_type: str\n"
+" :param draw_type: Usually `POST_PIXEL` for 2D drawing and `POST_VIEW` for 3D drawing. In some cases `PRE_VIEW` can be used.\n"
+" :type draw_type: str\n"
+" :return: Handler that can be removed later on.\n"
+" :rtype: object"
+);
+
+PyDoc_STRVAR(pyrna_draw_handler_remove_doc,
+".. method:: draw_handler_remove(handler, region_type)\n"
+"\n"
+" Remove a draw handler that was added previously.\n"
+"\n"
+" :param handler: The draw handler that should be removed.\n"
+" :type handler: object\n"
+" :param region_type: Region type the callback was added to.\n"
+" :type region_type: str\n"
+);
+
static struct BPyRNA_CallBack pyrna_cb_methods[] = {
- {{"draw_handler_add", (PyCFunction)pyrna_callback_classmethod_add, METH_VARARGS | METH_STATIC, ""}, &RNA_Space},
- {{"draw_handler_remove", (PyCFunction)pyrna_callback_classmethod_remove, METH_VARARGS | METH_STATIC, ""}, &RNA_Space},
+ {{"draw_handler_add", (PyCFunction)pyrna_callback_classmethod_add,
+ METH_VARARGS | METH_STATIC, pyrna_draw_handler_add_doc}, &RNA_Space},
+ {{"draw_handler_remove", (PyCFunction)pyrna_callback_classmethod_remove,
+ METH_VARARGS | METH_STATIC, pyrna_draw_handler_remove_doc}, &RNA_Space},
+
+ {{"draw_cursor_add", (PyCFunction)pyrna_callback_classmethod_add, METH_VARARGS | METH_STATIC, ""}, &RNA_WindowManager},
+ {{"draw_cursor_remove", (PyCFunction)pyrna_callback_classmethod_remove, METH_VARARGS | METH_STATIC, ""}, &RNA_WindowManager},
{{NULL, NULL, 0, NULL}, NULL}
};
diff --git a/source/blender/python/intern/bpy_rna.h b/source/blender/python/intern/bpy_rna.h
index f666294666e..32a63acde40 100644
--- a/source/blender/python/intern/bpy_rna.h
+++ b/source/blender/python/intern/bpy_rna.h
@@ -225,4 +225,8 @@ int pyrna_prop_validity_check(BPy_PropertyRNA *self);
extern PyMethodDef meth_bpy_register_class;
extern PyMethodDef meth_bpy_unregister_class;
+/* bpy.utils._bl_owner_(get/set) */
+extern PyMethodDef meth_bpy_owner_id_set;
+extern PyMethodDef meth_bpy_owner_id_get;
+
#endif
diff --git a/source/blender/python/intern/bpy_rna_anim.c b/source/blender/python/intern/bpy_rna_anim.c
index 73809e96560..2727b81e1cf 100644
--- a/source/blender/python/intern/bpy_rna_anim.c
+++ b/source/blender/python/intern/bpy_rna_anim.c
@@ -33,6 +33,7 @@
#include "BLI_utildefines.h"
#include "BLI_string.h"
+#include "BLI_string_utils.h"
#include "DNA_scene_types.h"
#include "DNA_anim_types.h"
@@ -61,9 +62,9 @@
#include "../generic/python_utildefines.h"
/* for keyframes and drivers */
-static int pyrna_struct_anim_args_parse(
+static int pyrna_struct_anim_args_parse_ex(
PointerRNA *ptr, const char *error_prefix, const char *path,
- const char **path_full, int *index)
+ const char **r_path_full, int *r_index, bool *r_path_no_validate)
{
const bool is_idbase = RNA_struct_is_ID(ptr->type);
PropertyRNA *prop;
@@ -78,11 +79,11 @@ static int pyrna_struct_anim_args_parse(
/* full paths can only be given from ID base */
if (is_idbase) {
- int r_index = -1;
- if (RNA_path_resolve_property_full(ptr, path, &r_ptr, &prop, &r_index) == false) {
+ int path_index = -1;
+ if (RNA_path_resolve_property_full(ptr, path, &r_ptr, &prop, &path_index) == false) {
prop = NULL;
}
- else if (r_index != -1) {
+ else if (path_index != -1) {
PyErr_Format(PyExc_ValueError,
"%.200s path includes index, must be a separate argument",
error_prefix, path);
@@ -101,86 +102,167 @@ static int pyrna_struct_anim_args_parse(
}
if (prop == NULL) {
+ if (r_path_no_validate) {
+ *r_path_no_validate = true;
+ return -1;
+ }
PyErr_Format(PyExc_TypeError,
"%.200s property \"%s\" not found",
error_prefix, path);
return -1;
}
- if (!RNA_property_animateable(&r_ptr, prop)) {
- PyErr_Format(PyExc_TypeError,
- "%.200s property \"%s\" not animatable",
- error_prefix, path);
- return -1;
+ if (r_path_no_validate) {
+ /* Don't touch the index. */
}
+ else {
+ if (!RNA_property_animateable(&r_ptr, prop)) {
+ PyErr_Format(PyExc_TypeError,
+ "%.200s property \"%s\" not animatable",
+ error_prefix, path);
+ return -1;
+ }
- if (RNA_property_array_check(prop) == 0) {
- if ((*index) == -1) {
- *index = 0;
+ if (RNA_property_array_check(prop) == 0) {
+ if ((*r_index) == -1) {
+ *r_index = 0;
+ }
+ else {
+ PyErr_Format(PyExc_TypeError,
+ "%.200s index %d was given while property \"%s\" is not an array",
+ error_prefix, *r_index, path);
+ return -1;
+ }
}
else {
- PyErr_Format(PyExc_TypeError,
- "%.200s index %d was given while property \"%s\" is not an array",
- error_prefix, *index, path);
- return -1;
+ int array_len = RNA_property_array_length(&r_ptr, prop);
+ if ((*r_index) < -1 || (*r_index) >= array_len) {
+ PyErr_Format(PyExc_TypeError,
+ "%.200s index out of range \"%s\", given %d, array length is %d",
+ error_prefix, path, *r_index, array_len);
+ return -1;
+ }
}
}
+
+ if (is_idbase) {
+ *r_path_full = BLI_strdup(path);
+ }
else {
- int array_len = RNA_property_array_length(&r_ptr, prop);
- if ((*index) < -1 || (*index) >= array_len) {
+ *r_path_full = RNA_path_from_ID_to_property(&r_ptr, prop);
+
+ if (*r_path_full == NULL) {
PyErr_Format(PyExc_TypeError,
- "%.200s index out of range \"%s\", given %d, array length is %d",
- error_prefix, path, *index, array_len);
+ "%.200s could not make path to \"%s\"",
+ error_prefix, path);
return -1;
}
}
+ return 0;
+}
+
+static int pyrna_struct_anim_args_parse(
+ PointerRNA *ptr, const char *error_prefix, const char *path,
+ const char **r_path_full, int *r_index)
+{
+ return pyrna_struct_anim_args_parse_ex(ptr, error_prefix, path, r_path_full, r_index, NULL);
+}
+
+/**
+ * Unlike #pyrna_struct_anim_args_parse \a r_path_full may be copied from \a path.
+ */
+static int pyrna_struct_anim_args_parse_no_resolve(
+ PointerRNA *ptr, const char *error_prefix, const char *path,
+ const char **r_path_full)
+{
+ const bool is_idbase = RNA_struct_is_ID(ptr->type);
if (is_idbase) {
- *path_full = BLI_strdup(path);
+ *r_path_full = path;
+ return 0;
}
else {
- *path_full = RNA_path_from_ID_to_property(&r_ptr, prop);
-
- if (*path_full == NULL) {
+ char *path_prefix = RNA_path_from_ID_to_struct(ptr);
+ if (path_prefix == NULL) {
PyErr_Format(PyExc_TypeError,
- "%.200s could not make path to \"%s\"",
- error_prefix, path);
+ "%.200s could not make path for type %s",
+ error_prefix, RNA_struct_identifier(ptr->type));
return -1;
}
+
+ if (*path == '[') {
+ *r_path_full = BLI_string_joinN(path_prefix, path);
+ }
+ else {
+ *r_path_full = BLI_string_join_by_sep_charN('.', path_prefix, path);
+ }
+ MEM_freeN(path_prefix);
}
+ return 0;
+}
+static int pyrna_struct_anim_args_parse_no_resolve_fallback(
+ PointerRNA *ptr, const char *error_prefix, const char *path,
+ const char **r_path_full, int *r_index)
+{
+ bool path_unresolved = false;
+ if (pyrna_struct_anim_args_parse_ex(
+ ptr, error_prefix, path,
+ r_path_full, r_index, &path_unresolved) == -1)
+ {
+ if (path_unresolved == true) {
+ if (pyrna_struct_anim_args_parse_no_resolve(
+ ptr, error_prefix, path, r_path_full) == -1)
+ {
+ return -1;
+ }
+ }
+ else {
+ return -1;
+ }
+ }
return 0;
}
/* internal use for insert and delete */
static int pyrna_struct_keyframe_parse(
PointerRNA *ptr, PyObject *args, PyObject *kw, const char *parse_str, const char *error_prefix,
- const char **path_full, int *index, float *cfra, const char **group_name, int *options) /* return values */
+ /* return values */
+ const char **r_path_full, int *r_index, float *r_cfra, const char **r_group_name, int *r_options)
{
static const char *kwlist[] = {"data_path", "index", "frame", "group", "options", NULL};
PyObject *pyoptions = NULL;
const char *path;
/* note, parse_str MUST start with 's|ifsO!' */
- if (!PyArg_ParseTupleAndKeywords(args, kw, parse_str, (char **)kwlist, &path, index, cfra, group_name,
- &PySet_Type, &pyoptions))
+ if (!PyArg_ParseTupleAndKeywords(
+ args, kw, parse_str, (char **)kwlist, &path, r_index, r_cfra, r_group_name,
+ &PySet_Type, &pyoptions))
{
return -1;
}
- if (pyrna_struct_anim_args_parse(ptr, error_prefix, path, path_full, index) == -1)
+ if (pyrna_struct_anim_args_parse(
+ ptr, error_prefix, path,
+ r_path_full, r_index) == -1)
+ {
return -1;
+ }
- if (*cfra == FLT_MAX)
- *cfra = CTX_data_scene(BPy_GetContext())->r.cfra;
+ if (*r_cfra == FLT_MAX) {
+ *r_cfra = CTX_data_scene(BPy_GetContext())->r.cfra;
+ }
/* flag may be null (no option currently for remove keyframes e.g.). */
- if (options) {
- if (pyoptions && (pyrna_set_to_enum_bitfield(rna_enum_keying_flag_items, pyoptions, options, error_prefix) == -1)) {
+ if (r_options) {
+ if (pyoptions &&
+ (pyrna_set_to_enum_bitfield(
+ rna_enum_keying_flag_items, pyoptions, r_options, error_prefix) == -1))
+ {
return -1;
}
- *options |= INSERTKEY_NO_USERPREF;
+ *r_options |= INSERTKEY_NO_USERPREF;
}
return 0; /* success */
@@ -222,9 +304,10 @@ PyObject *pyrna_struct_keyframe_insert(BPy_StructRNA *self, PyObject *args, PyOb
PYRNA_STRUCT_CHECK_OBJ(self);
- if (pyrna_struct_keyframe_parse(&self->ptr, args, kw,
- "s|ifsO!:bpy_struct.keyframe_insert()", "bpy_struct.keyframe_insert()",
- &path_full, &index, &cfra, &group_name, &options) == -1)
+ if (pyrna_struct_keyframe_parse(
+ &self->ptr, args, kw,
+ "s|ifsO!:bpy_struct.keyframe_insert()", "bpy_struct.keyframe_insert()",
+ &path_full, &index, &cfra, &group_name, &options) == -1)
{
return NULL;
}
@@ -233,6 +316,7 @@ PyObject *pyrna_struct_keyframe_insert(BPy_StructRNA *self, PyObject *args, PyOb
* strips themselves. These are stored separately or else the properties will
* not have any effect.
*/
+ struct Depsgraph *depsgraph = CTX_data_depsgraph(BPy_GetContext());
ReportList reports;
short result = 0;
@@ -254,7 +338,7 @@ PyObject *pyrna_struct_keyframe_insert(BPy_StructRNA *self, PyObject *args, PyOb
NlaStrip *strip = (NlaStrip *)ptr.data;
FCurve *fcu = list_find_fcurve(&strip->fcurves, RNA_property_identifier(prop), index);
- result = insert_keyframe_direct(&reports, ptr, prop, fcu, cfra, keytype, options);
+ result = insert_keyframe_direct(depsgraph, &reports, ptr, prop, fcu, cfra, keytype, NULL, options);
}
else {
BKE_reportf(&reports, RPT_ERROR, "Could not resolve path (%s)", path_full);
@@ -268,13 +352,14 @@ PyObject *pyrna_struct_keyframe_insert(BPy_StructRNA *self, PyObject *args, PyOb
}
else {
ID *id = self->ptr.id.data;
+ struct Depsgraph *depsgraph = CTX_data_depsgraph(BPy_GetContext());
ReportList reports;
short result;
BKE_reports_init(&reports, RPT_STORE);
- BLI_assert(BKE_id_is_in_gobal_main(id));
- result = insert_keyframe(G_MAIN, &reports, id, NULL, group_name, path_full, index, cfra, keytype, options);
+ BLI_assert(BKE_id_is_in_global_main(id));
+ result = insert_keyframe(G_MAIN, depsgraph, &reports, id, NULL, group_name, path_full, index, cfra, keytype, NULL, options);
MEM_freeN((void *)path_full);
if (BPy_reports_to_error(&reports, PyExc_RuntimeError, true) == -1)
@@ -384,7 +469,7 @@ PyObject *pyrna_struct_keyframe_delete(BPy_StructRNA *self, PyObject *args, PyOb
BKE_reports_init(&reports, RPT_STORE);
- result = delete_keyframe(&reports, (ID *)self->ptr.id.data, NULL, group_name, path_full, index, cfra, 0);
+ result = delete_keyframe(G.main, &reports, (ID *)self->ptr.id.data, NULL, group_name, path_full, index, cfra, 0);
MEM_freeN((void *)path_full);
if (BPy_reports_to_error(&reports, PyExc_RuntimeError, true) == -1)
@@ -417,7 +502,10 @@ PyObject *pyrna_struct_driver_add(BPy_StructRNA *self, PyObject *args)
if (!PyArg_ParseTuple(args, "s|i:driver_add", &path, &index))
return NULL;
- if (pyrna_struct_anim_args_parse(&self->ptr, "bpy_struct.driver_add():", path, &path_full, &index) == -1) {
+ if (pyrna_struct_anim_args_parse(
+ &self->ptr, "bpy_struct.driver_add():", path,
+ &path_full, &index) == -1)
+ {
return NULL;
}
else {
@@ -488,10 +576,14 @@ PyObject *pyrna_struct_driver_remove(BPy_StructRNA *self, PyObject *args)
PYRNA_STRUCT_CHECK_OBJ(self);
- if (!PyArg_ParseTuple(args, "s|i:driver_remove", &path, &index))
+ if (!PyArg_ParseTuple(args, "s|i:driver_remove", &path, &index)) {
return NULL;
+ }
- if (pyrna_struct_anim_args_parse(&self->ptr, "bpy_struct.driver_remove():", path, &path_full, &index) == -1) {
+ if (pyrna_struct_anim_args_parse_no_resolve_fallback(
+ &self->ptr, "bpy_struct.driver_remove():", path,
+ &path_full, &index) == -1)
+ {
return NULL;
}
else {
@@ -502,7 +594,9 @@ PyObject *pyrna_struct_driver_remove(BPy_StructRNA *self, PyObject *args)
result = ANIM_remove_driver(&reports, (ID *)self->ptr.id.data, path_full, index, 0);
- MEM_freeN((void *)path_full);
+ if (path != path_full) {
+ MEM_freeN((void *)path_full);
+ }
if (BPy_reports_to_error(&reports, PyExc_RuntimeError, true) == -1)
return NULL;
diff --git a/source/blender/python/intern/bpy_rna_callback.c b/source/blender/python/intern/bpy_rna_callback.c
index fbdcc03ddd0..ed29aa795e6 100644
--- a/source/blender/python/intern/bpy_rna_callback.c
+++ b/source/blender/python/intern/bpy_rna_callback.c
@@ -33,6 +33,7 @@
#include "RNA_types.h"
#include "BLI_utildefines.h"
+#include "BLI_listbase.h"
#include "bpy_rna.h"
#include "bpy_rna_callback.h"
@@ -47,8 +48,12 @@
#include "BKE_context.h"
#include "BKE_screen.h"
+#include "WM_api.h"
+
#include "ED_space_api.h"
+#include "../generic/python_utildefines.h"
+
/* use this to stop other capsules from being mis-used */
#define RNA_CAPSULE_ID "RNA_HANDLE"
#define RNA_CAPSULE_ID_INVALID "RNA_HANDLE_REMOVED"
@@ -82,6 +87,53 @@ static void cb_region_draw(const bContext *C, ARegion *UNUSED(ar), void *customd
bpy_context_clear((bContext *)C, &gilstate);
}
+/* We could make generic utility */
+static PyObject *PyC_Tuple_CopySized(PyObject *src, int len_dst)
+{
+ PyObject *dst = PyTuple_New(len_dst);
+ int len_src = PyTuple_GET_SIZE(src);
+ BLI_assert(len_src <= len_dst);
+ for (int i = 0; i < len_src; i++) {
+ PyObject *item = PyTuple_GET_ITEM(src, i);
+ PyTuple_SET_ITEM(dst, i, item);
+ Py_INCREF(item);
+ }
+ return dst;
+}
+
+static void cb_wm_cursor_draw(bContext *C, int x, int y, void *customdata)
+{
+ PyObject *cb_func, *cb_args, *result;
+ PyGILState_STATE gilstate;
+
+ bpy_context_set((bContext *)C, &gilstate);
+
+ cb_func = PyTuple_GET_ITEM((PyObject *)customdata, 1);
+ cb_args = PyTuple_GET_ITEM((PyObject *)customdata, 2);
+
+ const int cb_args_len = PyTuple_GET_SIZE(cb_args);
+
+ PyObject *cb_args_xy = PyTuple_New(2);
+ PyTuple_SET_ITEMS(cb_args_xy, PyLong_FromLong(x), PyLong_FromLong(y));
+
+ PyObject *cb_args_with_xy = PyC_Tuple_CopySized(cb_args, cb_args_len + 1);
+ PyTuple_SET_ITEM(cb_args_with_xy, cb_args_len, cb_args_xy);
+
+ result = PyObject_CallObject(cb_func, cb_args_with_xy);
+
+ Py_DECREF(cb_args_with_xy);
+
+ if (result) {
+ Py_DECREF(result);
+ }
+ else {
+ PyErr_Print();
+ PyErr_Clear();
+ }
+
+ bpy_context_clear((bContext *)C, &gilstate);
+}
+
#if 0
PyObject *pyrna_callback_add(BPy_StructRNA *self, PyObject *args)
{
@@ -171,11 +223,9 @@ static eSpace_Type rna_Space_refine_reverse(StructRNA *srna)
if (srna == &RNA_SpaceTextEditor) return SPACE_TEXT;
if (srna == &RNA_SpaceDopeSheetEditor) return SPACE_ACTION;
if (srna == &RNA_SpaceNLA) return SPACE_NLA;
- if (srna == &RNA_SpaceTimeline) return SPACE_TIME;
if (srna == &RNA_SpaceNodeEditor) return SPACE_NODE;
- if (srna == &RNA_SpaceLogicEditor) return SPACE_LOGIC;
if (srna == &RNA_SpaceConsole) return SPACE_CONSOLE;
- if (srna == &RNA_SpaceUserPreferences) return SPACE_USERPREF;
+ if (srna == &RNA_SpacePreferences) return SPACE_USERPREF;
if (srna == &RNA_SpaceClipEditor) return SPACE_CLIP;
return SPACE_EMPTY;
}
@@ -185,10 +235,6 @@ PyObject *pyrna_callback_classmethod_add(PyObject *UNUSED(self), PyObject *args)
void *handle;
PyObject *cls;
PyObject *cb_func, *cb_args;
- const char *cb_regiontype_str;
- const char *cb_event_str;
- int cb_event;
- int cb_regiontype;
StructRNA *srna;
if (PyTuple_GET_SIZE(args) < 2) {
@@ -207,23 +253,78 @@ PyObject *pyrna_callback_classmethod_add(PyObject *UNUSED(self), PyObject *args)
}
/* class specific callbacks */
- if (RNA_struct_is_a(srna, &RNA_Space)) {
- if (!PyArg_ParseTuple(args, "OOO!ss:Space.draw_handler_add",
- &cls, &cb_func, /* already assigned, no matter */
- &PyTuple_Type, &cb_args, &cb_regiontype_str, &cb_event_str))
+
+ if (srna == &RNA_WindowManager) {
+ const char *error_prefix = "WindowManager.draw_cursor_add";
+ struct {
+ const char *space_type_str;
+ const char *region_type_str;
+
+ int space_type;
+ int region_type;
+ } params = {
+ .space_type_str = NULL,
+ .region_type_str = NULL,
+ .space_type = SPACE_TYPE_ANY,
+ .region_type = RGN_TYPE_ANY,
+ };
+
+ if (!PyArg_ParseTuple(
+ args, "OOO!|ss:WindowManager.draw_cursor_add",
+ &cls, &cb_func, /* already assigned, no matter */
+ &PyTuple_Type, &cb_args, &params.space_type_str, &params.region_type_str))
+ {
+ return NULL;
+ }
+
+ if (params.space_type_str && pyrna_enum_value_from_id(
+ rna_enum_space_type_items, params.space_type_str,
+ &params.space_type, error_prefix) == -1)
+ {
+ return NULL;
+ }
+ else if (params.region_type_str && pyrna_enum_value_from_id(
+ rna_enum_region_type_items, params.region_type_str,
+ &params.region_type, error_prefix) == -1)
+ {
+ return NULL;
+ }
+
+ bContext *C = BPy_GetContext();
+ struct wmWindowManager *wm = CTX_wm_manager(C);
+ handle = WM_paint_cursor_activate(
+ wm,
+ params.space_type, params.region_type,
+ NULL, cb_wm_cursor_draw, (void *)args);
+ }
+ else if (RNA_struct_is_a(srna, &RNA_Space)) {
+ const char *error_prefix = "Space.draw_handler_add";
+ struct {
+ const char *region_type_str;
+ const char *event_str;
+
+ int region_type;
+ int event;
+ } params;
+
+ if (!PyArg_ParseTuple(
+ args, "OOO!ss:Space.draw_handler_add",
+ &cls, &cb_func, /* already assigned, no matter */
+ &PyTuple_Type, &cb_args,
+ &params.region_type_str, &params.event_str))
{
return NULL;
}
if (pyrna_enum_value_from_id(
- region_draw_mode_items, cb_event_str,
- &cb_event, "bpy_struct.callback_add()") == -1)
+ region_draw_mode_items, params.event_str,
+ &params.event, error_prefix) == -1)
{
return NULL;
}
else if (pyrna_enum_value_from_id(
- rna_enum_region_type_items, cb_regiontype_str,
- &cb_regiontype, "bpy_struct.callback_add()") == -1)
+ rna_enum_region_type_items, params.region_type_str,
+ &params.region_type, error_prefix) == -1)
{
return NULL;
}
@@ -235,13 +336,12 @@ PyObject *pyrna_callback_classmethod_add(PyObject *UNUSED(self), PyObject *args)
}
else {
SpaceType *st = BKE_spacetype_from_id(spaceid);
- ARegionType *art = BKE_regiontype_from_id(st, cb_regiontype);
+ ARegionType *art = BKE_regiontype_from_id(st, params.region_type);
if (art == NULL) {
- PyErr_Format(PyExc_TypeError, "region type '%.200s' not in space", cb_regiontype_str);
+ PyErr_Format(PyExc_TypeError, "region type '%.200s' not in space", params.region_type_str);
return NULL;
}
- handle = ED_region_draw_cb_activate(art, cb_region_draw, (void *)args, cb_event);
- Py_INCREF(args);
+ handle = ED_region_draw_cb_activate(art, cb_region_draw, (void *)args, params.event);
}
}
}
@@ -250,7 +350,14 @@ PyObject *pyrna_callback_classmethod_add(PyObject *UNUSED(self), PyObject *args)
return NULL;
}
- return PyCapsule_New((void *)handle, RNA_CAPSULE_ID, NULL);
+ PyObject *ret = PyCapsule_New((void *)handle, RNA_CAPSULE_ID, NULL);
+
+ /* Store 'args' in context as well as the handler custom-data,
+ * because the handle may be freed by Blender (new file, new window... etc) */
+ PyCapsule_SetContext(ret, args);
+ Py_INCREF(args);
+
+ return ret;
}
PyObject *pyrna_callback_classmethod_remove(PyObject *UNUSED(self), PyObject *args)
@@ -258,10 +365,8 @@ PyObject *pyrna_callback_classmethod_remove(PyObject *UNUSED(self), PyObject *ar
PyObject *cls;
PyObject *py_handle;
void *handle;
- void *customdata;
StructRNA *srna;
- const char *cb_regiontype_str;
- int cb_regiontype;
+ bool capsule_clear = false;
if (PyTuple_GET_SIZE(args) < 2) {
PyErr_SetString(PyExc_ValueError, "callback_remove(handler): expected at least 2 args");
@@ -278,21 +383,39 @@ PyObject *pyrna_callback_classmethod_remove(PyObject *UNUSED(self), PyObject *ar
PyErr_SetString(PyExc_ValueError, "callback_remove(handler): NULL handler given, invalid or already removed");
return NULL;
}
+ PyObject *handle_args = PyCapsule_GetContext(py_handle);
- if (RNA_struct_is_a(srna, &RNA_Space)) {
- if (!PyArg_ParseTuple(args, "OO!s:Space.draw_handler_remove",
- &cls, &PyCapsule_Type, &py_handle, /* already assigned, no matter */
- &cb_regiontype_str))
+ if (srna == &RNA_WindowManager) {
+ if (!PyArg_ParseTuple(
+ args, "OO!:WindowManager.draw_cursor_remove",
+ &cls, &PyCapsule_Type, &py_handle))
+ {
+ return NULL;
+ }
+ bContext *C = BPy_GetContext();
+ struct wmWindowManager *wm = CTX_wm_manager(C);
+ WM_paint_cursor_end(wm, handle);
+ capsule_clear = true;
+ }
+ else if (RNA_struct_is_a(srna, &RNA_Space)) {
+ const char *error_prefix = "Space.draw_handler_remove";
+ struct {
+ const char *region_type_str;
+
+ int region_type;
+ } params;
+
+ if (!PyArg_ParseTuple(
+ args, "OO!s:Space.draw_handler_remove",
+ &cls, &PyCapsule_Type, &py_handle, /* already assigned, no matter */
+ &params.region_type_str))
{
return NULL;
}
-
- customdata = ED_region_draw_cb_customdata(handle);
- Py_DECREF((PyObject *)customdata);
if (pyrna_enum_value_from_id(
- rna_enum_region_type_items, cb_regiontype_str,
- &cb_regiontype, "bpy_struct.callback_remove()") == -1)
+ rna_enum_region_type_items, params.region_type_str,
+ &params.region_type, error_prefix) == -1)
{
return NULL;
}
@@ -304,12 +427,13 @@ PyObject *pyrna_callback_classmethod_remove(PyObject *UNUSED(self), PyObject *ar
}
else {
SpaceType *st = BKE_spacetype_from_id(spaceid);
- ARegionType *art = BKE_regiontype_from_id(st, cb_regiontype);
+ ARegionType *art = BKE_regiontype_from_id(st, params.region_type);
if (art == NULL) {
- PyErr_Format(PyExc_TypeError, "region type '%.200s' not in space", cb_regiontype_str);
+ PyErr_Format(PyExc_TypeError, "region type '%.200s' not in space", params.region_type_str);
return NULL;
}
ED_region_draw_cb_exit(art, handle);
+ capsule_clear = true;
}
}
}
@@ -319,7 +443,10 @@ PyObject *pyrna_callback_classmethod_remove(PyObject *UNUSED(self), PyObject *ar
}
/* don't allow reuse */
- PyCapsule_SetName(py_handle, RNA_CAPSULE_ID_INVALID);
+ if (capsule_clear) {
+ Py_DECREF(handle_args);
+ PyCapsule_SetName(py_handle, RNA_CAPSULE_ID_INVALID);
+ }
Py_RETURN_NONE;
}
diff --git a/source/blender/python/intern/bpy_rna_gizmo.c b/source/blender/python/intern/bpy_rna_gizmo.c
new file mode 100644
index 00000000000..8189431dfc9
--- /dev/null
+++ b/source/blender/python/intern/bpy_rna_gizmo.c
@@ -0,0 +1,564 @@
+/*
+ * ***** BEGIN GPL LICENSE BLOCK *****
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ * ***** END GPL LICENSE BLOCK *****
+ */
+
+/** \file blender/python/intern/bpy_rna_gizmo.c
+ * \ingroup pythonintern
+ *
+ * .
+ */
+
+#include <Python.h>
+#include <stddef.h>
+
+#include "MEM_guardedalloc.h"
+
+#include "BLI_utildefines.h"
+#include "BLI_alloca.h"
+
+#include "BKE_main.h"
+
+#include "WM_api.h"
+#include "WM_types.h"
+
+#include "bpy_capi_utils.h"
+#include "bpy_rna_gizmo.h"
+
+#include "../generic/py_capi_utils.h"
+#include "../generic/python_utildefines.h"
+
+#include "RNA_access.h"
+#include "RNA_types.h"
+#include "RNA_enum_types.h"
+
+#include "bpy_rna.h"
+
+
+/* -------------------------------------------------------------------- */
+/** \name Gizmo Target Property Define API
+ * \{ */
+
+enum {
+ BPY_GIZMO_FN_SLOT_GET = 0,
+ BPY_GIZMO_FN_SLOT_SET,
+ BPY_GIZMO_FN_SLOT_RANGE_GET,
+};
+#define BPY_GIZMO_FN_SLOT_LEN (BPY_GIZMO_FN_SLOT_RANGE_GET + 1)
+
+struct BPyGizmoHandlerUserData {
+
+ PyObject *fn_slots[BPY_GIZMO_FN_SLOT_LEN];
+};
+
+static void py_rna_gizmo_handler_get_cb(
+ const wmGizmo *UNUSED(gz), wmGizmoProperty *gz_prop,
+ void *value_p)
+{
+ PyGILState_STATE gilstate = PyGILState_Ensure();
+
+ struct BPyGizmoHandlerUserData *data = gz_prop->custom_func.user_data;
+ PyObject *ret = PyObject_CallObject(data->fn_slots[BPY_GIZMO_FN_SLOT_GET], NULL);
+ if (ret == NULL) {
+ goto fail;
+ }
+
+ if (gz_prop->type->data_type == PROP_FLOAT) {
+ float *value = value_p;
+ if (gz_prop->type->array_length == 1) {
+ if ((*value = PyFloat_AsDouble(ret)) == -1.0f && PyErr_Occurred()) {
+ goto fail;
+ }
+ }
+ else {
+ if (PyC_AsArray(value, ret, gz_prop->type->array_length, &PyFloat_Type, false,
+ "Gizmo get callback: ") == -1)
+ {
+ goto fail;
+ }
+ }
+ }
+ else {
+ PyErr_SetString(PyExc_AttributeError, "internal error, unsupported type");
+ goto fail;
+ }
+
+ Py_DECREF(ret);
+
+ PyGILState_Release(gilstate);
+ return;
+
+fail:
+ PyErr_Print();
+ PyErr_Clear();
+
+ PyGILState_Release(gilstate);
+}
+
+static void py_rna_gizmo_handler_set_cb(
+ const wmGizmo *UNUSED(gz), wmGizmoProperty *gz_prop,
+ const void *value_p)
+{
+ PyGILState_STATE gilstate = PyGILState_Ensure();
+
+ struct BPyGizmoHandlerUserData *data = gz_prop->custom_func.user_data;
+
+ PyObject *args = PyTuple_New(1);
+
+ if (gz_prop->type->data_type == PROP_FLOAT) {
+ const float *value = value_p;
+ PyObject *py_value;
+ if (gz_prop->type->array_length == 1) {
+ py_value = PyFloat_FromDouble(*value);
+ }
+ else {
+ py_value = PyC_Tuple_PackArray_F32(value, gz_prop->type->array_length);
+ }
+ if (py_value == NULL) {
+ goto fail;
+ }
+ PyTuple_SET_ITEM(args, 0, py_value);
+ }
+ else {
+ PyErr_SetString(PyExc_AttributeError, "internal error, unsupported type");
+ goto fail;
+ }
+
+ PyObject *ret = PyObject_CallObject(data->fn_slots[BPY_GIZMO_FN_SLOT_SET], args);
+ if (ret == NULL) {
+ goto fail;
+ }
+ Py_DECREF(ret);
+
+ PyGILState_Release(gilstate);
+ return;
+
+fail:
+ PyErr_Print();
+ PyErr_Clear();
+
+ Py_DECREF(args);
+
+ PyGILState_Release(gilstate);
+}
+
+static void py_rna_gizmo_handler_range_get_cb(
+ const wmGizmo *UNUSED(gz), wmGizmoProperty *gz_prop,
+ void *value_p)
+{
+ struct BPyGizmoHandlerUserData *data = gz_prop->custom_func.user_data;
+
+ PyGILState_STATE gilstate = PyGILState_Ensure();
+
+ PyObject *ret = PyObject_CallObject(data->fn_slots[BPY_GIZMO_FN_SLOT_RANGE_GET], NULL);
+ if (ret == NULL) {
+ goto fail;
+ }
+
+ if (!PyTuple_Check(ret)) {
+ PyErr_Format(PyExc_TypeError,
+ "Expected a tuple, not %.200s",
+ Py_TYPE(ret)->tp_name);
+ goto fail;
+ }
+
+ if (PyTuple_GET_SIZE(ret) != 2) {
+ PyErr_Format(PyExc_TypeError,
+ "Expected a tuple of size 2, not %d",
+ PyTuple_GET_SIZE(ret));
+ goto fail;
+ }
+
+ if (gz_prop->type->data_type == PROP_FLOAT) {
+ float range[2];
+ for (int i = 0; i < 2; i++) {
+ if (((range[i] = PyFloat_AsDouble(PyTuple_GET_ITEM(ret, i))) == -1.0f && PyErr_Occurred()) == 0) {
+ /* pass */
+ }
+ else {
+ goto fail;
+ }
+ }
+ memcpy(value_p, range, sizeof(range));
+ }
+ else {
+ PyErr_SetString(PyExc_AttributeError, "internal error, unsupported type");
+ goto fail;
+ }
+
+ Py_DECREF(ret);
+ PyGILState_Release(gilstate);
+ return;
+
+fail:
+ Py_XDECREF(ret);
+
+ PyErr_Print();
+ PyErr_Clear();
+
+ PyGILState_Release(gilstate);
+}
+
+static void py_rna_gizmo_handler_free_cb(
+ const wmGizmo *UNUSED(gz), wmGizmoProperty *gz_prop)
+{
+ struct BPyGizmoHandlerUserData *data = gz_prop->custom_func.user_data;
+
+ PyGILState_STATE gilstate = PyGILState_Ensure();
+ for (int i = 0; i < BPY_GIZMO_FN_SLOT_LEN; i++) {
+ Py_XDECREF(data->fn_slots[i]);
+ }
+ PyGILState_Release(gilstate);
+
+ MEM_freeN(data);
+
+}
+
+PyDoc_STRVAR(bpy_gizmo_target_set_handler_doc,
+".. method:: target_set_handler(target, get, set, range=None):\n"
+"\n"
+" Assigns callbacks to a gizmos property.\n"
+"\n"
+" :arg get: Function that returns the value for this property (single value or sequence).\n"
+" :type get: callable\n"
+" :arg set: Function that takes a single value argument and applies it.\n"
+" :type set: callable\n"
+" :arg range: Function that returns a (min, max) tuple for gizmos that use a range.\n"
+" :type range: callable\n"
+);
+static PyObject *bpy_gizmo_target_set_handler(PyObject *UNUSED(self), PyObject *args, PyObject *kw)
+{
+ PyGILState_STATE gilstate = PyGILState_Ensure();
+
+ struct {
+ PyObject *self;
+ char *target;
+ PyObject *py_fn_slots[BPY_GIZMO_FN_SLOT_LEN];
+ } params = {
+ .self = NULL,
+ .target = NULL,
+ .py_fn_slots = {NULL},
+ };
+
+ /* Note: this is a counter-part to functions:
+ * 'Gizmo.target_set_prop & target_set_operator'
+ * (see: rna_wm_gizmo_api.c). conventions should match. */
+ static const char * const _keywords[] = {"self", "target", "get", "set", "range", NULL};
+ static _PyArg_Parser _parser = {"Os|$OOO:target_set_handler", _keywords, 0};
+ if (!_PyArg_ParseTupleAndKeywordsFast(
+ args, kw, &_parser,
+ &params.self,
+ &params.target,
+ &params.py_fn_slots[BPY_GIZMO_FN_SLOT_GET],
+ &params.py_fn_slots[BPY_GIZMO_FN_SLOT_SET],
+ &params.py_fn_slots[BPY_GIZMO_FN_SLOT_RANGE_GET]))
+ {
+ goto fail;
+ }
+
+ wmGizmo *gz = ((BPy_StructRNA *)params.self)->ptr.data;
+
+ const wmGizmoPropertyType *gz_prop_type =
+ WM_gizmotype_target_property_find(gz->type, params.target);
+ if (gz_prop_type == NULL) {
+ PyErr_Format(PyExc_ValueError,
+ "Gizmo target property '%s.%s' not found",
+ gz->type->idname, params.target);
+ goto fail;
+ }
+
+ {
+ const int slots_required = 2;
+ const int slots_start = 2;
+ for (int i = 0; i < BPY_GIZMO_FN_SLOT_LEN; i++) {
+ if (params.py_fn_slots[i] == NULL) {
+ if (i < slots_required) {
+ PyErr_Format(PyExc_ValueError, "Argument '%s' not given", _keywords[slots_start + i]);
+ goto fail;
+ }
+ }
+ else if (!PyCallable_Check(params.py_fn_slots[i])) {
+ PyErr_Format(PyExc_ValueError, "Argument '%s' not callable", _keywords[slots_start + i]);
+ goto fail;
+ }
+ }
+ }
+
+ struct BPyGizmoHandlerUserData *data = MEM_callocN(sizeof(*data), __func__);
+
+ for (int i = 0; i < BPY_GIZMO_FN_SLOT_LEN; i++) {
+ data->fn_slots[i] = params.py_fn_slots[i];
+ Py_XINCREF(params.py_fn_slots[i]);
+ }
+
+ WM_gizmo_target_property_def_func_ptr(
+ gz, gz_prop_type,
+ &(const struct wmGizmoPropertyFnParams) {
+ .value_get_fn = py_rna_gizmo_handler_get_cb,
+ .value_set_fn = py_rna_gizmo_handler_set_cb,
+ .range_get_fn = py_rna_gizmo_handler_range_get_cb,
+ .free_fn = py_rna_gizmo_handler_free_cb,
+ .user_data = data,
+ });
+
+ PyGILState_Release(gilstate);
+
+ Py_RETURN_NONE;
+
+fail:
+ PyGILState_Release(gilstate);
+ return NULL;
+}
+
+/** \} */
+
+/* -------------------------------------------------------------------- */
+/** \name Gizmo Target Property Access API
+ * \{ */
+
+PyDoc_STRVAR(bpy_gizmo_target_get_value_doc,
+".. method:: target_get_value(target):\n"
+"\n"
+" Get the value of this target property.\n"
+"\n"
+" :arg target: Target property name.\n"
+" :type target: string\n"
+" :return: The value of the target property.\n"
+" :rtype: Single value or array based on the target type\n"
+);
+static PyObject *bpy_gizmo_target_get_value(PyObject *UNUSED(self), PyObject *args, PyObject *kw)
+{
+ struct {
+ PyObject *self;
+ char *target;
+ } params = {
+ .self = NULL,
+ .target = NULL,
+ };
+
+ static const char * const _keywords[] = {"self", "target", NULL};
+ static _PyArg_Parser _parser = {"Os:target_get_value", _keywords, 0};
+ if (!_PyArg_ParseTupleAndKeywordsFast(
+ args, kw, &_parser,
+ &params.self,
+ &params.target))
+ {
+ goto fail;
+ }
+
+ wmGizmo *gz = ((BPy_StructRNA *)params.self)->ptr.data;
+
+ wmGizmoProperty *gz_prop =
+ WM_gizmo_target_property_find(gz, params.target);
+ if (gz_prop == NULL) {
+ PyErr_Format(PyExc_ValueError,
+ "Gizmo target property '%s.%s' not found",
+ gz->type->idname, params.target);
+ goto fail;
+ }
+
+ const int array_len = WM_gizmo_target_property_array_length(gz, gz_prop);
+ switch (gz_prop->type->data_type) {
+ case PROP_FLOAT:
+ {
+ if (array_len != 0) {
+ float *value = BLI_array_alloca(value, array_len);
+ WM_gizmo_target_property_float_get_array(gz, gz_prop, value);
+ return PyC_Tuple_PackArray_F32(value, array_len);
+ }
+ else {
+ float value = WM_gizmo_target_property_float_get(gz, gz_prop);
+ return PyFloat_FromDouble(value);
+ }
+ break;
+ }
+ default:
+ {
+ PyErr_SetString(PyExc_RuntimeError, "Not yet supported type");
+ goto fail;
+ }
+ }
+
+fail:
+ return NULL;
+}
+
+PyDoc_STRVAR(bpy_gizmo_target_set_value_doc,
+".. method:: target_set_value(target):\n"
+"\n"
+" Set the value of this target property.\n"
+"\n"
+" :arg target: Target property name.\n"
+" :type target: string\n"
+);
+static PyObject *bpy_gizmo_target_set_value(PyObject *UNUSED(self), PyObject *args, PyObject *kw)
+{
+ struct {
+ PyObject *self;
+ char *target;
+ PyObject *value;
+ } params = {
+ .self = NULL,
+ .target = NULL,
+ .value = NULL,
+ };
+
+ static const char * const _keywords[] = {"self", "target", "value", NULL};
+ static _PyArg_Parser _parser = {"OsO:target_set_value", _keywords, 0};
+ if (!_PyArg_ParseTupleAndKeywordsFast(
+ args, kw, &_parser,
+ &params.self,
+ &params.target,
+ &params.value))
+ {
+ goto fail;
+ }
+
+ wmGizmo *gz = ((BPy_StructRNA *)params.self)->ptr.data;
+
+ wmGizmoProperty *gz_prop =
+ WM_gizmo_target_property_find(gz, params.target);
+ if (gz_prop == NULL) {
+ PyErr_Format(PyExc_ValueError,
+ "Gizmo target property '%s.%s' not found",
+ gz->type->idname, params.target);
+ goto fail;
+ }
+
+ const int array_len = WM_gizmo_target_property_array_length(gz, gz_prop);
+ switch (gz_prop->type->data_type) {
+ case PROP_FLOAT:
+ {
+ if (array_len != 0) {
+ float *value = BLI_array_alloca(value, array_len);
+ if (PyC_AsArray(value, params.value, gz_prop->type->array_length, &PyFloat_Type, false,
+ "Gizmo target property array") == -1)
+ {
+ goto fail;
+ }
+ WM_gizmo_target_property_float_set_array(BPy_GetContext(), gz, gz_prop, value);
+ }
+ else {
+ float value;
+ if ((value = PyFloat_AsDouble(params.value)) == -1.0f && PyErr_Occurred()) {
+ goto fail;
+ }
+ WM_gizmo_target_property_float_set(BPy_GetContext(), gz, gz_prop, value);
+ }
+ Py_RETURN_NONE;
+ }
+ default:
+ {
+ PyErr_SetString(PyExc_RuntimeError, "Not yet supported type");
+ goto fail;
+ }
+ }
+
+fail:
+ return NULL;
+}
+
+
+PyDoc_STRVAR(bpy_gizmo_target_get_range_doc,
+".. method:: target_get_range(target):\n"
+"\n"
+" Get the range for this target property.\n"
+"\n"
+" :arg target: Target property name.\n"
+" :return: The range of this property (min, max).\n"
+" :rtype: tuple pair.\n"
+);
+static PyObject *bpy_gizmo_target_get_range(PyObject *UNUSED(self), PyObject *args, PyObject *kw)
+{
+ struct {
+ PyObject *self;
+ char *target;
+ } params = {
+ .self = NULL,
+ .target = NULL,
+ };
+
+ static const char * const _keywords[] = {"self", "target", NULL};
+ static _PyArg_Parser _parser = {"Os:target_get_range", _keywords, 0};
+ if (!_PyArg_ParseTupleAndKeywordsFast(
+ args, kw, &_parser,
+ &params.self,
+ &params.target))
+ {
+ goto fail;
+ }
+
+ wmGizmo *gz = ((BPy_StructRNA *)params.self)->ptr.data;
+
+ wmGizmoProperty *gz_prop =
+ WM_gizmo_target_property_find(gz, params.target);
+ if (gz_prop == NULL) {
+ PyErr_Format(PyExc_ValueError,
+ "Gizmo target property '%s.%s' not found",
+ gz->type->idname, params.target);
+ goto fail;
+ }
+
+ switch (gz_prop->type->data_type) {
+ case PROP_FLOAT:
+ {
+ float range[2];
+ WM_gizmo_target_property_float_range_get(gz, gz_prop, range);
+ return PyC_Tuple_PackArray_F32(range, 2);
+ }
+ default:
+ {
+ PyErr_SetString(PyExc_RuntimeError, "Not yet supported type");
+ goto fail;
+ }
+ }
+
+fail:
+ return NULL;
+}
+
+/** \} */
+
+int BPY_rna_gizmo_module(PyObject *mod_par)
+{
+ static PyMethodDef method_def_array[] = {
+ /* Gizmo Target Property Define API */
+ {"target_set_handler", (PyCFunction)bpy_gizmo_target_set_handler,
+ METH_VARARGS | METH_KEYWORDS, bpy_gizmo_target_set_handler_doc},
+ /* Gizmo Target Property Access API */
+ {"target_get_value", (PyCFunction)bpy_gizmo_target_get_value,
+ METH_VARARGS | METH_KEYWORDS, bpy_gizmo_target_get_value_doc},
+ {"target_set_value", (PyCFunction)bpy_gizmo_target_set_value,
+ METH_VARARGS | METH_KEYWORDS, bpy_gizmo_target_set_value_doc},
+ {"target_get_range", (PyCFunction)bpy_gizmo_target_get_range,
+ METH_VARARGS | METH_KEYWORDS, bpy_gizmo_target_get_range_doc},
+ /* no sentinel needed. */
+ };
+
+ for (int i = 0; i < ARRAY_SIZE(method_def_array); i++) {
+ PyMethodDef *m = &method_def_array[i];
+ PyObject *func = PyCFunction_New(m, NULL);
+ PyObject *func_inst = PyInstanceMethod_New(func);
+ char name_prefix[128];
+ PyOS_snprintf(name_prefix, sizeof(name_prefix), "_rna_gizmo_%s", m->ml_name);
+ /* TODO, return a type that binds nearly to a method. */
+ PyModule_AddObject(mod_par, name_prefix, func_inst);
+ }
+
+ return 0;
+}
diff --git a/source/blender/python/intern/gpu.h b/source/blender/python/intern/bpy_rna_gizmo.h
index 0da44a4eb87..68d8c1e052a 100644
--- a/source/blender/python/intern/gpu.h
+++ b/source/blender/python/intern/bpy_rna_gizmo.h
@@ -15,27 +15,18 @@
* along with this program; if not, write to the Free Software Foundation,
* Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*
- * The Original Code is Copyright (C) 2005 Blender Foundation.
- * All rights reserved.
- *
- * The Original Code is: all of this file.
- *
- * Contributor(s): Benoit Bolsee.
+ * Contributor(s): Bastien Montagne
*
* ***** END GPL LICENSE BLOCK *****
*/
-/** \file blender/python/intern/gpu.h
+/** \file blender/python/intern/bpy_rna_gizmo.h
* \ingroup pythonintern
- *
- * Initializes the gpu Python module.
*/
-#ifndef __GPU_H__
-#define __GPU_H__
-
-PyObject *GPU_initPython(void);
+#ifndef __BPY_RNA_GIZMO_H__
+#define __BPY_RNA_GIZMO_H__
-PyObject *BPyInit_gpu_offscreen(void);
+int BPY_rna_gizmo_module(PyObject *);
-#endif /* __GPU_H__ */
+#endif /* __BPY_RNA_GIZMO_H__ */
diff --git a/source/blender/python/intern/bpy_rna_id_collection.c b/source/blender/python/intern/bpy_rna_id_collection.c
index 4806c2266ba..3fc12d4cc54 100644
--- a/source/blender/python/intern/bpy_rna_id_collection.c
+++ b/source/blender/python/intern/bpy_rna_id_collection.c
@@ -35,9 +35,9 @@
#include "BLI_bitmap.h"
#include "BKE_global.h"
-#include "BKE_main.h"
#include "BKE_library.h"
#include "BKE_library_query.h"
+#include "BKE_main.h"
#include "DNA_ID.h"
/* Those folowing are only to support hack of not listing some internal 'backward' pointers in generated user_map... */
@@ -97,11 +97,11 @@ static int foreach_libblock_id_user_map_callback(
}
if ((GS(self_id->name) == ID_OB) && (id_p == (ID **)&((Object *)self_id)->proxy_from)) {
- /* We skip proxy_from here, since it some internal pointer which is not irrelevant info for py/API level. */
+ /* We skip proxy_from here, since it's some internal pointer which is not relevant info for py/API level. */
return IDWALK_RET_NOP;
}
else if ((GS(self_id->name) == ID_KE) && (id_p == (ID **)&((Key *)self_id)->from)) {
- /* We skip from here, since it some internal pointer which is not irrelevant info for py/API level. */
+ /* We skip from here, since it's some internal pointer which is not relevant info for py/API level. */
return IDWALK_RET_NOP;
}
@@ -290,6 +290,79 @@ error:
}
+PyDoc_STRVAR(bpy_batch_remove_doc,
+".. method:: batch_remove(ids=(id1, id2, ...))\n"
+"\n"
+" Remove (delete) several IDs at once.\n"
+"\n"
+" WARNING: Considered experimental feature currently.\n"
+"\n"
+" Note that this function is quicker than individual calls to :func:`remove()` (from :class:`bpy.types.BlendData`\n"
+" ID collections), but less safe/versatile (it can break Blender, e.g. by removing all scenes...).\n"
+"\n"
+" :arg ids: Iterables of IDs (types can be mixed).\n"
+" :type subset: sequence\n"
+);
+static PyObject *bpy_batch_remove(PyObject *UNUSED(self), PyObject *args, PyObject *kwds)
+{
+#if 0 /* If someone knows how to get a proper 'self' in that case... */
+ BPy_StructRNA *pyrna = (BPy_StructRNA *)self;
+ Main *bmain = pyrna->ptr.data;
+#else
+ Main *bmain = G_MAIN; /* XXX Ugly, but should work! */
+#endif
+
+ PyObject *ids = NULL;
+
+ PyObject *ret = NULL;
+
+ static const char *_keywords[] = {"ids", NULL};
+ static _PyArg_Parser _parser = {"O:user_map", _keywords, 0};
+ if (!_PyArg_ParseTupleAndKeywordsFast(
+ args, kwds, &_parser,
+ &ids))
+ {
+ return ret;
+ }
+
+ if (ids) {
+ BKE_main_id_tag_all(bmain, LIB_TAG_DOIT, false);
+
+ PyObject *ids_fast = PySequence_Fast(ids, "batch_remove");
+ if (ids_fast == NULL) {
+ goto error;
+ }
+
+ PyObject **ids_array = PySequence_Fast_ITEMS(ids_fast);
+ Py_ssize_t ids_len = PySequence_Fast_GET_SIZE(ids_fast);
+
+ for (; ids_len; ids_array++, ids_len--) {
+ ID *id;
+ if (!pyrna_id_FromPyObject(*ids_array, &id)) {
+ PyErr_Format(PyExc_TypeError,
+ "Expected an ID type, not %.200s",
+ Py_TYPE(*ids_array)->tp_name);
+ Py_DECREF(ids_fast);
+ goto error;
+ }
+
+ id->tag |= LIB_TAG_DOIT;
+ }
+ Py_DECREF(ids_fast);
+
+ BKE_id_multi_tagged_delete(bmain);
+ }
+ else {
+ goto error;
+ }
+
+ Py_INCREF(Py_None);
+ ret = Py_None;
+
+error:
+ return ret;
+}
+
int BPY_rna_id_collection_module(PyObject *mod_par)
{
static PyMethodDef user_map = {
@@ -297,5 +370,10 @@ int BPY_rna_id_collection_module(PyObject *mod_par)
PyModule_AddObject(mod_par, "_rna_id_collection_user_map", PyCFunction_New(&user_map, NULL));
+ static PyMethodDef batch_remove = {
+ "batch_remove", (PyCFunction)bpy_batch_remove, METH_VARARGS | METH_KEYWORDS, bpy_batch_remove_doc};
+
+ PyModule_AddObject(mod_par, "_rna_id_collection_batch_remove", PyCFunction_New(&batch_remove, NULL));
+
return 0;
}
diff --git a/source/blender/python/intern/bpy_utils_units.c b/source/blender/python/intern/bpy_utils_units.c
index cbd8b67d1ce..1d1108e1af0 100644
--- a/source/blender/python/intern/bpy_utils_units.c
+++ b/source/blender/python/intern/bpy_utils_units.c
@@ -323,7 +323,6 @@ PyObject *BPY_utils_units(void)
submodule = PyModule_Create(&bpyunits_module);
PyDict_SetItemString(PyImport_GetModuleDict(), bpyunits_module.m_name, submodule);
- Py_INCREF(submodule);
/* Finalize our unit systems and types structseq definitions! */
diff --git a/source/blender/python/intern/gpu.c b/source/blender/python/intern/gpu.c
deleted file mode 100644
index d902b6838f4..00000000000
--- a/source/blender/python/intern/gpu.c
+++ /dev/null
@@ -1,342 +0,0 @@
-/*
- * ***** BEGIN GPL LICENSE BLOCK *****
- *
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU General Public License
- * as published by the Free Software Foundation; either version 2
- * of the License, or (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
- *
- * The Original Code is Copyright (C) 2006 Blender Foundation.
- * All rights reserved.
- *
- * The Original Code is: all of this file.
- *
- * Contributor(s): Benoit Bolsee.
- *
- * ***** END GPL LICENSE BLOCK *****
- */
-
-/** \file blender/python/intern/gpu.c
- * \ingroup pythonintern
- *
- * This file defines the 'gpu' module, used to get GLSL shader code and data
- * from blender materials.
- */
-
-#include <Python.h>
-
-#include "DNA_scene_types.h"
-#include "DNA_material_types.h"
-#include "DNA_ID.h"
-#include "DNA_customdata_types.h"
-
-#include "BLI_listbase.h"
-#include "BLI_utildefines.h"
-
-#include "RNA_access.h"
-
-#include "bpy_rna.h"
-
-#include "../generic/py_capi_utils.h"
-
-#include "GPU_material.h"
-
-#include "gpu.h"
-
-#define PY_MODULE_ADD_CONSTANT(module, name) PyModule_AddIntConstant(module, # name, name)
-
-PyDoc_STRVAR(M_gpu_doc,
-"This module provides access to the GLSL shader and Offscreen rendering functionalities."
-);
-static struct PyModuleDef gpumodule = {
- PyModuleDef_HEAD_INIT,
- "gpu", /* name of module */
- M_gpu_doc, /* module documentation */
- -1, /* size of per-interpreter state of the module,
- * or -1 if the module keeps state in global variables. */
- NULL, NULL, NULL, NULL, NULL
-};
-
-static PyObject *PyInit_gpu(void)
-{
- PyObject *m;
-
- m = PyModule_Create(&gpumodule);
- if (m == NULL)
- return NULL;
-
-
- /* Take care to update docs when editing: 'doc/python_api/rst/gpu.rst' */
-
-
- /* -------------------------------------------------------------------- */
- /* GPUDynamicType */
-
- /* device constant groups */
- PY_MODULE_ADD_CONSTANT(m, GPU_DYNAMIC_GROUP_MISC);
- PY_MODULE_ADD_CONSTANT(m, GPU_DYNAMIC_GROUP_LAMP);
- PY_MODULE_ADD_CONSTANT(m, GPU_DYNAMIC_GROUP_OBJECT);
- PY_MODULE_ADD_CONSTANT(m, GPU_DYNAMIC_GROUP_SAMPLER);
- PY_MODULE_ADD_CONSTANT(m, GPU_DYNAMIC_GROUP_MIST);
- PY_MODULE_ADD_CONSTANT(m, GPU_DYNAMIC_GROUP_WORLD);
- PY_MODULE_ADD_CONSTANT(m, GPU_DYNAMIC_GROUP_MAT);
-
- /* device constants */
- PY_MODULE_ADD_CONSTANT(m, GPU_DYNAMIC_NONE);
- /* GPU_DYNAMIC_GROUP_OBJECT */
- PY_MODULE_ADD_CONSTANT(m, GPU_DYNAMIC_OBJECT_VIEWMAT);
- PY_MODULE_ADD_CONSTANT(m, GPU_DYNAMIC_OBJECT_MAT);
- PY_MODULE_ADD_CONSTANT(m, GPU_DYNAMIC_OBJECT_VIEWIMAT);
- PY_MODULE_ADD_CONSTANT(m, GPU_DYNAMIC_OBJECT_IMAT);
- PY_MODULE_ADD_CONSTANT(m, GPU_DYNAMIC_OBJECT_LOCTOVIEWMAT);
- PY_MODULE_ADD_CONSTANT(m, GPU_DYNAMIC_OBJECT_LOCTOVIEWIMAT);
- PY_MODULE_ADD_CONSTANT(m, GPU_DYNAMIC_OBJECT_COLOR);
- PY_MODULE_ADD_CONSTANT(m, GPU_DYNAMIC_OBJECT_AUTOBUMPSCALE);
- /* GPU_DYNAMIC_GROUP_LAMP */
- PY_MODULE_ADD_CONSTANT(m, GPU_DYNAMIC_LAMP_DYNVEC);
- PY_MODULE_ADD_CONSTANT(m, GPU_DYNAMIC_LAMP_DYNCO);
- PY_MODULE_ADD_CONSTANT(m, GPU_DYNAMIC_LAMP_DYNIMAT);
- PY_MODULE_ADD_CONSTANT(m, GPU_DYNAMIC_LAMP_DYNPERSMAT);
- PY_MODULE_ADD_CONSTANT(m, GPU_DYNAMIC_LAMP_DYNENERGY);
- PY_MODULE_ADD_CONSTANT(m, GPU_DYNAMIC_LAMP_DYNCOL);
- PY_MODULE_ADD_CONSTANT(m, GPU_DYNAMIC_LAMP_ATT1);
- PY_MODULE_ADD_CONSTANT(m, GPU_DYNAMIC_LAMP_ATT2);
- PY_MODULE_ADD_CONSTANT(m, GPU_DYNAMIC_LAMP_DISTANCE);
- PY_MODULE_ADD_CONSTANT(m, GPU_DYNAMIC_LAMP_SPOTSIZE);
- PY_MODULE_ADD_CONSTANT(m, GPU_DYNAMIC_LAMP_SPOTBLEND);
- PY_MODULE_ADD_CONSTANT(m, GPU_DYNAMIC_LAMP_SPOTSCALE);
- /* GPU_DYNAMIC_GROUP_SAMPLER */
- PY_MODULE_ADD_CONSTANT(m, GPU_DYNAMIC_SAMPLER_2DBUFFER);
- PY_MODULE_ADD_CONSTANT(m, GPU_DYNAMIC_SAMPLER_2DIMAGE);
- PY_MODULE_ADD_CONSTANT(m, GPU_DYNAMIC_SAMPLER_2DSHADOW);
- /* GPU_DYNAMIC_GROUP_MIST */
- PY_MODULE_ADD_CONSTANT(m, GPU_DYNAMIC_MIST_ENABLE);
- PY_MODULE_ADD_CONSTANT(m, GPU_DYNAMIC_MIST_START);
- PY_MODULE_ADD_CONSTANT(m, GPU_DYNAMIC_MIST_DISTANCE);
- PY_MODULE_ADD_CONSTANT(m, GPU_DYNAMIC_MIST_INTENSITY);
- PY_MODULE_ADD_CONSTANT(m, GPU_DYNAMIC_MIST_TYPE);
- PY_MODULE_ADD_CONSTANT(m, GPU_DYNAMIC_MIST_COLOR);
- /* GPU_DYNAMIC_GROUP_WORLD */
- PY_MODULE_ADD_CONSTANT(m, GPU_DYNAMIC_HORIZON_COLOR);
- PY_MODULE_ADD_CONSTANT(m, GPU_DYNAMIC_AMBIENT_COLOR);
- PY_MODULE_ADD_CONSTANT(m, GPU_DYNAMIC_ZENITH_COLOR);
- /* GPU_DYNAMIC_GROUP_MAT */
- PY_MODULE_ADD_CONSTANT(m, GPU_DYNAMIC_MAT_DIFFRGB);
- PY_MODULE_ADD_CONSTANT(m, GPU_DYNAMIC_MAT_REF);
- PY_MODULE_ADD_CONSTANT(m, GPU_DYNAMIC_MAT_SPECRGB);
- PY_MODULE_ADD_CONSTANT(m, GPU_DYNAMIC_MAT_SPEC);
- PY_MODULE_ADD_CONSTANT(m, GPU_DYNAMIC_MAT_HARD);
- PY_MODULE_ADD_CONSTANT(m, GPU_DYNAMIC_MAT_EMIT);
- PY_MODULE_ADD_CONSTANT(m, GPU_DYNAMIC_MAT_AMB);
- PY_MODULE_ADD_CONSTANT(m, GPU_DYNAMIC_MAT_ALPHA);
- PY_MODULE_ADD_CONSTANT(m, GPU_DYNAMIC_MAT_MIR);
-
-
- /* -------------------------------------------------------------------- */
- /* GPUDataType */
-
- PY_MODULE_ADD_CONSTANT(m, GPU_DATA_1I);
- PY_MODULE_ADD_CONSTANT(m, GPU_DATA_1F);
- PY_MODULE_ADD_CONSTANT(m, GPU_DATA_2F);
- PY_MODULE_ADD_CONSTANT(m, GPU_DATA_3F);
- PY_MODULE_ADD_CONSTANT(m, GPU_DATA_4F);
- PY_MODULE_ADD_CONSTANT(m, GPU_DATA_9F);
- PY_MODULE_ADD_CONSTANT(m, GPU_DATA_16F);
- PY_MODULE_ADD_CONSTANT(m, GPU_DATA_4UB);
-
-
- /* -------------------------------------------------------------------- */
- /* CustomDataType
- *
- * Intentionally only include the subset used by the GPU API.
- */
- PY_MODULE_ADD_CONSTANT(m, CD_MTFACE);
- PY_MODULE_ADD_CONSTANT(m, CD_ORCO);
- PY_MODULE_ADD_CONSTANT(m, CD_TANGENT);
- PY_MODULE_ADD_CONSTANT(m, CD_MCOL);
- return m;
-}
-
-#define PY_DICT_ADD_STRING(d, s, f) \
- val = PyUnicode_FromString(s->f); \
- PyDict_SetItemString(d, # f, val); \
- Py_DECREF(val)
-
-#define PY_DICT_ADD_LONG(d, s, f) \
- val = PyLong_FromLong(s->f); \
- PyDict_SetItemString(d, # f, val); \
- Py_DECREF(val)
-
-#define PY_DICT_ADD_ID(d, s, f) \
- RNA_id_pointer_create((struct ID *)s->f, &tptr); \
- val = pyrna_struct_CreatePyObject(&tptr); \
- PyDict_SetItemString(d, # f, val); \
- Py_DECREF(val)
-
-#if 0 /* UNUSED */
-#define PY_OBJ_ADD_ID(d, s, f) \
- val = PyUnicode_FromString(&s->f->id.name[2]); \
- PyObject_SetAttrString(d, # f, val); \
- Py_DECREF(val)
-
-#define PY_OBJ_ADD_LONG(d, s, f) \
- val = PyLong_FromLong(s->f); \
- PyObject_SetAttrString(d, # f, val); \
- Py_DECREF(val)
-
-#define PY_OBJ_ADD_STRING(d, s, f) \
- val = PyUnicode_FromString(s->f); \
- PyObject_SetAttrString(d, # f, val); \
- Py_DECREF(val)
-#endif
-
-PyDoc_STRVAR(GPU_export_shader_doc,
-"export_shader(scene, material)\n"
-"\n"
-" Returns the GLSL shader that produces the visual effect of material in scene.\n"
-"\n"
-" :return: Dictionary defining the shader, uniforms and attributes.\n"
-" :rtype: Dict"
-);
-static PyObject *GPU_export_shader(PyObject *UNUSED(self), PyObject *args, PyObject *kw)
-{
- PyObject *pyscene;
- PyObject *pymat;
- PyObject *result;
- PyObject *dict;
- PyObject *val;
- PyObject *seq;
-
- int i;
- Scene *scene;
- PointerRNA tptr;
- Material *material;
- GPUShaderExport *shader;
- GPUInputUniform *uniform;
- GPUInputAttribute *attribute;
-
- static const char *_keywords[] = {"scene", "material", NULL};
- static _PyArg_Parser _parser = {"OO:export_shader", _keywords, 0};
- if (!_PyArg_ParseTupleAndKeywordsFast(
- args, kw, &_parser,
- &pyscene, &pymat))
- {
- return NULL;
- }
- scene = (Scene *)PyC_RNA_AsPointer(pyscene, "Scene");
- if (scene == NULL) {
- return NULL;
- }
-
- material = (Material *)PyC_RNA_AsPointer(pymat, "Material");
- if (material == NULL) {
- return NULL;
- }
-
- /* we can call our internal function at last: */
- shader = GPU_shader_export(scene, material);
- if (!shader) {
- PyErr_SetString(PyExc_RuntimeError, "cannot export shader");
- return NULL;
- }
- /* build a dictionary */
- result = PyDict_New();
- if (shader->fragment) {
- PY_DICT_ADD_STRING(result, shader, fragment);
- }
- if (shader->vertex) {
- PY_DICT_ADD_STRING(result, shader, vertex);
- }
- seq = PyList_New(BLI_listbase_count(&shader->uniforms));
- for (i = 0, uniform = shader->uniforms.first; uniform; uniform = uniform->next, i++) {
- dict = PyDict_New();
- PY_DICT_ADD_STRING(dict, uniform, varname);
- PY_DICT_ADD_LONG(dict, uniform, datatype);
- PY_DICT_ADD_LONG(dict, uniform, type);
- if (uniform->lamp) {
- PY_DICT_ADD_ID(dict, uniform, lamp);
- }
- if (uniform->material) {
- PY_DICT_ADD_ID(dict, uniform, material);
- }
- if (uniform->image) {
- PY_DICT_ADD_ID(dict, uniform, image);
- }
- if (uniform->type == GPU_DYNAMIC_SAMPLER_2DBUFFER ||
- uniform->type == GPU_DYNAMIC_SAMPLER_2DIMAGE ||
- uniform->type == GPU_DYNAMIC_SAMPLER_2DSHADOW)
- {
- PY_DICT_ADD_LONG(dict, uniform, texnumber);
- }
- if (uniform->texpixels) {
- val = PyByteArray_FromStringAndSize((const char *)uniform->texpixels, uniform->texsize * 4);
- PyDict_SetItemString(dict, "texpixels", val);
- Py_DECREF(val);
- PY_DICT_ADD_LONG(dict, uniform, texsize);
- }
- PyList_SET_ITEM(seq, i, dict);
- }
- PyDict_SetItemString(result, "uniforms", seq);
- Py_DECREF(seq);
-
- seq = PyList_New(BLI_listbase_count(&shader->attributes));
- for (i = 0, attribute = shader->attributes.first; attribute; attribute = attribute->next, i++) {
- dict = PyDict_New();
- PY_DICT_ADD_STRING(dict, attribute, varname);
- PY_DICT_ADD_LONG(dict, attribute, datatype);
- PY_DICT_ADD_LONG(dict, attribute, type);
- PY_DICT_ADD_LONG(dict, attribute, number);
- if (attribute->name) {
- if (attribute->name[0] != 0) {
- PY_DICT_ADD_STRING(dict, attribute, name);
- }
- else {
- val = PyLong_FromLong(0);
- PyDict_SetItemString(dict, "name", val);
- Py_DECREF(val);
- }
- }
- PyList_SET_ITEM(seq, i, dict);
- }
- PyDict_SetItemString(result, "attributes", seq);
- Py_DECREF(seq);
-
- GPU_free_shader_export(shader);
-
- return result;
-}
-
-static PyMethodDef meth_export_shader[] = {
- {"export_shader", (PyCFunction)GPU_export_shader, METH_VARARGS | METH_KEYWORDS, GPU_export_shader_doc}
-};
-
-/* -------------------------------------------------------------------- */
-/* Initialize Module */
-
-PyObject *GPU_initPython(void)
-{
- PyObject *module;
- PyObject *submodule;
- PyObject *sys_modules = PyImport_GetModuleDict();
-
- module = PyInit_gpu();
-
- PyModule_AddObject(module, "export_shader", (PyObject *)PyCFunction_New(meth_export_shader, NULL));
-
- /* gpu.offscreen */
- PyModule_AddObject(module, "offscreen", (submodule = BPyInit_gpu_offscreen()));
- PyDict_SetItem(sys_modules, PyModule_GetNameObject(submodule), submodule);
- Py_INCREF(submodule);
-
- PyDict_SetItem(sys_modules, PyModule_GetNameObject(module), module);
- return module;
-}
diff --git a/source/blender/python/intern/gpu_offscreen.c b/source/blender/python/intern/gpu_offscreen.c
deleted file mode 100644
index 3b9b3c70ead..00000000000
--- a/source/blender/python/intern/gpu_offscreen.c
+++ /dev/null
@@ -1,408 +0,0 @@
-/*
- * ***** BEGIN GPL LICENSE BLOCK *****
- *
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU General Public License
- * as published by the Free Software Foundation; either version 2
- * of the License, or (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
- *
- * Copyright 2015, Blender Foundation.
- *
- * ***** END GPL LICENSE BLOCK *****
- */
-
-/** \file blender/python/intern/gpu_offscreen.c
- * \ingroup pythonintern
- *
- * This file defines the offscreen functionalities of the 'gpu' module
- * used for off-screen OpenGL rendering.
- */
-
-#include <Python.h>
-
-#include "MEM_guardedalloc.h"
-
-#include "BLI_utildefines.h"
-
-#include "WM_types.h"
-
-#include "BKE_global.h"
-#include "BKE_library.h"
-
-#include "ED_screen.h"
-
-#include "GPU_compositing.h"
-#include "GPU_framebuffer.h"
-
-#include "../mathutils/mathutils.h"
-
-#include "../generic/py_capi_utils.h"
-
-#include "gpu.h"
-
-#include "ED_view3d.h"
-
-/* -------------------------------------------------------------------- */
-/* GPU Offscreen PyObject */
-
-typedef struct {
- PyObject_HEAD
- GPUOffScreen *ofs;
-} BPy_GPUOffScreen;
-
-static int bpy_gpu_offscreen_valid_check(BPy_GPUOffScreen *py_gpu_ofs)
-{
- if (UNLIKELY(py_gpu_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(pygpu) { \
- if (UNLIKELY(bpy_gpu_offscreen_valid_check(pygpu) == -1)) { \
- return NULL; \
- } \
-} ((void)0)
-
-PyDoc_STRVAR(pygpu_offscreen_width_doc, "Texture width.\n\n:type: int");
-static PyObject *pygpu_offscreen_width_get(BPy_GPUOffScreen *self, void *UNUSED(type))
-{
- BPY_GPU_OFFSCREEN_CHECK_OBJ(self);
- return PyLong_FromLong(GPU_offscreen_width(self->ofs));
-}
-
-PyDoc_STRVAR(pygpu_offscreen_height_doc, "Texture height.\n\n:type: int");
-static PyObject *pygpu_offscreen_height_get(BPy_GPUOffScreen *self, void *UNUSED(type))
-{
- BPY_GPU_OFFSCREEN_CHECK_OBJ(self);
- return PyLong_FromLong(GPU_offscreen_height(self->ofs));
-}
-
-PyDoc_STRVAR(pygpu_offscreen_color_texture_doc, "Color texture.\n\n:type: int");
-static PyObject *pygpu_offscreen_color_texture_get(BPy_GPUOffScreen *self, void *UNUSED(type))
-{
- BPY_GPU_OFFSCREEN_CHECK_OBJ(self);
- return PyLong_FromLong(GPU_offscreen_color_texture(self->ofs));
-}
-
-PyDoc_STRVAR(pygpu_offscreen_bind_doc,
-"bind(save=True)\n"
-"\n"
-" Bind the offscreen object.\n"
-"\n"
-" :param save: save OpenGL current states.\n"
-" :type save: bool\n"
-);
-static PyObject *pygpu_offscreen_bind(BPy_GPUOffScreen *self, PyObject *args, PyObject *kwds)
-{
- static const char *kwlist[] = {"save", NULL};
- bool save = true;
-
- BPY_GPU_OFFSCREEN_CHECK_OBJ(self);
-
- if (!PyArg_ParseTupleAndKeywords(
- args, kwds, "|O&:bind", (char **)(kwlist),
- PyC_ParseBool, &save))
- {
- return NULL;
- }
-
- GPU_offscreen_bind(self->ofs, save);
- Py_RETURN_NONE;
-}
-
-PyDoc_STRVAR(pygpu_offscreen_unbind_doc,
-"unbind(restore=True)\n"
-"\n"
-" Unbind the offscreen object.\n"
-"\n"
-" :param restore: restore OpenGL previous states.\n"
-" :type restore: bool\n"
-);
-static PyObject *pygpu_offscreen_unbind(BPy_GPUOffScreen *self, PyObject *args, PyObject *kwds)
-{
- static const char *kwlist[] = {"restore", NULL};
- bool restore = true;
-
- BPY_GPU_OFFSCREEN_CHECK_OBJ(self);
-
- if (!PyArg_ParseTupleAndKeywords(
- args, kwds, "|O&:unbind", (char **)(kwlist),
- PyC_ParseBool, &restore))
- {
- return NULL;
- }
-
- GPU_offscreen_unbind(self->ofs, restore);
- Py_RETURN_NONE;
-}
-
-PyDoc_STRVAR(pygpu_offscreen_draw_view3d_doc,
-"draw_view3d(scene, view3d, region, modelview_matrix, projection_matrix)\n"
-"\n"
-" Draw the 3d viewport in the offscreen object.\n"
-"\n"
-" :param scene: Scene to draw.\n"
-" :type scene: :class:`bpy.types.Scene`\n"
-" :param view3d: 3D View to get the drawing settings from.\n"
-" :type view3d: :class:`bpy.types.SpaceView3D`\n"
-" :param region: Region of the 3D View.\n"
-" :type region: :class:`bpy.types.Region`\n"
-" :param modelview_matrix: ModelView Matrix.\n"
-" :type modelview_matrix: :class:`mathutils.Matrix`\n"
-" :param projection_matrix: Projection Matrix.\n"
-" :type projection_matrix: :class:`mathutils.Matrix`\n"
-);
-static PyObject *pygpu_offscreen_draw_view3d(BPy_GPUOffScreen *self, PyObject *args, PyObject *kwds)
-{
- static const char *kwlist[] = {"scene", "view3d", "region", "projection_matrix", "modelview_matrix", NULL};
-
- MatrixObject *py_mat_modelview, *py_mat_projection;
- PyObject *py_scene, *py_region, *py_view3d;
-
- struct Main *bmain = G_MAIN; /* XXX UGLY! */
- Scene *scene;
- View3D *v3d;
- ARegion *ar;
- GPUFX *fx;
- GPUFXSettings fx_settings;
- struct RV3DMatrixStore *rv3d_mats;
-
- BPY_GPU_OFFSCREEN_CHECK_OBJ(self);
-
- if (!PyArg_ParseTupleAndKeywords(
- args, kwds, "OOOO&O&:draw_view3d", (char **)(kwlist),
- &py_scene, &py_view3d, &py_region,
- Matrix_Parse4x4, &py_mat_projection,
- Matrix_Parse4x4, &py_mat_modelview) ||
- (!(scene = PyC_RNA_AsPointer(py_scene, "Scene")) ||
- !(v3d = PyC_RNA_AsPointer(py_view3d, "SpaceView3D")) ||
- !(ar = PyC_RNA_AsPointer(py_region, "Region"))))
- {
- return NULL;
- }
-
- BLI_assert(BKE_id_is_in_gobal_main(&scene->id));
-
- fx = GPU_fx_compositor_create();
-
- fx_settings = v3d->fx_settings; /* full copy */
-
- ED_view3d_draw_offscreen_init(bmain, scene, v3d);
-
- rv3d_mats = ED_view3d_mats_rv3d_backup(ar->regiondata);
-
- GPU_offscreen_bind(self->ofs, true); /* bind */
-
- ED_view3d_draw_offscreen(
- bmain, scene, v3d, ar, GPU_offscreen_width(self->ofs), GPU_offscreen_height(self->ofs),
- (float(*)[4])py_mat_modelview->matrix, (float(*)[4])py_mat_projection->matrix,
- false, true, true, "",
- fx, &fx_settings,
- self->ofs);
-
- GPU_fx_compositor_destroy(fx);
- GPU_offscreen_unbind(self->ofs, true); /* unbind */
-
- ED_view3d_mats_rv3d_restore(ar->regiondata, rv3d_mats);
- MEM_freeN(rv3d_mats);
-
- Py_RETURN_NONE;
-}
-
-PyDoc_STRVAR(pygpu_offscreen_free_doc,
-"free()\n"
-"\n"
-" Free the offscreen object\n"
-" The framebuffer, texture and render objects will no longer be accessible.\n"
-);
-static PyObject *pygpu_offscreen_free(BPy_GPUOffScreen *self)
-{
- BPY_GPU_OFFSCREEN_CHECK_OBJ(self);
-
- GPU_offscreen_free(self->ofs);
- self->ofs = NULL;
- Py_RETURN_NONE;
-}
-
-static void BPy_GPUOffScreen__tp_dealloc(BPy_GPUOffScreen *self)
-{
- if (self->ofs)
- GPU_offscreen_free(self->ofs);
- Py_TYPE(self)->tp_free((PyObject *)self);
-}
-
-static PyGetSetDef bpy_gpu_offscreen_getseters[] = {
- {(char *)"color_texture", (getter)pygpu_offscreen_color_texture_get, (setter)NULL, pygpu_offscreen_color_texture_doc, NULL},
- {(char *)"width", (getter)pygpu_offscreen_width_get, (setter)NULL, pygpu_offscreen_width_doc, NULL},
- {(char *)"height", (getter)pygpu_offscreen_height_get, (setter)NULL, pygpu_offscreen_height_doc, NULL},
- {NULL, NULL, NULL, NULL, NULL} /* Sentinel */
-};
-
-static struct PyMethodDef bpy_gpu_offscreen_methods[] = {
- {"bind", (PyCFunction)pygpu_offscreen_bind, METH_VARARGS | METH_KEYWORDS, pygpu_offscreen_bind_doc},
- {"unbind", (PyCFunction)pygpu_offscreen_unbind, METH_VARARGS | METH_KEYWORDS, pygpu_offscreen_unbind_doc},
- {"draw_view3d", (PyCFunction)pygpu_offscreen_draw_view3d, METH_VARARGS | METH_KEYWORDS, pygpu_offscreen_draw_view3d_doc},
- {"free", (PyCFunction)pygpu_offscreen_free, METH_NOARGS, pygpu_offscreen_free_doc},
- {NULL, NULL, 0, NULL}
-};
-
-PyDoc_STRVAR(py_gpu_offscreen_doc,
-".. class:: GPUOffscreen"
-"\n"
-" This object gives access to off screen buffers.\n"
-);
-static PyTypeObject BPy_GPUOffScreen_Type = {
- PyVarObject_HEAD_INIT(NULL, 0)
- "GPUOffScreen", /* tp_name */
- sizeof(BPy_GPUOffScreen), /* tp_basicsize */
- 0, /* tp_itemsize */
- /* methods */
- (destructor)BPy_GPUOffScreen__tp_dealloc, /* tp_dealloc */
- NULL, /* tp_print */
- NULL, /* tp_getattr */
- NULL, /* tp_setattr */
- NULL, /* tp_compare */
- NULL, /* tp_repr */
- NULL, /* tp_as_number */
- NULL, /* tp_as_sequence */
- NULL, /* tp_as_mapping */
- NULL, /* tp_hash */
- NULL, /* tp_call */
- NULL, /* tp_str */
- NULL, /* tp_getattro */
- NULL, /* tp_setattro */
- NULL, /* tp_as_buffer */
- Py_TPFLAGS_DEFAULT, /* tp_flags */
- py_gpu_offscreen_doc, /* Documentation string */
- NULL, /* tp_traverse */
- NULL, /* tp_clear */
- NULL, /* tp_richcompare */
- 0, /* tp_weaklistoffset */
- NULL, /* tp_iter */
- NULL, /* tp_iternext */
- bpy_gpu_offscreen_methods, /* tp_methods */
- NULL, /* tp_members */
- bpy_gpu_offscreen_getseters, /* tp_getset */
- NULL, /* tp_base */
- NULL, /* tp_dict */
- NULL, /* tp_descr_get */
- NULL, /* tp_descr_set */
- 0, /* tp_dictoffset */
- 0, /* tp_init */
- NULL, /* tp_alloc */
- NULL, /* tp_new */
- (freefunc)0, /* tp_free */
- NULL, /* tp_is_gc */
- NULL, /* tp_bases */
- NULL, /* tp_mro */
- NULL, /* tp_cache */
- NULL, /* tp_subclasses */
- NULL, /* tp_weaklist */
- (destructor) NULL /* tp_del */
-};
-
-/* -------------------------------------------------------------------- */
-/* GPU offscreen methods */
-
-static PyObject *BPy_GPU_OffScreen_CreatePyObject(GPUOffScreen *ofs)
-{
- BPy_GPUOffScreen *self;
- self = PyObject_New(BPy_GPUOffScreen, &BPy_GPUOffScreen_Type);
- self->ofs = ofs;
- return (PyObject *)self;
-}
-
-PyDoc_STRVAR(pygpu_offscreen_new_doc,
-"new(width, height, samples=0)\n"
-"\n"
-" Return a GPUOffScreen.\n"
-"\n"
-" :param width: Horizontal dimension of the buffer.\n"
-" :type width: int`\n"
-" :param height: Vertical dimension of the buffer.\n"
-" :type height: int`\n"
-" :param samples: OpenGL samples to use for MSAA or zero to disable.\n"
-" :type samples: int\n"
-" :return: Newly created off-screen buffer.\n"
-" :rtype: :class:`gpu.GPUOffscreen`\n"
-);
-static PyObject *pygpu_offscreen_new(PyObject *UNUSED(self), PyObject *args, PyObject *kwds)
-{
- static const char *kwlist[] = {"width", "height", "samples", NULL};
-
- GPUOffScreen *ofs;
- int width, height, samples = 0;
- char err_out[256];
-
- if (!PyArg_ParseTupleAndKeywords(
- args, kwds, "ii|i:new", (char **)(kwlist),
- &width, &height, &samples))
- {
- return NULL;
- }
-
- ofs = GPU_offscreen_create(width, height, samples, err_out);
-
- if (ofs == NULL) {
- PyErr_Format(PyExc_RuntimeError,
- "gpu.offscreen.new(...) failed with '%s'",
- err_out[0] ? err_out : "unknown error");
- return NULL;
- }
-
- return BPy_GPU_OffScreen_CreatePyObject(ofs);
-}
-
-static struct PyMethodDef BPy_GPU_offscreen_methods[] = {
- {"new", (PyCFunction)pygpu_offscreen_new, METH_VARARGS | METH_KEYWORDS, pygpu_offscreen_new_doc},
- {NULL, NULL, 0, NULL}
-};
-
-PyDoc_STRVAR(BPy_GPU_offscreen_doc,
-"This module provides access to offscreen rendering functions."
-);
-static PyModuleDef BPy_GPU_offscreen_module_def = {
- PyModuleDef_HEAD_INIT,
- "gpu.offscreen", /* m_name */
- BPy_GPU_offscreen_doc, /* m_doc */
- 0, /* m_size */
- BPy_GPU_offscreen_methods, /* m_methods */
- NULL, /* m_reload */
- NULL, /* m_traverse */
- NULL, /* m_clear */
- NULL, /* m_free */
-};
-
-PyObject *BPyInit_gpu_offscreen(void)
-{
- PyObject *submodule;
-
- /* Register the 'GPUOffscreen' class */
- if (PyType_Ready(&BPy_GPUOffScreen_Type)) {
- return NULL;
- }
-
- submodule = PyModule_Create(&BPy_GPU_offscreen_module_def);
-
-#define MODULE_TYPE_ADD(s, t) \
- PyModule_AddObject(s, t.tp_name, (PyObject *)&t); Py_INCREF((PyObject *)&t)
-
- MODULE_TYPE_ADD(submodule, BPy_GPUOffScreen_Type);
-
-#undef MODULE_TYPE_ADD
-
- return submodule;
-}
-
-#undef BPY_GPU_OFFSCREEN_CHECK_OBJ
diff --git a/source/blender/python/mathutils/CMakeLists.txt b/source/blender/python/mathutils/CMakeLists.txt
index adf7c85d7c9..811cc1acbab 100644
--- a/source/blender/python/mathutils/CMakeLists.txt
+++ b/source/blender/python/mathutils/CMakeLists.txt
@@ -23,6 +23,7 @@ set(INC
../../blenlib
../../blenkernel
../../bmesh
+ ../../depsgraph
../../makesdna
../../../../intern/guardedalloc
)
diff --git a/source/blender/python/mathutils/mathutils.c b/source/blender/python/mathutils/mathutils.c
index 566bac9cb09..07905d2be89 100644
--- a/source/blender/python/mathutils/mathutils.c
+++ b/source/blender/python/mathutils/mathutils.c
@@ -645,30 +645,25 @@ PyMODINIT_FUNC PyInit_mathutils(void)
* 'from mathutils.geometry import PolyFill'
* ...fails without this. */
PyDict_SetItem(sys_modules, PyModule_GetNameObject(submodule), submodule);
- Py_INCREF(submodule);
PyModule_AddObject(mod, "interpolate", (submodule = PyInit_mathutils_interpolate()));
/* XXX, python doesnt do imports with this usefully yet
* 'from mathutils.geometry import PolyFill'
* ...fails without this. */
PyDict_SetItem(sys_modules, PyModule_GetNameObject(submodule), submodule);
- Py_INCREF(submodule);
#ifndef MATH_STANDALONE
/* Noise submodule */
PyModule_AddObject(mod, "noise", (submodule = PyInit_mathutils_noise()));
PyDict_SetItem(sys_modules, PyModule_GetNameObject(submodule), submodule);
- Py_INCREF(submodule);
/* BVHTree submodule */
PyModule_AddObject(mod, "bvhtree", (submodule = PyInit_mathutils_bvhtree()));
PyDict_SetItem(sys_modules, PyModule_GetNameObject(submodule), submodule);
- Py_INCREF(submodule);
/* KDTree submodule */
PyModule_AddObject(mod, "kdtree", (submodule = PyInit_mathutils_kdtree()));
PyDict_SetItem(sys_modules, PyModule_GetNameObject(submodule), submodule);
- Py_INCREF(submodule);
#endif
mathutils_matrix_row_cb_index = Mathutils_RegisterCallback(&mathutils_matrix_row_cb);
diff --git a/source/blender/python/mathutils/mathutils.h b/source/blender/python/mathutils/mathutils.h
index 286dd9f0750..ab78009ff89 100644
--- a/source/blender/python/mathutils/mathutils.h
+++ b/source/blender/python/mathutils/mathutils.h
@@ -62,7 +62,7 @@ enum {
float *_data; /* array of data (alias), wrapped status depends on wrapped status */ \
PyObject *cb_user; /* if this vector references another object, otherwise NULL, \
* *Note* this owns its reference */ \
- unsigned char cb_type; /* which user funcs do we adhere to, RNA, GameObject, etc */ \
+ unsigned char cb_type; /* which user funcs do we adhere to, RNA, etc */ \
unsigned char cb_subtype; /* subtype: location, rotation... \
* to avoid defining many new functions for every attribute of the same type */ \
unsigned char flag /* wrapped data type? */ \
diff --git a/source/blender/python/mathutils/mathutils_Matrix.c b/source/blender/python/mathutils/mathutils_Matrix.c
index d4f9e5e80e2..c033a990901 100644
--- a/source/blender/python/mathutils/mathutils_Matrix.c
+++ b/source/blender/python/mathutils/mathutils_Matrix.c
@@ -2321,7 +2321,7 @@ static PyObject *Matrix_sub(PyObject *m1, PyObject *m2)
return Matrix_CreatePyObject(mat, mat1->num_col, mat1->num_row, Py_TYPE(mat1));
}
/*------------------------obj * obj------------------------------
- * multiplication */
+ * element-wise multiplication */
static PyObject *matrix_mul_float(MatrixObject *mat, const float scalar)
{
float tmat[MATRIX_MAX_DIM * MATRIX_MAX_DIM];
@@ -2332,7 +2332,6 @@ static PyObject *matrix_mul_float(MatrixObject *mat, const float scalar)
static PyObject *Matrix_mul(PyObject *m1, PyObject *m2)
{
float scalar;
- int vec_size;
MatrixObject *mat1 = NULL, *mat2 = NULL;
@@ -2348,9 +2347,118 @@ static PyObject *Matrix_mul(PyObject *m1, PyObject *m2)
}
if (mat1 && mat2) {
+#ifdef USE_MATHUTILS_ELEM_MUL
/* MATRIX * MATRIX */
float mat[MATRIX_MAX_DIM * MATRIX_MAX_DIM];
+ if ((mat1->num_row != mat2->num_row) || (mat1->num_col != mat2->num_col)) {
+ PyErr_SetString(PyExc_ValueError,
+ "matrix1 * matrix2: matrix1 number of rows/columns "
+ "and the matrix2 number of rows/columns must be the same");
+ return NULL;
+ }
+
+ mul_vn_vnvn(mat, mat1->matrix, mat2->matrix, mat1->num_col * mat1->num_row);
+
+ return Matrix_CreatePyObject(mat, mat2->num_col, mat1->num_row, Py_TYPE(mat1));
+#endif
+ }
+ else if (mat2) {
+ /*FLOAT/INT * MATRIX */
+ if (((scalar = PyFloat_AsDouble(m1)) == -1.0f && PyErr_Occurred()) == 0) {
+ return matrix_mul_float(mat2, scalar);
+ }
+ }
+ else if (mat1) {
+ /* MATRIX * FLOAT/INT */
+ if (((scalar = PyFloat_AsDouble(m2)) == -1.0f && PyErr_Occurred()) == 0) {
+ return matrix_mul_float(mat1, scalar);
+ }
+ }
+
+ PyErr_Format(PyExc_TypeError,
+ "Element-wise multiplication: "
+ "not supported between '%.200s' and '%.200s' types",
+ Py_TYPE(m1)->tp_name, Py_TYPE(m2)->tp_name);
+ return NULL;
+}
+/*------------------------obj *= obj------------------------------
+ * Inplace element-wise multiplication */
+static PyObject *Matrix_imul(PyObject *m1, PyObject *m2)
+{
+ float scalar;
+
+ MatrixObject *mat1 = NULL, *mat2 = NULL;
+
+ if (MatrixObject_Check(m1)) {
+ mat1 = (MatrixObject *)m1;
+ if (BaseMath_ReadCallback(mat1) == -1)
+ return NULL;
+ }
+ if (MatrixObject_Check(m2)) {
+ mat2 = (MatrixObject *)m2;
+ if (BaseMath_ReadCallback(mat2) == -1)
+ return NULL;
+ }
+
+ if (mat1 && mat2) {
+#ifdef USE_MATHUTILS_ELEM_MUL
+ /* MATRIX *= MATRIX */
+ if ((mat1->num_row != mat2->num_row) || (mat1->num_col != mat2->num_col)) {
+ PyErr_SetString(PyExc_ValueError,
+ "matrix1 *= matrix2: matrix1 number of rows/columns "
+ "and the matrix2 number of rows/columns must be the same");
+ return NULL;
+ }
+
+ mul_vn_vn(mat1->matrix, mat2->matrix, mat1->num_col * mat1->num_row);
+#else
+ PyErr_Format(PyExc_TypeError,
+ "Inplace element-wise multiplication: "
+ "not supported between '%.200s' and '%.200s' types",
+ Py_TYPE(m1)->tp_name, Py_TYPE(m2)->tp_name);
+ return NULL;
+#endif
+ }
+ else if (mat1 && (((scalar = PyFloat_AsDouble(m2)) == -1.0f && PyErr_Occurred()) == 0)) {
+ /* MATRIX *= FLOAT/INT */
+ mul_vn_fl(mat1->matrix, mat1->num_row * mat1->num_col, scalar);
+ }
+ else {
+ PyErr_Format(PyExc_TypeError,
+ "Inplace element-wise multiplication: "
+ "not supported between '%.200s' and '%.200s' types",
+ Py_TYPE(m1)->tp_name, Py_TYPE(m2)->tp_name);
+ return NULL;
+ }
+
+ (void)BaseMath_WriteCallback(mat1);
+ Py_INCREF(m1);
+ return m1;
+}
+/*------------------------obj @ obj------------------------------
+ * matrix multiplication */
+static PyObject *Matrix_matmul(PyObject *m1, PyObject *m2)
+{
+ int vec_size;
+
+ MatrixObject *mat1 = NULL, *mat2 = NULL;
+
+ if (MatrixObject_Check(m1)) {
+ mat1 = (MatrixObject *)m1;
+ if (BaseMath_ReadCallback(mat1) == -1)
+ return NULL;
+ }
+ if (MatrixObject_Check(m2)) {
+ mat2 = (MatrixObject *)m2;
+ if (BaseMath_ReadCallback(mat2) == -1)
+ return NULL;
+ }
+
+ if (mat1 && mat2) {
+ /* MATRIX @ MATRIX */
+ float mat[MATRIX_MAX_DIM * MATRIX_MAX_DIM];
+
int col, row, item;
if (mat1->num_col != mat2->num_row) {
@@ -2372,14 +2480,8 @@ static PyObject *Matrix_mul(PyObject *m1, PyObject *m2)
return Matrix_CreatePyObject(mat, mat2->num_col, mat1->num_row, Py_TYPE(mat1));
}
- else if (mat2) {
- /*FLOAT/INT * MATRIX */
- if (((scalar = PyFloat_AsDouble(m1)) == -1.0f && PyErr_Occurred()) == 0) {
- return matrix_mul_float(mat2, scalar);
- }
- }
else if (mat1) {
- /* MATRIX * VECTOR */
+ /* MATRIX @ VECTOR */
if (VectorObject_Check(m2)) {
VectorObject *vec2 = (VectorObject *)m2;
float tvec[MATRIX_MAX_DIM];
@@ -2398,13 +2500,6 @@ static PyObject *Matrix_mul(PyObject *m1, PyObject *m2)
return Vector_CreatePyObject(tvec, vec_size, Py_TYPE(m2));
}
- /*FLOAT/INT * MATRIX */
- else if (((scalar = PyFloat_AsDouble(m2)) == -1.0f && PyErr_Occurred()) == 0) {
- return matrix_mul_float(mat1, scalar);
- }
- }
- else {
- BLI_assert(!"internal error");
}
PyErr_Format(PyExc_TypeError,
@@ -2413,6 +2508,62 @@ static PyObject *Matrix_mul(PyObject *m1, PyObject *m2)
Py_TYPE(m1)->tp_name, Py_TYPE(m2)->tp_name);
return NULL;
}
+/*------------------------obj @= obj------------------------------
+ * inplace matrix multiplication */
+static PyObject *Matrix_imatmul(PyObject *m1, PyObject *m2)
+{
+ MatrixObject *mat1 = NULL, *mat2 = NULL;
+
+ if (MatrixObject_Check(m1)) {
+ mat1 = (MatrixObject *)m1;
+ if (BaseMath_ReadCallback(mat1) == -1)
+ return NULL;
+ }
+ if (MatrixObject_Check(m2)) {
+ mat2 = (MatrixObject *)m2;
+ if (BaseMath_ReadCallback(mat2) == -1)
+ return NULL;
+ }
+
+ if (mat1 && mat2) {
+ /* MATRIX @= MATRIX */
+ float mat[MATRIX_MAX_DIM * MATRIX_MAX_DIM];
+ int col, row, item;
+
+ if (mat1->num_col != mat2->num_row) {
+ PyErr_SetString(PyExc_ValueError,
+ "matrix1 * matrix2: matrix1 number of columns "
+ "and the matrix2 number of rows must be the same");
+ return NULL;
+ }
+
+ for (col = 0; col < mat2->num_col; col++) {
+ for (row = 0; row < mat1->num_row; row++) {
+ double dot = 0.0f;
+ for (item = 0; item < mat1->num_col; item++) {
+ dot += (double)(MATRIX_ITEM(mat1, row, item) * MATRIX_ITEM(mat2, item, col));
+ }
+ /* store in new matrix as overwriting original at this point will cause
+ * subsequent iterations to use incorrect values */
+ mat[(col * mat1->num_row) + row] = (float)dot;
+ }
+ }
+
+ /* copy matrix back */
+ memcpy(mat1->matrix, mat, (mat1->num_row * mat1->num_col) * sizeof(float));
+ }
+ else {
+ PyErr_Format(PyExc_TypeError,
+ "Inplace matrix multiplication: "
+ "not supported between '%.200s' and '%.200s' types",
+ Py_TYPE(m1)->tp_name, Py_TYPE(m2)->tp_name);
+ return NULL;
+ }
+
+ (void)BaseMath_WriteCallback(mat1);
+ Py_INCREF(m1);
+ return m1;
+}
/*-----------------PROTOCOL DECLARATIONS--------------------------*/
static PySequenceMethods Matrix_SeqMethods = {
@@ -2527,7 +2678,7 @@ static PyNumberMethods Matrix_NumMethods = {
NULL, /*nb_float*/
NULL, /* nb_inplace_add */
NULL, /* nb_inplace_subtract */
- NULL, /* nb_inplace_multiply */
+ (binaryfunc) Matrix_imul, /* nb_inplace_multiply */
NULL, /* nb_inplace_remainder */
NULL, /* nb_inplace_power */
NULL, /* nb_inplace_lshift */
@@ -2540,6 +2691,8 @@ static PyNumberMethods Matrix_NumMethods = {
NULL, /* nb_inplace_floor_divide */
NULL, /* nb_inplace_true_divide */
NULL, /* nb_index */
+ (binaryfunc) Matrix_matmul, /* nb_matrix_multiply */
+ (binaryfunc) Matrix_imatmul, /* nb_inplace_matrix_multiply */
};
PyDoc_STRVAR(Matrix_translation_doc,
diff --git a/source/blender/python/mathutils/mathutils_Quaternion.c b/source/blender/python/mathutils/mathutils_Quaternion.c
index 645fa96c22e..a2b4480584a 100644
--- a/source/blender/python/mathutils/mathutils_Quaternion.c
+++ b/source/blender/python/mathutils/mathutils_Quaternion.c
@@ -834,7 +834,7 @@ static PyObject *quat_mul_float(QuaternionObject *quat, const float scalar)
* multiplication */
static PyObject *Quaternion_mul(PyObject *q1, PyObject *q2)
{
- float quat[QUAT_SIZE], scalar;
+ float scalar;
QuaternionObject *quat1 = NULL, *quat2 = NULL;
if (QuaternionObject_Check(q1)) {
@@ -848,9 +848,12 @@ static PyObject *Quaternion_mul(PyObject *q1, PyObject *q2)
return NULL;
}
- if (quat1 && quat2) { /* QUAT * QUAT (cross product) */
- mul_qt_qtqt(quat, quat1->quat, quat2->quat);
+ if (quat1 && quat2) { /* QUAT * QUAT (element-wise product) */
+#ifdef USE_MATHUTILS_ELEM_MUL
+ float quat[QUAT_SIZE];
+ mul_vn_vnvn(quat, quat1->quat, quat2->quat, QUAT_SIZE);
return Quaternion_CreatePyObject(quat, Py_TYPE(q1));
+#endif
}
/* the only case this can happen (for a supported type is "FLOAT * QUAT") */
else if (quat2) { /* FLOAT * QUAT */
@@ -858,8 +861,87 @@ static PyObject *Quaternion_mul(PyObject *q1, PyObject *q2)
return quat_mul_float(quat2, scalar);
}
}
+ else if (quat1) { /* QUAT * FLOAT */
+ if ((((scalar = PyFloat_AsDouble(q2)) == -1.0f && PyErr_Occurred()) == 0)) {
+ return quat_mul_float(quat1, scalar);
+ }
+ }
+
+ PyErr_Format(PyExc_TypeError,
+ "Element-wise multiplication: "
+ "not supported between '%.200s' and '%.200s' types",
+ Py_TYPE(q1)->tp_name, Py_TYPE(q2)->tp_name);
+ return NULL;
+}
+/*------------------------obj *= obj------------------------------
+ * inplace multiplication */
+static PyObject *Quaternion_imul(PyObject *q1, PyObject *q2)
+{
+ float scalar;
+ QuaternionObject *quat1 = NULL, *quat2 = NULL;
+
+ if (QuaternionObject_Check(q1)) {
+ quat1 = (QuaternionObject *)q1;
+ if (BaseMath_ReadCallback(quat1) == -1)
+ return NULL;
+ }
+ if (QuaternionObject_Check(q2)) {
+ quat2 = (QuaternionObject *)q2;
+ if (BaseMath_ReadCallback(quat2) == -1)
+ return NULL;
+ }
+
+ if (quat1 && quat2) { /* QUAT *= QUAT (inplace element-wise product) */
+#ifdef USE_MATHUTILS_ELEM_MUL
+ mul_vn_vn(quat1->quat, quat2->quat, QUAT_SIZE);
+#else
+ PyErr_Format(PyExc_TypeError,
+ "Inplace element-wise multiplication: "
+ "not supported between '%.200s' and '%.200s' types",
+ Py_TYPE(q1)->tp_name, Py_TYPE(q2)->tp_name);
+ return NULL;
+#endif
+ }
+ else if (quat1 && (((scalar = PyFloat_AsDouble(q2)) == -1.0f && PyErr_Occurred()) == 0)) {
+ /* QUAT *= FLOAT */
+ mul_qt_fl(quat1->quat, scalar);
+ }
+ else {
+ PyErr_Format(PyExc_TypeError,
+ "Element-wise multiplication: "
+ "not supported between '%.200s' and '%.200s' types",
+ Py_TYPE(q1)->tp_name, Py_TYPE(q2)->tp_name);
+ return NULL;
+ }
+
+ (void)BaseMath_WriteCallback(quat1);
+ Py_INCREF(q1);
+ return q1;
+}
+/*------------------------obj @ obj------------------------------
+ * quaternion multiplication */
+static PyObject *Quaternion_matmul(PyObject *q1, PyObject *q2)
+{
+ float quat[QUAT_SIZE];
+ QuaternionObject *quat1 = NULL, *quat2 = NULL;
+
+ if (QuaternionObject_Check(q1)) {
+ quat1 = (QuaternionObject *)q1;
+ if (BaseMath_ReadCallback(quat1) == -1)
+ return NULL;
+ }
+ if (QuaternionObject_Check(q2)) {
+ quat2 = (QuaternionObject *)q2;
+ if (BaseMath_ReadCallback(quat2) == -1)
+ return NULL;
+ }
+
+ if (quat1 && quat2) { /* QUAT @ QUAT (cross product) */
+ mul_qt_qtqt(quat, quat1->quat, quat2->quat);
+ return Quaternion_CreatePyObject(quat, Py_TYPE(q1));
+ }
else if (quat1) {
- /* QUAT * VEC */
+ /* QUAT @ VEC */
if (VectorObject_Check(q2)) {
VectorObject *vec2 = (VectorObject *)q2;
float tvec[3];
@@ -880,13 +962,6 @@ static PyObject *Quaternion_mul(PyObject *q1, PyObject *q2)
return Vector_CreatePyObject(tvec, 3, Py_TYPE(vec2));
}
- /* QUAT * FLOAT */
- else if ((((scalar = PyFloat_AsDouble(q2)) == -1.0f && PyErr_Occurred()) == 0)) {
- return quat_mul_float(quat1, scalar);
- }
- }
- else {
- BLI_assert(!"internal error");
}
PyErr_Format(PyExc_TypeError,
@@ -895,6 +970,40 @@ static PyObject *Quaternion_mul(PyObject *q1, PyObject *q2)
Py_TYPE(q1)->tp_name, Py_TYPE(q2)->tp_name);
return NULL;
}
+/*------------------------obj @= obj------------------------------
+ * inplace quaternion multiplication */
+static PyObject *Quaternion_imatmul(PyObject *q1, PyObject *q2)
+{
+ float quat[QUAT_SIZE];
+ QuaternionObject *quat1 = NULL, *quat2 = NULL;
+
+ if (QuaternionObject_Check(q1)) {
+ quat1 = (QuaternionObject *)q1;
+ if (BaseMath_ReadCallback(quat1) == -1)
+ return NULL;
+ }
+ if (QuaternionObject_Check(q2)) {
+ quat2 = (QuaternionObject *)q2;
+ if (BaseMath_ReadCallback(quat2) == -1)
+ return NULL;
+ }
+
+ if (quat1 && quat2) { /* QUAT @ QUAT (cross product) */
+ mul_qt_qtqt(quat, quat1->quat, quat2->quat);
+ copy_qt_qt(quat1->quat, quat);
+ }
+ else {
+ PyErr_Format(PyExc_TypeError,
+ "Inplace quaternion multiplication: "
+ "not supported between '%.200s' and '%.200s' types",
+ Py_TYPE(q1)->tp_name, Py_TYPE(q2)->tp_name);
+ return NULL;
+ }
+
+ (void)BaseMath_WriteCallback(quat1);
+ Py_INCREF(q1);
+ return q1;
+}
/* -obj
* returns the negative of this object*/
@@ -952,7 +1061,7 @@ static PyNumberMethods Quaternion_NumMethods = {
NULL, /*nb_float*/
NULL, /* nb_inplace_add */
NULL, /* nb_inplace_subtract */
- NULL, /* nb_inplace_multiply */
+ (binaryfunc) Quaternion_imul, /* nb_inplace_multiply */
NULL, /* nb_inplace_remainder */
NULL, /* nb_inplace_power */
NULL, /* nb_inplace_lshift */
@@ -965,6 +1074,8 @@ static PyNumberMethods Quaternion_NumMethods = {
NULL, /* nb_inplace_floor_divide */
NULL, /* nb_inplace_true_divide */
NULL, /* nb_index */
+ (binaryfunc) Quaternion_matmul, /* nb_matrix_multiply */
+ (binaryfunc) Quaternion_imatmul, /* nb_inplace_matrix_multiply */
};
PyDoc_STRVAR(Quaternion_axis_doc,
diff --git a/source/blender/python/mathutils/mathutils_Vector.c b/source/blender/python/mathutils/mathutils_Vector.c
index e7776f836aa..16a242fc718 100644
--- a/source/blender/python/mathutils/mathutils_Vector.c
+++ b/source/blender/python/mathutils/mathutils_Vector.c
@@ -1706,12 +1706,25 @@ static PyObject *vector_mul_float(VectorObject *vec, const float scalar)
mul_vn_vn_fl(tvec, vec->vec, vec->size, scalar);
return Vector_CreatePyObject_alloc(tvec, vec->size, Py_TYPE(vec));
}
+#ifdef USE_MATHUTILS_ELEM_MUL
+static PyObject *vector_mul_vec(VectorObject *vec1, VectorObject *vec2)
+{
+ float *tvec = PyMem_Malloc(vec1->size * sizeof(float));
+ if (tvec == NULL) {
+ PyErr_SetString(PyExc_MemoryError,
+ "vec * vec: "
+ "problem allocating pointer space");
+ return NULL;
+ }
+ mul_vn_vnvn(tvec, vec1->vec, vec2->vec, vec1->size);
+ return Vector_CreatePyObject_alloc(tvec, vec1->size, Py_TYPE(vec1));
+}
+#endif
static PyObject *Vector_mul(PyObject *v1, PyObject *v2)
{
VectorObject *vec1 = NULL, *vec2 = NULL;
float scalar;
- int vec_size;
if (VectorObject_Check(v1)) {
vec1 = (VectorObject *)v1;
@@ -1729,6 +1742,7 @@ static PyObject *Vector_mul(PyObject *v1, PyObject *v2)
/* make sure v1 is always the vector */
if (vec1 && vec2) {
+#ifdef USE_MATHUTILS_ELEM_MUL
if (vec1->size != vec2->size) {
PyErr_SetString(PyExc_ValueError,
"Vector multiplication: "
@@ -1736,30 +1750,12 @@ static PyObject *Vector_mul(PyObject *v1, PyObject *v2)
return NULL;
}
- /*dot product*/
- return PyFloat_FromDouble(dot_vn_vn(vec1->vec, vec2->vec, vec1->size));
+ /* element-wise product */
+ return vector_mul_vec(vec1, vec2);
+#endif
}
else if (vec1) {
- if (MatrixObject_Check(v2)) {
- /* VEC * MATRIX */
- float tvec[MAX_DIMENSIONS];
-
- if (BaseMath_ReadCallback((MatrixObject *)v2) == -1)
- return NULL;
- if (row_vector_multiplication(tvec, vec1, (MatrixObject *)v2) == -1) {
- return NULL;
- }
-
- if (((MatrixObject *)v2)->num_row == 4 && vec1->size == 3) {
- vec_size = 3;
- }
- else {
- vec_size = ((MatrixObject *)v2)->num_col;
- }
-
- return Vector_CreatePyObject(tvec, vec_size, Py_TYPE(vec1));
- }
- else if (((scalar = PyFloat_AsDouble(v2)) == -1.0f && PyErr_Occurred()) == 0) { /* VEC * FLOAT */
+ if (((scalar = PyFloat_AsDouble(v2)) == -1.0f && PyErr_Occurred()) == 0) { /* VEC * FLOAT */
return vector_mul_float(vec1, scalar);
}
}
@@ -1768,12 +1764,9 @@ static PyObject *Vector_mul(PyObject *v1, PyObject *v2)
return vector_mul_float(vec2, scalar);
}
}
- else {
- BLI_assert(!"internal error");
- }
PyErr_Format(PyExc_TypeError,
- "Vector multiplication: "
+ "Element-wise multiplication: "
"not supported between '%.200s' and '%.200s' types",
Py_TYPE(v1)->tp_name, Py_TYPE(v2)->tp_name);
return NULL;
@@ -1782,32 +1775,129 @@ static PyObject *Vector_mul(PyObject *v1, PyObject *v2)
/* multiplication in-place: obj *= obj */
static PyObject *Vector_imul(PyObject *v1, PyObject *v2)
{
- VectorObject *vec = (VectorObject *)v1;
+ VectorObject *vec1 = NULL, *vec2 = NULL;
float scalar;
- if (BaseMath_ReadCallback_ForWrite(vec) == -1)
+ if (VectorObject_Check(v1)) {
+ vec1 = (VectorObject *)v1;
+ if (BaseMath_ReadCallback(vec1) == -1)
+ return NULL;
+ }
+ if (VectorObject_Check(v2)) {
+ vec2 = (VectorObject *)v2;
+ if (BaseMath_ReadCallback(vec2) == -1)
+ return NULL;
+ }
+
+ if (BaseMath_ReadCallback_ForWrite(vec1) == -1)
return NULL;
/* Intentionally don't support (Quaternion, Matrix) here, uses reverse order instead. */
- /* only support 'vec *= float'
- * vec*=vec result is a float so that wont work */
- if (((scalar = PyFloat_AsDouble(v2)) == -1.0f && PyErr_Occurred()) == 0) { /* VEC *= FLOAT */
- mul_vn_fl(vec->vec, vec->size, scalar);
+ if (vec1 && vec2) {
+#ifdef USE_MATHUTILS_ELEM_MUL
+ if (vec1->size != vec2->size) {
+ PyErr_SetString(PyExc_ValueError,
+ "Vector multiplication: "
+ "vectors must have the same dimensions for this operation");
+ return NULL;
+ }
+
+ /* element-wise product inplace */
+ mul_vn_vn(vec1->vec, vec2->vec, vec1->size);
+#else
+ PyErr_Format(PyExc_TypeError,
+ "Inplace element-wise multiplication: "
+ "not supported between '%.200s' and '%.200s' types",
+ Py_TYPE(v1)->tp_name, Py_TYPE(v2)->tp_name);
+ return NULL;
+#endif
+ }
+ else if (vec1 && (((scalar = PyFloat_AsDouble(v2)) == -1.0f && PyErr_Occurred()) == 0)) { /* VEC *= FLOAT */
+ mul_vn_fl(vec1->vec, vec1->size, scalar);
}
else {
PyErr_Format(PyExc_TypeError,
- "Vector multiplication: (%s *= %s) "
- "invalid type for this operation",
+ "Inplace element-wise multiplication: "
+ "not supported between '%.200s' and '%.200s' types",
Py_TYPE(v1)->tp_name, Py_TYPE(v2)->tp_name);
return NULL;
}
- (void)BaseMath_WriteCallback(vec);
+ (void)BaseMath_WriteCallback(vec1);
Py_INCREF(v1);
return v1;
}
+static PyObject *Vector_matmul(PyObject *v1, PyObject *v2)
+{
+ VectorObject *vec1 = NULL, *vec2 = NULL;
+ int vec_size;
+
+ if (VectorObject_Check(v1)) {
+ vec1 = (VectorObject *)v1;
+ if (BaseMath_ReadCallback(vec1) == -1)
+ return NULL;
+ }
+ if (VectorObject_Check(v2)) {
+ vec2 = (VectorObject *)v2;
+ if (BaseMath_ReadCallback(vec2) == -1)
+ return NULL;
+ }
+
+
+ /* Intentionally don't support (Quaternion) here, uses reverse order instead. */
+
+ /* make sure v1 is always the vector */
+ if (vec1 && vec2) {
+ if (vec1->size != vec2->size) {
+ PyErr_SetString(PyExc_ValueError,
+ "Vector multiplication: "
+ "vectors must have the same dimensions for this operation");
+ return NULL;
+ }
+
+ /*dot product*/
+ return PyFloat_FromDouble(dot_vn_vn(vec1->vec, vec2->vec, vec1->size));
+ }
+ else if (vec1) {
+ if (MatrixObject_Check(v2)) {
+ /* VEC @ MATRIX */
+ float tvec[MAX_DIMENSIONS];
+
+ if (BaseMath_ReadCallback((MatrixObject *)v2) == -1)
+ return NULL;
+ if (row_vector_multiplication(tvec, vec1, (MatrixObject *)v2) == -1) {
+ return NULL;
+ }
+
+ if (((MatrixObject *)v2)->num_row == 4 && vec1->size == 3) {
+ vec_size = 3;
+ }
+ else {
+ vec_size = ((MatrixObject *)v2)->num_col;
+ }
+
+ return Vector_CreatePyObject(tvec, vec_size, Py_TYPE(vec1));
+ }
+ }
+
+ PyErr_Format(PyExc_TypeError,
+ "Vector multiplication: "
+ "not supported between '%.200s' and '%.200s' types",
+ Py_TYPE(v1)->tp_name, Py_TYPE(v2)->tp_name);
+ return NULL;
+}
+
+static PyObject *Vector_imatmul(PyObject *v1, PyObject *v2)
+{
+ PyErr_Format(PyExc_TypeError,
+ "Inplace vector multiplication: "
+ "not supported between '%.200s' and '%.200s' types",
+ Py_TYPE(v1)->tp_name, Py_TYPE(v2)->tp_name);
+ return NULL;
+}
+
/* divid: obj / obj */
static PyObject *Vector_div(PyObject *v1, PyObject *v2)
{
@@ -2119,6 +2209,8 @@ static PyNumberMethods Vector_NumMethods = {
NULL, /* nb_inplace_floor_divide */
Vector_idiv, /* nb_inplace_true_divide */
NULL, /* nb_index */
+ (binaryfunc) Vector_matmul, /* nb_matrix_multiply */
+ (binaryfunc) Vector_imatmul, /* nb_inplace_matrix_multiply */
};
/*------------------PY_OBECT DEFINITION--------------------------*/
diff --git a/source/blender/python/mathutils/mathutils_bvhtree.c b/source/blender/python/mathutils/mathutils_bvhtree.c
index 36727fb91ae..fce0dd7d2af 100644
--- a/source/blender/python/mathutils/mathutils_bvhtree.c
+++ b/source/blender/python/mathutils/mathutils_bvhtree.c
@@ -48,10 +48,16 @@
#ifndef MATH_STANDALONE
#include "DNA_object_types.h"
+#include "DNA_mesh_types.h"
+#include "DNA_meshdata_types.h"
#include "BKE_customdata.h"
-#include "BKE_DerivedMesh.h"
#include "BKE_editmesh_bvh.h"
+#include "BKE_library.h"
+#include "BKE_mesh.h"
+#include "BKE_mesh_runtime.h"
+
+#include "DEG_depsgraph_query.h"
#include "bmesh.h"
@@ -1045,88 +1051,98 @@ static PyObject *C_BVHTree_FromBMesh(PyObject *UNUSED(cls), PyObject *args, PyOb
}
/* return various derived meshes based on requested settings */
-static DerivedMesh *bvh_get_derived_mesh(
- const char *funcname, struct Scene *scene, Object *ob,
- bool use_deform, bool use_render, bool use_cage)
+static Mesh *bvh_get_mesh(
+ const char *funcname, struct Depsgraph *depsgraph, struct Scene *scene, Object *ob,
+ const bool use_deform, const bool use_cage, bool *r_free_mesh)
{
+ Object *ob_eval = DEG_get_evaluated_object(depsgraph, ob);
/* we only need minimum mesh data for topology and vertex locations */
CustomDataMask mask = CD_MASK_BAREMESH;
+ const bool use_render = DEG_get_mode(depsgraph) == DAG_EVAL_RENDER;
+ *r_free_mesh = false;
/* Write the display mesh into the dummy mesh */
if (use_deform) {
if (use_render) {
if (use_cage) {
PyErr_Format(PyExc_ValueError,
- "%s(...): cage arg is unsupported when (render=True)", funcname);
+ "%s(...): cage arg is unsupported when dependency graph evaluation mode is RENDER", funcname);
return NULL;
}
else {
- return mesh_create_derived_render(scene, ob, mask);
+ *r_free_mesh = true;
+ return mesh_create_eval_final_render(depsgraph, scene, ob, mask);
}
}
- else {
+ else if (ob_eval != NULL) {
if (use_cage) {
- return mesh_get_derived_deform(scene, ob, mask); /* ob->derivedDeform */
+ return mesh_get_eval_deform(depsgraph, scene, ob_eval, mask); /* ob->derivedDeform */
}
else {
- return mesh_get_derived_final(scene, ob, mask); /* ob->derivedFinal */
+ return mesh_get_eval_final(depsgraph, scene, ob_eval, mask); /* ob->derivedFinal */
}
}
+ else {
+ PyErr_Format(PyExc_ValueError,
+ "%s(...): Cannot get evaluated data from given dependency graph / object pair", funcname);
+ return NULL;
+ }
}
else {
/* !use_deform */
if (use_render) {
if (use_cage) {
PyErr_Format(PyExc_ValueError,
- "%s(...): cage arg is unsupported when (render=True)", funcname);
+ "%s(...): cage arg is unsupported when dependency graph evaluation mode is RENDER", funcname);
return NULL;
}
else {
- return mesh_create_derived_no_deform_render(scene, ob, NULL, mask);
+ *r_free_mesh = true;
+ return mesh_create_eval_no_deform_render(depsgraph, scene, ob, NULL, mask);
}
}
else {
if (use_cage) {
PyErr_Format(PyExc_ValueError,
- "%s(...): cage arg is unsupported when (deform=False, render=False)", funcname);
+ "%s(...): cage arg is unsupported when deform=False and dependency graph evaluation mode is not RENDER", funcname);
return NULL;
}
else {
- return mesh_create_derived_no_deform(scene, ob, NULL, mask);
+ *r_free_mesh = true;
+ return mesh_create_eval_no_deform(depsgraph, scene, ob, NULL, mask);
}
}
}
}
PyDoc_STRVAR(C_BVHTree_FromObject_doc,
-".. classmethod:: FromObject(object, scene, deform=True, render=False, cage=False, epsilon=0.0)\n"
+".. classmethod:: FromObject(object, depsgraph, deform=True, render=False, cage=False, epsilon=0.0)\n"
"\n"
" BVH tree based on :class:`Object` data.\n"
"\n"
" :arg object: Object data.\n"
" :type object: :class:`Object`\n"
-" :arg scene: Scene data to use for evaluating the mesh.\n"
-" :type scene: :class:`Scene`\n"
+" :arg depsgraph: Depsgraph to use for evaluating the mesh.\n"
+" :type depsgraph: :class:`Depsgraph`\n"
" :arg deform: Use mesh with deformations.\n"
" :type deform: bool\n"
-" :arg render: Use render settings.\n"
-" :type render: bool\n"
-" :arg cage: Use render settings.\n"
+" :arg cage: Use modifiers cage.\n"
" :type cage: bool\n"
PYBVH_FROM_GENERIC_EPSILON_DOC
);
static PyObject *C_BVHTree_FromObject(PyObject *UNUSED(cls), PyObject *args, PyObject *kwargs)
{
/* note, options here match 'bpy_bmesh_from_object' */
- const char *keywords[] = {"object", "scene", "deform", "render", "cage", "epsilon", NULL};
+ const char *keywords[] = {"object", "depsgraph", "deform", "cage", "epsilon", NULL};
- PyObject *py_ob, *py_scene;
+ PyObject *py_ob, *py_depsgraph;
Object *ob;
+ struct Depsgraph *depsgraph;
struct Scene *scene;
- DerivedMesh *dm;
+ Mesh *mesh;
bool use_deform = true;
- bool use_render = false;
bool use_cage = false;
+ bool free_mesh = false;
const MLoopTri *lt;
const MLoop *mloop;
@@ -1137,36 +1153,40 @@ static PyObject *C_BVHTree_FromObject(PyObject *UNUSED(cls), PyObject *args, PyO
float epsilon = 0.0f;
if (!PyArg_ParseTupleAndKeywords(
- args, kwargs, (char *)"OO|$O&O&O&f:BVHTree.FromObject", (char **)keywords,
- &py_ob, &py_scene,
+ args, kwargs, (char *)"OO|$O&O&f:BVHTree.FromObject", (char **)keywords,
+ &py_ob, &py_depsgraph,
PyC_ParseBool, &use_deform,
- PyC_ParseBool, &use_render,
PyC_ParseBool, &use_cage,
&epsilon) ||
((ob = PyC_RNA_AsPointer(py_ob, "Object")) == NULL) ||
- ((scene = PyC_RNA_AsPointer(py_scene, "Scene")) == NULL))
+ ((depsgraph = PyC_RNA_AsPointer(py_depsgraph, "Depsgraph")) == NULL))
{
return NULL;
}
- dm = bvh_get_derived_mesh("BVHTree", scene, ob, use_deform, use_render, use_cage);
- if (dm == NULL) {
+ scene = DEG_get_evaluated_scene(depsgraph);
+ mesh = bvh_get_mesh("BVHTree", depsgraph, scene, ob, use_deform, use_cage, &free_mesh);
+
+ if (mesh == NULL) {
return NULL;
}
/* Get data for tessellation */
{
- lt = dm->getLoopTriArray(dm);
+ lt = BKE_mesh_runtime_looptri_ensure(mesh);
- tris_len = (unsigned int)dm->getNumLoopTri(dm);
- coords_len = (unsigned int)dm->getNumVerts(dm);
+ tris_len = (unsigned int)BKE_mesh_runtime_looptri_len(mesh);
+ coords_len = (unsigned int)mesh->totvert;
coords = MEM_mallocN(sizeof(*coords) * (size_t)coords_len, __func__);
tris = MEM_mallocN(sizeof(*tris) * (size_t)tris_len, __func__);
- dm->getVertCos(dm, coords);
+ MVert *mv = mesh->mvert;
+ for (int i = 0; i < mesh->totvert; i++, mv++) {
+ copy_v3_v3(coords[i], mv->co);
+ }
- mloop = dm->getLoopArray(dm);
+ mloop = mesh->mloop;
}
{
@@ -1179,7 +1199,8 @@ static PyObject *C_BVHTree_FromObject(PyObject *UNUSED(cls), PyObject *args, PyO
tree = BLI_bvhtree_new((int)tris_len, epsilon, PY_BVH_TREE_TYPE_DEFAULT, PY_BVH_AXIS_DEFAULT);
if (tree) {
orig_index = MEM_mallocN(sizeof(*orig_index) * (size_t)tris_len, __func__);
- orig_normal = dm->getPolyDataArray(dm, CD_NORMAL); /* can be NULL */
+ CustomData *pdata = &mesh->pdata;
+ orig_normal = CustomData_get_layer(pdata, CD_NORMAL); /* can be NULL */
if (orig_normal) {
orig_normal = MEM_dupallocN(orig_normal);
}
@@ -1202,7 +1223,9 @@ static PyObject *C_BVHTree_FromObject(PyObject *UNUSED(cls), PyObject *args, PyO
BLI_bvhtree_balance(tree);
}
- dm->release(dm);
+ if (free_mesh) {
+ BKE_id_free(NULL, mesh);
+ }
return bvhtree_CreatePyObject(
tree, epsilon,
diff --git a/source/blender/python/mathutils/mathutils_noise.c b/source/blender/python/mathutils/mathutils_noise.c
index 834322c0aed..5e3e86c8ddf 100644
--- a/source/blender/python/mathutils/mathutils_noise.c
+++ b/source/blender/python/mathutils/mathutils_noise.c
@@ -40,18 +40,11 @@
#include "DNA_texture_types.h"
+#include "../generic/py_capi_utils.h"
+
#include "mathutils.h"
#include "mathutils_noise.h"
-/* 2.6 update
- * Moved to submodule of mathutils.
- * All vector functions now return mathutils.Vector
- * Updated docs to be compatible with autodocs generation.
- * Updated vector functions to use nD array functions.
- * noise.vl_vector --> noise.variable_lacunarity
- * noise.vector --> noise.noise_vector
- */
-
/*-----------------------------------------*/
/* 'mersenne twister' random number generator */
@@ -198,6 +191,48 @@ static float frand(void)
/* Utility Functions */
/*------------------------------------------------------------*/
+#define BPY_NOISE_BASIS_ENUM_DOC \
+" :arg noise_basis: Enumerator in ['BLENDER', 'PERLIN_ORIGINAL', 'PERLIN_NEW', 'VORONOI_F1', 'VORONOI_F2', " \
+ "'VORONOI_F3', 'VORONOI_F4', 'VORONOI_F2F1', 'VORONOI_CRACKLE', " \
+ "'CELLNOISE'].\n" \
+" :type noise_basis: string\n" \
+
+#define BPY_NOISE_METRIC_ENUM_DOC \
+" :arg distance_metric: Enumerator in ['DISTANCE', 'DISTANCE_SQUARED', 'MANHATTAN', 'CHEBYCHEV', " \
+ "'MINKOVSKY', 'MINKOVSKY_HALF', 'MINKOVSKY_FOUR'].\n" \
+" :type distance_metric: string\n" \
+
+/* Noise basis enum */
+#define DEFAULT_NOISE_TYPE TEX_STDPERLIN
+
+static PyC_FlagSet bpy_noise_types[] = {
+ {TEX_BLENDER, "BLENDER"},
+ {TEX_STDPERLIN, "PERLIN_ORIGINAL"},
+ {TEX_NEWPERLIN, "PERLIN_NEW"},
+ {TEX_VORONOI_F1, "VORONOI_F1"},
+ {TEX_VORONOI_F2, "VORONOI_F2"},
+ {TEX_VORONOI_F3, "VORONOI_F3"},
+ {TEX_VORONOI_F4, "VORONOI_F4"},
+ {TEX_VORONOI_F2F1, "VORONOI_F2F1"},
+ {TEX_VORONOI_CRACKLE, "VORONOI_CRACKLE"},
+ {TEX_CELLNOISE, "CELLNOISE"},
+ {0, NULL}
+};
+
+/* Metric basis enum */
+#define DEFAULT_METRIC_TYPE TEX_DISTANCE
+
+static PyC_FlagSet bpy_noise_metrics[] = {
+ {TEX_DISTANCE, "DISTANCE"},
+ {TEX_DISTANCE_SQUARED, "DISTANCE_SQUARED"},
+ {TEX_MANHATTAN, "MANHATTAN"},
+ {TEX_CHEBYCHEV, "CHEBYCHEV"},
+ {TEX_MINKOVSKY, "MINKOVSKY"},
+ {TEX_MINKOVSKY_HALF, "MINKOVSKY_HALF"},
+ {TEX_MINKOVSKY_FOUR, "MINKOVSKY_FOUR"},
+ {0, NULL}
+};
+
/* Fills an array of length size with random numbers in the range (-1, 1)*/
static void rand_vn(float *array_tar, const int size)
{
@@ -218,8 +253,9 @@ static void noise_vector(float x, float y, float z, int nb, float v[3])
}
/* Returns a turbulence value for a given position (x, y, z) */
-static float turb(float x, float y, float z, int oct, int hard, int nb,
- float ampscale, float freqscale)
+static float turb(
+ float x, float y, float z, int oct, int hard, int nb,
+ float ampscale, float freqscale)
{
float amp, out, t;
int i;
@@ -242,8 +278,9 @@ static float turb(float x, float y, float z, int oct, int hard, int nb,
/* Fills an array of length 3 with the turbulence vector for a given
* position (x, y, z) */
-static void vTurb(float x, float y, float z, int oct, int hard, int nb,
- float ampscale, float freqscale, float v[3])
+static void vTurb(
+ float x, float y, float z, int oct, int hard, int nb,
+ float ampscale, float freqscale, float v[3])
{
float amp, t[3];
int i;
@@ -283,7 +320,7 @@ PyDoc_STRVAR(M_Noise_doc,
PyDoc_STRVAR(M_Noise_random_doc,
".. function:: random()\n"
"\n"
-" Returns a random number in the range [0, 1].\n"
+" Returns a random number in the range [0, 1).\n"
"\n"
" :return: The random number.\n"
" :rtype: float\n"
@@ -298,71 +335,81 @@ PyDoc_STRVAR(M_Noise_random_unit_vector_doc,
"\n"
" Returns a unit vector with random entries.\n"
"\n"
-" :arg size: The size of the vector to be produced.\n"
-" :type size: Int\n"
+" :arg size: The size of the vector to be produced, in the range [2, 4].\n"
+" :type size: int\n"
" :return: The random unit vector.\n"
" :rtype: :class:`mathutils.Vector`\n"
);
-static PyObject *M_Noise_random_unit_vector(PyObject *UNUSED(self), PyObject *args)
+static PyObject *M_Noise_random_unit_vector(PyObject *UNUSED(self), PyObject *args, PyObject *kw)
{
+ static const char *kwlist[] = {"size", NULL};
float vec[4] = {0.0f, 0.0f, 0.0f, 0.0f};
float norm = 2.0f;
int size = 3;
- if (!PyArg_ParseTuple(args, "|i:random_vector", &size))
+ if (!PyArg_ParseTupleAndKeywords(
+ args, kw, "|$i:random_unit_vector", (char **)kwlist,
+ &size))
+ {
return NULL;
+ }
if (size > 4 || size < 2) {
PyErr_SetString(PyExc_ValueError, "Vector(): invalid size");
return NULL;
}
- while (norm == 0.0f || norm >= 1.0f) {
+ while (norm == 0.0f || norm > 1.0f) {
rand_vn(vec, size);
norm = normalize_vn(vec, size);
}
return Vector_CreatePyObject(vec, size, NULL);
}
-/* This is dumb, most people will want a unit vector anyway, since this doesn't have uniform distribution over a sphere*/
-#if 0
+
PyDoc_STRVAR(M_Noise_random_vector_doc,
".. function:: random_vector(size=3)\n"
"\n"
-" Returns a vector with random entries in the range [0, 1).\n"
+" Returns a vector with random entries in the range (-1, 1).\n"
"\n"
" :arg size: The size of the vector to be produced.\n"
-" :type size: Int\n"
+" :type size: int\n"
" :return: The random vector.\n"
" :rtype: :class:`mathutils.Vector`\n"
);
-static PyObject *M_Noise_random_vector(PyObject *UNUSED(self), PyObject *args)
+static PyObject *M_Noise_random_vector(PyObject *UNUSED(self), PyObject *args, PyObject *kw)
{
- float vec[4] = {0.0f, 0.0f, 0.0f, 0.0f};
+ static const char *kwlist[] = {"size", NULL};
+ float *vec = NULL;
int size = 3;
- if (!PyArg_ParseTuple(args, "|i:random_vector", &size))
+ if (!PyArg_ParseTupleAndKeywords(
+ args, kw, "|$i:random_vector", (char **)kwlist,
+ &size))
+ {
return NULL;
+ }
- if (size > 4 || size < 2) {
+ if (size < 2) {
PyErr_SetString(PyExc_ValueError, "Vector(): invalid size");
return NULL;
}
+ vec = PyMem_New(float, size);
+
rand_vn(vec, size);
- return Vector_CreatePyObject(vec, size, NULL);
+ return Vector_CreatePyObject_alloc(vec, size, NULL);
}
-#endif
PyDoc_STRVAR(M_Noise_seed_set_doc,
".. function:: seed_set(seed)\n"
"\n"
-" Sets the random seed used for random_unit_vector, random_vector and random.\n"
+" Sets the random seed used for random_unit_vector, and random.\n"
"\n"
" :arg seed: Seed used for the random generator.\n"
" When seed is zero, the current time will be used instead.\n"
-" :type seed: Int\n"
+" :type seed: int\n"
);
static PyObject *M_Noise_seed_set(PyObject *UNUSED(self), PyObject *args)
{
@@ -374,139 +421,198 @@ static PyObject *M_Noise_seed_set(PyObject *UNUSED(self), PyObject *args)
}
PyDoc_STRVAR(M_Noise_noise_doc,
-".. function:: noise(position, noise_basis=noise.types.STDPERLIN)\n"
+".. function:: noise(position, noise_basis='PERLIN_ORIGINAL')\n"
"\n"
" Returns noise value from the noise basis at the position specified.\n"
"\n"
-" :arg position: The position to evaluate the selected noise function at.\n"
+" :arg position: The position to evaluate the selected noise function.\n"
" :type position: :class:`mathutils.Vector`\n"
-" :arg noise_basis: The type of noise to be evaluated.\n"
-" :type noise_basis: Value in noise.types or int\n"
+BPY_NOISE_BASIS_ENUM_DOC
" :return: The noise value.\n"
" :rtype: float\n"
);
-static PyObject *M_Noise_noise(PyObject *UNUSED(self), PyObject *args)
+static PyObject *M_Noise_noise(PyObject *UNUSED(self), PyObject *args, PyObject *kw)
{
+ static const char *kwlist[] = {"", "noise_basis", NULL};
PyObject *value;
float vec[3];
- int nb = 1;
- if (!PyArg_ParseTuple(args, "O|i:noise", &value, &nb))
+ const char *noise_basis_str = NULL;
+ int noise_basis_enum = DEFAULT_NOISE_TYPE;
+
+ if (!PyArg_ParseTupleAndKeywords(
+ args, kw, "O|$s:noise", (char **)kwlist,
+ &value, &noise_basis_str))
+ {
+ return NULL;
+ }
+
+ if (!noise_basis_str) {
+ /* pass through */
+ }
+ else if (PyC_FlagSet_ValueFromID(
+ bpy_noise_types, noise_basis_str, &noise_basis_enum, "noise") == -1)
+ {
return NULL;
+ }
if (mathutils_array_parse(vec, 3, 3, value, "noise: invalid 'position' arg") == -1)
return NULL;
- return PyFloat_FromDouble((2.0f * BLI_gNoise(1.0f, vec[0], vec[1], vec[2], 0, nb) - 1.0f));
+ return PyFloat_FromDouble((2.0f * BLI_gNoise(1.0f, vec[0], vec[1], vec[2], 0, noise_basis_enum) - 1.0f));
}
PyDoc_STRVAR(M_Noise_noise_vector_doc,
-".. function:: noise_vector(position, noise_basis=noise.types.STDPERLIN)\n"
+".. function:: noise_vector(position, noise_basis='PERLIN_ORIGINAL')\n"
"\n"
" Returns the noise vector from the noise basis at the specified position.\n"
"\n"
-" :arg position: The position to evaluate the selected noise function at.\n"
+" :arg position: The position to evaluate the selected noise function.\n"
" :type position: :class:`mathutils.Vector`\n"
-" :arg noise_basis: The type of noise to be evaluated.\n"
-" :type noise_basis: Value in noise.types or int\n"
+BPY_NOISE_BASIS_ENUM_DOC
" :return: The noise vector.\n"
" :rtype: :class:`mathutils.Vector`\n"
);
-static PyObject *M_Noise_noise_vector(PyObject *UNUSED(self), PyObject *args)
+static PyObject *M_Noise_noise_vector(PyObject *UNUSED(self), PyObject *args, PyObject *kw)
{
+ static const char *kwlist[] = {"", "noise_basis", NULL};
PyObject *value;
float vec[3], r_vec[3];
- int nb = 1;
+ const char *noise_basis_str = NULL;
+ int noise_basis_enum = DEFAULT_NOISE_TYPE;
- if (!PyArg_ParseTuple(args, "O|i:noise_vector", &value, &nb))
+ if (!PyArg_ParseTupleAndKeywords(
+ args, kw, "O|$s:noise_vector", (char **)kwlist,
+ &value, &noise_basis_str))
+ {
+ return NULL;
+ }
+
+ if (!noise_basis_str) {
+ /* pass through */
+ }
+ else if (PyC_FlagSet_ValueFromID(
+ bpy_noise_types, noise_basis_str, &noise_basis_enum, "noise_vector") == -1)
+ {
return NULL;
+ }
if (mathutils_array_parse(vec, 3, 3, value, "noise_vector: invalid 'position' arg") == -1)
return NULL;
- noise_vector(vec[0], vec[1], vec[2], nb, r_vec);
+ noise_vector(vec[0], vec[1], vec[2], noise_basis_enum, r_vec);
return Vector_CreatePyObject(r_vec, 3, NULL);
}
PyDoc_STRVAR(M_Noise_turbulence_doc,
-".. function:: turbulence(position, octaves, hard, noise_basis=noise.types.STDPERLIN, amplitude_scale=0.5, frequency_scale=2.0)\n"
+".. function:: turbulence(position, octaves, hard, noise_basis='PERLIN_ORIGINAL', amplitude_scale=0.5, frequency_scale=2.0)\n"
"\n"
" Returns the turbulence value from the noise basis at the specified position.\n"
"\n"
-" :arg position: The position to evaluate the selected noise function at.\n"
+" :arg position: The position to evaluate the selected noise function.\n"
" :type position: :class:`mathutils.Vector`\n"
" :arg octaves: The number of different noise frequencies used.\n"
" :type octaves: int\n"
" :arg hard: Specifies whether returned turbulence is hard (sharp transitions) or soft (smooth transitions).\n"
-" :type hard: :boolean\n"
-" :arg noise_basis: The type of noise to be evaluated.\n"
-" :type noise_basis: Value in mathutils.noise.types or int\n"
+" :type hard: boolean\n"
+BPY_NOISE_BASIS_ENUM_DOC
" :arg amplitude_scale: The amplitude scaling factor.\n"
" :type amplitude_scale: float\n"
" :arg frequency_scale: The frequency scaling factor\n"
-" :type frequency_scale: Value in noise.types or int\n"
+" :type frequency_scale: float\n"
" :return: The turbulence value.\n"
" :rtype: float\n"
);
-static PyObject *M_Noise_turbulence(PyObject *UNUSED(self), PyObject *args)
+static PyObject *M_Noise_turbulence(PyObject *UNUSED(self), PyObject *args, PyObject *kw)
{
+ static const char *kwlist[] = {"", "", "", "noise_basis", "amplitude_scale", "frequency_scale", NULL};
PyObject *value;
float vec[3];
- int oct, hd, nb = 1;
+ const char *noise_basis_str = NULL;
+ int oct, hd, noise_basis_enum = DEFAULT_NOISE_TYPE;
float as = 0.5f, fs = 2.0f;
- if (!PyArg_ParseTuple(args, "Oii|iff:turbulence", &value, &oct, &hd, &nb, &as, &fs))
+ if (!PyArg_ParseTupleAndKeywords(
+ args, kw, "Oii|$sff:turbulence", (char **)kwlist,
+ &value, &oct, &hd, &noise_basis_str, &as, &fs))
+ {
return NULL;
+ }
+
+ if (!noise_basis_str) {
+ /* pass through */
+ }
+ else if (PyC_FlagSet_ValueFromID(
+ bpy_noise_types, noise_basis_str, &noise_basis_enum, "turbulence") == -1)
+ {
+ return NULL;
+ }
if (mathutils_array_parse(vec, 3, 3, value, "turbulence: invalid 'position' arg") == -1)
return NULL;
- return PyFloat_FromDouble(turb(vec[0], vec[1], vec[2], oct, hd, nb, as, fs));
+ return PyFloat_FromDouble(turb(vec[0], vec[1], vec[2], oct, hd, noise_basis_enum, as, fs));
}
PyDoc_STRVAR(M_Noise_turbulence_vector_doc,
-".. function:: turbulence_vector(position, octaves, hard, noise_basis=noise.types.STDPERLIN, amplitude_scale=0.5, frequency_scale=2.0)\n"
+".. function:: turbulence_vector(position, octaves, hard, noise_basis='PERLIN_ORIGINAL', amplitude_scale=0.5, frequency_scale=2.0)\n"
"\n"
" Returns the turbulence vector from the noise basis at the specified position.\n"
"\n"
-" :arg position: The position to evaluate the selected noise function at.\n"
+" :arg position: The position to evaluate the selected noise function.\n"
" :type position: :class:`mathutils.Vector`\n"
" :arg octaves: The number of different noise frequencies used.\n"
" :type octaves: int\n"
" :arg hard: Specifies whether returned turbulence is hard (sharp transitions) or soft (smooth transitions).\n"
" :type hard: :boolean\n"
-" :arg noise_basis: The type of noise to be evaluated.\n"
-" :type noise_basis: Value in mathutils.noise.types or int\n"
+BPY_NOISE_BASIS_ENUM_DOC
" :arg amplitude_scale: The amplitude scaling factor.\n"
" :type amplitude_scale: float\n"
" :arg frequency_scale: The frequency scaling factor\n"
-" :type frequency_scale: Value in noise.types or int\n"
+" :type frequency_scale: float\n"
" :return: The turbulence vector.\n"
" :rtype: :class:`mathutils.Vector`\n"
);
-static PyObject *M_Noise_turbulence_vector(PyObject *UNUSED(self), PyObject *args)
+static PyObject *M_Noise_turbulence_vector(PyObject *UNUSED(self), PyObject *args, PyObject *kw)
{
+ static const char *kwlist[] = {"", "", "", "noise_basis", "amplitude_scale", "frequency_scale", NULL};
PyObject *value;
float vec[3], r_vec[3];
- int oct, hd, nb = 1;
+ const char *noise_basis_str = NULL;
+ int oct, hd, noise_basis_enum = DEFAULT_NOISE_TYPE;
float as = 0.5f, fs = 2.0f;
- if (!PyArg_ParseTuple(args, "Oii|iff:turbulence_vector", &value, &oct, &hd, &nb, &as, &fs))
+
+ if (!PyArg_ParseTupleAndKeywords(
+ args, kw, "Oii|$sff:turbulence_vector", (char **)kwlist,
+ &value, &oct, &hd, &noise_basis_str, &as, &fs))
+ {
return NULL;
+ }
+
+ if (!noise_basis_str) {
+ /* pass through */
+ }
+ else if (PyC_FlagSet_ValueFromID(
+ bpy_noise_types, noise_basis_str, &noise_basis_enum, "turbulence_vector") == -1)
+ {
+ return NULL;
+ }
if (mathutils_array_parse(vec, 3, 3, value, "turbulence_vector: invalid 'position' arg") == -1)
return NULL;
- vTurb(vec[0], vec[1], vec[2], oct, hd, nb, as, fs, r_vec);
+ vTurb(vec[0], vec[1], vec[2], oct, hd, noise_basis_enum, as, fs, r_vec);
+
return Vector_CreatePyObject(r_vec, 3, NULL);
}
/* F. Kenton Musgrave's fractal functions */
PyDoc_STRVAR(M_Noise_fractal_doc,
-".. function:: fractal(position, H, lacunarity, octaves, noise_basis=noise.types.STDPERLIN)\n"
+".. function:: fractal(position, H, lacunarity, octaves, noise_basis='PERLIN_ORIGINAL')\n"
"\n"
" Returns the fractal Brownian motion (fBm) noise value from the noise basis at the specified position.\n"
"\n"
-" :arg position: The position to evaluate the selected noise function at.\n"
+" :arg position: The position to evaluate the selected noise function.\n"
" :type position: :class:`mathutils.Vector`\n"
" :arg H: The fractal increment factor.\n"
" :type H: float\n"
@@ -514,33 +620,47 @@ PyDoc_STRVAR(M_Noise_fractal_doc,
" :type lacunarity: float\n"
" :arg octaves: The number of different noise frequencies used.\n"
" :type octaves: int\n"
-" :arg noise_basis: The type of noise to be evaluated.\n"
-" :type noise_basis: Value in noise.types or int\n"
+BPY_NOISE_BASIS_ENUM_DOC
" :return: The fractal Brownian motion noise value.\n"
" :rtype: float\n"
);
-static PyObject *M_Noise_fractal(PyObject *UNUSED(self), PyObject *args)
+static PyObject *M_Noise_fractal(PyObject *UNUSED(self), PyObject *args, PyObject *kw)
{
+ static const char *kwlist[] = {"", "", "", "", "noise_basis", NULL};
PyObject *value;
float vec[3];
+ const char *noise_basis_str = NULL;
float H, lac, oct;
- int nb = 1;
+ int noise_basis_enum = DEFAULT_NOISE_TYPE;
- if (!PyArg_ParseTuple(args, "Offf|i:fractal", &value, &H, &lac, &oct, &nb))
+ if (!PyArg_ParseTupleAndKeywords(
+ args, kw, "Offf|$s:fractal", (char **)kwlist,
+ &value, &H, &lac, &oct, &noise_basis_str))
+ {
return NULL;
+ }
+
+ if (!noise_basis_str) {
+ /* pass through */
+ }
+ else if (PyC_FlagSet_ValueFromID(
+ bpy_noise_types, noise_basis_str, &noise_basis_enum, "fractal") == -1)
+ {
+ return NULL;
+ }
if (mathutils_array_parse(vec, 3, 3, value, "fractal: invalid 'position' arg") == -1)
return NULL;
- return PyFloat_FromDouble(mg_fBm(vec[0], vec[1], vec[2], H, lac, oct, nb));
+ return PyFloat_FromDouble(mg_fBm(vec[0], vec[1], vec[2], H, lac, oct, noise_basis_enum));
}
PyDoc_STRVAR(M_Noise_multi_fractal_doc,
-".. function:: multi_fractal(position, H, lacunarity, octaves, noise_basis=noise.types.STDPERLIN)\n"
+".. function:: multi_fractal(position, H, lacunarity, octaves, noise_basis='PERLIN_ORIGINAL')\n"
"\n"
" Returns multifractal noise value from the noise basis at the specified position.\n"
"\n"
-" :arg position: The position to evaluate the selected noise function at.\n"
+" :arg position: The position to evaluate the selected noise function.\n"
" :type position: :class:`mathutils.Vector`\n"
" :arg H: The fractal increment factor.\n"
" :type H: float\n"
@@ -548,65 +668,107 @@ PyDoc_STRVAR(M_Noise_multi_fractal_doc,
" :type lacunarity: float\n"
" :arg octaves: The number of different noise frequencies used.\n"
" :type octaves: int\n"
-" :arg noise_basis: The type of noise to be evaluated.\n"
-" :type noise_basis: Value in noise.types or int\n"
+BPY_NOISE_BASIS_ENUM_DOC
" :return: The multifractal noise value.\n"
" :rtype: float\n"
);
-static PyObject *M_Noise_multi_fractal(PyObject *UNUSED(self), PyObject *args)
+static PyObject *M_Noise_multi_fractal(PyObject *UNUSED(self), PyObject *args, PyObject *kw)
{
+ static const char *kwlist[] = {"", "", "", "", "noise_basis", NULL};
PyObject *value;
float vec[3];
+ const char *noise_basis_str = NULL;
float H, lac, oct;
- int nb = 1;
+ int noise_basis_enum = DEFAULT_NOISE_TYPE;
+
+ if (!PyArg_ParseTupleAndKeywords(
+ args, kw, "Offf|$s:multi_fractal", (char **)kwlist,
+ &value, &H, &lac, &oct, &noise_basis_str))
+ {
+ return NULL;
+ }
- if (!PyArg_ParseTuple(args, "Offf|i:multi_fractal", &value, &H, &lac, &oct, &nb))
+ if (!noise_basis_str) {
+ /* pass through */
+ }
+ else if (PyC_FlagSet_ValueFromID(
+ bpy_noise_types, noise_basis_str, &noise_basis_enum, "multi_fractal") == -1)
+ {
return NULL;
+ }
if (mathutils_array_parse(vec, 3, 3, value, "multi_fractal: invalid 'position' arg") == -1)
return NULL;
- return PyFloat_FromDouble(mg_MultiFractal(vec[0], vec[1], vec[2], H, lac, oct, nb));
+ return PyFloat_FromDouble(mg_MultiFractal(vec[0], vec[1], vec[2], H, lac, oct, noise_basis_enum));
}
PyDoc_STRVAR(M_Noise_variable_lacunarity_doc,
-".. function:: variable_lacunarity(position, distortion, noise_type1=noise.types.STDPERLIN, noise_type2=noise.types.STDPERLIN)\n"
+".. function:: variable_lacunarity(position, distortion, noise_type1='PERLIN_ORIGINAL', noise_type2='PERLIN_ORIGINAL')\n"
"\n"
" Returns variable lacunarity noise value, a distorted variety of noise, from noise type 1 distorted by noise type 2 at the specified position.\n"
"\n"
-" :arg position: The position to evaluate the selected noise function at.\n"
+" :arg position: The position to evaluate the selected noise function.\n"
" :type position: :class:`mathutils.Vector`\n"
" :arg distortion: The amount of distortion.\n"
" :type distortion: float\n"
-" :arg noise_type1: The type of noise to be distorted.\n"
-" :type noise_type1: Value in noise.types or int\n"
-" :arg noise_type2: The type of noise used to distort noise_type1.\n"
-" :type noise_type2: Value in noise.types or int\n"
+" :arg noise_type1: Enumerator in ['BLENDER', 'PERLIN_ORIGINAL', 'PERLIN_NEW', 'VORONOI_F1', 'VORONOI_F2', " \
+ "'VORONOI_F3', 'VORONOI_F4', 'VORONOI_F2F1', 'VORONOI_CRACKLE', " \
+ "'CELLNOISE'].\n"
+" :type noise_type1: string\n"
+" :arg noise_type2: Enumerator in ['BLENDER', 'PERLIN_ORIGINAL', 'PERLIN_NEW', 'VORONOI_F1', 'VORONOI_F2', " \
+ "'VORONOI_F3', 'VORONOI_F4', 'VORONOI_F2F1', 'VORONOI_CRACKLE', " \
+ "'CELLNOISE'].\n"
+" :type noise_type2: string\n"
" :return: The variable lacunarity noise value.\n"
" :rtype: float\n"
);
-static PyObject *M_Noise_variable_lacunarity(PyObject *UNUSED(self), PyObject *args)
+static PyObject *M_Noise_variable_lacunarity(PyObject *UNUSED(self), PyObject *args, PyObject *kw)
{
+ static const char *kwlist[] = {"", "", "noise_type1", "noise_type2", NULL};
PyObject *value;
float vec[3];
+ const char *noise_type1_str = NULL, *noise_type2_str = NULL;
float d;
- int nt1 = 1, nt2 = 1;
+ int noise_type1_enum = DEFAULT_NOISE_TYPE, noise_type2_enum = DEFAULT_NOISE_TYPE;
- if (!PyArg_ParseTuple(args, "Of|ii:variable_lacunarity", &value, &d, &nt1, &nt2))
+ if (!PyArg_ParseTupleAndKeywords(
+ args, kw, "Of|$ss:variable_lacunarity", (char **)kwlist,
+ &value, &d, &noise_type1_str, &noise_type2_str))
+ {
return NULL;
+ }
+
+ if (!noise_type1_str) {
+ /* pass through */
+ }
+ else if (PyC_FlagSet_ValueFromID(
+ bpy_noise_types, noise_type1_str, &noise_type1_enum, "variable_lacunarity") == -1)
+ {
+ return NULL;
+ }
+
+ if (!noise_type2_str) {
+ /* pass through */
+ }
+ else if (PyC_FlagSet_ValueFromID(
+ bpy_noise_types, noise_type2_str, &noise_type2_enum, "variable_lacunarity") == -1)
+ {
+ return NULL;
+ }
if (mathutils_array_parse(vec, 3, 3, value, "variable_lacunarity: invalid 'position' arg") == -1)
return NULL;
- return PyFloat_FromDouble(mg_VLNoise(vec[0], vec[1], vec[2], d, nt1, nt2));
+ return PyFloat_FromDouble(mg_VLNoise(vec[0], vec[1], vec[2], d, noise_type1_enum, noise_type2_enum));
}
PyDoc_STRVAR(M_Noise_hetero_terrain_doc,
-".. function:: hetero_terrain(position, H, lacunarity, octaves, offset, noise_basis=noise.types.STDPERLIN)\n"
+".. function:: hetero_terrain(position, H, lacunarity, octaves, offset, noise_basis='PERLIN_ORIGINAL')\n"
"\n"
" Returns the heterogeneous terrain value from the noise basis at the specified position.\n"
"\n"
-" :arg position: The position to evaluate the selected noise function at.\n"
+" :arg position: The position to evaluate the selected noise function.\n"
" :type position: :class:`mathutils.Vector`\n"
" :arg H: The fractal dimension of the roughest areas.\n"
" :type H: float\n"
@@ -616,33 +778,47 @@ PyDoc_STRVAR(M_Noise_hetero_terrain_doc,
" :type octaves: int\n"
" :arg offset: The height of the terrain above 'sea level'.\n"
" :type offset: float\n"
-" :arg noise_basis: The type of noise to be evaluated.\n"
-" :type noise_basis: Value in noise.types or int\n"
+BPY_NOISE_BASIS_ENUM_DOC
" :return: The heterogeneous terrain value.\n"
" :rtype: float\n"
);
-static PyObject *M_Noise_hetero_terrain(PyObject *UNUSED(self), PyObject *args)
+static PyObject *M_Noise_hetero_terrain(PyObject *UNUSED(self), PyObject *args, PyObject *kw)
{
+ static const char *kwlist[] = {"", "", "", "", "", "noise_basis", NULL};
PyObject *value;
float vec[3];
+ const char *noise_basis_str = NULL;
float H, lac, oct, ofs;
- int nb = 1;
+ int noise_basis_enum = DEFAULT_NOISE_TYPE;
- if (!PyArg_ParseTuple(args, "Offff|i:hetero_terrain", &value, &H, &lac, &oct, &ofs, &nb))
+ if (!PyArg_ParseTupleAndKeywords(
+ args, kw, "Offff|$s:hetero_terrain", (char **)kwlist,
+ &value, &H, &lac, &oct, &ofs, &noise_basis_str))
+ {
+ return NULL;
+ }
+
+ if (!noise_basis_str) {
+ /* pass through */
+ }
+ else if (PyC_FlagSet_ValueFromID(
+ bpy_noise_types, noise_basis_str, &noise_basis_enum, "hetero_terrain") == -1)
+ {
return NULL;
+ }
if (mathutils_array_parse(vec, 3, 3, value, "hetero_terrain: invalid 'position' arg") == -1)
return NULL;
- return PyFloat_FromDouble(mg_HeteroTerrain(vec[0], vec[1], vec[2], H, lac, oct, ofs, nb));
+ return PyFloat_FromDouble(mg_HeteroTerrain(vec[0], vec[1], vec[2], H, lac, oct, ofs, noise_basis_enum));
}
PyDoc_STRVAR(M_Noise_hybrid_multi_fractal_doc,
-".. function:: hybrid_multi_fractal(position, H, lacunarity, octaves, offset, gain, noise_basis=noise.types.STDPERLIN)\n"
+".. function:: hybrid_multi_fractal(position, H, lacunarity, octaves, offset, gain, noise_basis='PERLIN_ORIGINAL')\n"
"\n"
" Returns hybrid multifractal value from the noise basis at the specified position.\n"
"\n"
-" :arg position: The position to evaluate the selected noise function at.\n"
+" :arg position: The position to evaluate the selected noise function.\n"
" :type position: :class:`mathutils.Vector`\n"
" :arg H: The fractal dimension of the roughest areas.\n"
" :type H: float\n"
@@ -654,33 +830,47 @@ PyDoc_STRVAR(M_Noise_hybrid_multi_fractal_doc,
" :type offset: float\n"
" :arg gain: Scaling applied to the values.\n"
" :type gain: float\n"
-" :arg noise_basis: The type of noise to be evaluated.\n"
-" :type noise_basis: Value in noise.types or int\n"
+BPY_NOISE_BASIS_ENUM_DOC
" :return: The hybrid multifractal value.\n"
" :rtype: float\n"
);
-static PyObject *M_Noise_hybrid_multi_fractal(PyObject *UNUSED(self), PyObject *args)
+static PyObject *M_Noise_hybrid_multi_fractal(PyObject *UNUSED(self), PyObject *args, PyObject *kw)
{
+ static const char *kwlist[] = {"", "", "", "", "", "", "noise_basis", NULL};
PyObject *value;
float vec[3];
+ const char *noise_basis_str = NULL;
float H, lac, oct, ofs, gn;
- int nb = 1;
+ int noise_basis_enum = DEFAULT_NOISE_TYPE;
- if (!PyArg_ParseTuple(args, "Offfff|i:hybrid_multi_fractal", &value, &H, &lac, &oct, &ofs, &gn, &nb))
+ if (!PyArg_ParseTupleAndKeywords(
+ args, kw, "Offfff|$s:hybrid_multi_fractal", (char **)kwlist,
+ &value, &H, &lac, &oct, &ofs, &gn, &noise_basis_str))
+ {
return NULL;
+ }
+
+ if (!noise_basis_str) {
+ /* pass through */
+ }
+ else if (PyC_FlagSet_ValueFromID(
+ bpy_noise_types, noise_basis_str, &noise_basis_enum, "hybrid_multi_fractal") == -1)
+ {
+ return NULL;
+ }
if (mathutils_array_parse(vec, 3, 3, value, "hybrid_multi_fractal: invalid 'position' arg") == -1)
return NULL;
- return PyFloat_FromDouble(mg_HybridMultiFractal(vec[0], vec[1], vec[2], H, lac, oct, ofs, gn, nb));
+ return PyFloat_FromDouble(mg_HybridMultiFractal(vec[0], vec[1], vec[2], H, lac, oct, ofs, gn, noise_basis_enum));
}
PyDoc_STRVAR(M_Noise_ridged_multi_fractal_doc,
-".. function:: ridged_multi_fractal(position, H, lacunarity, octaves, offset, gain, noise_basis=noise.types.STDPERLIN)\n"
+".. function:: ridged_multi_fractal(position, H, lacunarity, octaves, offset, gain, noise_basis='PERLIN_ORIGINAL')\n"
"\n"
" Returns ridged multifractal value from the noise basis at the specified position.\n"
"\n"
-" :arg position: The position to evaluate the selected noise function at.\n"
+" :arg position: The position to evaluate the selected noise function.\n"
" :type position: :class:`mathutils.Vector`\n"
" :arg H: The fractal dimension of the roughest areas.\n"
" :type H: float\n"
@@ -692,67 +882,94 @@ PyDoc_STRVAR(M_Noise_ridged_multi_fractal_doc,
" :type offset: float\n"
" :arg gain: Scaling applied to the values.\n"
" :type gain: float\n"
-" :arg noise_basis: The type of noise to be evaluated.\n"
-" :type noise_basis: Value in noise.types or int\n"
+BPY_NOISE_BASIS_ENUM_DOC
" :return: The ridged multifractal value.\n"
" :rtype: float\n"
);
-static PyObject *M_Noise_ridged_multi_fractal(PyObject *UNUSED(self), PyObject *args)
+static PyObject *M_Noise_ridged_multi_fractal(PyObject *UNUSED(self), PyObject *args, PyObject *kw)
{
+ static const char *kwlist[] = {"", "", "", "", "", "", "noise_basis", NULL};
PyObject *value;
float vec[3];
+ const char *noise_basis_str = NULL;
float H, lac, oct, ofs, gn;
- int nb = 1;
+ int noise_basis_enum = DEFAULT_NOISE_TYPE;
+
+ if (!PyArg_ParseTupleAndKeywords(
+ args, kw, "Offfff|$s:ridged_multi_fractal", (char **)kwlist,
+ &value, &H, &lac, &oct, &ofs, &gn, &noise_basis_str))
+ {
+ return NULL;
+ }
- if (!PyArg_ParseTuple(args, "Offfff|i:ridged_multi_fractal", &value, &H, &lac, &oct, &ofs, &gn, &nb))
+ if (!noise_basis_str) {
+ /* pass through */
+ }
+ else if (PyC_FlagSet_ValueFromID(
+ bpy_noise_types, noise_basis_str, &noise_basis_enum, "ridged_multi_fractal") == -1)
+ {
return NULL;
+ }
if (mathutils_array_parse(vec, 3, 3, value, "ridged_multi_fractal: invalid 'position' arg") == -1)
return NULL;
- return PyFloat_FromDouble(mg_RidgedMultiFractal(vec[0], vec[1], vec[2], H, lac, oct, ofs, gn, nb));
+ return PyFloat_FromDouble(mg_RidgedMultiFractal(vec[0], vec[1], vec[2], H, lac, oct, ofs, gn, noise_basis_enum));
}
PyDoc_STRVAR(M_Noise_voronoi_doc,
-".. function:: voronoi(position, distance_metric=noise.distance_metrics.DISTANCE, exponent=2.5)\n"
+".. function:: voronoi(position, distance_metric='DISTANCE', exponent=2.5)\n"
"\n"
" Returns a list of distances to the four closest features and their locations.\n"
"\n"
-" :arg position: The position to evaluate the selected noise function at.\n"
+" :arg position: The position to evaluate the selected noise function.\n"
" :type position: :class:`mathutils.Vector`\n"
-" :arg distance_metric: Method of measuring distance.\n"
-" :type distance_metric: Value in noise.distance_metrics or int\n"
+BPY_NOISE_METRIC_ENUM_DOC
" :arg exponent: The exponent for Minkowski distance metric.\n"
" :type exponent: float\n"
" :return: A list of distances to the four closest features and their locations.\n"
" :rtype: list of four floats, list of four :class:`mathutils.Vector` types\n"
);
-static PyObject *M_Noise_voronoi(PyObject *UNUSED(self), PyObject *args)
+static PyObject *M_Noise_voronoi(PyObject *UNUSED(self), PyObject *args, PyObject *kw)
{
+ static const char *kwlist[] = {"", "distance_metric", "exponent", NULL};
PyObject *value;
PyObject *list;
PyObject *ret;
float vec[3];
+ const char *metric_str = NULL;
float da[4], pa[12];
- int dtype = 0;
+ int metric_enum = DEFAULT_METRIC_TYPE;
float me = 2.5f; /* default minkowski exponent */
int i;
- if (!PyArg_ParseTuple(args, "O|if:voronoi", &value, &dtype, &me))
+ if (!PyArg_ParseTupleAndKeywords(
+ args, kw, "O|$sf:voronoi", (char **)kwlist,
+ &value, &metric_str, &me))
+ {
return NULL;
+ }
+
+ if (!metric_str) {
+ /* pass through */
+ }
+ else if (PyC_FlagSet_ValueFromID(
+ bpy_noise_metrics, metric_str, &metric_enum, "voronoi") == -1)
+ {
+ return NULL;
+ }
if (mathutils_array_parse(vec, 3, 3, value, "voronoi: invalid 'position' arg") == -1)
return NULL;
list = PyList_New(4);
- voronoi(vec[0], vec[1], vec[2], da, pa, me, dtype);
+ voronoi(vec[0], vec[1], vec[2], da, pa, me, metric_enum);
for (i = 0; i < 4; i++) {
PyObject *v = Vector_CreatePyObject(pa + 3 * i, 3, NULL);
PyList_SET_ITEM(list, i, v);
- Py_DECREF(v);
}
ret = Py_BuildValue("[[ffff]O]", da[0], da[1], da[2], da[3], list);
@@ -765,7 +982,7 @@ PyDoc_STRVAR(M_Noise_cell_doc,
"\n"
" Returns cell noise value at the specified position.\n"
"\n"
-" :arg position: The position to evaluate the selected noise function at.\n"
+" :arg position: The position to evaluate the selected noise function.\n"
" :type position: :class:`mathutils.Vector`\n"
" :return: The cell noise value.\n"
" :rtype: float\n"
@@ -789,7 +1006,7 @@ PyDoc_STRVAR(M_Noise_cell_vector_doc,
"\n"
" Returns cell noise vector at the specified position.\n"
"\n"
-" :arg position: The position to evaluate the selected noise function at.\n"
+" :arg position: The position to evaluate the selected noise function.\n"
" :type position: :class:`mathutils.Vector`\n"
" :return: The cell noise vector.\n"
" :rtype: :class:`mathutils.Vector`\n"
@@ -812,19 +1029,19 @@ static PyObject *M_Noise_cell_vector(PyObject *UNUSED(self), PyObject *args)
static PyMethodDef M_Noise_methods[] = {
{"seed_set", (PyCFunction) M_Noise_seed_set, METH_VARARGS, M_Noise_seed_set_doc},
{"random", (PyCFunction) M_Noise_random, METH_NOARGS, M_Noise_random_doc},
- {"random_unit_vector", (PyCFunction) M_Noise_random_unit_vector, METH_VARARGS, M_Noise_random_unit_vector_doc},
- /*{"random_vector", (PyCFunction) M_Noise_random_vector, METH_VARARGS, M_Noise_random_vector_doc},*/
- {"noise", (PyCFunction) M_Noise_noise, METH_VARARGS, M_Noise_noise_doc},
- {"noise_vector", (PyCFunction) M_Noise_noise_vector, METH_VARARGS, M_Noise_noise_vector_doc},
- {"turbulence", (PyCFunction) M_Noise_turbulence, METH_VARARGS, M_Noise_turbulence_doc},
- {"turbulence_vector", (PyCFunction) M_Noise_turbulence_vector, METH_VARARGS, M_Noise_turbulence_vector_doc},
- {"fractal", (PyCFunction) M_Noise_fractal, METH_VARARGS, M_Noise_fractal_doc},
- {"multi_fractal", (PyCFunction) M_Noise_multi_fractal, METH_VARARGS, M_Noise_multi_fractal_doc},
- {"variable_lacunarity", (PyCFunction) M_Noise_variable_lacunarity, METH_VARARGS, M_Noise_variable_lacunarity_doc},
- {"hetero_terrain", (PyCFunction) M_Noise_hetero_terrain, METH_VARARGS, M_Noise_hetero_terrain_doc},
- {"hybrid_multi_fractal", (PyCFunction) M_Noise_hybrid_multi_fractal, METH_VARARGS, M_Noise_hybrid_multi_fractal_doc},
- {"ridged_multi_fractal", (PyCFunction) M_Noise_ridged_multi_fractal, METH_VARARGS, M_Noise_ridged_multi_fractal_doc},
- {"voronoi", (PyCFunction) M_Noise_voronoi, METH_VARARGS, M_Noise_voronoi_doc},
+ {"random_unit_vector", (PyCFunction) M_Noise_random_unit_vector, METH_VARARGS | METH_KEYWORDS, M_Noise_random_unit_vector_doc},
+ {"random_vector", (PyCFunction) M_Noise_random_vector, METH_VARARGS | METH_KEYWORDS, M_Noise_random_vector_doc},
+ {"noise", (PyCFunction) M_Noise_noise, METH_VARARGS | METH_KEYWORDS, M_Noise_noise_doc},
+ {"noise_vector", (PyCFunction) M_Noise_noise_vector, METH_VARARGS | METH_KEYWORDS, M_Noise_noise_vector_doc},
+ {"turbulence", (PyCFunction) M_Noise_turbulence, METH_VARARGS | METH_KEYWORDS, M_Noise_turbulence_doc},
+ {"turbulence_vector", (PyCFunction) M_Noise_turbulence_vector, METH_VARARGS | METH_KEYWORDS, M_Noise_turbulence_vector_doc},
+ {"fractal", (PyCFunction) M_Noise_fractal, METH_VARARGS | METH_KEYWORDS, M_Noise_fractal_doc},
+ {"multi_fractal", (PyCFunction) M_Noise_multi_fractal, METH_VARARGS | METH_KEYWORDS, M_Noise_multi_fractal_doc},
+ {"variable_lacunarity", (PyCFunction) M_Noise_variable_lacunarity, METH_VARARGS | METH_KEYWORDS, M_Noise_variable_lacunarity_doc},
+ {"hetero_terrain", (PyCFunction) M_Noise_hetero_terrain, METH_VARARGS | METH_KEYWORDS, M_Noise_hetero_terrain_doc},
+ {"hybrid_multi_fractal", (PyCFunction) M_Noise_hybrid_multi_fractal, METH_VARARGS | METH_KEYWORDS, M_Noise_hybrid_multi_fractal_doc},
+ {"ridged_multi_fractal", (PyCFunction) M_Noise_ridged_multi_fractal, METH_VARARGS | METH_KEYWORDS, M_Noise_ridged_multi_fractal_doc},
+ {"voronoi", (PyCFunction) M_Noise_voronoi, METH_VARARGS | METH_KEYWORDS, M_Noise_voronoi_doc},
{"cell", (PyCFunction) M_Noise_cell, METH_VARARGS, M_Noise_cell_doc},
{"cell_vector", (PyCFunction) M_Noise_cell_vector, METH_VARARGS, M_Noise_cell_vector_doc},
{NULL, NULL, 0, NULL}
@@ -845,78 +1062,10 @@ static struct PyModuleDef M_Noise_module_def = {
/*----------------------------MODULE INIT-------------------------*/
PyMODINIT_FUNC PyInit_mathutils_noise(void)
{
- PyObject *sys_modules = PyImport_GetModuleDict();
PyObject *submodule = PyModule_Create(&M_Noise_module_def);
- PyObject *item_types, *item_metrics;
/* use current time as seed for random number generator by default */
setRndSeed(0);
- PyModule_AddObject(submodule, "types", (item_types = PyInit_mathutils_noise_types()));
- PyDict_SetItemString(sys_modules, "noise.types", item_types);
- Py_INCREF(item_types);
-
- PyModule_AddObject(submodule, "distance_metrics", (item_metrics = PyInit_mathutils_noise_metrics()));
- PyDict_SetItemString(sys_modules, "noise.distance_metrics", item_metrics);
- Py_INCREF(item_metrics);
-
- return submodule;
-}
-
-/*----------------------------SUBMODULE INIT-------------------------*/
-static struct PyModuleDef M_NoiseTypes_module_def = {
- PyModuleDef_HEAD_INIT,
- "mathutils.noise.types", /* m_name */
- NULL, /* m_doc */
- 0, /* m_size */
- NULL, /* m_methods */
- NULL, /* m_reload */
- NULL, /* m_traverse */
- NULL, /* m_clear */
- NULL, /* m_free */
-};
-
-PyMODINIT_FUNC PyInit_mathutils_noise_types(void)
-{
- PyObject *submodule = PyModule_Create(&M_NoiseTypes_module_def);
-
- PyModule_AddIntConstant(submodule, "BLENDER", TEX_BLENDER);
- PyModule_AddIntConstant(submodule, "STDPERLIN", TEX_STDPERLIN);
- PyModule_AddIntConstant(submodule, "NEWPERLIN", TEX_NEWPERLIN);
- PyModule_AddIntConstant(submodule, "VORONOI_F1", TEX_VORONOI_F1);
- PyModule_AddIntConstant(submodule, "VORONOI_F2", TEX_VORONOI_F2);
- PyModule_AddIntConstant(submodule, "VORONOI_F3", TEX_VORONOI_F3);
- PyModule_AddIntConstant(submodule, "VORONOI_F4", TEX_VORONOI_F4);
- PyModule_AddIntConstant(submodule, "VORONOI_F2F1", TEX_VORONOI_F2F1);
- PyModule_AddIntConstant(submodule, "VORONOI_CRACKLE", TEX_VORONOI_CRACKLE);
- PyModule_AddIntConstant(submodule, "CELLNOISE", TEX_CELLNOISE);
-
- return submodule;
-}
-
-static struct PyModuleDef M_NoiseMetrics_module_def = {
- PyModuleDef_HEAD_INIT,
- "mathutils.noise.distance_metrics", /* m_name */
- NULL, /* m_doc */
- 0, /* m_size */
- NULL, /* m_methods */
- NULL, /* m_reload */
- NULL, /* m_traverse */
- NULL, /* m_clear */
- NULL, /* m_free */
-};
-
-PyMODINIT_FUNC PyInit_mathutils_noise_metrics(void)
-{
- PyObject *submodule = PyModule_Create(&M_NoiseMetrics_module_def);
-
- PyModule_AddIntConstant(submodule, "DISTANCE", TEX_DISTANCE);
- PyModule_AddIntConstant(submodule, "DISTANCE_SQUARED", TEX_DISTANCE_SQUARED);
- PyModule_AddIntConstant(submodule, "MANHATTAN", TEX_MANHATTAN);
- PyModule_AddIntConstant(submodule, "CHEBYCHEV", TEX_CHEBYCHEV);
- PyModule_AddIntConstant(submodule, "MINKOVSKY_HALF", TEX_MINKOVSKY_HALF);
- PyModule_AddIntConstant(submodule, "MINKOVSKY_FOUR", TEX_MINKOVSKY_FOUR);
- PyModule_AddIntConstant(submodule, "MINKOVSKY", TEX_MINKOVSKY);
-
return submodule;
}
diff --git a/source/blender/python/mathutils/mathutils_noise.h b/source/blender/python/mathutils/mathutils_noise.h
index f2218b28f8f..469cd9636e6 100644
--- a/source/blender/python/mathutils/mathutils_noise.h
+++ b/source/blender/python/mathutils/mathutils_noise.h
@@ -28,7 +28,5 @@
#define __MATHUTILS_NOISE_H__
PyMODINIT_FUNC PyInit_mathutils_noise(void);
-PyMODINIT_FUNC PyInit_mathutils_noise_types(void);
-PyMODINIT_FUNC PyInit_mathutils_noise_metrics(void);
#endif /* __MATHUTILS_NOISE_H__ */
diff --git a/source/blender/python/simple_enum_gen.py b/source/blender/python/simple_enum_gen.py
index 4f3159b9b25..3a9c1847fc7 100644
--- a/source/blender/python/simple_enum_gen.py
+++ b/source/blender/python/simple_enum_gen.py
@@ -34,7 +34,7 @@ defs = """
SPACE_ACTION,
SPACE_NLA,
SPACE_SCRIPT, #Deprecated
- SPACE_TIME,
+ SPACE_TIME, #Deprecated
SPACE_NODE,
SPACEICONMAX
"""