|
Blender
V2.59
|
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 }