2011-02-23 10:52:22 +00:00
|
|
|
/*
|
2009-12-08 22:35:03 +00:00
|
|
|
* 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,
|
2010-02-12 13:34:04 +00:00
|
|
|
* Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
|
2009-12-08 22:35:03 +00:00
|
|
|
*/
|
2011-02-27 20:10:08 +00:00
|
|
|
|
2019-02-18 08:08:12 +11:00
|
|
|
/** \file
|
|
|
|
* \ingroup pythonintern
|
2011-11-05 08:21:12 +00:00
|
|
|
*
|
2011-11-05 08:40:07 +00:00
|
|
|
* This file defines the 'BPY_driver_exec' to execute python driver expressions,
|
2011-11-05 08:21:12 +00:00
|
|
|
* called by the animation system, there are also some utility functions
|
|
|
|
* to deal with the namespace used for driver execution.
|
2011-02-27 20:10:08 +00:00
|
|
|
*/
|
|
|
|
|
2009-12-08 22:35:03 +00:00
|
|
|
/* ****************************************** */
|
|
|
|
/* Drivers - PyExpression Evaluation */
|
|
|
|
|
2010-04-24 10:08:07 +00:00
|
|
|
#include <Python.h>
|
|
|
|
|
2009-12-08 22:35:03 +00:00
|
|
|
#include "DNA_anim_types.h"
|
|
|
|
|
2010-01-05 10:54:54 +00:00
|
|
|
#include "BLI_listbase.h"
|
2010-03-15 18:52:22 +00:00
|
|
|
#include "BLI_math_base.h"
|
2019-03-26 03:57:39 +01:00
|
|
|
#include "BLI_string.h"
|
2010-01-05 10:54:54 +00:00
|
|
|
|
T77086 Animation: Passing Dependency Graph to Drivers
Custom driver functions need access to the dependency graph that is
triggering the evaluation of the driver. This patch passes the
dependency graph pointer through all the animation-related calls.
Instead of passing the evaluation time to functions, the code now passes
an `AnimationEvalContext` pointer:
```
typedef struct AnimationEvalContext {
struct Depsgraph *const depsgraph;
const float eval_time;
} AnimationEvalContext;
```
These structs are read-only, meaning that the code cannot change the
evaluation time. Note that the `depsgraph` pointer itself is const, but
it points to a non-const depsgraph.
FCurves and Drivers can be evaluated at a different time than the
current scene time, for example when evaluating NLA strips. This means
that, even though the current time is stored in the dependency graph, we
need an explicit evaluation time.
There are two functions that allow creation of `AnimationEvalContext`
objects:
- `BKE_animsys_eval_context_construct(Depsgraph *depsgraph, float
eval_time)`, which creates a new context object from scratch, and
- `BKE_animsys_eval_context_construct_at(AnimationEvalContext
*anim_eval_context, float eval_time)`, which can be used to create a
`AnimationEvalContext` with the same depsgraph, but at a different
time. This makes it possible to later add fields without changing any
of the code that just want to change the eval time.
This also provides a fix for T75553, although it does require a change
to the custom driver function. The driver should call
`custom_function(depsgraph)`, and the function should use that depsgraph
instead of information from `bpy.context`.
Reviewed By: brecht, sergey
Differential Revision: https://developer.blender.org/D8047
2020-07-17 17:38:09 +02:00
|
|
|
#include "BKE_animsys.h"
|
2020-05-01 12:43:12 +02:00
|
|
|
#include "BKE_fcurve_driver.h"
|
2010-02-27 01:27:22 +00:00
|
|
|
#include "BKE_global.h"
|
2009-12-08 22:35:03 +00:00
|
|
|
|
T77086 Animation: Passing Dependency Graph to Drivers
Custom driver functions need access to the dependency graph that is
triggering the evaluation of the driver. This patch passes the
dependency graph pointer through all the animation-related calls.
Instead of passing the evaluation time to functions, the code now passes
an `AnimationEvalContext` pointer:
```
typedef struct AnimationEvalContext {
struct Depsgraph *const depsgraph;
const float eval_time;
} AnimationEvalContext;
```
These structs are read-only, meaning that the code cannot change the
evaluation time. Note that the `depsgraph` pointer itself is const, but
it points to a non-const depsgraph.
FCurves and Drivers can be evaluated at a different time than the
current scene time, for example when evaluating NLA strips. This means
that, even though the current time is stored in the dependency graph, we
need an explicit evaluation time.
There are two functions that allow creation of `AnimationEvalContext`
objects:
- `BKE_animsys_eval_context_construct(Depsgraph *depsgraph, float
eval_time)`, which creates a new context object from scratch, and
- `BKE_animsys_eval_context_construct_at(AnimationEvalContext
*anim_eval_context, float eval_time)`, which can be used to create a
`AnimationEvalContext` with the same depsgraph, but at a different
time. This makes it possible to later add fields without changing any
of the code that just want to change the eval time.
This also provides a fix for T75553, although it does require a change
to the custom driver function. The driver should call
`custom_function(depsgraph)`, and the function should use that depsgraph
instead of information from `bpy.context`.
Reviewed By: brecht, sergey
Differential Revision: https://developer.blender.org/D8047
2020-07-17 17:38:09 +02:00
|
|
|
#include "RNA_access.h"
|
|
|
|
#include "RNA_types.h"
|
|
|
|
|
2019-04-17 06:17:24 +02:00
|
|
|
#include "bpy_rna_driver.h" /* for pyrna_driver_get_variable_value */
|
2016-04-05 07:02:43 +10:00
|
|
|
|
2016-07-31 11:22:02 +10:00
|
|
|
#include "bpy_intern_string.h"
|
|
|
|
|
2011-02-14 18:20:10 +00:00
|
|
|
#include "bpy_driver.h"
|
T77086 Animation: Passing Dependency Graph to Drivers
Custom driver functions need access to the dependency graph that is
triggering the evaluation of the driver. This patch passes the
dependency graph pointer through all the animation-related calls.
Instead of passing the evaluation time to functions, the code now passes
an `AnimationEvalContext` pointer:
```
typedef struct AnimationEvalContext {
struct Depsgraph *const depsgraph;
const float eval_time;
} AnimationEvalContext;
```
These structs are read-only, meaning that the code cannot change the
evaluation time. Note that the `depsgraph` pointer itself is const, but
it points to a non-const depsgraph.
FCurves and Drivers can be evaluated at a different time than the
current scene time, for example when evaluating NLA strips. This means
that, even though the current time is stored in the dependency graph, we
need an explicit evaluation time.
There are two functions that allow creation of `AnimationEvalContext`
objects:
- `BKE_animsys_eval_context_construct(Depsgraph *depsgraph, float
eval_time)`, which creates a new context object from scratch, and
- `BKE_animsys_eval_context_construct_at(AnimationEvalContext
*anim_eval_context, float eval_time)`, which can be used to create a
`AnimationEvalContext` with the same depsgraph, but at a different
time. This makes it possible to later add fields without changing any
of the code that just want to change the eval time.
This also provides a fix for T75553, although it does require a change
to the custom driver function. The driver should call
`custom_function(depsgraph)`, and the function should use that depsgraph
instead of information from `bpy.context`.
Reviewed By: brecht, sergey
Differential Revision: https://developer.blender.org/D8047
2020-07-17 17:38:09 +02:00
|
|
|
#include "bpy_rna.h"
|
2011-02-14 18:20:10 +00:00
|
|
|
|
2018-06-11 20:00:03 +02:00
|
|
|
#include "BPY_extern.h"
|
|
|
|
|
2016-04-05 07:02:43 +10:00
|
|
|
#define USE_RNA_AS_PYOBJECT
|
2011-10-05 07:28:59 +00:00
|
|
|
|
2018-06-17 19:51:05 +02:00
|
|
|
#define USE_BYTECODE_WHITELIST
|
|
|
|
|
|
|
|
#ifdef USE_BYTECODE_WHITELIST
|
|
|
|
# include <opcode.h>
|
|
|
|
#endif
|
|
|
|
|
2019-04-29 19:59:13 +10:00
|
|
|
/**
|
|
|
|
* For PyDrivers
|
|
|
|
* (drivers using one-line Python expressions to express relationships between targets).
|
|
|
|
*/
|
2011-12-26 12:26:11 +00:00
|
|
|
PyObject *bpy_pydriver_Dict = NULL;
|
2009-12-08 22:35:03 +00:00
|
|
|
|
2018-06-17 19:51:05 +02:00
|
|
|
#ifdef USE_BYTECODE_WHITELIST
|
|
|
|
static PyObject *bpy_pydriver_Dict__whitelist = NULL;
|
|
|
|
#endif
|
|
|
|
|
2009-12-08 22:35:03 +00:00
|
|
|
/* For faster execution we keep a special dictionary for pydrivers, with
|
|
|
|
* the needed modules and aliases.
|
|
|
|
*/
|
2010-11-27 02:39:51 +00:00
|
|
|
int bpy_pydriver_create_dict(void)
|
2009-12-08 22:35:03 +00:00
|
|
|
{
|
2019-04-17 06:17:24 +02:00
|
|
|
PyObject *d, *mod;
|
|
|
|
|
|
|
|
/* validate namespace for driver evaluation */
|
|
|
|
if (bpy_pydriver_Dict) {
|
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
|
|
|
|
d = PyDict_New();
|
|
|
|
if (d == NULL) {
|
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
else {
|
|
|
|
bpy_pydriver_Dict = d;
|
|
|
|
}
|
|
|
|
|
|
|
|
/* import some modules: builtins, bpy, math, (Blender.noise)*/
|
|
|
|
PyDict_SetItemString(d, "__builtins__", PyEval_GetBuiltins());
|
|
|
|
|
|
|
|
mod = PyImport_ImportModule("math");
|
|
|
|
if (mod) {
|
|
|
|
PyDict_Merge(d, PyModule_GetDict(mod), 0); /* 0 - don't overwrite existing values */
|
|
|
|
Py_DECREF(mod);
|
|
|
|
}
|
2018-06-17 19:51:05 +02:00
|
|
|
#ifdef USE_BYTECODE_WHITELIST
|
2019-04-17 06:17:24 +02:00
|
|
|
PyObject *mod_math = mod;
|
2018-06-17 19:51:05 +02:00
|
|
|
#endif
|
2009-12-08 22:35:03 +00:00
|
|
|
|
2019-04-17 06:17:24 +02:00
|
|
|
/* add bpy to global namespace */
|
|
|
|
mod = PyImport_ImportModuleLevel("bpy", NULL, NULL, NULL, 0);
|
|
|
|
if (mod) {
|
|
|
|
PyDict_SetItemString(bpy_pydriver_Dict, "bpy", mod);
|
|
|
|
Py_DECREF(mod);
|
|
|
|
}
|
|
|
|
|
|
|
|
/* add noise to global namespace */
|
|
|
|
mod = PyImport_ImportModuleLevel("mathutils", NULL, NULL, NULL, 0);
|
|
|
|
if (mod) {
|
|
|
|
PyObject *modsub = PyDict_GetItemString(PyModule_GetDict(mod), "noise");
|
|
|
|
PyDict_SetItemString(bpy_pydriver_Dict, "noise", modsub);
|
|
|
|
Py_DECREF(mod);
|
|
|
|
}
|
2011-09-05 05:42:49 +00:00
|
|
|
|
2018-06-17 19:51:05 +02:00
|
|
|
#ifdef USE_BYTECODE_WHITELIST
|
2019-04-17 06:17:24 +02:00
|
|
|
/* setup the whitelist */
|
|
|
|
{
|
|
|
|
bpy_pydriver_Dict__whitelist = PyDict_New();
|
|
|
|
const char *whitelist[] = {
|
|
|
|
/* builtins (basic) */
|
|
|
|
"all",
|
|
|
|
"any",
|
|
|
|
"len",
|
|
|
|
/* builtins (numeric) */
|
|
|
|
"max",
|
|
|
|
"min",
|
|
|
|
"pow",
|
|
|
|
"round",
|
|
|
|
"sum",
|
|
|
|
/* types */
|
|
|
|
"bool",
|
|
|
|
"float",
|
|
|
|
"int",
|
|
|
|
|
|
|
|
NULL,
|
|
|
|
};
|
|
|
|
|
|
|
|
for (int i = 0; whitelist[i]; i++) {
|
|
|
|
PyDict_SetItemString(bpy_pydriver_Dict__whitelist, whitelist[i], Py_None);
|
|
|
|
}
|
|
|
|
|
|
|
|
/* Add all of 'math' functions. */
|
|
|
|
if (mod_math != NULL) {
|
|
|
|
PyObject *mod_math_dict = PyModule_GetDict(mod_math);
|
|
|
|
PyObject *arg_key, *arg_value;
|
|
|
|
Py_ssize_t arg_pos = 0;
|
|
|
|
while (PyDict_Next(mod_math_dict, &arg_pos, &arg_key, &arg_value)) {
|
|
|
|
const char *arg_str = _PyUnicode_AsString(arg_key);
|
|
|
|
if (arg_str[0] && arg_str[1] != '_') {
|
|
|
|
PyDict_SetItem(bpy_pydriver_Dict__whitelist, arg_key, Py_None);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
#endif /* USE_BYTECODE_WHITELIST */
|
|
|
|
|
|
|
|
return 0;
|
2009-12-08 22:35:03 +00:00
|
|
|
}
|
|
|
|
|
2011-11-17 07:08:09 +00:00
|
|
|
/* note, this function should do nothing most runs, only when changing frame */
|
2011-12-16 03:06:56 +00:00
|
|
|
/* not thread safe but neither is python */
|
2016-07-31 11:43:24 +10:00
|
|
|
static struct {
|
2019-04-17 06:17:24 +02:00
|
|
|
float evaltime;
|
2016-07-31 11:43:24 +10:00
|
|
|
|
2019-04-17 06:17:24 +02:00
|
|
|
/* borrowed reference to the 'self' in 'bpy_pydriver_Dict'
|
|
|
|
* keep for as long as the same self is used. */
|
|
|
|
PyObject *self;
|
2016-07-31 11:43:24 +10:00
|
|
|
} g_pydriver_state_prev = {
|
2019-04-17 06:17:24 +02:00
|
|
|
.evaltime = FLT_MAX,
|
|
|
|
.self = NULL,
|
2016-07-31 11:43:24 +10:00
|
|
|
};
|
2011-11-17 07:08:09 +00:00
|
|
|
|
2016-07-31 11:22:02 +10:00
|
|
|
static void bpy_pydriver_namespace_update_frame(const float evaltime)
|
2011-11-17 07:08:09 +00:00
|
|
|
{
|
2019-04-17 06:17:24 +02:00
|
|
|
if (g_pydriver_state_prev.evaltime != evaltime) {
|
|
|
|
PyObject *item = PyFloat_FromDouble(evaltime);
|
|
|
|
PyDict_SetItem(bpy_pydriver_Dict, bpy_intern_str_frame, item);
|
|
|
|
Py_DECREF(item);
|
2011-11-17 07:08:09 +00:00
|
|
|
|
2019-04-17 06:17:24 +02:00
|
|
|
g_pydriver_state_prev.evaltime = evaltime;
|
|
|
|
}
|
2011-11-17 07:08:09 +00:00
|
|
|
}
|
|
|
|
|
2016-07-31 11:22:02 +10:00
|
|
|
static void bpy_pydriver_namespace_update_self(struct PathResolvedRNA *anim_rna)
|
2016-07-30 16:34:01 +10:00
|
|
|
{
|
2019-04-17 06:17:24 +02:00
|
|
|
if ((g_pydriver_state_prev.self == NULL) ||
|
|
|
|
(pyrna_driver_is_equal_anim_rna(anim_rna, g_pydriver_state_prev.self) == false)) {
|
|
|
|
PyObject *item = pyrna_driver_self_from_anim_rna(anim_rna);
|
|
|
|
PyDict_SetItem(bpy_pydriver_Dict, bpy_intern_str_self, item);
|
|
|
|
Py_DECREF(item);
|
|
|
|
|
|
|
|
g_pydriver_state_prev.self = item;
|
|
|
|
}
|
2016-07-31 11:43:24 +10:00
|
|
|
}
|
|
|
|
|
|
|
|
static void bpy_pydriver_namespace_clear_self(void)
|
|
|
|
{
|
2019-04-17 06:17:24 +02:00
|
|
|
if (g_pydriver_state_prev.self) {
|
|
|
|
PyDict_DelItem(bpy_pydriver_Dict, bpy_intern_str_self);
|
2016-07-31 11:43:24 +10:00
|
|
|
|
2019-04-17 06:17:24 +02:00
|
|
|
g_pydriver_state_prev.self = NULL;
|
|
|
|
}
|
2016-07-30 16:34:01 +10:00
|
|
|
}
|
|
|
|
|
2009-12-08 22:35:03 +00:00
|
|
|
/* Update function, it gets rid of pydrivers global dictionary, forcing
|
2011-01-05 02:08:54 +00:00
|
|
|
* BPY_driver_exec to recreate it. This function is used to force
|
2009-12-08 22:35:03 +00:00
|
|
|
* reloading the Blender text module "pydrivers.py", if available, so
|
|
|
|
* updates in it reach pydriver evaluation.
|
|
|
|
*/
|
2011-01-05 02:08:54 +00:00
|
|
|
void BPY_driver_reset(void)
|
2009-12-08 22:35:03 +00:00
|
|
|
{
|
2019-04-17 06:17:24 +02:00
|
|
|
PyGILState_STATE gilstate;
|
|
|
|
bool use_gil = true; /* !PyC_IsInterpreterActive(); */
|
2010-05-18 14:38:25 +00:00
|
|
|
|
2019-04-17 06:17:24 +02:00
|
|
|
if (use_gil) {
|
|
|
|
gilstate = PyGILState_Ensure();
|
|
|
|
}
|
2009-12-08 22:35:03 +00:00
|
|
|
|
2019-04-17 06:17:24 +02:00
|
|
|
if (bpy_pydriver_Dict) { /* free the global dict used by pydrivers */
|
|
|
|
PyDict_Clear(bpy_pydriver_Dict);
|
|
|
|
Py_DECREF(bpy_pydriver_Dict);
|
|
|
|
bpy_pydriver_Dict = NULL;
|
|
|
|
}
|
2009-12-08 22:35:03 +00:00
|
|
|
|
2018-06-17 19:51:05 +02:00
|
|
|
#ifdef USE_BYTECODE_WHITELIST
|
2019-04-17 06:17:24 +02:00
|
|
|
if (bpy_pydriver_Dict__whitelist) {
|
|
|
|
PyDict_Clear(bpy_pydriver_Dict__whitelist);
|
|
|
|
Py_DECREF(bpy_pydriver_Dict__whitelist);
|
|
|
|
bpy_pydriver_Dict__whitelist = NULL;
|
|
|
|
}
|
2018-06-17 19:51:05 +02:00
|
|
|
#endif
|
|
|
|
|
2019-04-17 06:17:24 +02:00
|
|
|
g_pydriver_state_prev.evaltime = FLT_MAX;
|
2016-07-31 11:43:24 +10:00
|
|
|
|
2019-04-17 06:17:24 +02:00
|
|
|
/* freed when clearing driver dict */
|
|
|
|
g_pydriver_state_prev.self = NULL;
|
2011-11-17 07:08:09 +00:00
|
|
|
|
2019-04-17 06:17:24 +02:00
|
|
|
if (use_gil) {
|
|
|
|
PyGILState_Release(gilstate);
|
|
|
|
}
|
2009-12-08 22:35:03 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
/* error return function for BPY_eval_pydriver */
|
2011-01-03 12:11:05 +00:00
|
|
|
static void pydriver_error(ChannelDriver *driver)
|
2009-12-08 22:35:03 +00:00
|
|
|
{
|
2019-04-17 06:17:24 +02:00
|
|
|
driver->flag |= DRIVER_FLAG_INVALID; /* py expression failed */
|
|
|
|
fprintf(stderr,
|
|
|
|
"\nError in Driver: The following Python expression failed:\n\t'%s'\n\n",
|
|
|
|
driver->expression);
|
|
|
|
|
|
|
|
// BPy_errors_to_report(NULL); // TODO - reports
|
|
|
|
PyErr_Print();
|
|
|
|
PyErr_Clear();
|
2009-12-08 22:35:03 +00:00
|
|
|
}
|
|
|
|
|
2018-06-17 19:51:05 +02:00
|
|
|
#ifdef USE_BYTECODE_WHITELIST
|
|
|
|
|
2019-04-17 06:17:24 +02:00
|
|
|
# define OK_OP(op) [op] = 1
|
2018-06-17 19:51:05 +02:00
|
|
|
|
2018-08-01 08:57:31 +10:00
|
|
|
static const char secure_opcodes[255] = {
|
2019-04-17 06:17:24 +02:00
|
|
|
OK_OP(POP_TOP),
|
|
|
|
OK_OP(ROT_TWO),
|
|
|
|
OK_OP(ROT_THREE),
|
|
|
|
OK_OP(DUP_TOP),
|
|
|
|
OK_OP(DUP_TOP_TWO),
|
|
|
|
OK_OP(NOP),
|
|
|
|
OK_OP(UNARY_POSITIVE),
|
|
|
|
OK_OP(UNARY_NEGATIVE),
|
|
|
|
OK_OP(UNARY_NOT),
|
|
|
|
OK_OP(UNARY_INVERT),
|
|
|
|
OK_OP(BINARY_MATRIX_MULTIPLY),
|
|
|
|
OK_OP(INPLACE_MATRIX_MULTIPLY),
|
|
|
|
OK_OP(BINARY_POWER),
|
|
|
|
OK_OP(BINARY_MULTIPLY),
|
|
|
|
OK_OP(BINARY_MODULO),
|
|
|
|
OK_OP(BINARY_ADD),
|
|
|
|
OK_OP(BINARY_SUBTRACT),
|
|
|
|
OK_OP(BINARY_SUBSCR),
|
|
|
|
OK_OP(BINARY_FLOOR_DIVIDE),
|
|
|
|
OK_OP(BINARY_TRUE_DIVIDE),
|
|
|
|
OK_OP(INPLACE_FLOOR_DIVIDE),
|
|
|
|
OK_OP(INPLACE_TRUE_DIVIDE),
|
|
|
|
OK_OP(INPLACE_ADD),
|
|
|
|
OK_OP(INPLACE_SUBTRACT),
|
|
|
|
OK_OP(INPLACE_MULTIPLY),
|
|
|
|
OK_OP(INPLACE_MODULO),
|
|
|
|
OK_OP(BINARY_LSHIFT),
|
|
|
|
OK_OP(BINARY_RSHIFT),
|
|
|
|
OK_OP(BINARY_AND),
|
|
|
|
OK_OP(BINARY_XOR),
|
|
|
|
OK_OP(BINARY_OR),
|
|
|
|
OK_OP(INPLACE_POWER),
|
|
|
|
OK_OP(INPLACE_LSHIFT),
|
|
|
|
OK_OP(INPLACE_RSHIFT),
|
|
|
|
OK_OP(INPLACE_AND),
|
|
|
|
OK_OP(INPLACE_XOR),
|
|
|
|
OK_OP(INPLACE_OR),
|
|
|
|
OK_OP(RETURN_VALUE),
|
|
|
|
OK_OP(BUILD_TUPLE),
|
|
|
|
OK_OP(BUILD_LIST),
|
|
|
|
OK_OP(BUILD_SET),
|
|
|
|
OK_OP(BUILD_MAP),
|
|
|
|
OK_OP(COMPARE_OP),
|
|
|
|
OK_OP(JUMP_FORWARD),
|
|
|
|
OK_OP(JUMP_IF_FALSE_OR_POP),
|
|
|
|
OK_OP(JUMP_IF_TRUE_OR_POP),
|
|
|
|
OK_OP(JUMP_ABSOLUTE),
|
|
|
|
OK_OP(POP_JUMP_IF_FALSE),
|
|
|
|
OK_OP(POP_JUMP_IF_TRUE),
|
|
|
|
OK_OP(LOAD_GLOBAL),
|
|
|
|
OK_OP(LOAD_FAST),
|
|
|
|
OK_OP(STORE_FAST),
|
|
|
|
OK_OP(DELETE_FAST),
|
|
|
|
OK_OP(LOAD_DEREF),
|
|
|
|
OK_OP(STORE_DEREF),
|
|
|
|
|
|
|
|
/* special cases */
|
|
|
|
OK_OP(LOAD_CONST), /* ok because constants are accepted */
|
|
|
|
OK_OP(LOAD_NAME), /* ok, because PyCodeObject.names is checked */
|
|
|
|
OK_OP(CALL_FUNCTION), /* ok, because we check its 'name' before calling */
|
|
|
|
OK_OP(CALL_FUNCTION_KW),
|
|
|
|
OK_OP(CALL_FUNCTION_EX),
|
2018-06-17 19:51:05 +02:00
|
|
|
};
|
|
|
|
|
2019-04-17 06:17:24 +02:00
|
|
|
# undef OK_OP
|
2018-06-17 19:51:05 +02:00
|
|
|
|
|
|
|
static bool bpy_driver_secure_bytecode_validate(PyObject *expr_code, PyObject *dict_arr[])
|
|
|
|
{
|
2019-04-17 06:17:24 +02:00
|
|
|
PyCodeObject *py_code = (PyCodeObject *)expr_code;
|
|
|
|
|
|
|
|
/* Check names. */
|
|
|
|
{
|
|
|
|
for (int i = 0; i < PyTuple_GET_SIZE(py_code->co_names); i++) {
|
|
|
|
PyObject *name = PyTuple_GET_ITEM(py_code->co_names, i);
|
|
|
|
|
|
|
|
bool contains_name = false;
|
|
|
|
for (int j = 0; dict_arr[j]; j++) {
|
|
|
|
if (PyDict_Contains(dict_arr[j], name)) {
|
|
|
|
contains_name = true;
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
if (contains_name == false) {
|
|
|
|
fprintf(stderr,
|
|
|
|
"\tBPY_driver_eval() - restricted access disallows name '%s', "
|
|
|
|
"enable auto-execution to support\n",
|
|
|
|
_PyUnicode_AsString(name));
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
/* Check opcodes. */
|
|
|
|
{
|
|
|
|
const _Py_CODEUNIT *codestr;
|
|
|
|
Py_ssize_t code_len;
|
|
|
|
|
|
|
|
PyBytes_AsStringAndSize(py_code->co_code, (char **)&codestr, &code_len);
|
|
|
|
code_len /= sizeof(*codestr);
|
|
|
|
|
|
|
|
for (Py_ssize_t i = 0; i < code_len; i++) {
|
|
|
|
const int opcode = _Py_OPCODE(codestr[i]);
|
|
|
|
if (secure_opcodes[opcode] == 0) {
|
|
|
|
fprintf(stderr,
|
|
|
|
"\tBPY_driver_eval() - restricted access disallows opcode '%d', "
|
|
|
|
"enable auto-execution to support\n",
|
|
|
|
opcode);
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
# undef CODESIZE
|
|
|
|
}
|
|
|
|
|
|
|
|
return true;
|
2018-06-17 19:51:05 +02:00
|
|
|
}
|
|
|
|
|
2019-04-17 06:17:24 +02:00
|
|
|
#endif /* USE_BYTECODE_WHITELIST */
|
2018-06-17 19:51:05 +02:00
|
|
|
|
T77086 Animation: Passing Dependency Graph to Drivers
Custom driver functions need access to the dependency graph that is
triggering the evaluation of the driver. This patch passes the
dependency graph pointer through all the animation-related calls.
Instead of passing the evaluation time to functions, the code now passes
an `AnimationEvalContext` pointer:
```
typedef struct AnimationEvalContext {
struct Depsgraph *const depsgraph;
const float eval_time;
} AnimationEvalContext;
```
These structs are read-only, meaning that the code cannot change the
evaluation time. Note that the `depsgraph` pointer itself is const, but
it points to a non-const depsgraph.
FCurves and Drivers can be evaluated at a different time than the
current scene time, for example when evaluating NLA strips. This means
that, even though the current time is stored in the dependency graph, we
need an explicit evaluation time.
There are two functions that allow creation of `AnimationEvalContext`
objects:
- `BKE_animsys_eval_context_construct(Depsgraph *depsgraph, float
eval_time)`, which creates a new context object from scratch, and
- `BKE_animsys_eval_context_construct_at(AnimationEvalContext
*anim_eval_context, float eval_time)`, which can be used to create a
`AnimationEvalContext` with the same depsgraph, but at a different
time. This makes it possible to later add fields without changing any
of the code that just want to change the eval time.
This also provides a fix for T75553, although it does require a change
to the custom driver function. The driver should call
`custom_function(depsgraph)`, and the function should use that depsgraph
instead of information from `bpy.context`.
Reviewed By: brecht, sergey
Differential Revision: https://developer.blender.org/D8047
2020-07-17 17:38:09 +02:00
|
|
|
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();
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2009-12-08 22:35:03 +00:00
|
|
|
/* This evals py driver expressions, 'expr' is a Python expression that
|
|
|
|
* should evaluate to a float number, which is returned.
|
2010-05-18 14:38:25 +00:00
|
|
|
*
|
2012-03-18 07:38:51 +00:00
|
|
|
* (old)note: PyGILState_Ensure() isn't always called because python can call
|
2011-08-04 01:56:36 +00:00
|
|
|
* the bake operator which intern starts a thread which calls scene update
|
2013-09-18 23:21:24 +00:00
|
|
|
* which does a driver update. to avoid a deadlock check PyC_IsInterpreterActive()
|
2011-08-04 01:56:36 +00:00
|
|
|
* if PyGILState_Ensure() is needed - see [#27683]
|
|
|
|
*
|
|
|
|
* (new)note: checking if python is running is not threadsafe [#28114]
|
|
|
|
* now release the GIL on python operator execution instead, using
|
2012-03-18 07:38:51 +00:00
|
|
|
* PyEval_SaveThread() / PyEval_RestoreThread() so we don't lock up blender.
|
2018-06-11 20:00:03 +02:00
|
|
|
*
|
|
|
|
* 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.
|
2009-12-08 22:35:03 +00:00
|
|
|
*/
|
2019-04-17 06:17:24 +02:00
|
|
|
float BPY_driver_exec(struct PathResolvedRNA *anim_rna,
|
|
|
|
ChannelDriver *driver,
|
|
|
|
ChannelDriver *driver_orig,
|
T77086 Animation: Passing Dependency Graph to Drivers
Custom driver functions need access to the dependency graph that is
triggering the evaluation of the driver. This patch passes the
dependency graph pointer through all the animation-related calls.
Instead of passing the evaluation time to functions, the code now passes
an `AnimationEvalContext` pointer:
```
typedef struct AnimationEvalContext {
struct Depsgraph *const depsgraph;
const float eval_time;
} AnimationEvalContext;
```
These structs are read-only, meaning that the code cannot change the
evaluation time. Note that the `depsgraph` pointer itself is const, but
it points to a non-const depsgraph.
FCurves and Drivers can be evaluated at a different time than the
current scene time, for example when evaluating NLA strips. This means
that, even though the current time is stored in the dependency graph, we
need an explicit evaluation time.
There are two functions that allow creation of `AnimationEvalContext`
objects:
- `BKE_animsys_eval_context_construct(Depsgraph *depsgraph, float
eval_time)`, which creates a new context object from scratch, and
- `BKE_animsys_eval_context_construct_at(AnimationEvalContext
*anim_eval_context, float eval_time)`, which can be used to create a
`AnimationEvalContext` with the same depsgraph, but at a different
time. This makes it possible to later add fields without changing any
of the code that just want to change the eval time.
This also provides a fix for T75553, although it does require a change
to the custom driver function. The driver should call
`custom_function(depsgraph)`, and the function should use that depsgraph
instead of information from `bpy.context`.
Reviewed By: brecht, sergey
Differential Revision: https://developer.blender.org/D8047
2020-07-17 17:38:09 +02:00
|
|
|
const AnimationEvalContext *anim_eval_context)
|
2009-12-08 22:35:03 +00:00
|
|
|
{
|
2019-04-17 06:17:24 +02:00
|
|
|
PyObject *driver_vars = NULL;
|
|
|
|
PyObject *retval = NULL;
|
2019-04-29 19:59:13 +10:00
|
|
|
|
|
|
|
/* Speed up by pre-hashing string & avoids re-converting unicode strings for every execution. */
|
|
|
|
PyObject *expr_vars;
|
|
|
|
|
2019-04-17 06:17:24 +02:00
|
|
|
PyObject *expr_code;
|
|
|
|
PyGILState_STATE gilstate;
|
|
|
|
bool use_gil;
|
|
|
|
|
|
|
|
DriverVar *dvar;
|
|
|
|
double result = 0.0; /* default return */
|
|
|
|
const char *expr;
|
|
|
|
short targets_ok = 1;
|
|
|
|
int i;
|
|
|
|
|
|
|
|
/* get the py expression to be evaluated */
|
|
|
|
expr = driver_orig->expression;
|
|
|
|
if (expr[0] == '\0') {
|
|
|
|
return 0.0f;
|
|
|
|
}
|
2009-12-08 22:35:03 +00:00
|
|
|
|
2018-06-17 19:51:05 +02:00
|
|
|
#ifndef USE_BYTECODE_WHITELIST
|
2019-04-17 06:17:24 +02:00
|
|
|
if (!(G.f & G_FLAG_SCRIPT_AUTOEXEC)) {
|
|
|
|
if (!(G.f & G_FLAG_SCRIPT_AUTOEXEC_FAIL_QUIET)) {
|
|
|
|
G.f |= G_FLAG_SCRIPT_AUTOEXEC_FAIL;
|
|
|
|
BLI_snprintf(G.autoexec_fail, sizeof(G.autoexec_fail), "Driver '%s'", expr);
|
|
|
|
|
|
|
|
printf("skipping driver '%s', automatic scripts are disabled\n", expr);
|
|
|
|
}
|
|
|
|
return 0.0f;
|
|
|
|
}
|
2018-06-17 19:51:05 +02:00
|
|
|
#else
|
2019-04-17 06:17:24 +02:00
|
|
|
bool is_recompile = false;
|
2018-06-17 19:51:05 +02:00
|
|
|
#endif
|
2010-02-27 01:27:22 +00:00
|
|
|
|
2019-04-17 06:17:24 +02:00
|
|
|
use_gil = true; /* !PyC_IsInterpreterActive(); */
|
|
|
|
|
|
|
|
if (use_gil) {
|
|
|
|
gilstate = PyGILState_Ensure();
|
|
|
|
}
|
|
|
|
|
|
|
|
/* needed since drivers are updated directly after undo where 'main' is
|
|
|
|
* re-allocated [#28807] */
|
|
|
|
BPY_update_rna_module();
|
|
|
|
|
|
|
|
/* init global dictionary for py-driver evaluation settings */
|
|
|
|
if (!bpy_pydriver_Dict) {
|
|
|
|
if (bpy_pydriver_create_dict() != 0) {
|
|
|
|
fprintf(stderr, "PyDriver error: couldn't create Python dictionary\n");
|
|
|
|
if (use_gil) {
|
|
|
|
PyGILState_Release(gilstate);
|
|
|
|
}
|
|
|
|
return 0.0f;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
/* update global namespace */
|
T77086 Animation: Passing Dependency Graph to Drivers
Custom driver functions need access to the dependency graph that is
triggering the evaluation of the driver. This patch passes the
dependency graph pointer through all the animation-related calls.
Instead of passing the evaluation time to functions, the code now passes
an `AnimationEvalContext` pointer:
```
typedef struct AnimationEvalContext {
struct Depsgraph *const depsgraph;
const float eval_time;
} AnimationEvalContext;
```
These structs are read-only, meaning that the code cannot change the
evaluation time. Note that the `depsgraph` pointer itself is const, but
it points to a non-const depsgraph.
FCurves and Drivers can be evaluated at a different time than the
current scene time, for example when evaluating NLA strips. This means
that, even though the current time is stored in the dependency graph, we
need an explicit evaluation time.
There are two functions that allow creation of `AnimationEvalContext`
objects:
- `BKE_animsys_eval_context_construct(Depsgraph *depsgraph, float
eval_time)`, which creates a new context object from scratch, and
- `BKE_animsys_eval_context_construct_at(AnimationEvalContext
*anim_eval_context, float eval_time)`, which can be used to create a
`AnimationEvalContext` with the same depsgraph, but at a different
time. This makes it possible to later add fields without changing any
of the code that just want to change the eval time.
This also provides a fix for T75553, although it does require a change
to the custom driver function. The driver should call
`custom_function(depsgraph)`, and the function should use that depsgraph
instead of information from `bpy.context`.
Reviewed By: brecht, sergey
Differential Revision: https://developer.blender.org/D8047
2020-07-17 17:38:09 +02:00
|
|
|
bpy_pydriver_namespace_update_frame(anim_eval_context->eval_time);
|
2019-04-17 06:17:24 +02:00
|
|
|
|
|
|
|
if (driver_orig->flag & DRIVER_FLAG_USE_SELF) {
|
|
|
|
bpy_pydriver_namespace_update_self(anim_rna);
|
|
|
|
}
|
|
|
|
else {
|
|
|
|
bpy_pydriver_namespace_clear_self();
|
|
|
|
}
|
|
|
|
|
|
|
|
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_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_orig->expr_comp), 0, expr_code);
|
|
|
|
|
|
|
|
driver_orig->flag &= ~DRIVER_FLAG_RECOMPILE;
|
2019-04-29 19:59:13 +10:00
|
|
|
|
|
|
|
/* Maybe this can be removed but for now best keep until were sure. */
|
|
|
|
driver_orig->flag |= DRIVER_FLAG_RENAMEVAR;
|
2018-06-17 19:51:05 +02:00
|
|
|
#ifdef USE_BYTECODE_WHITELIST
|
2019-04-17 06:17:24 +02:00
|
|
|
is_recompile = true;
|
2018-06-17 19:51:05 +02:00
|
|
|
#endif
|
2019-04-17 06:17:24 +02:00
|
|
|
}
|
|
|
|
else {
|
|
|
|
expr_code = PyTuple_GET_ITEM(((PyObject *)driver_orig->expr_comp), 0);
|
|
|
|
}
|
|
|
|
|
|
|
|
if (driver_orig->flag & DRIVER_FLAG_RENAMEVAR) {
|
|
|
|
/* may not be set */
|
|
|
|
expr_vars = PyTuple_GET_ITEM(((PyObject *)driver_orig->expr_comp), 1);
|
|
|
|
Py_XDECREF(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_orig->variables.first, i = 0; dvar; dvar = dvar->next) {
|
|
|
|
PyTuple_SET_ITEM(expr_vars, i++, PyUnicode_FromString(dvar->name));
|
|
|
|
}
|
|
|
|
|
|
|
|
driver_orig->flag &= ~DRIVER_FLAG_RENAMEVAR;
|
|
|
|
}
|
|
|
|
else {
|
|
|
|
expr_vars = PyTuple_GET_ITEM(((PyObject *)driver_orig->expr_comp), 1);
|
|
|
|
}
|
|
|
|
|
|
|
|
/* add target values to a dict that will be used as '__locals__' dict */
|
|
|
|
driver_vars = _PyDict_NewPresized(PyTuple_GET_SIZE(expr_vars));
|
|
|
|
for (dvar = driver->variables.first, i = 0; dvar; dvar = dvar->next) {
|
|
|
|
PyObject *driver_arg = NULL;
|
|
|
|
|
|
|
|
/* support for any RNA data */
|
2016-04-05 07:02:43 +10:00
|
|
|
#ifdef USE_RNA_AS_PYOBJECT
|
2019-04-17 06:17:24 +02:00
|
|
|
if (dvar->type == DVAR_TYPE_SINGLE_PROP) {
|
|
|
|
driver_arg = pyrna_driver_get_variable_value(driver, &dvar->targets[0]);
|
|
|
|
|
|
|
|
if (driver_arg == NULL) {
|
|
|
|
driver_arg = PyFloat_FromDouble(0.0);
|
|
|
|
dvar->curval = 0.0f;
|
|
|
|
}
|
|
|
|
else {
|
|
|
|
/* no need to worry about overflow here, values from RNA are within limits. */
|
|
|
|
if (PyFloat_CheckExact(driver_arg)) {
|
|
|
|
dvar->curval = (float)PyFloat_AsDouble(driver_arg);
|
|
|
|
}
|
|
|
|
else if (PyLong_CheckExact(driver_arg)) {
|
|
|
|
dvar->curval = (float)PyLong_AsLong(driver_arg);
|
|
|
|
}
|
|
|
|
else if (PyBool_Check(driver_arg)) {
|
|
|
|
dvar->curval = (driver_arg == Py_True);
|
|
|
|
}
|
|
|
|
else {
|
|
|
|
dvar->curval = 0.0f;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
else
|
2016-04-05 07:02:43 +10:00
|
|
|
#endif
|
2019-04-17 06:17:24 +02:00
|
|
|
{
|
|
|
|
/* try to get variable value */
|
|
|
|
float tval = driver_get_variable_value(driver, dvar);
|
|
|
|
driver_arg = PyFloat_FromDouble((double)tval);
|
|
|
|
}
|
|
|
|
|
|
|
|
/* try to add to dictionary */
|
|
|
|
/* if (PyDict_SetItemString(driver_vars, dvar->name, driver_arg)) { */
|
|
|
|
if (PyDict_SetItem(driver_vars, PyTuple_GET_ITEM(expr_vars, i++), driver_arg) != -1) {
|
|
|
|
Py_DECREF(driver_arg);
|
|
|
|
}
|
|
|
|
else {
|
|
|
|
/* this target failed - bad name */
|
|
|
|
if (targets_ok) {
|
|
|
|
/* first one - print some extra info for easier identification */
|
|
|
|
fprintf(stderr, "\nBPY_driver_eval() - Error while evaluating PyDriver:\n");
|
|
|
|
targets_ok = 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
fprintf(
|
|
|
|
stderr, "\tBPY_driver_eval() - couldn't add variable '%s' to namespace\n", dvar->name);
|
|
|
|
// BPy_errors_to_report(NULL); // TODO - reports
|
|
|
|
PyErr_Print();
|
|
|
|
PyErr_Clear();
|
|
|
|
}
|
|
|
|
}
|
2009-12-08 22:35:03 +00:00
|
|
|
|
2018-06-17 19:51:05 +02:00
|
|
|
#ifdef USE_BYTECODE_WHITELIST
|
2019-04-17 06:17:24 +02:00
|
|
|
if (is_recompile && expr_code) {
|
|
|
|
if (!(G.f & G_FLAG_SCRIPT_AUTOEXEC)) {
|
|
|
|
if (!bpy_driver_secure_bytecode_validate(expr_code,
|
|
|
|
(PyObject *[]){
|
|
|
|
bpy_pydriver_Dict,
|
|
|
|
bpy_pydriver_Dict__whitelist,
|
|
|
|
driver_vars,
|
|
|
|
NULL,
|
|
|
|
})) {
|
|
|
|
if (!(G.f & G_FLAG_SCRIPT_AUTOEXEC_FAIL_QUIET)) {
|
|
|
|
G.f |= G_FLAG_SCRIPT_AUTOEXEC_FAIL;
|
|
|
|
BLI_snprintf(G.autoexec_fail, sizeof(G.autoexec_fail), "Driver '%s'", expr);
|
|
|
|
}
|
|
|
|
|
|
|
|
Py_DECREF(expr_code);
|
|
|
|
expr_code = NULL;
|
|
|
|
PyTuple_SET_ITEM(((PyObject *)driver_orig->expr_comp), 0, NULL);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
#endif /* USE_BYTECODE_WHITELIST */
|
|
|
|
|
T77086 Animation: Passing Dependency Graph to Drivers
Custom driver functions need access to the dependency graph that is
triggering the evaluation of the driver. This patch passes the
dependency graph pointer through all the animation-related calls.
Instead of passing the evaluation time to functions, the code now passes
an `AnimationEvalContext` pointer:
```
typedef struct AnimationEvalContext {
struct Depsgraph *const depsgraph;
const float eval_time;
} AnimationEvalContext;
```
These structs are read-only, meaning that the code cannot change the
evaluation time. Note that the `depsgraph` pointer itself is const, but
it points to a non-const depsgraph.
FCurves and Drivers can be evaluated at a different time than the
current scene time, for example when evaluating NLA strips. This means
that, even though the current time is stored in the dependency graph, we
need an explicit evaluation time.
There are two functions that allow creation of `AnimationEvalContext`
objects:
- `BKE_animsys_eval_context_construct(Depsgraph *depsgraph, float
eval_time)`, which creates a new context object from scratch, and
- `BKE_animsys_eval_context_construct_at(AnimationEvalContext
*anim_eval_context, float eval_time)`, which can be used to create a
`AnimationEvalContext` with the same depsgraph, but at a different
time. This makes it possible to later add fields without changing any
of the code that just want to change the eval time.
This also provides a fix for T75553, although it does require a change
to the custom driver function. The driver should call
`custom_function(depsgraph)`, and the function should use that depsgraph
instead of information from `bpy.context`.
Reviewed By: brecht, sergey
Differential Revision: https://developer.blender.org/D8047
2020-07-17 17:38:09 +02:00
|
|
|
bpy_pydriver_namespace_add_depsgraph(driver_vars, anim_eval_context->depsgraph);
|
|
|
|
|
2019-04-17 06:17:24 +02:00
|
|
|
#if 0 /* slow, with this can avoid all Py_CompileString above. */
|
|
|
|
/* execute expression to get a value */
|
|
|
|
retval = PyRun_String(expr, Py_eval_input, bpy_pydriver_Dict, driver_vars);
|
2009-12-08 22:35:03 +00:00
|
|
|
#else
|
2019-04-17 06:17:24 +02:00
|
|
|
/* evaluate the compiled expression */
|
|
|
|
if (expr_code) {
|
|
|
|
retval = PyEval_EvalCode((void *)expr_code, bpy_pydriver_Dict, driver_vars);
|
|
|
|
}
|
2009-12-08 22:35:03 +00:00
|
|
|
#endif
|
|
|
|
|
2019-04-17 06:17:24 +02:00
|
|
|
/* decref the driver vars first... */
|
|
|
|
Py_DECREF(driver_vars);
|
|
|
|
|
|
|
|
/* process the result */
|
|
|
|
if (retval == NULL) {
|
|
|
|
pydriver_error(driver);
|
|
|
|
}
|
|
|
|
else if ((result = PyFloat_AsDouble(retval)) == -1.0 && PyErr_Occurred()) {
|
|
|
|
pydriver_error(driver);
|
|
|
|
Py_DECREF(retval);
|
|
|
|
result = 0.0;
|
|
|
|
}
|
|
|
|
else {
|
|
|
|
/* all fine, make sure the "invalid expression" flag is cleared */
|
|
|
|
driver->flag &= ~DRIVER_FLAG_INVALID;
|
|
|
|
Py_DECREF(retval);
|
|
|
|
}
|
|
|
|
|
|
|
|
if (use_gil) {
|
|
|
|
PyGILState_Release(gilstate);
|
|
|
|
}
|
|
|
|
|
|
|
|
if (isfinite(result)) {
|
|
|
|
return (float)result;
|
|
|
|
}
|
|
|
|
else {
|
|
|
|
fprintf(stderr,
|
|
|
|
"\tBPY_driver_eval() - driver '%s' evaluates to '%f'\n",
|
|
|
|
driver->expression,
|
|
|
|
result);
|
|
|
|
return 0.0f;
|
|
|
|
}
|
2009-12-08 22:35:03 +00:00
|
|
|
}
|