* Added 3 missing functions, 2 of them called by blender/src/drawtext.c:
[blender-staging.git] / source / blender / python / BPY_interface.c
1 /* 
2  *
3  * ***** BEGIN GPL/BL DUAL LICENSE BLOCK *****
4  *
5  * This program is free software; you can redistribute it and/or
6  * modify it under the terms of the GNU General Public License
7  * as published by the Free Software Foundation; either version 2
8  * of the License, or (at your option) any later version. The Blender
9  * Foundation also sells licenses for use in proprietary software under
10  * the Blender License.  See http://www.blender.org/BL/ for information
11  * about this.
12  *
13  * This program is distributed in the hope that it will be useful,
14  * but WITHOUT ANY WARRANTY; without even the implied warranty of
15  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
16  * GNU General Public License for more details.
17  *
18  * You should have received a copy of the GNU General Public License
19  * along with this program; if not, write to the Free Software Foundation,
20  * Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
21  *
22  * The Original Code is Copyright (C) 2001-2002 by NaN Holding BV.
23  * All rights reserved.
24  *
25  * This is a new part of Blender.
26  *
27  * Contributor(s): Michel Selten, Willian P. Germano
28  *
29  * ***** END GPL/BL DUAL LICENSE BLOCK *****
30 */
31 #ifdef HAVE_CONFIG_H
32 #include <config.h>
33 #endif
34
35 #include <Python.h>
36 #include "compile.h" /* for the PyCodeObject */
37 #include "eval.h" /* for PyEval_EvalCode */
38
39 #include <stdio.h>
40
41 #include <MEM_guardedalloc.h>
42
43 #include <BKE_global.h>
44 #include <BKE_main.h>
45 #include <BKE_text.h>
46 #include <DNA_camera_types.h>
47 #include <DNA_ID.h>
48 #include <DNA_lamp_types.h>
49 #include <DNA_material_types.h>
50 #include <DNA_object_types.h>
51 #include <DNA_scene_types.h>
52 #include <DNA_scriptlink_types.h>
53 #include <DNA_space_types.h>
54 #include <DNA_text_types.h>
55 #include <DNA_world_types.h>
56
57 #include "BPY_extern.h"
58 #include "api2_2x/EXPP_interface.h"
59
60
61 /*****************************************************************************/
62 /* Structure definitions                                                     */
63 /*****************************************************************************/
64 #define FILENAME_LENGTH 24
65 typedef struct _ScriptError {
66   char filename[FILENAME_LENGTH];
67   int lineno;
68 } ScriptError;
69
70 /*****************************************************************************/
71 /* Global variables                                                          */
72 /*****************************************************************************/
73 ScriptError g_script_error;
74 short EXPP_releaseGlobalDict = 1;
75
76 /*****************************************************************************/
77 /* Function prototypes                                                       */
78 /*****************************************************************************/
79 PyObject *RunPython(Text *text, PyObject *globaldict);
80 char     *GetName(Text *text);
81 PyObject *CreateGlobalDictionary (void);
82 void      ReleaseGlobalDictionary (PyObject * dict);
83 void      DoAllScriptsFromList (ListBase * list, short event);
84
85 /*****************************************************************************/
86 /* Description: This function will initialise Python and all the implemented */
87 /*              api variations.                                              */
88 /* Notes:       Currently only the api for 2.2x will be initialised.         */
89 /*****************************************************************************/
90 void BPY_start_python(void)
91 {
92   printf ("In BPY_start_python\n");
93 /* TODO: Shouldn't "blender" be replaced by PACKAGE ?? (config.h) */
94   Py_SetProgramName("blender");
95
96   Py_Initialize ();
97
98   initBlenderApi2_2x ();
99
100   return; /* We could take away all these return; ... */
101 }
102
103 /*****************************************************************************/
104 /* Description: This function will terminate the Python interpreter          */
105 /*****************************************************************************/
106 void BPY_end_python(void)
107 {
108   printf ("In BPY_end_python\n");
109   Py_Finalize();
110   return;
111 }
112
113 /*****************************************************************************/
114 /* Description: This function will return the linenumber on which an error   */
115 /*              has occurred in the Python script.                           */
116 /*****************************************************************************/
117 int BPY_Err_getLinenumber(void)
118 {
119   printf ("In BPY_Err_getLinenumber\n");
120   return g_script_error.lineno;
121 }
122
123 /*****************************************************************************/
124 /* Description: This function will return the filename of the python script. */
125 /*****************************************************************************/
126 const char *BPY_Err_getFilename(void)
127 {
128   printf ("In BPY_Err_getFilename\n");
129   return g_script_error.filename;
130 }
131
132 /*****************************************************************************/
133 /* Description: Return PyString filename from a traceback object             */
134 /*****************************************************************************/
135 PyObject *traceback_getFilename(PyObject *tb)
136 {
137   PyObject *v;
138
139 /* co_filename is in f_code, which is in tb_frame, which is in tb */
140
141   v = PyObject_GetAttrString(tb, "tb_frame"); Py_XDECREF(v);
142   v = PyObject_GetAttrString(v, "f_code"); Py_XDECREF(v);
143   v = PyObject_GetAttrString(v, "co_filename");
144
145   return v;
146 }
147
148 /*****************************************************************************/
149 /* Description: Blender Python error handler. This catches the error and     */
150 /* stores filename and line number in a global                               */
151 /*****************************************************************************/
152 void BPY_Err_Handle(Text *text)
153 {
154   PyObject *exception, *err, *tb, *v;
155
156   PyErr_Fetch(&exception, &err, &tb);
157
158   if (!exception && !tb) {
159     printf("FATAL: spurious exception\n");
160     return;
161   }
162
163   strcpy(g_script_error.filename, GetName(text));
164
165   if (exception && PyErr_GivenExceptionMatches(exception, PyExc_SyntaxError)) {
166     /* no traceback available when SyntaxError */
167     PyErr_Restore(exception, err, tb); /* takes away reference! */
168     PyErr_Print();
169     v = PyObject_GetAttrString(err, "lineno");
170     g_script_error.lineno = PyInt_AsLong(v);
171     Py_XDECREF(v);
172     return; 
173   } else {
174     PyErr_NormalizeException(&exception, &err, &tb);
175     PyErr_Restore(exception, err, tb); // takes away reference!
176     PyErr_Print();
177     tb = PySys_GetObject("last_traceback");
178     Py_INCREF(tb);
179
180 /* From old bpython BPY_main.c:
181  * 'check traceback objects and look for last traceback in the
182  *  same text file. This is used to jump to the line of where the
183  *  error occured. "If the error occured in another text file or module,
184  *  the last frame in the current file is adressed."' */
185
186       while (1) { 
187         v = PyObject_GetAttrString(tb, "tb_next");
188
189         if (v == Py_None || 
190           strcmp(PyString_AsString(traceback_getFilename(v)), GetName(text)))
191           break;
192         Py_DECREF(tb);
193         tb = v;
194       }
195
196     v = PyObject_GetAttrString(tb, "tb_lineno");
197     g_script_error.lineno = PyInt_AsLong(v);
198     Py_XDECREF(v);
199     v = traceback_getFilename(tb);
200     strncpy(g_script_error.filename, PyString_AsString(v), FILENAME_LENGTH);
201     Py_XDECREF(v);
202     Py_DECREF(tb);
203   }
204
205         return;
206 }
207
208 /*****************************************************************************/
209 /* Description: This function executes the script passed by st.              */
210 /* Notes:       It is called by blender/src/drawtext.c when a Blender user   */
211 /*              presses ALT+PKEY in the script's text window.                */
212 /*****************************************************************************/
213 struct _object *BPY_txt_do_python(struct SpaceText* st)
214 {
215   PyObject *dict, *ret;
216
217   printf ("In BPY_txt_do_python\n");
218
219   if (!st->text) return NULL;
220
221 /* The EXPP_releaseGlobalDict global variable controls whether we should run
222  * the script with a clean global dictionary or should keep the current one,
223  * possibly already "polluted" by other calls to the Python Interpreter.
224  * The default is to use a clean one.  To change this the script writer must
225  * call Blender.releaseGlobalDict(bool), with bool != 0, in the script */
226
227   if (EXPP_releaseGlobalDict) {
228     printf("Using a clean Global Dictionary.\n");
229     st->flags |= ST_CLEAR_NAMESPACE;
230     dict = CreateGlobalDictionary();
231   }
232   else
233     dict = PyModule_GetDict(PyImport_AddModule("__main__"));
234
235   ret = RunPython (st->text, dict); /* Run the script */
236
237   if (!ret) { /* Failed execution of the script */
238
239     if (EXPP_releaseGlobalDict) ReleaseGlobalDictionary(dict);
240
241     BPY_Err_Handle(st->text);
242     BPY_end_python();
243     BPY_start_python();
244
245     return NULL;
246   }
247
248   else Py_DECREF (ret);
249
250 /* From the old BPY_main.c:
251  * 'The following lines clear the global name space of the python
252  *  interpreter. This is desired to release objects after execution
253  *  of a script (remember that each wrapper object increments the refcount
254  *  of the Blender Object. 
255  *  Exception: scripts that use the GUI rely on the
256  *  persistent global namespace, so they need a workaround: The namespace
257  *  is released when the GUI is exit.'
258  * See api2_2x/Draw.c: Method_Register() */
259
260   if (EXPP_releaseGlobalDict) {     
261     if (st->flags & ST_CLEAR_NAMESPACE) {
262       ReleaseGlobalDictionary(dict);
263       /*garbage_collect(&G.main); Unfinished in the previous implementation */ 
264     }
265   }
266
267 /* Edited from old BPY_main.c:
268  * 'The return value is the global namespace dictionary of the script
269  *  context.  This may be stored in the SpaceText instance to give control
270  *  over namespace persistence.  Remember that the same script may be
271  *  executed in several windows ...  Namespace persistence is desired for
272  *  scripts that use the GUI and store callbacks to the current script.' */
273
274   return dict;
275 }
276
277 /*****************************************************************************/
278 /* Description:                                                              */
279 /* Notes:                                                                    */
280 /*****************************************************************************/
281 void BPY_free_compiled_text(struct Text* text)
282 {
283   printf ("In BPY_free_compiled_text\n");
284   if (!text->compiled) return;
285   Py_DECREF((PyObject*) text->compiled);
286   text->compiled = NULL;
287
288         return;
289 }
290
291 /*****************************************************************************/
292 /* ScriptLinks                                                               */
293 /*****************************************************************************/
294
295 /*****************************************************************************/
296 /* Description:                                                              */
297 /* Notes:       Not implemented yet                                          */
298 /*****************************************************************************/
299 void BPY_clear_bad_scriptlinks(struct Text *byebye)
300 {
301   printf ("In BPY_clear_bad_scriptlinks\n");
302 /*
303   BPY_clear_bad_scriptlist(getObjectList(), byebye);
304   BPY_clear_bad_scriptlist(getLampList(), byebye);
305   BPY_clear_bad_scriptlist(getCameraList(), byebye);
306   BPY_clear_bad_scriptlist(getMaterialList(), byebye);
307   BPY_clear_bad_scriptlist(getWorldList(),  byebye);
308   BPY_clear_bad_scriptlink(&scene_getCurrent()->id, byebye);
309
310   allqueue(REDRAWBUTSSCRIPT, 0);
311 */
312         return;
313 }
314
315 /*****************************************************************************/
316 /* Description: Loop through all scripts of a list of object types, and      */
317 /*              execute these scripts.                                       */
318 /*              For the scene, only the current active scene the scripts are */
319 /*              executed (if any).                                           */
320 /*****************************************************************************/
321 void BPY_do_all_scripts(short event)
322 {
323   printf ("In BPY_do_all_scripts(event=%d)\n",event);
324
325   DoAllScriptsFromList (&(G.main->object), event);
326   DoAllScriptsFromList (&(G.main->lamp), event);
327   DoAllScriptsFromList (&(G.main->camera), event);
328   DoAllScriptsFromList (&(G.main->mat), event);
329   DoAllScriptsFromList (&(G.main->world), event);
330
331   BPY_do_pyscript (&(G.scene->id), event);
332
333         return;
334 }
335
336 /*****************************************************************************/
337 /* Description: Execute a Python script when an event occurs. The following  */
338 /*              events are possible: frame changed, load script and redraw.  */
339 /*              Only events happening to one of the following object types   */
340 /*              are handled: Object, Lamp, Camera, Material, World and       */
341 /*              Scene.                                                       */
342 /*****************************************************************************/
343 void BPY_do_pyscript(struct ID *id, short event)
344 {
345   ScriptLink  * scriptlink;
346   int           index;
347   PyObject    * dict;
348
349   printf ("In BPY_do_pyscript(id=%s, event=%d)\n",id->name, event);
350
351   scriptlink = setScriptLinks (id, event);
352
353   if (scriptlink == NULL) return;
354
355   for (index = 0; index < scriptlink->totscript; index++)
356   {
357     printf ("scriptnr: %d\tevent=%d, flag[index]=%d\n", index,
358         event, scriptlink->flag[index]);
359     if ((scriptlink->flag[index] == event) &&
360         (scriptlink->scripts[index] != NULL))
361     {
362       dict = CreateGlobalDictionary();
363       RunPython ((Text*) scriptlink->scripts[index], dict);
364       ReleaseGlobalDictionary (dict);
365     }
366   }
367
368         return;
369 }
370
371 /*****************************************************************************/
372 /* Description:                                                              */
373 /* Notes:                                                                    */
374 /*****************************************************************************/
375 void BPY_free_scriptlink(struct ScriptLink *slink)
376 {
377   printf ("In BPY_free_scriptlink\n");
378
379   if (slink->totscript) {
380     if(slink->flag) MEM_freeN(slink->flag);
381     if(slink->scripts) MEM_freeN(slink->scripts); 
382   }
383
384         return;
385 }
386
387 /*****************************************************************************/
388 /* Description:                                                              */
389 /* Notes:                                                                    */
390 /*****************************************************************************/
391 void BPY_copy_scriptlink(struct ScriptLink *scriptlink)
392 {
393   void *tmp;
394
395   printf ("In BPY_copy_scriptlink\n");
396
397   if (scriptlink->totscript) {
398
399     tmp = scriptlink->scripts;
400     scriptlink->scripts =
401       MEM_mallocN(sizeof(ID*)*scriptlink->totscript, "scriptlistL");
402     memcpy(scriptlink->scripts, tmp, sizeof(ID*)*scriptlink->totscript);
403
404     tmp = scriptlink->flag;
405     scriptlink->flag =
406       MEM_mallocN(sizeof(short)*scriptlink->totscript, "scriptlistF");
407     memcpy(scriptlink->flag, tmp, sizeof(short)*scriptlink->totscript);
408   }
409
410         return;
411 }
412
413 /*****************************************************************************/
414 /* Description:                                                              */
415 /* Notes:       Not implemented yet                                          */
416 /*****************************************************************************/
417 int BPY_call_importloader(char *name)
418 { /* XXX Should this function go away from Blender? */
419   printf ("In BPY_call_importloader(name=%s)\n",name);
420   return (0);
421 }
422
423 /* XXX THE 3 FUNCTIONS BELOW ARE IMPLEMENTED IN DRAW.C */
424
425 /*****************************************************************************/
426 /* Description:                                                              */
427 /* Notes:       Not implemented yet                                          */
428 /*****************************************************************************/
429 //int BPY_spacetext_is_pywin(struct SpaceText *st)
430 //{
431 //  /* No printf is done here because it is called with every mouse move */
432 //  return (0);
433 //}
434
435 /*****************************************************************************/
436 /* Description:                                                              */
437 /* Notes:       Not implemented yet                                          */
438 /*****************************************************************************/
439 //void BPY_spacetext_do_pywin_draw(struct SpaceText *st)
440 //{
441 //  printf ("In BPY_spacetext_do_pywin_draw\n");
442 //  return;
443 //}
444
445 /*****************************************************************************/
446 /* Description:                                                              */
447 /* Notes:       Not implemented yet                                          */
448 /*****************************************************************************/
449 //void BPY_spacetext_do_pywin_event(struct SpaceText *st,
450 //                                  unsigned short event,
451 //                                  short val)
452 //{
453 //  printf ("In BPY_spacetext_do_pywin_event(st=?, event=%d, val=%d)\n",
454 //          event, val);
455 //  return;
456 //}
457
458 /*****************************************************************************/
459 /* Private functions                                                         */
460 /*****************************************************************************/
461
462 /*****************************************************************************/
463 /* Description: This function executes the python script passed by text.     */
464 /*              The Python dictionary containing global variables needs to   */
465 /*              be passed in globaldict.                                     */
466 /*****************************************************************************/
467 PyObject * RunPython(Text *text, PyObject *globaldict)
468 {
469   char *buf = NULL;
470
471   printf("Run Python script \"%s\" ...\n", GetName(text));
472
473 /* The script text is compiled to Python bytecode and saved at text->compiled
474  * to speed-up execution if the user executes the script multiple times */
475
476   if (!text->compiled) { /* if it wasn't already compiled, do it now */
477     buf = txt_to_buf(text);
478
479     text->compiled = Py_CompileString(buf, GetName(text), Py_file_input);
480
481     MEM_freeN(buf);
482
483     if (PyErr_Occurred()) {
484       BPY_free_compiled_text(text);
485                         PyErr_SetString (PyExc_RuntimeError,
486                                                                                         "couldn't compile script to Python bytecode");
487                         return NULL;
488     }
489
490   }
491
492   return PyEval_EvalCode(text->compiled, globaldict, globaldict);
493 }
494
495 /*****************************************************************************/
496 /* Description: This function returns the value of the name field of the     */
497 /*              given Text struct.                                           */
498 /*****************************************************************************/
499 char * GetName(Text *text)
500 {
501   return (text->id.name+2);
502 }
503
504 /*****************************************************************************/
505 /* Description: This function creates a new Python dictionary object.        */
506 /*****************************************************************************/
507 PyObject * CreateGlobalDictionary (void)
508 {
509   PyObject *dict = PyDict_New();
510
511   PyDict_SetItemString (dict, "__builtins__", PyEval_GetBuiltins());
512   PyDict_SetItemString (dict, "__name__", PyString_FromString("__main__"));
513
514   return dict;
515 }
516
517 /*****************************************************************************/
518 /* Description: This function deletes a given Python dictionary object.      */
519 /*****************************************************************************/
520 void ReleaseGlobalDictionary (PyObject * dict)
521 {
522   PyDict_Clear (dict);
523   Py_DECREF (dict);   /* Release dictionary. */
524
525         return;
526 }
527
528 /*****************************************************************************/
529 /* Description: This function runs all scripts (if any) present in the       */
530 /*              list argument. The event by which the function has been      */
531 /*              called, is passed in the event argument.                     */
532 /*****************************************************************************/
533 void DoAllScriptsFromList (ListBase *list, short event)
534 {
535   ID *id;
536
537   id = list->first;
538
539   while (id != NULL) {
540     BPY_do_pyscript (id, event);
541     id = id->next;
542   }
543
544         return;
545 }
546