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:
authorSergey Sharybin <sergey.vfx@gmail.com>2019-09-09 11:25:04 +0300
committerSergey Sharybin <sergey.vfx@gmail.com>2019-09-11 11:43:27 +0300
commita650258158dd7ad8fa9b6cb1b7da749e30ae15c1 (patch)
tree840b324fbf9739dce8ac50da1acde80e2fb4f140 /source/blender/python/intern/bpy_app_handlers.c
parent022de797f1773f512f21cf9038787dd77e0fd5de (diff)
Python handlers: Pass depsgraph to events where it makes sense
The goal is to make it possible to access evaluated datablocks at a corresponding context. For example, be able to check evaluated state if an object used for rendering. Allows to write scripts in a safe manner for T63548 and T60094. Reviewers: brecht Differential Revision: https://developer.blender.org/D5726
Diffstat (limited to 'source/blender/python/intern/bpy_app_handlers.c')
-rw-r--r--source/blender/python/intern/bpy_app_handlers.c50
1 files changed, 41 insertions, 9 deletions
diff --git a/source/blender/python/intern/bpy_app_handlers.c b/source/blender/python/intern/bpy_app_handlers.c
index 77d036532f4..e6a8febbf29 100644
--- a/source/blender/python/intern/bpy_app_handlers.c
+++ b/source/blender/python/intern/bpy_app_handlers.c
@@ -36,7 +36,10 @@
#include "BPY_extern.h"
-void bpy_app_generic_callback(struct Main *main, struct ID *id, void *arg);
+void bpy_app_generic_callback(struct Main *main,
+ struct PointerRNA **pointers,
+ const int num_pointers,
+ void *arg);
static PyTypeObject BlenderAppCbType;
@@ -290,32 +293,58 @@ void BPY_app_handlers_reset(const short do_all)
PyGILState_Release(gilstate);
}
+static PyObject *choose_arguments(PyObject *func, PyObject *args_all, PyObject *args_single)
+{
+ if (!PyFunction_Check(func)) {
+ return args_all;
+ }
+ PyCodeObject *code = (PyCodeObject *)PyFunction_GetCode(func);
+ if (code->co_argcount == 1) {
+ return args_single;
+ }
+ return args_all;
+}
+
/* the actual callback - not necessarily called from py */
-void bpy_app_generic_callback(struct Main *UNUSED(main), struct ID *id, void *arg)
+void bpy_app_generic_callback(struct Main *UNUSED(main),
+ struct PointerRNA **pointers,
+ const int num_pointers,
+ void *arg)
{
PyObject *cb_list = py_cb_array[POINTER_AS_INT(arg)];
if (PyList_GET_SIZE(cb_list) > 0) {
PyGILState_STATE gilstate = PyGILState_Ensure();
- PyObject *args = PyTuple_New(1); /* save python creating each call */
+ const int num_arguments = 2;
+ PyObject *args_all = PyTuple_New(num_arguments); /* save python creating each call */
+ PyObject *args_single = PyTuple_New(1);
PyObject *func;
PyObject *ret;
Py_ssize_t pos;
/* setup arguments */
- if (id) {
- PointerRNA id_ptr;
- RNA_id_pointer_create(id, &id_ptr);
- PyTuple_SET_ITEM(args, 0, pyrna_struct_CreatePyObject(&id_ptr));
+ for (int i = 0; i < num_pointers; ++i) {
+ PyTuple_SET_ITEM(args_all, i, pyrna_struct_CreatePyObject(pointers[i]));
+ }
+ for (int i = num_pointers; i < num_arguments; ++i) {
+ PyTuple_SET_ITEM(args_all, i, Py_INCREF_RET(Py_None));
+ }
+
+ if (num_pointers == 0) {
+ PyTuple_SET_ITEM(args_single, 0, Py_INCREF_RET(Py_None));
+ }
+ else if (num_pointers == 1) {
+ args_single = args_all;
}
else {
- PyTuple_SET_ITEM(args, 0, Py_INCREF_RET(Py_None));
+ PyTuple_SET_ITEM(args_single, 0, pyrna_struct_CreatePyObject(pointers[0]));
}
/* Iterate the list and run the callbacks
* note: don't store the list size since the scripts may remove themselves */
for (pos = 0; pos < PyList_GET_SIZE(cb_list); pos++) {
func = PyList_GET_ITEM(cb_list, pos);
+ PyObject *args = choose_arguments(func, args_all, args_single);
ret = PyObject_Call(func, args, NULL);
if (ret == NULL) {
/* Don't set last system variables because they might cause some
@@ -332,7 +361,10 @@ void bpy_app_generic_callback(struct Main *UNUSED(main), struct ID *id, void *ar
}
}
- Py_DECREF(args);
+ Py_DECREF(args_all);
+ if (args_single != args_all) {
+ Py_DECREF(args_single);
+ }
PyGILState_Release(gilstate);
}