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