edits for BPY_extern.h functions, no functional changes
[blender.git] / source / blender / python / intern / bpy_driver.c
1 /**
2  * $Id$
3  *
4  * ***** BEGIN GPL LICENSE BLOCK *****
5  *
6  * This program is free software; you can redistribute it and/or
7  * modify it under the terms of the GNU General Public License
8  * as published by the Free Software Foundation; either version 2
9  * of the License, or (at your option) any later version.
10  *
11  * This program is distributed in the hope that it will be useful,
12  * but WITHOUT ANY WARRANTY; without even the implied warranty of
13  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14  * GNU General Public License for more details.
15  *
16  * You should have received a copy of the GNU General Public License
17  * along with this program; if not, write to the Free Software Foundation,
18  * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
19  *
20  * Contributor(s): Willian P. Germano, Campbell Barton
21  *
22  * ***** END GPL LICENSE BLOCK *****
23  */
24 /* ****************************************** */
25 /* Drivers - PyExpression Evaluation */
26
27 #include <Python.h>
28
29 #include "DNA_anim_types.h"
30
31 #include "BLI_listbase.h"
32 #include "BLI_math_base.h"
33
34 #include "BKE_fcurve.h"
35 #include "BKE_global.h"
36
37 /* for pydrivers (drivers using one-line Python expressions to express relationships between targets) */
38 PyObject *bpy_pydriver_Dict = NULL;
39
40 /* For faster execution we keep a special dictionary for pydrivers, with
41  * the needed modules and aliases.
42  */
43 int bpy_pydriver_create_dict(void)
44 {
45         PyObject *d, *mod;
46
47         /* validate namespace for driver evaluation */
48         if (bpy_pydriver_Dict) return -1;
49
50         d = PyDict_New();
51         if (d == NULL)
52                 return -1;
53         else
54                 bpy_pydriver_Dict = d;
55
56         /* import some modules: builtins, bpy, math, (Blender.noise )*/
57         PyDict_SetItemString(d, "__builtins__", PyEval_GetBuiltins());
58
59         mod = PyImport_ImportModule("math");
60         if (mod) {
61                 PyDict_Merge(d, PyModule_GetDict(mod), 0); /* 0 - dont overwrite existing values */
62                 Py_DECREF(mod);
63         }
64
65         /* add bpy to global namespace */
66         mod= PyImport_ImportModuleLevel((char *)"bpy", NULL, NULL, NULL, 0);
67         if (mod) {
68                 PyDict_SetItemString(bpy_pydriver_Dict, "bpy", mod);
69                 Py_DECREF(mod);
70         }
71
72         return 0;
73 }
74
75 /* Update function, it gets rid of pydrivers global dictionary, forcing
76  * BPY_driver_exec to recreate it. This function is used to force
77  * reloading the Blender text module "pydrivers.py", if available, so
78  * updates in it reach pydriver evaluation.
79  */
80 void BPY_driver_reset(void)
81 {
82         PyGILState_STATE gilstate;
83         int use_gil= 1; // (PyThreadState_Get()==NULL);
84
85         if(use_gil)
86                 gilstate = PyGILState_Ensure();
87
88         if (bpy_pydriver_Dict) { /* free the global dict used by pydrivers */
89                 PyDict_Clear(bpy_pydriver_Dict);
90                 Py_DECREF(bpy_pydriver_Dict);
91                 bpy_pydriver_Dict = NULL;
92         }
93
94         if(use_gil)
95                 PyGILState_Release(gilstate);
96
97         return;
98 }
99
100 /* error return function for BPY_eval_pydriver */
101 static void pydriver_error(ChannelDriver *driver)
102 {
103         driver->flag |= DRIVER_FLAG_INVALID; /* py expression failed */
104         fprintf(stderr, "\nError in Driver: The following Python expression failed:\n\t'%s'\n\n", driver->expression);
105
106         // BPy_errors_to_report(NULL); // TODO - reports
107         PyErr_Print();
108         PyErr_Clear();
109 }
110
111 /* This evals py driver expressions, 'expr' is a Python expression that
112  * should evaluate to a float number, which is returned.
113  *
114  * note: PyGILState_Ensure() isnt always called because python can call the
115  * bake operator which intern starts a thread which calls scene update which
116  * does a driver update. to avoid a deadlock check PyThreadState_Get() if PyGILState_Ensure() is needed.
117  */
118 float BPY_driver_exec(ChannelDriver *driver)
119 {
120         PyObject *driver_vars=NULL;
121         PyObject *retval= NULL;
122         PyObject *expr_vars; /* speed up by pre-hashing string & avoids re-converting unicode strings for every execution */
123         PyObject *expr_code;
124         PyGILState_STATE gilstate;
125         int use_gil;
126
127         DriverVar *dvar;
128         double result = 0.0; /* default return */
129         char *expr = NULL;
130         short targets_ok= 1;
131         int i;
132
133         /* get the py expression to be evaluated */
134         expr = driver->expression;
135         if ((expr == NULL) || (expr[0]=='\0'))
136                 return 0.0f;
137
138         if(!(G.f & G_SCRIPT_AUTOEXEC)) {
139                 printf("skipping driver '%s', automatic scripts are disabled\n", driver->expression);
140                 return 0.0f;
141         }
142
143         use_gil= 1; //(PyThreadState_Get()==NULL);
144
145         if(use_gil)
146                 gilstate = PyGILState_Ensure();
147
148         /* init global dictionary for py-driver evaluation settings */
149         if (!bpy_pydriver_Dict) {
150                 if (bpy_pydriver_create_dict() != 0) {
151                         fprintf(stderr, "Pydriver error: couldn't create Python dictionary");
152                         if(use_gil)
153                                 PyGILState_Release(gilstate);
154                         return 0.0f;
155                 }
156         }
157
158         if(driver->expr_comp==NULL)
159                 driver->flag |= DRIVER_FLAG_RECOMPILE;
160
161         /* compile the expression first if it hasn't been compiled or needs to be rebuilt */
162         if(driver->flag & DRIVER_FLAG_RECOMPILE) {
163                 Py_XDECREF(driver->expr_comp);
164                 driver->expr_comp= PyTuple_New(2);
165
166                 expr_code= Py_CompileString(expr, "<bpy driver>", Py_eval_input);
167                 PyTuple_SET_ITEM(((PyObject *)driver->expr_comp), 0, expr_code);
168
169                 driver->flag &= ~DRIVER_FLAG_RECOMPILE;
170                 driver->flag |= DRIVER_FLAG_RENAMEVAR; /* maybe this can be removed but for now best keep until were sure */
171         }
172         else {
173                 expr_code= PyTuple_GET_ITEM(((PyObject *)driver->expr_comp), 0);
174         }
175
176         if(driver->flag & DRIVER_FLAG_RENAMEVAR) {
177                 /* may not be set */
178                 expr_vars= PyTuple_GET_ITEM(((PyObject *)driver->expr_comp), 1);
179                 Py_XDECREF(expr_vars);
180
181                 /* intern the arg names so creating the namespace for every run is faster */
182                 expr_vars= PyTuple_New(BLI_countlist(&driver->variables));
183                 PyTuple_SET_ITEM(((PyObject *)driver->expr_comp), 1, expr_vars);
184
185                 for (dvar= driver->variables.first, i=0; dvar; dvar= dvar->next) {
186                         PyTuple_SET_ITEM(expr_vars, i++, PyUnicode_InternFromString(dvar->name));
187                 }
188                 
189                 driver->flag &= ~DRIVER_FLAG_RENAMEVAR;
190         }
191         else {
192                 expr_vars= PyTuple_GET_ITEM(((PyObject *)driver->expr_comp), 1);
193         }
194
195         /* add target values to a dict that will be used as '__locals__' dict */
196         driver_vars = PyDict_New(); // XXX do we need to decref this?
197         for (dvar= driver->variables.first, i=0; dvar; dvar= dvar->next) {
198                 PyObject *driver_arg = NULL;
199                 float tval = 0.0f;
200                 
201                 /* try to get variable value */
202                 tval= driver_get_variable_value(driver, dvar);
203                 driver_arg= PyFloat_FromDouble((double)tval);
204                 
205                 /* try to add to dictionary */
206                 /* if (PyDict_SetItemString(driver_vars, dvar->name, driver_arg)) { */
207                 if (PyDict_SetItem(driver_vars, PyTuple_GET_ITEM(expr_vars, i++), driver_arg) < 0) { /* use string interning for faster namespace creation */
208                         /* this target failed - bad name */
209                         if (targets_ok) {
210                                 /* first one - print some extra info for easier identification */
211                                 fprintf(stderr, "\nBPY_driver_eval() - Error while evaluating PyDriver:\n");
212                                 targets_ok= 0;
213                         }
214                         
215                         fprintf(stderr, "\tBPY_driver_eval() - couldn't add variable '%s' to namespace\n", dvar->name);
216                         // BPy_errors_to_report(NULL); // TODO - reports
217                         PyErr_Print();
218                         PyErr_Clear();
219                 }
220         }
221
222 #if 0 // slow, with this can avoid all Py_CompileString above.
223         /* execute expression to get a value */
224         retval = PyRun_String(expr, Py_eval_input, bpy_pydriver_Dict, driver_vars);
225 #else
226         /* evaluate the compiled expression */
227         if (expr_code)
228                 retval= PyEval_EvalCode((PyCodeObject *)expr_code, bpy_pydriver_Dict, driver_vars);
229 #endif
230
231         /* decref the driver vars first...  */
232         Py_DECREF(driver_vars);
233
234         /* process the result */
235         if (retval == NULL) {
236                 pydriver_error(driver);
237         } else if((result= PyFloat_AsDouble(retval)) == -1.0 && PyErr_Occurred()) {
238                 pydriver_error(driver);
239                 Py_DECREF(retval);
240                 result = 0.0;
241         }
242         else {
243                 /* all fine, make sure the "invalid expression" flag is cleared */
244                 driver->flag &= ~DRIVER_FLAG_INVALID;
245                 Py_DECREF(retval);
246         }
247
248         if(use_gil)
249                 PyGILState_Release(gilstate);
250     
251         if(finite(result)) {
252                 return (float)result;
253         }
254         else {
255                 fprintf(stderr, "\tBPY_driver_eval() - driver '%s' evaluates to '%f'\n", dvar->name, result);
256                 return 0.0f;
257         }
258 }