Changeset View
Changeset View
Standalone View
Standalone View
source/blender/python/intern/bpy_driver.c
| Show All 27 Lines | |||||
| #include <Python.h> | #include <Python.h> | ||||
| #include "DNA_anim_types.h" | #include "DNA_anim_types.h" | ||||
| #include "BLI_listbase.h" | #include "BLI_listbase.h" | ||||
| #include "BLI_math_base.h" | #include "BLI_math_base.h" | ||||
| #include "BLI_string.h" | #include "BLI_string.h" | ||||
| #include "BKE_animsys.h" | |||||
| #include "BKE_fcurve_driver.h" | #include "BKE_fcurve_driver.h" | ||||
| #include "BKE_global.h" | #include "BKE_global.h" | ||||
| #include "RNA_access.h" | |||||
| #include "RNA_types.h" | |||||
| #include "bpy_rna_driver.h" /* for pyrna_driver_get_variable_value */ | #include "bpy_rna_driver.h" /* for pyrna_driver_get_variable_value */ | ||||
| #include "bpy_intern_string.h" | #include "bpy_intern_string.h" | ||||
| #include "bpy_driver.h" | #include "bpy_driver.h" | ||||
| #include "bpy_rna.h" | |||||
| #include "BPY_extern.h" | #include "BPY_extern.h" | ||||
| extern void BPY_update_rna_module(void); | |||||
| #define USE_RNA_AS_PYOBJECT | #define USE_RNA_AS_PYOBJECT | ||||
| #define USE_BYTECODE_WHITELIST | #define USE_BYTECODE_WHITELIST | ||||
| #ifdef USE_BYTECODE_WHITELIST | #ifdef USE_BYTECODE_WHITELIST | ||||
| # include <opcode.h> | # include <opcode.h> | ||||
| #endif | #endif | ||||
| ▲ Show 20 Lines • Show All 315 Lines • ▼ Show 20 Lines | |||||
| # undef CODESIZE | # undef CODESIZE | ||||
| } | } | ||||
| return true; | return true; | ||||
| } | } | ||||
| #endif /* USE_BYTECODE_WHITELIST */ | #endif /* USE_BYTECODE_WHITELIST */ | ||||
| static PyObject *bpy_pydriver_depsgraph_as_pyobject(struct Depsgraph *depsgraph) | |||||
| { | |||||
| /* This should never happen, but it's probably better to have None in Python | |||||
| * than a NULL-wrapping Depsgraph py struct. */ | |||||
| BLI_assert(depsgraph != NULL); | |||||
| if (depsgraph == NULL) { | |||||
| Py_RETURN_NONE; | |||||
| } | |||||
| struct PointerRNA depsgraph_ptr; | |||||
| RNA_pointer_create(NULL, &RNA_Depsgraph, depsgraph, &depsgraph_ptr); | |||||
| return pyrna_struct_CreatePyObject(&depsgraph_ptr); | |||||
| } | |||||
| /* Adds a variable 'depsgraph' to the driver variables. This can then be used to obtain evaluated | |||||
| * datablocks, and the current view layer and scene. See T75553. */ | |||||
| static void bpy_pydriver_namespace_add_depsgraph(PyObject *driver_vars, | |||||
| struct Depsgraph *depsgraph) | |||||
| { | |||||
| PyObject *py_depsgraph = bpy_pydriver_depsgraph_as_pyobject(depsgraph); | |||||
| const char *depsgraph_variable_name = "depsgraph"; | |||||
| if (PyDict_SetItemString(driver_vars, depsgraph_variable_name, py_depsgraph) == -1) { | |||||
| fprintf(stderr, | |||||
| "\tBPY_driver_eval() - couldn't add variable '%s' to namespace\n", | |||||
| depsgraph_variable_name); | |||||
| PyErr_Print(); | |||||
| PyErr_Clear(); | |||||
| } | |||||
| } | |||||
| /* This evals py driver expressions, 'expr' is a Python expression that | /* This evals py driver expressions, 'expr' is a Python expression that | ||||
| * should evaluate to a float number, which is returned. | * should evaluate to a float number, which is returned. | ||||
| * | * | ||||
| * (old)note: PyGILState_Ensure() isn't always called because python can call | * (old)note: PyGILState_Ensure() isn't always called because python can call | ||||
| * the bake operator which intern starts a thread which calls scene update | * the bake operator which intern starts a thread which calls scene update | ||||
| * which does a driver update. to avoid a deadlock check PyC_IsInterpreterActive() | * which does a driver update. to avoid a deadlock check PyC_IsInterpreterActive() | ||||
| * if PyGILState_Ensure() is needed - see [#27683] | * if PyGILState_Ensure() is needed - see [#27683] | ||||
| * | * | ||||
| * (new)note: checking if python is running is not threadsafe [#28114] | * (new)note: checking if python is running is not threadsafe [#28114] | ||||
| * now release the GIL on python operator execution instead, using | * now release the GIL on python operator execution instead, using | ||||
| * PyEval_SaveThread() / PyEval_RestoreThread() so we don't lock up blender. | * PyEval_SaveThread() / PyEval_RestoreThread() so we don't lock up blender. | ||||
| * | * | ||||
| * For copy-on-write we always cache expressions and write errors in the | * For copy-on-write we always cache expressions and write errors in the | ||||
| * original driver, otherwise these would get freed while editing. Due to | * original driver, otherwise these would get freed while editing. Due to | ||||
| * the GIL this is thread-safe. | * the GIL this is thread-safe. | ||||
| */ | */ | ||||
| float BPY_driver_exec(struct PathResolvedRNA *anim_rna, | float BPY_driver_exec(struct PathResolvedRNA *anim_rna, | ||||
| ChannelDriver *driver, | ChannelDriver *driver, | ||||
| ChannelDriver *driver_orig, | ChannelDriver *driver_orig, | ||||
| const float evaltime) | const AnimationEvalContext *anim_eval_context) | ||||
| { | { | ||||
| PyObject *driver_vars = NULL; | PyObject *driver_vars = NULL; | ||||
| PyObject *retval = NULL; | PyObject *retval = NULL; | ||||
| /* Speed up by pre-hashing string & avoids re-converting unicode strings for every execution. */ | /* Speed up by pre-hashing string & avoids re-converting unicode strings for every execution. */ | ||||
| PyObject *expr_vars; | PyObject *expr_vars; | ||||
| PyObject *expr_code; | PyObject *expr_code; | ||||
| ▲ Show 20 Lines • Show All 43 Lines • ▼ Show 20 Lines | if (bpy_pydriver_create_dict() != 0) { | ||||
| if (use_gil) { | if (use_gil) { | ||||
| PyGILState_Release(gilstate); | PyGILState_Release(gilstate); | ||||
| } | } | ||||
| return 0.0f; | return 0.0f; | ||||
| } | } | ||||
| } | } | ||||
| /* update global namespace */ | /* update global namespace */ | ||||
| bpy_pydriver_namespace_update_frame(evaltime); | bpy_pydriver_namespace_update_frame(anim_eval_context->eval_time); | ||||
| if (driver_orig->flag & DRIVER_FLAG_USE_SELF) { | if (driver_orig->flag & DRIVER_FLAG_USE_SELF) { | ||||
| bpy_pydriver_namespace_update_self(anim_rna); | bpy_pydriver_namespace_update_self(anim_rna); | ||||
| } | } | ||||
| else { | else { | ||||
| bpy_pydriver_namespace_clear_self(); | bpy_pydriver_namespace_clear_self(); | ||||
| } | } | ||||
| ▲ Show 20 Lines • Show All 116 Lines • ▼ Show 20 Lines | if (!(G.f & G_FLAG_SCRIPT_AUTOEXEC)) { | ||||
| Py_DECREF(expr_code); | Py_DECREF(expr_code); | ||||
| expr_code = NULL; | expr_code = NULL; | ||||
| PyTuple_SET_ITEM(((PyObject *)driver_orig->expr_comp), 0, NULL); | PyTuple_SET_ITEM(((PyObject *)driver_orig->expr_comp), 0, NULL); | ||||
| } | } | ||||
| } | } | ||||
| } | } | ||||
| #endif /* USE_BYTECODE_WHITELIST */ | #endif /* USE_BYTECODE_WHITELIST */ | ||||
| bpy_pydriver_namespace_add_depsgraph(driver_vars, anim_eval_context->depsgraph); | |||||
| #if 0 /* slow, with this can avoid all Py_CompileString above. */ | #if 0 /* slow, with this can avoid all Py_CompileString above. */ | ||||
| /* execute expression to get a value */ | /* execute expression to get a value */ | ||||
| retval = PyRun_String(expr, Py_eval_input, bpy_pydriver_Dict, driver_vars); | retval = PyRun_String(expr, Py_eval_input, bpy_pydriver_Dict, driver_vars); | ||||
| #else | #else | ||||
| /* evaluate the compiled expression */ | /* evaluate the compiled expression */ | ||||
| if (expr_code) { | if (expr_code) { | ||||
| retval = PyEval_EvalCode((void *)expr_code, bpy_pydriver_Dict, driver_vars); | retval = PyEval_EvalCode((void *)expr_code, bpy_pydriver_Dict, driver_vars); | ||||
| } | } | ||||
| Show All 35 Lines | |||||