compile python driver expressions for faster re-evaluation.
approx 15-25x speedup
This commit is contained in:
@@ -758,7 +758,12 @@ void fcurve_free_driver(FCurve *fcu)
|
|||||||
dtarn= dtar->next;
|
dtarn= dtar->next;
|
||||||
driver_free_target(driver, dtar);
|
driver_free_target(driver, dtar);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#ifndef DISABLE_PYTHON
|
||||||
|
if(driver->expr_comp)
|
||||||
|
BPY_DECREF(driver->expr_comp);
|
||||||
|
#endif
|
||||||
|
|
||||||
/* free driver itself, then set F-Curve's point to this to NULL (as the curve may still be used) */
|
/* free driver itself, then set F-Curve's point to this to NULL (as the curve may still be used) */
|
||||||
MEM_freeN(driver);
|
MEM_freeN(driver);
|
||||||
fcu->driver= NULL;
|
fcu->driver= NULL;
|
||||||
|
|||||||
@@ -934,8 +934,14 @@ static void write_fcurves(WriteData *wd, ListBase *fcurves)
|
|||||||
ChannelDriver *driver= fcu->driver;
|
ChannelDriver *driver= fcu->driver;
|
||||||
DriverTarget *dtar;
|
DriverTarget *dtar;
|
||||||
|
|
||||||
|
/* don't save compiled python bytecode */
|
||||||
|
void *expr_comp= driver->expr_comp;
|
||||||
|
driver->expr_comp= NULL;
|
||||||
|
|
||||||
writestruct(wd, DATA, "ChannelDriver", 1, driver);
|
writestruct(wd, DATA, "ChannelDriver", 1, driver);
|
||||||
|
|
||||||
|
driver->expr_comp= expr_comp; /* restore */
|
||||||
|
|
||||||
/* targets */
|
/* targets */
|
||||||
for (dtar= driver->targets.first; dtar; dtar= dtar->next) {
|
for (dtar= driver->targets.first; dtar; dtar= dtar->next) {
|
||||||
writestruct(wd, DATA, "DriverTarget", 1, dtar);
|
writestruct(wd, DATA, "DriverTarget", 1, dtar);
|
||||||
|
|||||||
@@ -291,7 +291,8 @@ typedef struct ChannelDriver {
|
|||||||
/* python expression to execute (may call functions defined in an accessory file)
|
/* python expression to execute (may call functions defined in an accessory file)
|
||||||
* which relates the target 'variables' in some way to yield a single usable value
|
* which relates the target 'variables' in some way to yield a single usable value
|
||||||
*/
|
*/
|
||||||
char expression[256];
|
char expression[256];
|
||||||
|
void *expr_comp; /* PyObject - compiled expression, dont save this */
|
||||||
|
|
||||||
float curval; /* result of previous evaluation, for subtraction from result under certain circumstances */
|
float curval; /* result of previous evaluation, for subtraction from result under certain circumstances */
|
||||||
float influence; /* influence of driver on result */ // XXX to be implemented... this is like the constraint influence setting
|
float influence; /* influence of driver on result */ // XXX to be implemented... this is like the constraint influence setting
|
||||||
@@ -322,6 +323,8 @@ typedef enum eDriver_Flags {
|
|||||||
/* driver does replace value, but overrides (for layering of animation over driver) */
|
/* driver does replace value, but overrides (for layering of animation over driver) */
|
||||||
// TODO: this needs to be implemented at some stage or left out...
|
// TODO: this needs to be implemented at some stage or left out...
|
||||||
DRIVER_FLAG_LAYERING = (1<<2),
|
DRIVER_FLAG_LAYERING = (1<<2),
|
||||||
|
|
||||||
|
DRIVER_FLAG_RECOMPILE = (1<<3), /* use when the expression needs to be recompiled */
|
||||||
} eDriver_Flags;
|
} eDriver_Flags;
|
||||||
|
|
||||||
/* F-Curves -------------------------------------- */
|
/* F-Curves -------------------------------------- */
|
||||||
|
|||||||
@@ -105,6 +105,13 @@ static void rna_ChannelDriver_update_data(bContext *C, PointerRNA *ptr)
|
|||||||
WM_event_add_notifier(C, NC_SCENE|ND_FRAME, CTX_data_scene(C));
|
WM_event_add_notifier(C, NC_SCENE|ND_FRAME, CTX_data_scene(C));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void rna_ChannelDriver_update_expr(bContext *C, PointerRNA *ptr)
|
||||||
|
{
|
||||||
|
ChannelDriver *driver= ptr->data;
|
||||||
|
driver->flag |= DRIVER_FLAG_RECOMPILE;
|
||||||
|
rna_ChannelDriver_update_data(C, ptr);
|
||||||
|
}
|
||||||
|
|
||||||
static void rna_DriverTarget_update_data(bContext *C, PointerRNA *ptr)
|
static void rna_DriverTarget_update_data(bContext *C, PointerRNA *ptr)
|
||||||
{
|
{
|
||||||
PointerRNA driverptr;
|
PointerRNA driverptr;
|
||||||
@@ -807,7 +814,7 @@ static void rna_def_channeldriver(BlenderRNA *brna)
|
|||||||
/* String values */
|
/* String values */
|
||||||
prop= RNA_def_property(srna, "expression", PROP_STRING, PROP_NONE);
|
prop= RNA_def_property(srna, "expression", PROP_STRING, PROP_NONE);
|
||||||
RNA_def_property_ui_text(prop, "Expression", "Expression to use for Scripted Expression.");
|
RNA_def_property_ui_text(prop, "Expression", "Expression to use for Scripted Expression.");
|
||||||
RNA_def_property_update(prop, 0, "rna_ChannelDriver_update_data");
|
RNA_def_property_update(prop, 0, "rna_ChannelDriver_update_expr");
|
||||||
|
|
||||||
/* Collections */
|
/* Collections */
|
||||||
prop= RNA_def_property(srna, "targets", PROP_COLLECTION, PROP_NONE);
|
prop= RNA_def_property(srna, "targets", PROP_COLLECTION, PROP_NONE);
|
||||||
|
|||||||
@@ -134,7 +134,7 @@ extern "C" {
|
|||||||
// void BPY_scripts_clear_pyobjects( void );
|
// void BPY_scripts_clear_pyobjects( void );
|
||||||
//
|
//
|
||||||
// void error_pyscript( void );
|
// void error_pyscript( void );
|
||||||
// void BPY_DECREF(void *pyob_ptr); /* Py_DECREF() */
|
void BPY_DECREF(void *pyob_ptr); /* Py_DECREF() */
|
||||||
void BPY_set_context(struct bContext *C);
|
void BPY_set_context(struct bContext *C);
|
||||||
/* void BPY_Err_Handle(struct Text *text); */
|
/* void BPY_Err_Handle(struct Text *text); */
|
||||||
/* int BPY_spacetext_is_pywin(struct SpaceText *st); */
|
/* int BPY_spacetext_is_pywin(struct SpaceText *st); */
|
||||||
|
|||||||
@@ -549,7 +549,9 @@ int BPY_run_script_space_listener(bContext *C, SpaceScript * sc)
|
|||||||
|
|
||||||
void BPY_DECREF(void *pyob_ptr)
|
void BPY_DECREF(void *pyob_ptr)
|
||||||
{
|
{
|
||||||
|
PyGILState_STATE gilstate = PyGILState_Ensure();
|
||||||
Py_DECREF((PyObject *)pyob_ptr);
|
Py_DECREF((PyObject *)pyob_ptr);
|
||||||
|
PyGILState_Release(gilstate);
|
||||||
}
|
}
|
||||||
|
|
||||||
#if 0
|
#if 0
|
||||||
@@ -721,7 +723,7 @@ static float pydriver_error(ChannelDriver *driver)
|
|||||||
float BPY_pydriver_eval (ChannelDriver *driver)
|
float BPY_pydriver_eval (ChannelDriver *driver)
|
||||||
{
|
{
|
||||||
PyObject *driver_vars=NULL;
|
PyObject *driver_vars=NULL;
|
||||||
PyObject *retval;
|
PyObject *retval= NULL;
|
||||||
PyGILState_STATE gilstate;
|
PyGILState_STATE gilstate;
|
||||||
|
|
||||||
DriverTarget *dtar;
|
DriverTarget *dtar;
|
||||||
@@ -772,10 +774,20 @@ float BPY_pydriver_eval (ChannelDriver *driver)
|
|||||||
BPy_errors_to_report(NULL); // TODO - reports
|
BPy_errors_to_report(NULL); // TODO - reports
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#if 0 // slow
|
||||||
/* 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
|
||||||
|
if(driver->flag & DRIVER_FLAG_RECOMPILE || driver->expr_comp==NULL) {
|
||||||
|
Py_XDECREF(driver->expr_comp);
|
||||||
|
driver->expr_comp= Py_CompileString(expr, "<bpy driver>", Py_eval_input);
|
||||||
|
driver->flag &= ~DRIVER_FLAG_RECOMPILE;
|
||||||
|
}
|
||||||
|
if(driver->expr_comp)
|
||||||
|
retval= PyEval_EvalCode(driver->expr_comp, bpy_pydriver_Dict, driver_vars);
|
||||||
|
#endif
|
||||||
|
|
||||||
/* decref the driver vars first... */
|
/* decref the driver vars first... */
|
||||||
Py_DECREF(driver_vars);
|
Py_DECREF(driver_vars);
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user