Blender V2.61 - r43446

bpy_driver.c

Go to the documentation of this file.
00001 /*
00002  * ***** BEGIN GPL LICENSE BLOCK *****
00003  *
00004  * This program is free software; you can redistribute it and/or
00005  * modify it under the terms of the GNU General Public License
00006  * as published by the Free Software Foundation; either version 2
00007  * of the License, or (at your option) any later version.
00008  *
00009  * This program is distributed in the hope that it will be useful,
00010  * but WITHOUT ANY WARRANTY; without even the implied warranty of
00011  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00012  * GNU General Public License for more details.
00013  *
00014  * You should have received a copy of the GNU General Public License
00015  * along with this program; if not, write to the Free Software Foundation,
00016  * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
00017  *
00018  * Contributor(s): Willian P. Germano, Campbell Barton
00019  *
00020  * ***** END GPL LICENSE BLOCK *****
00021  */
00022 
00031 /* ****************************************** */
00032 /* Drivers - PyExpression Evaluation */
00033 
00034 #include <Python.h>
00035 
00036 #include "DNA_anim_types.h"
00037 
00038 #include "BLI_listbase.h"
00039 #include "BLI_math_base.h"
00040 
00041 #include "BKE_fcurve.h"
00042 #include "BKE_global.h"
00043 
00044 #include "bpy_driver.h"
00045 
00046 extern void BPY_update_rna_module(void);
00047 
00048 
00049 /* for pydrivers (drivers using one-line Python expressions to express relationships between targets) */
00050 PyObject *bpy_pydriver_Dict = NULL;
00051 
00052 /* For faster execution we keep a special dictionary for pydrivers, with
00053  * the needed modules and aliases.
00054  */
00055 int bpy_pydriver_create_dict(void)
00056 {
00057     PyObject *d, *mod;
00058 
00059     /* validate namespace for driver evaluation */
00060     if (bpy_pydriver_Dict) return -1;
00061 
00062     d = PyDict_New();
00063     if (d == NULL)
00064         return -1;
00065     else
00066         bpy_pydriver_Dict = d;
00067 
00068     /* import some modules: builtins, bpy, math, (Blender.noise)*/
00069     PyDict_SetItemString(d, "__builtins__", PyEval_GetBuiltins());
00070 
00071     mod = PyImport_ImportModule("math");
00072     if (mod) {
00073         PyDict_Merge(d, PyModule_GetDict(mod), 0); /* 0 - dont overwrite existing values */
00074         Py_DECREF(mod);
00075     }
00076 
00077     /* add bpy to global namespace */
00078     mod = PyImport_ImportModuleLevel((char *)"bpy", NULL, NULL, NULL, 0);
00079     if (mod) {
00080         PyDict_SetItemString(bpy_pydriver_Dict, "bpy", mod);
00081         Py_DECREF(mod);
00082     }
00083 
00084     /* add noise to global namespace */
00085     mod = PyImport_ImportModuleLevel((char *)"mathutils", NULL, NULL, NULL, 0);
00086     if (mod) {
00087         PyObject *modsub = PyDict_GetItemString(PyModule_GetDict(mod), "noise");
00088         PyDict_SetItemString(bpy_pydriver_Dict, "noise", modsub);
00089         Py_DECREF(mod);
00090     }
00091 
00092     return 0;
00093 }
00094 
00095 /* note, this function should do nothing most runs, only when changing frame */
00096 static PyObject *bpy_pydriver_InternStr__frame = NULL;
00097 /* not thread safe but neither is python */
00098 static float bpy_pydriver_evaltime_prev = FLT_MAX;
00099 
00100 static void bpy_pydriver_update_dict(const float evaltime)
00101 {
00102     if (bpy_pydriver_evaltime_prev != evaltime) {
00103 
00104         /* currently only update the frame */
00105         if (bpy_pydriver_InternStr__frame == NULL) {
00106             bpy_pydriver_InternStr__frame = PyUnicode_FromString("frame");
00107         }
00108 
00109         PyDict_SetItem(bpy_pydriver_Dict,
00110                        bpy_pydriver_InternStr__frame,
00111                        PyFloat_FromDouble(evaltime));
00112 
00113         bpy_pydriver_evaltime_prev = evaltime;
00114     }
00115 }
00116 
00117 /* Update function, it gets rid of pydrivers global dictionary, forcing
00118  * BPY_driver_exec to recreate it. This function is used to force
00119  * reloading the Blender text module "pydrivers.py", if available, so
00120  * updates in it reach pydriver evaluation.
00121  */
00122 void BPY_driver_reset(void)
00123 {
00124     PyGILState_STATE gilstate;
00125     int use_gil = 1; /* !PYC_INTERPRETER_ACTIVE; */
00126 
00127     if (use_gil)
00128         gilstate = PyGILState_Ensure();
00129 
00130     if (bpy_pydriver_Dict) { /* free the global dict used by pydrivers */
00131         PyDict_Clear(bpy_pydriver_Dict);
00132         Py_DECREF(bpy_pydriver_Dict);
00133         bpy_pydriver_Dict = NULL;
00134     }
00135 
00136     if (bpy_pydriver_InternStr__frame) {
00137         Py_DECREF(bpy_pydriver_InternStr__frame);
00138         bpy_pydriver_InternStr__frame = NULL;
00139         bpy_pydriver_evaltime_prev = FLT_MAX;
00140     }
00141 
00142     if (use_gil)
00143         PyGILState_Release(gilstate);
00144 
00145     return;
00146 }
00147 
00148 /* error return function for BPY_eval_pydriver */
00149 static void pydriver_error(ChannelDriver *driver)
00150 {
00151     driver->flag |= DRIVER_FLAG_INVALID; /* py expression failed */
00152     fprintf(stderr, "\nError in Driver: The following Python expression failed:\n\t'%s'\n\n", driver->expression);
00153 
00154     // BPy_errors_to_report(NULL); // TODO - reports
00155     PyErr_Print();
00156     PyErr_Clear();
00157 }
00158 
00159 /* This evals py driver expressions, 'expr' is a Python expression that
00160  * should evaluate to a float number, which is returned.
00161  *
00162  * (old)note: PyGILState_Ensure() isnt always called because python can call
00163  * the bake operator which intern starts a thread which calls scene update
00164  * which does a driver update. to avoid a deadlock check PYC_INTERPRETER_ACTIVE
00165  * if PyGILState_Ensure() is needed - see [#27683]
00166  *
00167  * (new)note: checking if python is running is not threadsafe [#28114]
00168  * now release the GIL on python operator execution instead, using
00169  * PyEval_SaveThread() / PyEval_RestoreThread() so we dont lock up blender.
00170  */
00171 float BPY_driver_exec(ChannelDriver *driver, const float evaltime)
00172 {
00173     PyObject *driver_vars = NULL;
00174     PyObject *retval = NULL;
00175     PyObject *expr_vars; /* speed up by pre-hashing string & avoids re-converting unicode strings for every execution */
00176     PyObject *expr_code;
00177     PyGILState_STATE gilstate;
00178     int use_gil;
00179 
00180     DriverVar *dvar;
00181     double result = 0.0; /* default return */
00182     char *expr = NULL;
00183     short targets_ok = 1;
00184     int i;
00185 
00186     /* get the py expression to be evaluated */
00187     expr = driver->expression;
00188     if ((expr == NULL) || (expr[0] == '\0'))
00189         return 0.0f;
00190 
00191     if (!(G.f & G_SCRIPT_AUTOEXEC)) {
00192         printf("skipping driver '%s', automatic scripts are disabled\n", driver->expression);
00193         return 0.0f;
00194     }
00195 
00196     use_gil = 1; /* !PYC_INTERPRETER_ACTIVE; */
00197 
00198     if (use_gil)
00199         gilstate = PyGILState_Ensure();
00200 
00201     /* needed since drivers are updated directly after undo where 'main' is
00202      * re-allocated [#28807] */
00203     BPY_update_rna_module();
00204 
00205     /* init global dictionary for py-driver evaluation settings */
00206     if (!bpy_pydriver_Dict) {
00207         if (bpy_pydriver_create_dict() != 0) {
00208             fprintf(stderr, "Pydriver error: couldn't create Python dictionary");
00209             if (use_gil)
00210                 PyGILState_Release(gilstate);
00211             return 0.0f;
00212         }
00213     }
00214 
00215     /* update global namespace */
00216     bpy_pydriver_update_dict(evaltime);
00217 
00218 
00219     if (driver->expr_comp == NULL)
00220         driver->flag |= DRIVER_FLAG_RECOMPILE;
00221 
00222     /* compile the expression first if it hasn't been compiled or needs to be rebuilt */
00223     if (driver->flag & DRIVER_FLAG_RECOMPILE) {
00224         Py_XDECREF(driver->expr_comp);
00225         driver->expr_comp = PyTuple_New(2);
00226 
00227         expr_code = Py_CompileString(expr, "<bpy driver>", Py_eval_input);
00228         PyTuple_SET_ITEM(((PyObject *)driver->expr_comp), 0, expr_code);
00229 
00230         driver->flag &= ~DRIVER_FLAG_RECOMPILE;
00231         driver->flag |= DRIVER_FLAG_RENAMEVAR; /* maybe this can be removed but for now best keep until were sure */
00232     }
00233     else {
00234         expr_code = PyTuple_GET_ITEM(((PyObject *)driver->expr_comp), 0);
00235     }
00236 
00237     if (driver->flag & DRIVER_FLAG_RENAMEVAR) {
00238         /* may not be set */
00239         expr_vars = PyTuple_GET_ITEM(((PyObject *)driver->expr_comp), 1);
00240         Py_XDECREF(expr_vars);
00241 
00242         expr_vars = PyTuple_New(BLI_countlist(&driver->variables));
00243         PyTuple_SET_ITEM(((PyObject *)driver->expr_comp), 1, expr_vars);
00244 
00245         for (dvar = driver->variables.first, i = 0; dvar; dvar = dvar->next) {
00246             PyTuple_SET_ITEM(expr_vars, i++, PyUnicode_FromString(dvar->name));
00247         }
00248         
00249         driver->flag &= ~DRIVER_FLAG_RENAMEVAR;
00250     }
00251     else {
00252         expr_vars = PyTuple_GET_ITEM(((PyObject *)driver->expr_comp), 1);
00253     }
00254 
00255     /* add target values to a dict that will be used as '__locals__' dict */
00256     driver_vars = PyDict_New(); // XXX do we need to decref this?
00257     for (dvar = driver->variables.first, i = 0; dvar; dvar = dvar->next) {
00258         PyObject *driver_arg = NULL;
00259         float tval = 0.0f;
00260         
00261         /* try to get variable value */
00262         tval = driver_get_variable_value(driver, dvar);
00263         driver_arg = PyFloat_FromDouble((double)tval);
00264         
00265         /* try to add to dictionary */
00266         /* if (PyDict_SetItemString(driver_vars, dvar->name, driver_arg)) { */
00267         if (PyDict_SetItem(driver_vars, PyTuple_GET_ITEM(expr_vars, i++), driver_arg) < 0) {
00268             /* this target failed - bad name */
00269             if (targets_ok) {
00270                 /* first one - print some extra info for easier identification */
00271                 fprintf(stderr, "\nBPY_driver_eval() - Error while evaluating PyDriver:\n");
00272                 targets_ok = 0;
00273             }
00274             
00275             fprintf(stderr, "\tBPY_driver_eval() - couldn't add variable '%s' to namespace\n", dvar->name);
00276             // BPy_errors_to_report(NULL); // TODO - reports
00277             PyErr_Print();
00278             PyErr_Clear();
00279         }
00280     }
00281 
00282 
00283 #if 0 // slow, with this can avoid all Py_CompileString above.
00284     /* execute expression to get a value */
00285     retval = PyRun_String(expr, Py_eval_input, bpy_pydriver_Dict, driver_vars);
00286 #else
00287     /* evaluate the compiled expression */
00288     if (expr_code)
00289         retval = PyEval_EvalCode((void *)expr_code, bpy_pydriver_Dict, driver_vars);
00290 #endif
00291 
00292     /* decref the driver vars first...  */
00293     Py_DECREF(driver_vars);
00294 
00295     /* process the result */
00296     if (retval == NULL) {
00297         pydriver_error(driver);
00298     }
00299     else if ((result = PyFloat_AsDouble(retval)) == -1.0 && PyErr_Occurred()) {
00300         pydriver_error(driver);
00301         Py_DECREF(retval);
00302         result = 0.0;
00303     }
00304     else {
00305         /* all fine, make sure the "invalid expression" flag is cleared */
00306         driver->flag &= ~DRIVER_FLAG_INVALID;
00307         Py_DECREF(retval);
00308     }
00309 
00310     if (use_gil)
00311         PyGILState_Release(gilstate);
00312 
00313     if (finite(result)) {
00314         return (float)result;
00315     }
00316     else {
00317         fprintf(stderr, "\tBPY_driver_eval() - driver '%s' evaluates to '%f'\n", dvar->name, result);
00318         return 0.0f;
00319     }
00320 }