diff options
Diffstat (limited to 'source/blender/python/intern')
21 files changed, 385 insertions, 193 deletions
diff --git a/source/blender/python/intern/CMakeLists.txt b/source/blender/python/intern/CMakeLists.txt index 0b05a0dfcfe..769618005af 100644 --- a/source/blender/python/intern/CMakeLists.txt +++ b/source/blender/python/intern/CMakeLists.txt @@ -77,6 +77,7 @@ set(SRC bpy_rna_driver.c bpy_rna_gizmo.c bpy_rna_id_collection.c + bpy_rna_types_capi.c bpy_traceback.c bpy_utils_previews.c bpy_utils_units.c @@ -113,6 +114,7 @@ set(SRC bpy_rna_driver.h bpy_rna_gizmo.h bpy_rna_id_collection.h + bpy_rna_types_capi.h bpy_traceback.h bpy_utils_previews.h bpy_utils_units.h diff --git a/source/blender/python/intern/bpy.c b/source/blender/python/intern/bpy.c index 5a36535f3e3..de8fd87db58 100644 --- a/source/blender/python/intern/bpy.c +++ b/source/blender/python/intern/bpy.c @@ -44,6 +44,7 @@ #include "bpy_rna.h" #include "bpy_rna_gizmo.h" #include "bpy_rna_id_collection.h" +#include "bpy_rna_types_capi.h" #include "bpy_utils_previews.h" #include "bpy_utils_units.h" @@ -379,10 +380,7 @@ void BPy_init_modules(void) PyModule_AddObject(mod, "types", BPY_rna_types()); /* needs to be first so bpy_types can run */ - BPY_library_load_module(mod); - BPY_library_write_module(mod); - - BPY_rna_id_collection_module(mod); + BPY_library_load_type_ready(); BPY_rna_gizmo_module(mod); @@ -406,8 +404,8 @@ void BPy_init_modules(void) PyModule_AddObject(mod, "context", (PyObject *)bpy_context_module); - /* register bpy/rna classmethod callbacks */ - BPY_rna_register_cb(); + /* Register methods and property get/set for RNA types. */ + BPY_rna_types_extend_capi(); /* utility func's that have nowhere else to go */ PyModule_AddObject(mod, diff --git a/source/blender/python/intern/bpy_app.c b/source/blender/python/intern/bpy_app.c index a9bdef1c3e4..957d49eb04e 100644 --- a/source/blender/python/intern/bpy_app.c +++ b/source/blender/python/intern/bpy_app.c @@ -82,10 +82,10 @@ extern char build_system[]; static PyTypeObject BlenderAppType; static PyStructSequence_Field app_info_fields[] = { - {"version", "The Blender version as a tuple of 3 numbers. eg. (2, 50, 11)"}, + {"version", "The Blender version as a tuple of 3 numbers. eg. (2, 83, 1)"}, {"version_string", "The Blender version formatted as a string"}, - {"version_char", "The Blender version character (for minor releases)"}, {"version_cycle", "The release status of this build alpha/beta/rc/release"}, + {"version_char", "Deprecated, always an empty string"}, {"binary_path", "The location of Blender's executable, useful for utilities that open new instances"}, {"background", @@ -160,12 +160,12 @@ static PyObject *make_app_info(void) #define SetBytesItem(str) PyStructSequence_SET_ITEM(app_info, pos++, PyBytes_FromString(str)) #define SetObjItem(obj) PyStructSequence_SET_ITEM(app_info, pos++, obj) - SetObjItem(PyC_Tuple_Pack_I32(BLENDER_VERSION / 100, BLENDER_VERSION % 100, BLENDER_SUBVERSION)); - SetObjItem(PyUnicode_FromFormat( - "%d.%02d (sub %d)", BLENDER_VERSION / 100, BLENDER_VERSION % 100, BLENDER_SUBVERSION)); + SetObjItem( + PyC_Tuple_Pack_I32(BLENDER_VERSION / 100, BLENDER_VERSION % 100, BLENDER_VERSION_PATCH)); + SetStrItem(BKE_blender_version_string()); - SetStrItem(STRINGIFY(BLENDER_VERSION_CHAR)); SetStrItem(STRINGIFY(BLENDER_VERSION_CYCLE)); + SetStrItem(""); SetStrItem(BKE_appdir_program_path()); SetObjItem(PyBool_FromLong(G.background)); SetObjItem(PyBool_FromLong(G.factory_startup)); diff --git a/source/blender/python/intern/bpy_app_handlers.c b/source/blender/python/intern/bpy_app_handlers.c index 28498e116df..dde1d13477f 100644 --- a/source/blender/python/intern/bpy_app_handlers.c +++ b/source/blender/python/intern/bpy_app_handlers.c @@ -44,8 +44,16 @@ void bpy_app_generic_callback(struct Main *main, static PyTypeObject BlenderAppCbType; static PyStructSequence_Field app_cb_info_fields[] = { - {"frame_change_pre", "on frame change for playback and rendering (before)"}, - {"frame_change_post", "on frame change for playback and rendering (after)"}, + {"frame_change_pre", + "Called after frame change for playback and rendering, before any data is evaluated for the " + "new frame. This makes it possible to change data and relations (for example swap an object " + "to another mesh) for the new frame. Note that this handler is **not** to be used as 'before " + "the frame changes' event. The dependency graph is not available in this handler, as data " + "and relations may have been altered and the dependency graph has not yet been updated for " + "that."}, + {"frame_change_post", + "Called after frame change for playback and rendering, after the data has been evaluated " + "for the new frame."}, {"render_pre", "on render (before)"}, {"render_post", "on render (after)"}, {"render_write", "on writing a render frame (directly after the frame is written)"}, diff --git a/source/blender/python/intern/bpy_capi_utils.c b/source/blender/python/intern/bpy_capi_utils.c index f63b77e1726..89ef2f40a30 100644 --- a/source/blender/python/intern/bpy_capi_utils.c +++ b/source/blender/python/intern/bpy_capi_utils.c @@ -24,6 +24,7 @@ #include <Python.h> #include "BLI_dynstr.h" +#include "BLI_listbase.h" #include "BLI_utildefines.h" #include "bpy_capi_utils.h" @@ -91,7 +92,7 @@ void BPy_reports_write_stdout(const ReportList *reports, const char *header) PySys_WriteStdout("%s\n", header); } - for (const Report *report = reports->list.first; report; report = report->next) { + LISTBASE_FOREACH (const Report *, report, &reports->list) { PySys_WriteStdout("%s: %s\n", report->typestr, report->message); } } diff --git a/source/blender/python/intern/bpy_driver.c b/source/blender/python/intern/bpy_driver.c index 726599ff06e..50ae05694eb 100644 --- a/source/blender/python/intern/bpy_driver.c +++ b/source/blender/python/intern/bpy_driver.c @@ -33,7 +33,7 @@ #include "BLI_math_base.h" #include "BLI_string.h" -#include "BKE_fcurve.h" +#include "BKE_fcurve_driver.h" #include "BKE_global.h" #include "bpy_rna_driver.h" /* for pyrna_driver_get_variable_value */ diff --git a/source/blender/python/intern/bpy_gizmo_wrap.c b/source/blender/python/intern/bpy_gizmo_wrap.c index 8ff3af59930..774ad95c3eb 100644 --- a/source/blender/python/intern/bpy_gizmo_wrap.c +++ b/source/blender/python/intern/bpy_gizmo_wrap.c @@ -101,8 +101,8 @@ fail: static void gizmo_properties_init(wmGizmoType *gzt) { - PyTypeObject *py_class = gzt->ext.data; - RNA_struct_blender_type_set(gzt->ext.srna, gzt); + PyTypeObject *py_class = gzt->rna_ext.data; + RNA_struct_blender_type_set(gzt->rna_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 @@ -160,9 +160,9 @@ void BPY_RNA_gizmo_wrapper(wmGizmoType *gzt, void *userdata) /* don't do translations here yet */ #if 0 - /* Use i18n context from ext.srna if possible (py gizmogroups). */ - if (gt->ext.srna) { - RNA_def_struct_translation_context(gt->srna, RNA_struct_translation_context(gt->ext.srna)); + /* Use i18n context from rna_ext.srna if possible (py gizmogroups). */ + if (gt->rna_ext.srna) { + RNA_def_struct_translation_context(gt->srna, RNA_struct_translation_context(gt->rna_ext.srna)); } #endif @@ -179,8 +179,8 @@ void BPY_RNA_gizmo_wrapper(wmGizmoType *gzt, void *userdata) static void gizmogroup_properties_init(wmGizmoGroupType *gzgt) { - PyTypeObject *py_class = gzgt->ext.data; - RNA_struct_blender_type_set(gzgt->ext.srna, gzgt); + PyTypeObject *py_class = gzgt->rna_ext.data; + RNA_struct_blender_type_set(gzgt->rna_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 @@ -203,9 +203,9 @@ void BPY_RNA_gizmogroup_wrapper(wmGizmoGroupType *gzgt, void *userdata) /* don't do translations here yet */ #if 0 - /* Use i18n context from ext.srna if possible (py gizmogroups). */ - if (gzgt->ext.srna) { - RNA_def_struct_translation_context(gzgt->srna, RNA_struct_translation_context(gzgt->ext.srna)); + /* Use i18n context from rna_ext.srna if possible (py gizmogroups). */ + if (gzgt->rna_ext.srna) { + RNA_def_struct_translation_context(gzgt->srna, RNA_struct_translation_context(gzgt->rna_ext.srna)); } #endif diff --git a/source/blender/python/intern/bpy_interface.c b/source/blender/python/intern/bpy_interface.c index fdf7e127af9..6da1715b02d 100644 --- a/source/blender/python/intern/bpy_interface.c +++ b/source/blender/python/intern/bpy_interface.c @@ -279,9 +279,10 @@ void BPY_python_start(int argc, const char **argv) * While harmless, it's noisy. */ Py_FrozenFlag = 1; - /* Only use the systems environment variables when explicitly requested. + /* Only use the systems environment variables and site when explicitly requested. * Since an incorrect 'PYTHONPATH' causes difficult to debug errors, see: T72807. */ Py_IgnoreEnvironmentFlag = !py_use_system_env; + Py_NoUserSiteDirectory = !py_use_system_env; Py_Initialize(); @@ -940,7 +941,7 @@ static void bpy_module_delay_init(PyObject *bpy_proxy) char filename_abs[1024]; BLI_strncpy(filename_abs, filename_rel, sizeof(filename_abs)); - BLI_path_cwd(filename_abs, sizeof(filename_abs)); + BLI_path_abs_from_cwd(filename_abs, sizeof(filename_abs)); Py_DECREF(filename_obj); argv[0] = filename_abs; diff --git a/source/blender/python/intern/bpy_library.h b/source/blender/python/intern/bpy_library.h index 3fd116d7028..6840807d2b0 100644 --- a/source/blender/python/intern/bpy_library.h +++ b/source/blender/python/intern/bpy_library.h @@ -21,7 +21,9 @@ #ifndef __BPY_LIBRARY_H__ #define __BPY_LIBRARY_H__ -int BPY_library_load_module(PyObject *mod_par); -int BPY_library_write_module(PyObject *mod_par); +int BPY_library_load_type_ready(void); +extern PyMethodDef BPY_library_load_method_def; + +extern PyMethodDef BPY_library_write_method_def; #endif /* __BPY_LIBRARY_H__ */ diff --git a/source/blender/python/intern/bpy_library_load.c b/source/blender/python/intern/bpy_library_load.c index 989b7931444..05cbc9af601 100644 --- a/source/blender/python/intern/bpy_library_load.c +++ b/source/blender/python/intern/bpy_library_load.c @@ -459,15 +459,15 @@ static PyObject *bpy_lib_dir(BPy_Library *self) return PyDict_Keys(self->dict); } -int BPY_library_load_module(PyObject *mod_par) +PyMethodDef BPY_library_load_method_def = { + "load", + (PyCFunction)bpy_lib_load, + METH_STATIC | METH_VARARGS | METH_KEYWORDS, + bpy_lib_load_doc, +}; + +int BPY_library_load_type_ready(void) { - static PyMethodDef load_meth = { - "load", - (PyCFunction)bpy_lib_load, - METH_STATIC | METH_VARARGS | METH_KEYWORDS, - bpy_lib_load_doc, - }; - PyModule_AddObject(mod_par, "_library_load", PyCFunction_New(&load_meth, NULL)); /* some compilers don't like accessing this directly, delay assignment */ bpy_lib_Type.tp_getattro = PyObject_GenericGetAttr; diff --git a/source/blender/python/intern/bpy_library_write.c b/source/blender/python/intern/bpy_library_write.c index 6c8f1deb126..fec0cef7b05 100644 --- a/source/blender/python/intern/bpy_library_write.c +++ b/source/blender/python/intern/bpy_library_write.c @@ -204,16 +204,9 @@ finally: return ret; } -int BPY_library_write_module(PyObject *mod_par) -{ - static PyMethodDef write_meth = { - "write", - (PyCFunction)bpy_lib_write, - METH_STATIC | METH_VARARGS | METH_KEYWORDS, - bpy_lib_write_doc, - }; - - PyModule_AddObject(mod_par, "_library_write", PyCFunction_New(&write_meth, NULL)); - - return 0; -} +PyMethodDef BPY_library_write_method_def = { + "write", + (PyCFunction)bpy_lib_write, + METH_STATIC | METH_VARARGS | METH_KEYWORDS, + bpy_lib_write_doc, +}; diff --git a/source/blender/python/intern/bpy_operator_wrap.c b/source/blender/python/intern/bpy_operator_wrap.c index b7d3c99d3da..9fb25d41844 100644 --- a/source/blender/python/intern/bpy_operator_wrap.c +++ b/source/blender/python/intern/bpy_operator_wrap.c @@ -39,8 +39,8 @@ static void operator_properties_init(wmOperatorType *ot) { - PyTypeObject *py_class = ot->ext.data; - RNA_struct_blender_type_set(ot->ext.srna, ot); + PyTypeObject *py_class = ot->rna_ext.data; + RNA_struct_blender_type_set(ot->rna_ext.srna, ot); /* Only call this so pyrna_deferred_register_class gives a useful error * WM_operatortype_append_ptr will call RNA_def_struct_identifier later. @@ -123,9 +123,9 @@ void BPY_RNA_operator_wrapper(wmOperatorType *ot, void *userdata) *ot = *((wmOperatorType *)userdata); ot->srna = srna; /* restore */ - /* Use i18n context from ext.srna if possible (py operators). */ - if (ot->ext.srna) { - RNA_def_struct_translation_context(ot->srna, RNA_struct_translation_context(ot->ext.srna)); + /* Use i18n context from rna_ext.srna if possible (py operators). */ + if (ot->rna_ext.srna) { + RNA_def_struct_translation_context(ot->srna, RNA_struct_translation_context(ot->rna_ext.srna)); } operator_properties_init(ot); @@ -142,11 +142,11 @@ void BPY_RNA_operator_macro_wrapper(wmOperatorType *ot, void *userdata) ot->flag |= data->flag; /* append flags to the one set by registration */ ot->pyop_poll = data->pyop_poll; ot->ui = data->ui; - ot->ext = data->ext; + ot->rna_ext = data->rna_ext; - /* Use i18n context from ext.srna if possible (py operators). */ - if (ot->ext.srna) { - RNA_def_struct_translation_context(ot->srna, RNA_struct_translation_context(ot->ext.srna)); + /* Use i18n context from rna_ext.srna if possible (py operators). */ + if (ot->rna_ext.srna) { + RNA_def_struct_translation_context(ot->srna, RNA_struct_translation_context(ot->rna_ext.srna)); } operator_properties_init(ot); diff --git a/source/blender/python/intern/bpy_rna.c b/source/blender/python/intern/bpy_rna.c index 9579f78be30..179daad2f60 100644 --- a/source/blender/python/intern/bpy_rna.c +++ b/source/blender/python/intern/bpy_rna.c @@ -4091,7 +4091,7 @@ static PyObject *pyrna_struct_bl_rna_get_subclass(PyObject *cls, PyObject *args) if (srna_base == &RNA_Node) { bNodeType *nt = nodeTypeFind(id); if (nt) { - RNA_pointer_create(NULL, &RNA_Struct, nt->ext.srna, &ptr); + RNA_pointer_create(NULL, &RNA_Struct, nt->rna_ext.srna, &ptr); return pyrna_struct_CreatePyObject(&ptr); } } @@ -9033,6 +9033,50 @@ static PyObject *pyrna_unregister_class(PyObject *UNUSED(self), PyObject *py_cla Py_RETURN_NONE; } +/** + * Extend RNA types with C/API methods, properties. + */ +void pyrna_struct_type_extend_capi(struct StructRNA *srna, + struct PyMethodDef *method, + struct PyGetSetDef *getset) +{ + /* See 'add_methods' in Python's 'typeobject.c'. */ + PyTypeObject *type = (PyTypeObject *)pyrna_srna_Subtype(srna); + PyObject *dict = type->tp_dict; + if (method != NULL) { + for (; method->ml_name != NULL; method++) { + PyObject *py_method; + + if (method->ml_flags & METH_CLASS) { + PyObject *cfunc = PyCFunction_New(method, (PyObject *)type); + py_method = PyClassMethod_New(cfunc); + Py_DECREF(cfunc); + } + else { + /* Currently only static and class methods are used. */ + BLI_assert(method->ml_flags & METH_STATIC); + py_method = PyCFunction_New(method, NULL); + } + + int err = PyDict_SetItemString(dict, method->ml_name, py_method); + Py_DECREF(py_method); + BLI_assert(!(err < 0)); + UNUSED_VARS_NDEBUG(err); + } + } + + if (getset != NULL) { + for (; getset->name != NULL; getset++) { + PyObject *descr = PyDescr_NewGetSet(type, getset); + /* Ensure we're not overwriting anything that already exists. */ + BLI_assert(PyDict_GetItem(dict, PyDescr_NAME(descr)) == NULL); + PyDict_SetItem(dict, PyDescr_NAME(descr), descr); + Py_DECREF(descr); + } + } + Py_DECREF(type); +} + /* Access to 'owner_id' internal global. */ static PyObject *pyrna_bl_owner_id_get(PyObject *UNUSED(self)) @@ -9076,92 +9120,3 @@ PyMethodDef meth_bpy_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 { - PyMethodDef py_method; - 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. ``BACKDROP`` can be used for backdrops in the node " - "editor.\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, - 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}, -}; - -void BPY_rna_register_cb(void) -{ - int i; - - for (i = 0; pyrna_cb_methods[i].bpy_srna; i++) { - PyObject *cls; - PyObject *func; - PyObject *classmethod; - PyObject *args = PyTuple_New(1); - - cls = pyrna_srna_Subtype(pyrna_cb_methods[i].bpy_srna); - func = PyCFunction_New(&pyrna_cb_methods[i].py_method, NULL); - PyTuple_SET_ITEM(args, 0, func); - classmethod = PyObject_CallObject((PyObject *)&PyClassMethod_Type, args); - - PyObject_SetAttrString(cls, pyrna_cb_methods[i].py_method.ml_name, classmethod); - - Py_DECREF(classmethod); - Py_DECREF(args); /* Clears 'func' too. */ - Py_DECREF(cls); - } -} diff --git a/source/blender/python/intern/bpy_rna.h b/source/blender/python/intern/bpy_rna.h index 5899c1659b5..652d65fe64c 100644 --- a/source/blender/python/intern/bpy_rna.h +++ b/source/blender/python/intern/bpy_rna.h @@ -185,7 +185,6 @@ PyObject *BPY_rna_module(void); void BPY_update_rna_module(void); /*PyObject *BPY_rna_doc(void);*/ PyObject *BPY_rna_types(void); -void BPY_rna_register_cb(void); PyObject *pyrna_struct_CreatePyObject(PointerRNA *ptr); PyObject *pyrna_prop_CreatePyObject(PointerRNA *ptr, PropertyRNA *prop); @@ -221,6 +220,10 @@ int pyrna_enum_value_from_id(const EnumPropertyItem *item, int pyrna_deferred_register_class(struct StructRNA *srna, PyTypeObject *py_class); +void pyrna_struct_type_extend_capi(struct StructRNA *srna, + struct PyMethodDef *py_method, + struct PyGetSetDef *py_getset); + /* called before stopping python */ void pyrna_alloc_types(void); void pyrna_free_types(void); diff --git a/source/blender/python/intern/bpy_rna_anim.c b/source/blender/python/intern/bpy_rna_anim.c index c8af6377d59..d792b2032b5 100644 --- a/source/blender/python/intern/bpy_rna_anim.c +++ b/source/blender/python/intern/bpy_rna_anim.c @@ -35,7 +35,7 @@ #include "ED_keyframes_edit.h" #include "ED_keyframing.h" -#include "BKE_animsys.h" +#include "BKE_anim_data.h" #include "BKE_context.h" #include "BKE_fcurve.h" #include "BKE_global.h" @@ -354,7 +354,7 @@ PyObject *pyrna_struct_keyframe_insert(BPy_StructRNA *self, PyObject *args, PyOb if (prop) { NlaStrip *strip = ptr.data; - FCurve *fcu = list_find_fcurve(&strip->fcurves, RNA_property_identifier(prop), index); + FCurve *fcu = BKE_fcurve_find(&strip->fcurves, RNA_property_identifier(prop), index); result = insert_keyframe_direct(&reports, ptr, prop, fcu, cfra, keytype, NULL, options); } @@ -462,7 +462,7 @@ PyObject *pyrna_struct_keyframe_delete(BPy_StructRNA *self, PyObject *args, PyOb if (prop) { ID *id = ptr.owner_id; NlaStrip *strip = ptr.data; - FCurve *fcu = list_find_fcurve(&strip->fcurves, RNA_property_identifier(prop), index); + FCurve *fcu = BKE_fcurve_find(&strip->fcurves, RNA_property_identifier(prop), index); /* NOTE: This should be true, or else we wouldn't be able to get here. */ BLI_assert(fcu != NULL); @@ -577,13 +577,13 @@ PyObject *pyrna_struct_driver_add(BPy_StructRNA *self, PyObject *args) if (index == -1) { /* all, use a list */ int i = 0; ret = PyList_New(0); - while ((fcu = list_find_fcurve(&adt->drivers, path_full, i++))) { + while ((fcu = BKE_fcurve_find(&adt->drivers, path_full, i++))) { RNA_pointer_create(id, &RNA_FCurve, fcu, &tptr); PyList_APPEND(ret, pyrna_struct_CreatePyObject(&tptr)); } } else { - fcu = list_find_fcurve(&adt->drivers, path_full, index); + fcu = BKE_fcurve_find(&adt->drivers, path_full, index); RNA_pointer_create(id, &RNA_FCurve, fcu, &tptr); ret = pyrna_struct_CreatePyObject(&tptr); } diff --git a/source/blender/python/intern/bpy_rna_callback.c b/source/blender/python/intern/bpy_rna_callback.c index cc9f5746bba..f9bcb8943f4 100644 --- a/source/blender/python/intern/bpy_rna_callback.c +++ b/source/blender/python/intern/bpy_rna_callback.c @@ -324,10 +324,8 @@ PyObject *pyrna_callback_classmethod_add(PyObject *UNUSED(self), PyObject *args) 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); + 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"; @@ -424,9 +422,7 @@ PyObject *pyrna_callback_classmethod_remove(PyObject *UNUSED(self), PyObject *ar 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); + WM_paint_cursor_end(handle); capsule_clear = true; } else if (RNA_struct_is_a(srna, &RNA_Space)) { diff --git a/source/blender/python/intern/bpy_rna_driver.c b/source/blender/python/intern/bpy_rna_driver.c index a8d8252b231..9240e34bbab 100644 --- a/source/blender/python/intern/bpy_rna_driver.c +++ b/source/blender/python/intern/bpy_rna_driver.c @@ -26,7 +26,7 @@ #include "BLI_utildefines.h" -#include "BKE_fcurve.h" +#include "BKE_fcurve_driver.h" #include "RNA_access.h" diff --git a/source/blender/python/intern/bpy_rna_id_collection.c b/source/blender/python/intern/bpy_rna_id_collection.c index 6b6ffa97995..b607f1635e6 100644 --- a/source/blender/python/intern/bpy_rna_id_collection.c +++ b/source/blender/python/intern/bpy_rna_id_collection.c @@ -385,32 +385,21 @@ static PyObject *bpy_orphans_purge(PyObject *UNUSED(self), return Py_None; } -int BPY_rna_id_collection_module(PyObject *mod_par) -{ - static PyMethodDef user_map = { - "user_map", (PyCFunction)bpy_user_map, METH_VARARGS | METH_KEYWORDS, bpy_user_map_doc}; - - 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)); - - static PyMethodDef orphans_purge = { - "orphans_purge", - (PyCFunction)bpy_orphans_purge, - METH_VARARGS | METH_KEYWORDS, - bpy_orphans_purge_doc, - }; - - PyModule_AddObject( - mod_par, "_rna_id_collection_orphans_purge", PyCFunction_New(&orphans_purge, NULL)); - - return 0; -} +PyMethodDef BPY_rna_id_collection_user_map_method_def = { + "user_map", + (PyCFunction)bpy_user_map, + METH_STATIC | METH_VARARGS | METH_KEYWORDS, + bpy_user_map_doc, +}; +PyMethodDef BPY_rna_id_collection_batch_remove_method_def = { + "batch_remove", + (PyCFunction)bpy_batch_remove, + METH_STATIC | METH_VARARGS | METH_KEYWORDS, + bpy_batch_remove_doc, +}; +PyMethodDef BPY_rna_id_collection_orphans_purge_method_def = { + "orphans_purge", + (PyCFunction)bpy_orphans_purge, + METH_STATIC | METH_VARARGS | METH_KEYWORDS, + bpy_orphans_purge_doc, +}; diff --git a/source/blender/python/intern/bpy_rna_id_collection.h b/source/blender/python/intern/bpy_rna_id_collection.h index 8cb375960a9..ee8f4c666a8 100644 --- a/source/blender/python/intern/bpy_rna_id_collection.h +++ b/source/blender/python/intern/bpy_rna_id_collection.h @@ -21,6 +21,8 @@ #ifndef __BPY_RNA_ID_COLLECTION_H__ #define __BPY_RNA_ID_COLLECTION_H__ -int BPY_rna_id_collection_module(PyObject *); +extern PyMethodDef BPY_rna_id_collection_user_map_method_def; +extern PyMethodDef BPY_rna_id_collection_batch_remove_method_def; +extern PyMethodDef BPY_rna_id_collection_orphans_purge_method_def; #endif /* __BPY_RNA_ID_COLLECTION_H__ */ diff --git a/source/blender/python/intern/bpy_rna_types_capi.c b/source/blender/python/intern/bpy_rna_types_capi.c new file mode 100644 index 00000000000..5a2ba4a5cdb --- /dev/null +++ b/source/blender/python/intern/bpy_rna_types_capi.c @@ -0,0 +1,216 @@ +/* + * 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. + */ + +/** \file + * \ingroup pythonintern + * + * This file extends RNA types from `bpy.types` with C/Python API methods and attributes. + * + * We should avoid adding code here, and prefer: + * - `source/blender/makesrna/intern/rna_context.c` using the RNA C API. + * - `release/scripts/modules/bpy_types.py` when additions c an be written in Python. + * + * Otherwise functions can be added here as a last resort. + */ + +#include <Python.h> +#include <descrobject.h> + +#include "RNA_types.h" + +#include "BLI_utildefines.h" + +#include "bpy_library.h" +#include "bpy_rna.h" +#include "bpy_rna_callback.h" +#include "bpy_rna_id_collection.h" +#include "bpy_rna_types_capi.h" + +#include "../generic/py_capi_utils.h" + +#include "RNA_access.h" + +#include "MEM_guardedalloc.h" + +#include "WM_api.h" + +/* -------------------------------------------------------------------- */ +/** \name Blend Data + * \{ */ + +static struct PyMethodDef pyrna_blenddata_methods[] = { + {NULL, NULL, 0, NULL}, /* #BPY_rna_id_collection_user_map_method_def */ + {NULL, NULL, 0, NULL}, /* #BPY_rna_id_collection_batch_remove_method_def */ + {NULL, NULL, 0, NULL}, /* #BPY_rna_id_collection_orphans_purge_method_def */ + {NULL, NULL, 0, NULL}, +}; + +/** \} */ + +/* -------------------------------------------------------------------- */ +/** \name Blend Data Libraries + * \{ */ + +static struct PyMethodDef pyrna_blenddatalibraries_methods[] = { + {NULL, NULL, 0, NULL}, /* #BPY_library_load_method_def */ + {NULL, NULL, 0, NULL}, /* #BPY_library_write_method_def */ + {NULL, NULL, 0, NULL}, +}; + +/** \} */ + +/* -------------------------------------------------------------------- */ +/** \name Window Manager Clipboard Property + * + * Avoid using the RNA API because this value may change between checking it's length + * and creating the buffer, causing writes past the allocated length. + * \{ */ + +static PyObject *pyrna_WindowManager_clipboard_get(PyObject *UNUSED(self), void *UNUSED(flag)) +{ + int text_len = 0; + char *text = WM_clipboard_text_get(false, &text_len); + PyObject *result = PyC_UnicodeFromByteAndSize(text ? text : "", text_len); + if (text != NULL) { + MEM_freeN(text); + } + return result; +} + +static int pyrna_WindowManager_clipboard_set(PyObject *UNUSED(self), + PyObject *value, + void *UNUSED(flag)) +{ + PyObject *value_coerce = NULL; + const char *text = PyC_UnicodeAsByte(value, &value_coerce); + if (text == NULL) { + return -1; + } + WM_clipboard_text_set(text, false); + Py_XDECREF(value_coerce); + return 0; +} + +/** \} */ + +/* -------------------------------------------------------------------- */ +/** \name Window Manager Type + * \{ */ + +static struct PyMethodDef pyrna_windowmanager_methods[] = { + {"draw_cursor_add", + (PyCFunction)pyrna_callback_classmethod_add, + METH_VARARGS | METH_CLASS, + ""}, + {"draw_cursor_remove", + (PyCFunction)pyrna_callback_classmethod_remove, + METH_VARARGS | METH_CLASS, + ""}, + {NULL, NULL, 0, NULL}, +}; + +static struct PyGetSetDef pyrna_windowmanager_getset[] = { + {"clipboard", + pyrna_WindowManager_clipboard_get, + pyrna_WindowManager_clipboard_set, + NULL, + NULL}, + {NULL, NULL, NULL, NULL, NULL} /* Sentinel */ +}; + +/** \} */ + +/* -------------------------------------------------------------------- */ +/** \name Space Type + * \{ */ + +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. ``BACKDROP`` can be used for backdrops in the node " + "editor.\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 PyMethodDef pyrna_space_methods[] = { + {"draw_handler_add", + (PyCFunction)pyrna_callback_classmethod_add, + METH_VARARGS | METH_CLASS, + pyrna_draw_handler_add_doc}, + {"draw_handler_remove", + (PyCFunction)pyrna_callback_classmethod_remove, + METH_VARARGS | METH_CLASS, + pyrna_draw_handler_remove_doc}, + {NULL, NULL, 0, NULL}, +}; + +/** \} */ + +/* -------------------------------------------------------------------- */ +/** \name Public API + * \{ */ + +void BPY_rna_types_extend_capi(void) +{ + /* BlendData */ + ARRAY_SET_ITEMS(pyrna_blenddata_methods, + BPY_rna_id_collection_user_map_method_def, + BPY_rna_id_collection_batch_remove_method_def, + BPY_rna_id_collection_orphans_purge_method_def); + BLI_assert(ARRAY_SIZE(pyrna_blenddata_methods) == 4); + pyrna_struct_type_extend_capi(&RNA_BlendData, pyrna_blenddata_methods, NULL); + + /* BlendDataLibraries */ + ARRAY_SET_ITEMS( + pyrna_blenddatalibraries_methods, BPY_library_load_method_def, BPY_library_write_method_def); + BLI_assert(ARRAY_SIZE(pyrna_blenddatalibraries_methods) == 3); + pyrna_struct_type_extend_capi(&RNA_BlendDataLibraries, pyrna_blenddatalibraries_methods, NULL); + + /* Space */ + pyrna_struct_type_extend_capi(&RNA_Space, pyrna_space_methods, NULL); + + /* WindowManager */ + pyrna_struct_type_extend_capi( + &RNA_WindowManager, pyrna_windowmanager_methods, pyrna_windowmanager_getset); +} + +/** \} */ diff --git a/source/blender/python/intern/bpy_rna_types_capi.h b/source/blender/python/intern/bpy_rna_types_capi.h new file mode 100644 index 00000000000..1049122e468 --- /dev/null +++ b/source/blender/python/intern/bpy_rna_types_capi.h @@ -0,0 +1,26 @@ +/* + * 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. + */ + +/** \file + * \ingroup pythonintern + */ + +#ifndef __BPY_RNA_TYPES_CAPI_H__ +#define __BPY_RNA_TYPES_CAPI_H__ + +void BPY_rna_types_extend_capi(void); + +#endif /* __BPY_RNA_TYPES_CAPI_H__ */ |