compile python driver expressions for faster re-evaluation.

approx 15-25x speedup
This commit is contained in:
2009-12-08 10:36:46 +00:00
parent 445d077cf4
commit 0391b1ab78
6 changed files with 40 additions and 7 deletions

View File

@@ -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;

View File

@@ -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);

View File

@@ -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 -------------------------------------- */

View File

@@ -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);

View File

@@ -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); */

View File

@@ -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);