f628e7e8569388d37647f7c1601242424bbe32b5
[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 "DNA_anim_types.h"
28
29 #include "BLI_listbase.h"
30
31 #include "BPY_extern.h"
32 #include "BKE_fcurve.h"
33 #include "BKE_global.h"
34
35 #include <Python.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 static 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
63                 /* Only keep for backwards compat! - just import all math into root, they are standard */
64                 PyDict_SetItemString(d, "math", mod);
65                 PyDict_SetItemString(d, "m", mod);
66                 Py_DECREF(mod);
67         }
68
69         /* add bpy to global namespace */
70         mod= PyImport_ImportModuleLevel("bpy", NULL, NULL, NULL, 0);
71         if (mod) {
72                 PyDict_SetItemString(bpy_pydriver_Dict, "bpy", mod);
73                 Py_DECREF(mod);
74         }
75
76
77 #if 0 // non existant yet
78         mod = PyImport_ImportModule("Blender.Noise");
79         if (mod) {
80                 PyDict_SetItemString(d, "noise", mod);
81                 PyDict_SetItemString(d, "n", mod);
82                 Py_DECREF(mod);
83         } else {
84                 PyErr_Clear();
85         }
86
87         /* If there's a Blender text called pydrivers.py, import it.
88          * Users can add their own functions to this module.
89          */
90         if (G.f & G_SCRIPT_AUTOEXEC) {
91                 mod = importText("pydrivers"); /* can also use PyImport_Import() */
92                 if (mod) {
93                         PyDict_SetItemString(d, "pydrivers", mod);
94                         PyDict_SetItemString(d, "p", mod);
95                         Py_DECREF(mod);
96                 } else {
97                         PyErr_Clear();
98                 }
99         }
100 #endif // non existant yet
101
102         return 0;
103 }
104
105 /* Update function, it gets rid of pydrivers global dictionary, forcing
106  * BPY_pydriver_eval to recreate it. This function is used to force
107  * reloading the Blender text module "pydrivers.py", if available, so
108  * updates in it reach pydriver evaluation.
109  */
110 void BPY_pydriver_update(void)
111 {
112         PyGILState_STATE gilstate = PyGILState_Ensure();
113
114         if (bpy_pydriver_Dict) { /* free the global dict used by pydrivers */
115                 PyDict_Clear(bpy_pydriver_Dict);
116                 Py_DECREF(bpy_pydriver_Dict);
117                 bpy_pydriver_Dict = NULL;
118         }
119
120         PyGILState_Release(gilstate);
121
122         return;
123 }
124
125 /* error return function for BPY_eval_pydriver */
126 static float pydriver_error(ChannelDriver *driver)
127 {
128         if (bpy_pydriver_Dict) { /* free the global dict used by pydrivers */
129                 PyDict_Clear(bpy_pydriver_Dict);
130                 Py_DECREF(bpy_pydriver_Dict);
131                 bpy_pydriver_Dict = NULL;
132         }
133
134         driver->flag |= DRIVER_FLAG_INVALID; /* py expression failed */
135         fprintf(stderr, "\nError in Driver: The following Python expression failed:\n\t'%s'\n\n", driver->expression);
136
137         // BPy_errors_to_report(NULL); // TODO - reports
138         PyErr_Print();
139         PyErr_Clear();
140
141         return 0.0f;
142 }
143
144 /* This evals py driver expressions, 'expr' is a Python expression that
145  * should evaluate to a float number, which is returned.
146  */
147 float BPY_pydriver_eval (ChannelDriver *driver)
148 {
149         PyObject *driver_vars=NULL;
150         PyObject *retval= NULL;
151         PyObject *expr_vars; /* speed up by pre-hashing string & avoids re-converting unicode strings for every execution */
152         PyObject *expr_code;
153         PyGILState_STATE gilstate;
154
155         DriverVar *dvar;
156         float result = 0.0f; /* default return */
157         char *expr = NULL;
158         short targets_ok= 1;
159         int i;
160
161         /* sanity checks - should driver be executed? */
162         /*if (G.f & G_SCRIPT_AUTOEXEC)==0) return result; */
163
164         /* get the py expression to be evaluated */
165         expr = driver->expression;
166         if ((expr == NULL) || (expr[0]=='\0'))
167                 return result;
168
169         if(!(G.f & G_SCRIPT_AUTOEXEC)) {
170                 printf("skipping driver '%s', automatic scripts are disabled\n", driver->expression);
171                 return result;
172         }
173
174         gilstate = PyGILState_Ensure();
175
176         /* init global dictionary for py-driver evaluation settings */
177         if (!bpy_pydriver_Dict) {
178                 if (bpy_pydriver_create_dict() != 0) {
179                         fprintf(stderr, "Pydriver error: couldn't create Python dictionary");
180                         PyGILState_Release(gilstate);
181                         return result;
182                 }
183         }
184
185         if(driver->expr_comp==NULL)
186                 driver->flag |= DRIVER_FLAG_RECOMPILE;
187
188         /* compile the expression first if it hasn't been compiled or needs to be rebuilt */
189         if(driver->flag & DRIVER_FLAG_RECOMPILE) {
190                 Py_XDECREF(driver->expr_comp);
191                 driver->expr_comp= PyTuple_New(2);
192
193                 expr_code= Py_CompileString(expr, "<bpy driver>", Py_eval_input);
194                 PyTuple_SET_ITEM(((PyObject *)driver->expr_comp), 0, expr_code);
195
196                 driver->flag &= ~DRIVER_FLAG_RECOMPILE;
197                 driver->flag |= DRIVER_FLAG_RENAMEVAR; /* maybe this can be removed but for now best keep until were sure */
198         }
199         else {
200                 expr_code= PyTuple_GET_ITEM(((PyObject *)driver->expr_comp), 0);
201         }
202
203         if(driver->flag & DRIVER_FLAG_RENAMEVAR) {
204                 /* may not be set */
205                 expr_vars= PyTuple_GET_ITEM(((PyObject *)driver->expr_comp), 1);
206                 Py_XDECREF(expr_vars);
207
208                 /* intern the arg names so creating the namespace for every run is faster */
209                 expr_vars= PyTuple_New(BLI_countlist(&driver->variables));
210                 PyTuple_SET_ITEM(((PyObject *)driver->expr_comp), 1, expr_vars);
211
212                 for (dvar= driver->variables.first, i=0; dvar; dvar= dvar->next) {
213                         PyTuple_SET_ITEM(expr_vars, i++, PyUnicode_InternFromString(dvar->name));
214                 }
215                 
216                 driver->flag &= ~DRIVER_FLAG_RENAMEVAR;
217         }
218         else {
219                 expr_vars= PyTuple_GET_ITEM(((PyObject *)driver->expr_comp), 1);
220         }
221
222         /* add target values to a dict that will be used as '__locals__' dict */
223         driver_vars = PyDict_New(); // XXX do we need to decref this?
224         for (dvar= driver->variables.first, i=0; dvar; dvar= dvar->next) {
225                 PyObject *driver_arg = NULL;
226                 float tval = 0.0f;
227                 
228                 /* try to get variable value */
229                 tval= driver_get_variable_value(driver, dvar);
230                 driver_arg= PyFloat_FromDouble((double)tval);
231                 
232                 /* try to add to dictionary */
233                 /* if (PyDict_SetItemString(driver_vars, dvar->name, driver_arg)) { */
234                 if (PyDict_SetItem(driver_vars, PyTuple_GET_ITEM(expr_vars, i++), driver_arg)) { /* use string interning for faster namespace creation */
235                         /* this target failed - bad name */
236                         if (targets_ok) {
237                                 /* first one - print some extra info for easier identification */
238                                 fprintf(stderr, "\nBPY_pydriver_eval() - Error while evaluating PyDriver:\n");
239                                 targets_ok= 0;
240                         }
241                         
242                         fprintf(stderr, "\tBPY_pydriver_eval() - couldn't add variable '%s' to namespace \n", dvar->name);
243                         // BPy_errors_to_report(NULL); // TODO - reports
244                         PyErr_Print();
245                         PyErr_Clear();
246                 }
247         }
248
249 #if 0 // slow, with this can avoid all Py_CompileString above.
250         /* execute expression to get a value */
251         retval = PyRun_String(expr, Py_eval_input, bpy_pydriver_Dict, driver_vars);
252 #else
253         /* evaluate the compiled expression */
254         if (expr_code)
255                 retval= PyEval_EvalCode((PyCodeObject *)expr_code, bpy_pydriver_Dict, driver_vars);
256 #endif
257
258         /* decref the driver vars first...  */
259         Py_DECREF(driver_vars);
260
261         /* process the result */
262         if (retval == NULL) {
263                 pydriver_error(driver);
264                 result = 0.0f;
265         } else if((result= (float)PyFloat_AsDouble(retval)) == -1.0f && PyErr_Occurred()) {
266                 pydriver_error(driver);
267                 Py_DECREF(retval);
268                 result = 0.0f;
269
270         }
271         else {
272                 /* all fine, make sure the "invalid expression" flag is cleared */
273                 driver->flag &= ~DRIVER_FLAG_INVALID;
274                 Py_DECREF(retval);
275         }
276
277         PyGILState_Release(gilstate);
278         return result;
279 }