Py-Driver: re-use self PyObject when its unchanged.

This commit is contained in:
Campbell Barton 2016-07-31 11:43:24 +10:00
parent 55f481d052
commit 01d5d2853b
Notes: blender-bot 2023-02-14 10:14:07 +01:00
Referenced by issue #48988, BBones Ease in/out don´t update the mesh deformation at current frame
Referenced by issue #48980, crash when loading a file that contains a custom node tree
3 changed files with 56 additions and 8 deletions

View File

@ -100,24 +100,48 @@ int bpy_pydriver_create_dict(void)
/* note, this function should do nothing most runs, only when changing frame */
/* not thread safe but neither is python */
static float bpy_pydriver_evaltime_prev = FLT_MAX;
static struct {
float evaltime;
/* borrowed reference to the 'self' in 'bpy_pydriver_Dict'
* keep for as long as the same self is used. */
PyObject *self;
} g_pydriver_state_prev = {
.evaltime = FLT_MAX,
.self = NULL,
};
static void bpy_pydriver_namespace_update_frame(const float evaltime)
{
if (bpy_pydriver_evaltime_prev != evaltime) {
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);
bpy_pydriver_evaltime_prev = evaltime;
g_pydriver_state_prev.evaltime = evaltime;
}
}
static void bpy_pydriver_namespace_update_self(struct PathResolvedRNA *anim_rna)
{
PyObject *item = pyrna_driver_self_from_anim_rna(anim_rna);
PyDict_SetItem(bpy_pydriver_Dict, bpy_intern_str_self, item);
Py_DECREF(item);
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;
}
}
static void bpy_pydriver_namespace_clear_self(void)
{
if (g_pydriver_state_prev.self) {
PyDict_DelItem(bpy_pydriver_Dict, bpy_intern_str_self);
g_pydriver_state_prev.self = NULL;
}
}
/* Update function, it gets rid of pydrivers global dictionary, forcing
@ -139,7 +163,10 @@ void BPY_driver_reset(void)
bpy_pydriver_Dict = NULL;
}
bpy_pydriver_evaltime_prev = FLT_MAX;
g_pydriver_state_prev.evaltime = FLT_MAX;
/* freed when clearing driver dict */
g_pydriver_state_prev.self = NULL;
if (use_gil)
PyGILState_Release(gilstate);
@ -225,6 +252,9 @@ float BPY_driver_exec(struct PathResolvedRNA *anim_rna, ChannelDriver *driver, c
if (driver->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;

View File

@ -78,7 +78,23 @@ PyObject *pyrna_driver_get_variable_value(
return driver_arg;
}
PyObject *pyrna_driver_self_from_anim_rna(struct PathResolvedRNA *anim_rna)
PyObject *pyrna_driver_self_from_anim_rna(PathResolvedRNA *anim_rna)
{
return pyrna_struct_CreatePyObject(&anim_rna->ptr);
}
bool pyrna_driver_is_equal_anim_rna(const PathResolvedRNA *anim_rna, const PyObject *py_anim_rna)
{
if (BPy_StructRNA_Check(py_anim_rna)) {
const PointerRNA *ptr_a = &anim_rna->ptr;
const PointerRNA *ptr_b = &(((const BPy_StructRNA *)py_anim_rna)->ptr);
if ((ptr_a->id.data == ptr_b->id.data) &&
(ptr_a->type == ptr_b->type) &&
(ptr_a->data == ptr_b->data))
{
return true;
}
}
return false;
}

View File

@ -30,6 +30,8 @@ struct DriverTarget;
struct PathResolvedRNA;
PyObject *pyrna_driver_get_variable_value(struct ChannelDriver *driver, struct DriverTarget *dtar);
PyObject *pyrna_driver_self_from_anim_rna(struct PathResolvedRNA *anim_rna);
bool pyrna_driver_is_equal_anim_rna(const struct PathResolvedRNA *anim_rna, const PyObject *py_anim_rna);
#endif /* __BPY_RNA_DRIVER_H__ */