Drivers: ensure Python expressions are cached with copy-on-write.
Store the compiled expressions on the original driver. Ref T55442.
This commit is contained in:
parent
2bbe0c4ef4
commit
3816502b7c
|
@ -108,7 +108,8 @@ bool driver_get_variable_property(
|
|||
struct ChannelDriver *driver, struct DriverTarget *dtar,
|
||||
struct PointerRNA *r_ptr, struct PropertyRNA **r_prop, int *r_index);
|
||||
|
||||
float evaluate_driver(struct PathResolvedRNA *anim_rna, struct ChannelDriver *driver, const float evaltime);
|
||||
float evaluate_driver(struct PathResolvedRNA *anim_rna, struct ChannelDriver *driver,
|
||||
struct ChannelDriver *driver_orig, const float evaltime);
|
||||
|
||||
/* ************** F-Curve Modifiers *************** */
|
||||
|
||||
|
@ -282,7 +283,8 @@ void correct_bezpart(float v1[2], float v2[2], float v3[2], float v4[2]);
|
|||
|
||||
/* evaluate fcurve */
|
||||
float evaluate_fcurve(struct FCurve *fcu, float evaltime);
|
||||
float evaluate_fcurve_driver(struct PathResolvedRNA *anim_rna, struct FCurve *fcu, float evaltime);
|
||||
float evaluate_fcurve_driver(struct PathResolvedRNA *anim_rna, struct FCurve *fcu,
|
||||
struct ChannelDriver *driver_orig, float evaltime);
|
||||
/* evaluate fcurve and store value */
|
||||
float calculate_fcurve(struct PathResolvedRNA *anim_rna, struct FCurve *fcu, float evaltime);
|
||||
|
||||
|
|
|
@ -3017,7 +3017,7 @@ void BKE_animsys_eval_driver(Depsgraph *depsgraph,
|
|||
PathResolvedRNA anim_rna;
|
||||
if (animsys_store_rna_setting(&id_ptr, NULL, fcu->rna_path, fcu->array_index, &anim_rna)) {
|
||||
const float ctime = DEG_get_ctime(depsgraph);
|
||||
const float curval = calculate_fcurve(&anim_rna, fcu, ctime);
|
||||
const float curval = evaluate_fcurve_driver(&anim_rna, fcu, driver_orig, ctime);
|
||||
ok = animsys_write_rna_setting(&anim_rna, curval);
|
||||
if (ok && DEG_is_active(depsgraph)) {
|
||||
animsys_write_orig_anim_rna(&id_ptr, NULL, fcu, curval);
|
||||
|
|
|
@ -1922,13 +1922,14 @@ float driver_get_variable_value(ChannelDriver *driver, DriverVar *dvar)
|
|||
/* Evaluate an Channel-Driver to get a 'time' value to use instead of "evaltime"
|
||||
* - "evaltime" is the frame at which F-Curve is being evaluated
|
||||
* - has to return a float value
|
||||
* - driver_orig is where we cache Python expressions, in case of COW
|
||||
*/
|
||||
float evaluate_driver(PathResolvedRNA *anim_rna, ChannelDriver *driver, const float evaltime)
|
||||
float evaluate_driver(PathResolvedRNA *anim_rna, ChannelDriver *driver, ChannelDriver *driver_orig, const float evaltime)
|
||||
{
|
||||
DriverVar *dvar;
|
||||
|
||||
/* check if driver can be evaluated */
|
||||
if (driver->flag & DRIVER_FLAG_INVALID)
|
||||
if (driver_orig->flag & DRIVER_FLAG_INVALID)
|
||||
return 0.0f;
|
||||
|
||||
switch (driver->type) {
|
||||
|
@ -1998,8 +1999,8 @@ float evaluate_driver(PathResolvedRNA *anim_rna, ChannelDriver *driver, const fl
|
|||
{
|
||||
#ifdef WITH_PYTHON
|
||||
/* check for empty or invalid expression */
|
||||
if ( (driver->expression[0] == '\0') ||
|
||||
(driver->flag & DRIVER_FLAG_INVALID) )
|
||||
if ( (driver_orig->expression[0] == '\0') ||
|
||||
(driver_orig->flag & DRIVER_FLAG_INVALID) )
|
||||
{
|
||||
driver->curval = 0.0f;
|
||||
}
|
||||
|
@ -2009,7 +2010,7 @@ float evaluate_driver(PathResolvedRNA *anim_rna, ChannelDriver *driver, const fl
|
|||
*/
|
||||
BLI_mutex_lock(&python_driver_lock);
|
||||
|
||||
driver->curval = BPY_driver_exec(anim_rna, driver, evaltime);
|
||||
driver->curval = BPY_driver_exec(anim_rna, driver, driver_orig, evaltime);
|
||||
|
||||
BLI_mutex_unlock(&python_driver_lock);
|
||||
}
|
||||
|
@ -2705,7 +2706,7 @@ float evaluate_fcurve(FCurve *fcu, float evaltime)
|
|||
return evaluate_fcurve_ex(fcu, evaltime, 0.0);
|
||||
}
|
||||
|
||||
float evaluate_fcurve_driver(PathResolvedRNA *anim_rna, FCurve *fcu, float evaltime)
|
||||
float evaluate_fcurve_driver(PathResolvedRNA *anim_rna, FCurve *fcu, ChannelDriver *driver_orig, float evaltime)
|
||||
{
|
||||
BLI_assert(fcu->driver != NULL);
|
||||
float cvalue = 0.0f;
|
||||
|
@ -2715,7 +2716,7 @@ float evaluate_fcurve_driver(PathResolvedRNA *anim_rna, FCurve *fcu, float evalt
|
|||
*/
|
||||
if (fcu->driver) {
|
||||
/* evaltime now serves as input for the curve */
|
||||
evaltime = evaluate_driver(anim_rna, fcu->driver, evaltime);
|
||||
evaltime = evaluate_driver(anim_rna, fcu->driver, driver_orig, evaltime);
|
||||
|
||||
/* only do a default 1-1 mapping if it's unlikely that anything else will set a value... */
|
||||
if (fcu->totvert == 0) {
|
||||
|
@ -2762,7 +2763,7 @@ float calculate_fcurve(PathResolvedRNA *anim_rna, FCurve *fcu, float evaltime)
|
|||
/* calculate and set curval (evaluates driver too if necessary) */
|
||||
float curval;
|
||||
if (fcu->driver) {
|
||||
curval = evaluate_fcurve_driver(anim_rna, fcu, evaltime);
|
||||
curval = evaluate_fcurve_driver(anim_rna, fcu, fcu->driver, evaltime);
|
||||
}
|
||||
else {
|
||||
curval = evaluate_fcurve(fcu, evaltime);
|
||||
|
|
|
@ -954,7 +954,7 @@ bool insert_keyframe_direct(Depsgraph *depsgraph, ReportList *reports, PointerRN
|
|||
|
||||
if (RNA_path_resolved_create(&ptr, prop, fcu->array_index, &anim_rna)) {
|
||||
/* for making it easier to add corrective drivers... */
|
||||
cfra = evaluate_driver(&anim_rna, fcu->driver, cfra);
|
||||
cfra = evaluate_driver(&anim_rna, fcu->driver, fcu->driver, cfra);
|
||||
}
|
||||
else {
|
||||
cfra = 0.0f;
|
||||
|
|
|
@ -87,7 +87,8 @@ void BPY_modules_load_user(struct bContext *C);
|
|||
void BPY_app_handlers_reset(const short do_all);
|
||||
|
||||
void BPY_driver_reset(void);
|
||||
float BPY_driver_exec(struct PathResolvedRNA *anim_rna, struct ChannelDriver *driver, const float evaltime);
|
||||
float BPY_driver_exec(struct PathResolvedRNA *anim_rna, struct ChannelDriver *driver,
|
||||
struct ChannelDriver *driver_orig, const float evaltime);
|
||||
|
||||
void BPY_DECREF(void *pyob_ptr); /* Py_DECREF() */
|
||||
void BPY_DECREF_RNA_INVALIDATE(void *pyob_ptr);
|
||||
|
|
|
@ -48,6 +48,8 @@
|
|||
|
||||
#include "bpy_driver.h"
|
||||
|
||||
#include "BPY_extern.h"
|
||||
|
||||
extern void BPY_update_rna_module(void);
|
||||
|
||||
#define USE_RNA_AS_PYOBJECT
|
||||
|
@ -196,8 +198,12 @@ static void pydriver_error(ChannelDriver *driver)
|
|||
* (new)note: checking if python is running is not threadsafe [#28114]
|
||||
* now release the GIL on python operator execution instead, using
|
||||
* PyEval_SaveThread() / PyEval_RestoreThread() so we don't lock up blender.
|
||||
*
|
||||
* 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.
|
||||
*/
|
||||
float BPY_driver_exec(struct PathResolvedRNA *anim_rna, ChannelDriver *driver, const float evaltime)
|
||||
float BPY_driver_exec(struct PathResolvedRNA *anim_rna, ChannelDriver *driver, ChannelDriver *driver_orig, const float evaltime)
|
||||
{
|
||||
PyObject *driver_vars = NULL;
|
||||
PyObject *retval = NULL;
|
||||
|
@ -213,7 +219,7 @@ float BPY_driver_exec(struct PathResolvedRNA *anim_rna, ChannelDriver *driver, c
|
|||
int i;
|
||||
|
||||
/* get the py expression to be evaluated */
|
||||
expr = driver->expression;
|
||||
expr = driver_orig->expression;
|
||||
if (expr[0] == '\0')
|
||||
return 0.0f;
|
||||
|
||||
|
@ -249,47 +255,47 @@ float BPY_driver_exec(struct PathResolvedRNA *anim_rna, ChannelDriver *driver, c
|
|||
/* update global namespace */
|
||||
bpy_pydriver_namespace_update_frame(evaltime);
|
||||
|
||||
if (driver->flag & DRIVER_FLAG_USE_SELF) {
|
||||
if (driver_orig->flag & DRIVER_FLAG_USE_SELF) {
|
||||
bpy_pydriver_namespace_update_self(anim_rna);
|
||||
}
|
||||
else {
|
||||
bpy_pydriver_namespace_clear_self();
|
||||
}
|
||||
|
||||
if (driver->expr_comp == NULL)
|
||||
driver->flag |= DRIVER_FLAG_RECOMPILE;
|
||||
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->flag & DRIVER_FLAG_RECOMPILE) {
|
||||
Py_XDECREF(driver->expr_comp);
|
||||
driver->expr_comp = PyTuple_New(2);
|
||||
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->expr_comp), 0, expr_code);
|
||||
PyTuple_SET_ITEM(((PyObject *)driver_orig->expr_comp), 0, expr_code);
|
||||
|
||||
driver->flag &= ~DRIVER_FLAG_RECOMPILE;
|
||||
driver->flag |= DRIVER_FLAG_RENAMEVAR; /* maybe this can be removed but for now best keep until were sure */
|
||||
driver_orig->flag &= ~DRIVER_FLAG_RECOMPILE;
|
||||
driver_orig->flag |= DRIVER_FLAG_RENAMEVAR; /* maybe this can be removed but for now best keep until were sure */
|
||||
}
|
||||
else {
|
||||
expr_code = PyTuple_GET_ITEM(((PyObject *)driver->expr_comp), 0);
|
||||
expr_code = PyTuple_GET_ITEM(((PyObject *)driver_orig->expr_comp), 0);
|
||||
}
|
||||
|
||||
if (driver->flag & DRIVER_FLAG_RENAMEVAR) {
|
||||
if (driver_orig->flag & DRIVER_FLAG_RENAMEVAR) {
|
||||
/* may not be set */
|
||||
expr_vars = PyTuple_GET_ITEM(((PyObject *)driver->expr_comp), 1);
|
||||
expr_vars = PyTuple_GET_ITEM(((PyObject *)driver_orig->expr_comp), 1);
|
||||
Py_XDECREF(expr_vars);
|
||||
|
||||
expr_vars = PyTuple_New(BLI_listbase_count(&driver->variables));
|
||||
PyTuple_SET_ITEM(((PyObject *)driver->expr_comp), 1, 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->variables.first, i = 0; dvar; dvar = dvar->next) {
|
||||
for (dvar = driver_orig->variables.first, i = 0; dvar; dvar = dvar->next) {
|
||||
PyTuple_SET_ITEM(expr_vars, i++, PyUnicode_FromString(dvar->name));
|
||||
}
|
||||
|
||||
driver->flag &= ~DRIVER_FLAG_RENAMEVAR;
|
||||
driver_orig->flag &= ~DRIVER_FLAG_RENAMEVAR;
|
||||
}
|
||||
else {
|
||||
expr_vars = PyTuple_GET_ITEM(((PyObject *)driver->expr_comp), 1);
|
||||
expr_vars = PyTuple_GET_ITEM(((PyObject *)driver_orig->expr_comp), 1);
|
||||
}
|
||||
|
||||
/* add target values to a dict that will be used as '__locals__' dict */
|
||||
|
|
|
@ -27,14 +27,7 @@
|
|||
#ifndef __BPY_DRIVER_H__
|
||||
#define __BPY_DRIVER_H__
|
||||
|
||||
struct ChannelDriver;
|
||||
struct PathResolvedRNA;
|
||||
|
||||
int bpy_pydriver_create_dict(void);
|
||||
extern PyObject *bpy_pydriver_Dict;
|
||||
|
||||
/* externals */
|
||||
float BPY_driver_exec(struct PathResolvedRNA *anim_rna, struct ChannelDriver *driver, const float evaltime);
|
||||
void BPY_driver_reset(void);
|
||||
|
||||
#endif /* __BPY_DRIVER_H__ */
|
||||
|
|
Loading…
Reference in New Issue