Changeset View
Changeset View
Standalone View
Standalone View
source/blender/python/intern/bpy_app_handlers.c
| Show All 30 Lines | |||||
| #include "RNA_access.h" | #include "RNA_access.h" | ||||
| #include "bpy_rna.h" | #include "bpy_rna.h" | ||||
| #include "bpy_app_handlers.h" | #include "bpy_app_handlers.h" | ||||
| #include "../generic/python_utildefines.h" | #include "../generic/python_utildefines.h" | ||||
| #include "BPY_extern.h" | #include "BPY_extern.h" | ||||
| void bpy_app_generic_callback(struct Main *main, | void bpy_app_generic_callback(struct Main *main, struct ID *id, void *arg); | ||||
| struct PointerRNA **pointers, | |||||
| const int num_pointers, | |||||
| void *arg); | |||||
| static PyTypeObject BlenderAppCbType; | static PyTypeObject BlenderAppCbType; | ||||
| static PyStructSequence_Field app_cb_info_fields[] = { | static PyStructSequence_Field app_cb_info_fields[] = { | ||||
| {(char *)"frame_change_pre", (char *)"on frame change for playback and rendering (before)"}, | {(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 *)"frame_change_post", (char *)"on frame change for playback and rendering (after)"}, | ||||
| {(char *)"render_pre", (char *)"on render (before)"}, | {(char *)"render_pre", (char *)"on render (before)"}, | ||||
| {(char *)"render_post", (char *)"on render (after)"}, | {(char *)"render_post", (char *)"on render (after)"}, | ||||
| ▲ Show 20 Lines • Show All 184 Lines • ▼ Show 20 Lines | |||||
| } | } | ||||
| Py_DECREF(perm_id_str); | Py_DECREF(perm_id_str); | ||||
| } | } | ||||
| PyGILState_Release(gilstate); | 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 */ | /* the actual callback - not necessarily called from py */ | ||||
| void bpy_app_generic_callback(struct Main *UNUSED(main), | void bpy_app_generic_callback(struct Main *UNUSED(main), struct ID *id, void *arg) | ||||
| struct PointerRNA **pointers, | |||||
| const int num_pointers, | |||||
| void *arg) | |||||
| { | { | ||||
| PyObject *cb_list = py_cb_array[POINTER_AS_INT(arg)]; | PyObject *cb_list = py_cb_array[POINTER_AS_INT(arg)]; | ||||
| if (PyList_GET_SIZE(cb_list) > 0) { | if (PyList_GET_SIZE(cb_list) > 0) { | ||||
| PyGILState_STATE gilstate = PyGILState_Ensure(); | PyGILState_STATE gilstate = PyGILState_Ensure(); | ||||
| const int num_arguments = 2; | PyObject *args = PyTuple_New(1); /* save python creating each call */ | ||||
| PyObject *args_all = PyTuple_New(num_arguments); /* save python creating each call */ | |||||
| PyObject *args_single = PyTuple_New(1); | |||||
| PyObject *func; | PyObject *func; | ||||
| PyObject *ret; | PyObject *ret; | ||||
| Py_ssize_t pos; | Py_ssize_t pos; | ||||
| /* setup arguments */ | /* setup arguments */ | ||||
| for (int i = 0; i < num_pointers; ++i) { | if (id) { | ||||
| PyTuple_SET_ITEM(args_all, i, pyrna_struct_CreatePyObject(pointers[i])); | PointerRNA id_ptr; | ||||
| } | RNA_id_pointer_create(id, &id_ptr); | ||||
| for (int i = num_pointers; i < num_arguments; ++i) { | PyTuple_SET_ITEM(args, 0, pyrna_struct_CreatePyObject(&id_ptr)); | ||||
| 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 { | else { | ||||
| PyTuple_SET_ITEM(args_single, 0, pyrna_struct_CreatePyObject(pointers[0])); | PyTuple_SET_ITEM(args, 0, Py_INCREF_RET(Py_None)); | ||||
| } | } | ||||
| /* Iterate the list and run the callbacks | /* Iterate the list and run the callbacks | ||||
| * note: don't store the list size since the scripts may remove themselves */ | * note: don't store the list size since the scripts may remove themselves */ | ||||
| for (pos = 0; pos < PyList_GET_SIZE(cb_list); pos++) { | for (pos = 0; pos < PyList_GET_SIZE(cb_list); pos++) { | ||||
| func = PyList_GET_ITEM(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); | ret = PyObject_Call(func, args, NULL); | ||||
| if (ret == NULL) { | if (ret == NULL) { | ||||
| /* Don't set last system variables because they might cause some | /* Don't set last system variables because they might cause some | ||||
| * dangling pointers to external render engines (when exception | * dangling pointers to external render engines (when exception | ||||
| * happens during rendering) which will break logic of render pipeline | * happens during rendering) which will break logic of render pipeline | ||||
| * which expects to be the only user of render engine when rendering | * which expects to be the only user of render engine when rendering | ||||
| * is finished. | * is finished. | ||||
| */ | */ | ||||
| PyErr_PrintEx(0); | PyErr_PrintEx(0); | ||||
| PyErr_Clear(); | PyErr_Clear(); | ||||
| } | } | ||||
| else { | else { | ||||
| Py_DECREF(ret); | Py_DECREF(ret); | ||||
| } | } | ||||
| } | } | ||||
| Py_DECREF(args_all); | Py_DECREF(args); | ||||
| Py_DECREF(args_single); | |||||
| PyGILState_Release(gilstate); | PyGILState_Release(gilstate); | ||||
| } | } | ||||
| } | } | ||||
| Context not available. | |||||