Python Bugfix,
[blender-staging.git] / source / blender / python / BPY_interface.c
1 /* 
2  * $Id$
3  *
4  * ***** BEGIN GPL/BL DUAL 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. The Blender
10  * Foundation also sells licenses for use in proprietary software under
11  * the Blender License.  See http://www.blender.org/BL/ for information
12  * about this.
13  *
14  * This program is distributed in the hope that it will be useful,
15  * but WITHOUT ANY WARRANTY; without even the implied warranty of
16  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
17  * GNU General Public License for more details.
18  *
19  * You should have received a copy of the GNU General Public License
20  * along with this program; if not, write to the Free Software Foundation,
21  * Inc., 59 Temple Place - Suite 330, Boston, MA        02111-1307, USA.
22  *
23  * The Original Code is Copyright (C) 2001-2002 by NaN Holding BV.
24  * All rights reserved.
25  *
26  * This is a new part of Blender.
27  *
28  * Contributor(s): Michel Selten, Willian P. Germano, Stephen Swaney,
29  * Chris Keith, Chris Want, Ken Hughes
30  *
31  * ***** END GPL/BL DUAL LICENSE BLOCK *****
32 */
33
34 #include <Python.h>
35
36 #include "compile.h"            /* for the PyCodeObject */
37 #include "eval.h"               /* for PyEval_EvalCode */
38 #include "BLI_blenlib.h"        /* for BLI_last_slash() */
39 #include "BIF_interface.h"      /* for pupmenu() */
40 #include "BIF_space.h"
41 #include "BIF_screen.h"
42 #include "BIF_toolbox.h"
43 #include "BKE_action.h"         /* for get_pose_channel() */
44 #include "BKE_library.h"
45 #include "BKE_object.h"         /* during_scriptlink() */
46 #include "BKE_text.h"
47 #include "BKE_constraint.h" /* for bConstraintOb */
48 #include "BKE_idprop.h"
49
50 #include "DNA_curve_types.h" /* for struct IpoDriver */
51 #include "DNA_ID.h" /* ipo driver */
52 #include "DNA_object_types.h" /* ipo driver */
53 #include "DNA_constraint_types.h" /* for pyconstraint */
54
55 #include "DNA_screen_types.h"
56 #include "DNA_userdef_types.h"  /* for U.pythondir */
57 #include "MEM_guardedalloc.h"
58 #include "BPY_extern.h"
59 #include "BPY_menus.h"
60 #include "BPI_script.h"
61 #include "BKE_global.h"
62 #include "BKE_main.h"
63 #include "BKE_armature.h"
64 #include "api2_2x/EXPP_interface.h"
65 #include "api2_2x/constant.h"
66 #include "api2_2x/gen_utils.h"
67 #include "api2_2x/gen_library.h" /* GetPyObjectFromID */
68 #include "api2_2x/BGL.h" 
69 #include "api2_2x/Blender.h"
70 #include "api2_2x/Camera.h"
71 #include "api2_2x/Draw.h"
72 #include "api2_2x/Object.h"
73 #include "api2_2x/Registry.h"
74 #include "api2_2x/Pose.h"
75 #include "api2_2x/bpy.h" /* for the new "bpy" module */
76
77 /*these next two are for pyconstraints*/
78 #include "api2_2x/IDProp.h"
79 #include "api2_2x/matrix.h"
80
81 /* for scriptlinks */
82 #include "DNA_lamp_types.h"
83 #include "DNA_camera_types.h"
84 #include "DNA_world_types.h"
85 #include "DNA_scene_types.h"
86 #include "DNA_material_types.h"
87
88 /* bpy_registryDict is declared in api2_2x/Registry.h and defined
89  * in api2_2x/Registry.c
90  * This Python dictionary will be used to store data that scripts
91  * choose to preserve after they are executed, so user changes can be
92  * restored next time the script is used.  Check the Blender.Registry module. 
93  */
94 /*#include "api2_2x/Registry.h" */
95
96 /* for pydrivers (ipo drivers defined by one-line Python expressions) */
97 PyObject *bpy_pydriver_Dict = NULL;
98 PyObject *bpy_orig_syspath_List = NULL;
99
100 /*
101  * set up a weakref list for Armatures
102  *    creates list in __main__ module dict 
103  */
104   
105 int setup_armature_weakrefs()
106 {
107         PyObject *maindict;
108         PyObject *main_module;
109         char *list_name = ARM_WEAKREF_LIST_NAME;
110
111         main_module = PyImport_AddModule( "__main__");
112         if(main_module){
113                 PyObject *weakreflink;
114                 maindict= PyModule_GetDict(main_module);
115
116                 /* check if there is already a dict entry for the armature weakrefs,
117                  * and delete if so before making another one */
118
119                 weakreflink= PyDict_GetItemString(maindict,list_name);
120                 if( weakreflink != NULL ) {
121                         PyDict_DelItemString(maindict,list_name);
122                         Py_XDECREF( weakreflink );
123                 }
124
125                 if (PyDict_SetItemString(maindict, 
126                                                                  list_name, 
127                                                                  PyList_New(0)) == -1){
128                         printf("Oops - setup_armature_weakrefs()\n");
129                         
130                         return 0;
131                 }
132         }
133         return 1;
134 }
135
136 /* Declares the modules and their initialization functions
137  * These are TOP-LEVEL modules e.g. import `module` - there is no
138  * support for packages here e.g. import `package.module` */
139
140 static struct _inittab BPy_Inittab_Modules[] = {
141         {"Blender", M_Blender_Init},
142         {"bpy", m_bpy_init},
143         {NULL, NULL}
144 };
145
146 /*************************************************************************
147 * Structure definitions 
148 **************************************************************************/
149 #define FILENAME_LENGTH 24
150
151 typedef struct _ScriptError {
152         char filename[FILENAME_LENGTH];
153         int lineno;
154 } ScriptError;
155
156 /****************************************************************************
157 * Global variables 
158 ****************************************************************************/
159 ScriptError g_script_error;
160
161 /***************************************************************************
162 * Function prototypes 
163 ***************************************************************************/
164 PyObject *RunPython( Text * text, PyObject * globaldict );
165 char *GetName( Text * text );
166 PyObject *CreateGlobalDictionary( void );
167 void ReleaseGlobalDictionary( PyObject * dict );
168 void DoAllScriptsFromList( ListBase * list, short event );
169 PyObject *importText( char *name );
170 void init_ourImport( void );
171 void init_ourReload( void );
172 PyObject *blender_import( PyObject * self, PyObject * args );
173 PyObject *RunPython2( Text * text, PyObject * globaldict, PyObject *localdict );
174
175
176 void BPY_Err_Handle( char *script_name );
177 PyObject *traceback_getFilename( PyObject * tb );
178
179 /****************************************************************************
180 * Description: This function will start the interpreter and load all modules
181 * as well as search for a python installation.
182 ****************************************************************************/
183 void BPY_start_python( int argc, char **argv )
184 {
185         static int argc_copy = 0;
186         static char **argv_copy = NULL;
187         int first_time = argc;
188
189         /* we keep a copy of the values of argc and argv so that the game engine
190          * can call BPY_start_python(0, NULL) whenever a game ends, without having
191          * to know argc and argv there (in source/blender/src/space.c) */
192         if( first_time ) {
193                 argc_copy = argc;
194                 argv_copy = argv;
195         }
196
197         //stuff for Registry module
198         bpy_registryDict = PyDict_New(  );/* check comment at start of this file */
199         if( !bpy_registryDict )
200                 printf( "Error: Couldn't create the Registry Python Dictionary!" );
201         Py_SetProgramName( "blender" );
202
203         /* Py_Initialize() will attempt to import the site module and
204          * print an error if not found.  See init_syspath() for the
205          * rest of our init msgs.
206          */
207
208         /* print Python version
209          * Py_GetVersion() returns a ptr to a static string "9.9.9 (aaaa..." 
210          */
211         {
212                 int count = 3;  /* a nice default for major.minor.  example 2.5 */
213                 const char *version = Py_GetVersion();
214                 /* we know a blank is there somewhere! */
215                 char *blank_ptr = strchr( version, ' '); 
216                 if(blank_ptr)
217                         count = blank_ptr - version;
218                 
219                 printf( "Compiled with Python version %.*s.\n", count, version );
220         }
221
222
223         //Initialize the TOP-LEVEL modules
224         PyImport_ExtendInittab(BPy_Inittab_Modules);
225         
226         //Start the interpreter
227         Py_Initialize(  );
228         PySys_SetArgv( argc_copy, argv_copy );
229
230         //Overrides __import__
231         init_ourImport(  );
232         init_ourReload(  );
233
234         //init a global dictionary
235         g_blenderdict = NULL;
236
237         //Look for a python installation
238         init_syspath( first_time ); /* not first_time: some msgs are suppressed */
239
240         return;
241 }
242
243 /*****************************************************************************/
244 /* Description: This function will terminate the Python interpreter          */
245 /*****************************************************************************/
246 void BPY_end_python( void )
247 {
248         Script *script = NULL;
249
250         if( bpy_registryDict ) {
251                 Py_DECREF( bpy_registryDict );
252                 bpy_registryDict = NULL;
253         }
254
255         if( bpy_pydriver_Dict ) {
256                 Py_DECREF( bpy_pydriver_Dict );
257                 bpy_pydriver_Dict = NULL;
258         }
259         
260         if( bpy_orig_syspath_List ) {
261                 Py_DECREF( bpy_orig_syspath_List );
262                 bpy_orig_syspath_List = NULL;
263         }
264
265         /* Freeing all scripts here prevents problems with the order in which
266          * Python is finalized and G.main is freed in exit_usiblender() */
267         for (script = G.main->script.first; script; script = script->id.next) {
268                 BPY_clear_script(script);
269                 free_libblock( &G.main->script, script );
270         }
271
272         Py_Finalize(  );
273
274         BPyMenu_RemoveAllEntries(  );   /* freeing bpymenu mem */
275
276         /* a script might've opened a .blend file but didn't close it, so: */
277         EXPP_Library_Close(  );
278
279         return;
280 }
281
282 void syspath_append( char *dirname )
283 {
284         PyObject *mod_sys= NULL, *dict= NULL, *path= NULL, *dir= NULL;
285         short ok=1;
286         PyErr_Clear(  );
287
288         dir = Py_BuildValue( "s", dirname );
289
290         mod_sys = PyImport_ImportModule( "sys" );       /* new ref */
291         
292         if (mod_sys) {
293                 dict = PyModule_GetDict( mod_sys );     /* borrowed ref */
294                 path = PyDict_GetItemString( dict, "path" );    /* borrowed ref */
295                 if ( !PyList_Check( path ) ) {
296                         ok = 0;
297                 }
298         } else {
299                 /* cant get the sys module */
300                 ok = 0;
301         }
302         
303         if (PySequence_Contains(path, dir)==0) { /* Only add if we need to */
304                 if (ok && PyList_Append( path, dir ) != 0)
305                         ok = 0; /* append failed */
306         
307                 if( (ok==0) || PyErr_Occurred(  ) )
308                         Py_FatalError( "could import or build sys.path, can't continue" );
309         }
310         Py_XDECREF( mod_sys );
311 }
312
313 void init_syspath( int first_time )
314 {
315         PyObject *path;
316         PyObject *mod, *d;
317         char *progname;
318         char execdir[FILE_MAXDIR];      /*defines from DNA_space_types.h */
319
320         int n;
321         
322         
323         path = Py_BuildValue( "s", bprogname );
324
325         mod = PyImport_ImportModule( "Blender.sys" );
326
327         if( mod ) {
328                 d = PyModule_GetDict( mod );
329                 EXPP_dict_set_item_str( d, "progname", path );
330                 Py_DECREF( mod );
331         } else
332                 printf( "Warning: could not set Blender.sys.progname\n" );
333
334         progname = BLI_last_slash( bprogname ); /* looks for the last dir separator */
335
336         n = progname - bprogname;
337         if( n > 0 ) {
338                 strncpy( execdir, bprogname, n );
339                 if( execdir[n - 1] == '.' )
340                         n--;    /*fix for when run as ./blender */
341                 execdir[n] = '\0';
342
343                 syspath_append( execdir );      /* append to module search path */
344         } else {
345                 printf( "Warning: could not determine argv[0] path\n" );
346         }
347         
348         /* 
349            attempt to import 'site' module as a check for valid
350            python install found.
351         */
352
353         printf("Checking for installed Python... "); /* appears after msg "Compiled with Python 2.x"  */
354         mod = PyImport_ImportModule( "site" );  /* new ref */
355
356         if( mod ) {
357                 printf("got it!\n");  
358                 Py_DECREF( mod );
359         } else {                /* import 'site' failed */
360                 PyErr_Clear(  );
361                 if( first_time ) {
362                         printf( "No installed Python found.\n" );
363                         printf( "Only built-in modules are available.  Some scripts may not run.\n" );
364                         printf( "Continuing happily.\n" );
365                 }
366         }
367
368
369         /* 
370          * initialize the sys module
371          * set sys.executable to the Blender exe 
372          */
373
374         mod = PyImport_ImportModule( "sys" );   /* new ref */
375
376         if( mod ) {
377                 d = PyModule_GetDict( mod );    /* borrowed ref */
378                 EXPP_dict_set_item_str( d, "executable", Py_BuildValue( "s", bprogname ) );
379                 
380                 if (first_time) {
381                         /* backup the original sys.path to rebuild later */     
382                         PyObject *syspath = PyDict_GetItemString( d, "path" );  /* borrowed ref */
383                         if (bpy_orig_syspath_List) { /* This should never happen but just incase, be nice */
384                                 Py_DECREF(bpy_orig_syspath_List);
385                         }
386                         bpy_orig_syspath_List = PyList_GetSlice(syspath, 0, PyList_Size(syspath));
387                 }
388                 
389                 Py_DECREF( mod );
390         } else{
391                 printf("import of sys module failed\n");
392         }
393 }
394
395
396 void BPY_rebuild_syspath( void )
397 {
398         PyObject *mod, *dict, *syspath;
399         char dirpath[FILE_MAX];
400         char *sdir = NULL;
401         
402         mod = PyImport_ImportModule( "sys" );   
403         if (!mod) {
404                 printf("error: could not import python sys module. some modules may not import.");
405                 return;
406         }
407         
408         if (!bpy_orig_syspath_List) { /* should never happen */
409                 printf("error refershing python path");
410                 Py_DECREF(mod);
411                 return;
412         }
413         
414         dict = PyModule_GetDict( mod ); /* borrowed ref */
415         
416         /* Reset sys.path */    
417         syspath = PyDict_GetItemString( dict, "path" ); /* borrowed ref */
418         PyList_SetSlice(syspath, 0, PyList_Size(syspath), bpy_orig_syspath_List);
419         
420         if(U.pythondir[0] != '\0' ) {
421                 char modpath[FILE_MAX];
422                 int upyslen = strlen(U.pythondir);
423
424                 /* check if user pydir ends with a slash and, if so, remove the slash
425                  * (for eventual implementations of c library's stat function that might
426                  * not like it) */
427                 if (upyslen > 2) { /* avoids doing anything if dir == '//' */
428                         BLI_add_slash(U.pythondir);
429                 }
430
431                 BLI_strncpy(dirpath, U.pythondir, FILE_MAX);
432                 BLI_convertstringcode(dirpath, G.sce, 0);
433                 syspath_append(dirpath);        /* append to module search path */
434
435                 BLI_make_file_string("/", modpath, dirpath, "bpymodules");
436                 if (BLI_exists(modpath)) syspath_append(modpath);
437         }
438         
439         sdir = bpy_gethome(1);
440         if (sdir) {
441                 syspath_append(sdir);
442                 BLI_make_file_string("/", dirpath, sdir, "bpymodules");
443                 if (BLI_exists(dirpath)) syspath_append(dirpath);
444         }
445         
446         Py_DECREF(mod);
447 }
448
449 /****************************************************************************
450 * Description: This function finishes Python initialization in Blender.  
451
452 Because U.pythondir (user defined dir for scripts) isn't         
453 initialized when BPY_start_Python needs to be executed, we       
454 postpone adding U.pythondir to sys.path and also BPyMenus         
455 (mechanism to register scripts in Blender menus) for when  
456 that dir info is available.   
457 ****************************************************************************/
458 void BPY_post_start_python( void )
459 {
460         BPY_rebuild_syspath();
461         BPyMenu_Init( 0 );      /* get dynamic menus (registered scripts) data */
462 }
463
464 /****************************************************************************
465 * Description: This function will return the linenumber on which an error  
466 *               has occurred in the Python script.                      
467 ****************************************************************************/
468 int BPY_Err_getLinenumber( void )
469 {
470         return g_script_error.lineno;
471 }
472
473 /*****************************************************************************/
474 /* Description: This function will return the filename of the python script. */
475 /*****************************************************************************/
476 const char *BPY_Err_getFilename( void )
477 {
478         return g_script_error.filename;
479 }
480
481 /*****************************************************************************/
482 /* Description: Return PyString filename from a traceback object            */
483 /*****************************************************************************/
484 PyObject *traceback_getFilename( PyObject * tb )
485 {
486         PyObject *v = NULL;
487
488 /* co_filename is in f_code, which is in tb_frame, which is in tb */
489
490         v = PyObject_GetAttrString( tb, "tb_frame" );
491         if (v) {
492                 Py_DECREF( v );
493                 v = PyObject_GetAttrString( v, "f_code" );
494                 if (v) {
495                         Py_DECREF( v );
496                         v = PyObject_GetAttrString( v, "co_filename" );
497                 }
498         }
499
500         if (v) return v;
501         else return PyString_FromString("unknown");
502 }
503
504 /****************************************************************************
505 * Description: Blender Python error handler. This catches the error and 
506 * stores filename and line number in a global  
507 *****************************************************************************/
508 void BPY_Err_Handle( char *script_name )
509 {
510         PyObject *exception, *err, *tb, *v;
511
512         if( !script_name ) {
513                 printf( "Error: script has NULL name\n" );
514                 return;
515         }
516
517         PyErr_Fetch( &exception, &err, &tb );
518
519         if (!script_name) script_name = "untitled";
520         //if( !exception && !tb ) {
521         //      printf( "FATAL: spurious exception\n" );
522         //      return;
523         //}
524
525         strcpy( g_script_error.filename, script_name );
526
527         if( exception
528             && PyErr_GivenExceptionMatches( exception, PyExc_SyntaxError ) ) {
529                 /* no traceback available when SyntaxError */
530                 PyErr_Restore( exception, err, tb );    /* takes away reference! */
531                 PyErr_Print(  );
532                 v = PyObject_GetAttrString( err, "lineno" );
533                 if( v ) {
534                         g_script_error.lineno = PyInt_AsLong( v );
535                         Py_DECREF( v );
536                 } else {
537                         g_script_error.lineno = -1;
538                 }
539                 /* this avoids an abort in Python 2.3's garbage collecting: */
540                 PyErr_Clear(  );
541                 return;
542         } else {
543                 PyErr_NormalizeException( &exception, &err, &tb );
544                 PyErr_Restore( exception, err, tb );    /* takes away reference! */
545                 PyErr_Print(  );
546                 tb = PySys_GetObject( "last_traceback" );
547
548                 if( !tb ) {
549                         printf( "\nCan't get traceback\n" );
550                         return;
551                 }
552
553                 Py_INCREF( tb );
554
555 /* From old bpython BPY_main.c:
556  * 'check traceback objects and look for last traceback in the
557  *      same text file. This is used to jump to the line of where the
558  *      error occured. "If the error occured in another text file or module,
559  *      the last frame in the current file is adressed."' 
560  */
561
562                 for(;;) {
563                         v = PyObject_GetAttrString( tb, "tb_next" );
564
565                         if( !v || v == Py_None ||
566                                 strcmp(PyString_AsString(traceback_getFilename(v)), script_name)) {
567                                 break;
568                         }
569
570                         Py_DECREF( tb );
571                         tb = v;
572                 }
573
574                 v = PyObject_GetAttrString( tb, "tb_lineno" );
575                 if (v) {
576                         g_script_error.lineno = PyInt_AsLong(v);
577                         Py_DECREF(v);
578                 }
579                 v = traceback_getFilename( tb );
580                 if (v) {
581                         strncpy( g_script_error.filename, PyString_AsString( v ),
582                                 FILENAME_LENGTH );
583                         Py_DECREF(v);
584                 }
585                 Py_DECREF( tb );
586         }
587
588         return;
589 }
590
591 /****************************************************************************
592 * Description: This function executes the script passed by st.          
593 * Notes:        It is called by blender/src/drawtext.c when a Blender user  
594 *               presses ALT+PKEY in the script's text window. 
595 *****************************************************************************/
596 int BPY_txt_do_python_Text( struct Text *text )
597 {
598         PyObject *py_dict, *py_result;
599         BPy_constant *info;
600         char textname[24];
601         Script *script = G.main->script.first;
602
603         if( !text )
604                 return 0;
605
606         /* check if this text is already running */
607         while( script ) {
608                 if( !strcmp( script->id.name + 2, text->id.name + 2 ) ) {
609                         /* if this text is already a running script, 
610                          * just move to it: */
611                         SpaceScript *sc;
612                         newspace( curarea, SPACE_SCRIPT );
613                         sc = curarea->spacedata.first;
614                         sc->script = script;
615                         return 1;
616                 }
617                 script = script->id.next;
618         }
619
620         /* Create a new script structure and initialize it: */
621         script = alloc_libblock( &G.main->script, ID_SCRIPT, GetName( text ) );
622
623         if( !script ) {
624                 printf( "couldn't allocate memory for Script struct!" );
625                 return 0;
626         }
627
628         /* if in the script Blender.Load(blendfile) is not the last command,
629          * an error after it will call BPY_Err_Handle below, but the text struct
630          * will have been deallocated already, so we need to copy its name here.
631          */
632         BLI_strncpy( textname, GetName( text ),
633                      strlen( GetName( text ) ) + 1 );
634
635         script->id.us = 1;
636         script->flags = SCRIPT_RUNNING;
637         script->py_draw = NULL;
638         script->py_event = NULL;
639         script->py_button = NULL;
640         script->py_browsercallback = NULL;
641
642         py_dict = CreateGlobalDictionary(  );
643
644         if( !setup_armature_weakrefs()){
645                 printf("Oops - weakref dict\n");
646                 return 0;
647         }
648
649         script->py_globaldict = py_dict;
650
651         info = ( BPy_constant * ) PyConstant_New(  );
652         if( info ) {
653                 PyConstant_Insert( info, "name",
654                                  PyString_FromString( script->id.name + 2 ) );
655                 Py_INCREF( Py_None );
656                 PyConstant_Insert( info, "arg", Py_None );
657                 EXPP_dict_set_item_str( py_dict, "__script__",
658                                       ( PyObject * ) info );
659         }
660
661         py_result = RunPython( text, py_dict ); /* Run the script */
662
663         if( !py_result ) {      /* Failed execution of the script */
664
665                 BPY_Err_Handle( textname );
666                 ReleaseGlobalDictionary( py_dict );
667                 script->py_globaldict = NULL;
668                 if( G.main->script.first )
669                         free_libblock( &G.main->script, script );
670
671                 return 0;
672         } else {
673                 Py_DECREF( py_result );
674                 script->flags &= ~SCRIPT_RUNNING;
675                 if( !script->flags ) {
676                         ReleaseGlobalDictionary( py_dict );
677                         script->py_globaldict = NULL;
678                         free_libblock( &G.main->script, script );
679                 }
680         }
681
682         return 1;               /* normal return */
683 }
684
685 /****************************************************************************
686 * Description: Called from command line to run a Python script
687 * automatically. The script can be a file or a Blender Text in the current 
688 * .blend.
689 ****************************************************************************/
690 void BPY_run_python_script( char *fn )
691 {
692         Text *text = NULL;
693         int is_blender_text = 0;
694
695         if (!BLI_exists(fn)) {  /* if there's no such filename ... */
696                 text = G.main->text.first;      /* try an already existing Blender Text */
697
698                 while (text) {
699                         if (!strcmp(fn, text->id.name + 2)) break;
700                         text = text->id.next;
701                 }
702
703                 if (text == NULL) {
704                         printf("\nError: no such file or Blender text -- %s.\n", fn);
705                         return;
706                 }
707                 else is_blender_text = 1;       /* fn is already a Blender Text */
708         }
709
710         else {
711                 text = add_text(fn);
712
713                 if (text == NULL) {
714                         printf("\nError in BPY_run_python_script:\n"
715                                 "couldn't create Blender text from %s\n", fn);
716                 /* Chris: On Windows if I continue I just get a segmentation
717                  * violation.  To get a baseline file I exit here. */
718                 exit(2);
719                 /* return; */
720                 }
721         }
722
723         if (BPY_txt_do_python_Text(text) != 1) {
724                 printf("\nError executing Python script from command-line:\n"
725                         "%s (at line %d).\n", fn, BPY_Err_getLinenumber());
726         }
727
728         if (!is_blender_text) {
729                 /* We can't simply free the text, since the script might have called
730                  * Blender.Load() to load a new .blend, freeing previous data.
731                  * So we check if the pointer is still valid. */
732                 Text *txtptr = G.main->text.first;
733                 while (txtptr) {
734                         if (txtptr == text) {
735                                 free_libblock(&G.main->text, text);
736                                 break;
737                         }
738                         txtptr = txtptr->id.next;
739                 }
740         }
741 }
742
743 /****************************************************************************
744 * Description: This function executes the script chosen from a menu.
745 * Notes:        It is called by the ui code in src/header_???.c when a user  
746 *               clicks on a menu entry that refers to a script.
747 *               Scripts are searched in the BPyMenuTable, using the given
748 *               menutype and event values to know which one was chosen. 
749 *****************************************************************************/
750 int BPY_menu_do_python( short menutype, int event )
751 {
752         PyObject *py_dict, *py_res, *pyarg = NULL;
753         BPy_constant *info;
754         BPyMenu *pym;
755         BPySubMenu *pysm;
756         FILE *fp = NULL;
757         char *buffer, *s;
758         char filestr[FILE_MAXDIR + FILE_MAXFILE];
759         char scriptname[21];
760         Script *script = NULL;
761         int len;
762
763         pym = BPyMenu_GetEntry( menutype, ( short ) event );
764
765         if( !pym )
766                 return 0;
767
768         if( pym->version > G.version )
769                 notice( "Version mismatch: script was written for Blender %d. "
770                         "It may fail with yours: %d.", pym->version,
771                         G.version );
772
773 /* if there are submenus, let the user choose one from a pupmenu that we
774  * create here.*/
775         pysm = pym->submenus;
776         if( pysm ) {
777                 char *pupstr;
778                 int arg;
779
780                 pupstr = BPyMenu_CreatePupmenuStr( pym, menutype );
781
782                 if( pupstr ) {
783                         arg = pupmenu( pupstr );
784                         MEM_freeN( pupstr );
785
786                         if( arg >= 0 ) {
787                                 while( arg-- )
788                                         pysm = pysm->next;
789                                 pyarg = PyString_FromString( pysm->arg );
790                         } else
791                                 return 0;
792                 }
793         }
794
795         if( !pyarg ) { /* no submenus */
796                 Py_INCREF( Py_None );
797                 pyarg = Py_None;
798         }
799
800         if( pym->dir ) { /* script is in U.pythondir */
801                 char upythondir[FILE_MAXDIR];
802
803                 /* dirs in Blender can be "//", which has a special meaning */
804                 BLI_strncpy(upythondir, U.pythondir, FILE_MAXDIR);
805                 BLI_convertstringcode(upythondir, G.sce, 0); /* if so, this expands it */
806                 BLI_make_file_string( "/", filestr, upythondir, pym->filename );
807         }
808         else { /* script is in default scripts dir */
809                 char *scriptsdir = bpy_gethome(1);
810
811                 if (!scriptsdir) {
812                         printf("Error loading script: can't find default scripts dir!");
813                         return 0;
814                 }
815
816                 BLI_make_file_string( "/", filestr, scriptsdir, pym->filename );
817         }
818
819         fp = fopen( filestr, "rb" );
820         if( !fp ) {
821                 printf( "Error loading script: couldn't open file %s\n",
822                         filestr );
823                 return 0;
824         }
825
826         BLI_strncpy(scriptname, pym->name, 21);
827         len = strlen(scriptname) - 1;
828         /* by convention, scripts that open the file browser or have submenus
829          * display '...'.  Here we remove them from the datablock name */
830         while ((len > 0) && scriptname[len] == '.') {
831                 scriptname[len] = '\0';
832                 len--;
833         }
834         
835         /* Create a new script structure and initialize it: */
836         script = alloc_libblock( &G.main->script, ID_SCRIPT, scriptname );
837
838         if( !script ) {
839                 printf( "couldn't allocate memory for Script struct!" );
840                 fclose( fp );
841                 return 0;
842         }
843
844         /* let's find a proper area for an eventual script gui:
845          * (still experimenting here, need definition on which win
846          * each group will be put to code this properly) */
847         switch ( menutype ) {
848
849         case PYMENU_IMPORT:     /* first 4 were handled in header_info.c */
850         case PYMENU_EXPORT:
851         case PYMENU_HELP:
852         case PYMENU_RENDER:
853         case PYMENU_WIZARDS:
854         case PYMENU_SCRIPTTEMPLATE:
855         case PYMENU_MESHFACEKEY:
856                 break;
857
858         default:
859                 if( curarea->spacetype != SPACE_SCRIPT ) {
860                         ScrArea *sa = NULL;
861
862                         sa = find_biggest_area_of_type( SPACE_BUTS );
863                         if( sa ) {
864                                 if( ( 1.5 * sa->winx ) < sa->winy )
865                                         sa = NULL;      /* too narrow? */
866                         }
867
868                         if( !sa )
869                                 sa = find_biggest_area_of_type( SPACE_SCRIPT );
870                         if( !sa )
871                                 sa = find_biggest_area_of_type( SPACE_TEXT );
872                         if( !sa )
873                                 sa = find_biggest_area_of_type( SPACE_IMAGE );  /* group UV */
874                         if( !sa )
875                                 sa = find_biggest_area_of_type( SPACE_VIEW3D );
876
877                         if( !sa )
878                                 sa = find_biggest_area(  );
879
880                         areawinset( sa->win );
881                 }
882                 break;
883         }
884
885         script->id.us = 1;
886         script->flags = SCRIPT_RUNNING;
887         script->py_draw = NULL;
888         script->py_event = NULL;
889         script->py_button = NULL;
890         script->py_browsercallback = NULL;
891
892         py_dict = CreateGlobalDictionary(  );
893
894         script->py_globaldict = py_dict;
895
896         info = ( BPy_constant * ) PyConstant_New(  );
897         if( info ) {
898                 PyConstant_Insert( info, "name",
899                                  PyString_FromString( script->id.name + 2 ) );
900                 PyConstant_Insert( info, "arg", pyarg );
901                 EXPP_dict_set_item_str( py_dict, "__script__",
902                                       ( PyObject * ) info );
903         }
904
905         /* Previously we used PyRun_File to run directly the code on a FILE 
906          * object, but as written in the Python/C API Ref Manual, chapter 2,
907          * 'FILE structs for different C libraries can be different and 
908          * incompatible'.
909          * So now we load the script file data to a buffer */
910
911         fseek( fp, 0L, SEEK_END );
912         len = ftell( fp );
913         fseek( fp, 0L, SEEK_SET );
914
915         buffer = MEM_mallocN( len + 2, "pyfilebuf" );   /* len+2 to add '\n\0' */
916         len = fread( buffer, 1, len, fp );
917
918         buffer[len] = '\n';     /* fix syntax error in files w/o eol */
919         buffer[len + 1] = '\0';
920
921         /* fast clean-up of dos cr/lf line endings: change '\r' to space */
922
923         /* we also have to check for line splitters: '\\' */
924         /* to avoid possible syntax errors on dos files on win */
925          /**/
926                 /* but first make sure we won't disturb memory below &buffer[0]: */
927                 if( *buffer == '\r' )
928                 *buffer = ' ';
929
930         /* now handle the whole buffer */
931         for( s = buffer + 1; *s != '\0'; s++ ) {
932                 if( *s == '\r' ) {
933                         if( *( s - 1 ) == '\\' ) {      /* special case: long lines split with '\': */
934                                 *( s - 1 ) = ' ';       /* we write ' \', because '\ ' is a syntax error */
935                                 *s = '\\';
936                         } else
937                                 *s = ' ';       /* not a split line, just replace '\r' with ' ' */
938                 }
939         }
940
941         fclose( fp );
942
943
944         if( !setup_armature_weakrefs()){
945                 printf("Oops - weakref dict\n");
946                 MEM_freeN( buffer );
947                 return 0;
948         }
949
950         /* run the string buffer */
951
952         py_res = PyRun_String( buffer, Py_file_input, py_dict, py_dict );
953
954         MEM_freeN( buffer );
955
956         if( !py_res ) {         /* Failed execution of the script */
957
958                 BPY_Err_Handle( script->id.name + 2 );
959                 ReleaseGlobalDictionary( py_dict );
960                 script->py_globaldict = NULL;
961                 if( G.main->script.first )
962                         free_libblock( &G.main->script, script );
963                 error( "Python script error: check console" );
964
965                 return 0;
966         } else {
967                 Py_DECREF( py_res );
968                 script->flags &= ~SCRIPT_RUNNING;
969
970                 if( !script->flags ) {
971                         ReleaseGlobalDictionary( py_dict );
972                         script->py_globaldict = NULL;
973                         free_libblock( &G.main->script, script );
974
975                         /* special case: called from the menu in the Scripts window
976                          * we have to change sc->script pointer, since it'll be freed here.*/
977                         if( curarea->spacetype == SPACE_SCRIPT ) {
978                                 SpaceScript *sc = curarea->spacedata.first;
979                                 sc->script = G.main->script.first;      /* can be null, which is ok ... */
980                                 /* ... meaning no other script is running right now. */
981                         }
982
983                 }
984         }
985
986         return 1;               /* normal return */
987 }
988
989 /*****************************************************************************
990 * Description:  
991 * Notes:
992 *****************************************************************************/
993 void BPY_free_compiled_text( struct Text *text )
994 {
995         if( !text->compiled )
996                 return;
997         Py_DECREF( ( PyObject * ) text->compiled );
998         text->compiled = NULL;
999
1000         return;
1001 }
1002
1003 /*****************************************************************************
1004 * Description: This function frees a finished (flags == 0) script.
1005 *****************************************************************************/
1006 void BPY_free_finished_script( Script * script )
1007 {
1008         if( !script )
1009                 return;
1010
1011         if( PyErr_Occurred(  ) ) {      /* if script ended after filesel */
1012                 PyErr_Print(  );        /* eventual errors are handled now */
1013                 error( "Python script error: check console" );
1014         }
1015
1016         free_libblock( &G.main->script, script );
1017         return;
1018 }
1019
1020 static void unlink_script( Script * script )
1021 {       /* copied from unlink_text in drawtext.c */
1022         bScreen *scr;
1023         ScrArea *area;
1024         SpaceLink *sl;
1025
1026         for( scr = G.main->screen.first; scr; scr = scr->id.next ) {
1027                 for( area = scr->areabase.first; area; area = area->next ) {
1028                         for( sl = area->spacedata.first; sl; sl = sl->next ) {
1029                                 if( sl->spacetype == SPACE_SCRIPT ) {
1030                                         SpaceScript *sc = ( SpaceScript * ) sl;
1031
1032                                         if( sc->script == script ) {
1033                                                 sc->script = NULL;
1034
1035                                                 if( sc ==
1036                                                     area->spacedata.first ) {
1037                                                         scrarea_queue_redraw
1038                                                                 ( area );
1039                                                 }
1040                                         }
1041                                 }
1042                         }
1043                 }
1044         }
1045 }
1046
1047 void BPY_clear_script( Script * script )
1048 {
1049         PyObject *dict;
1050
1051         if( !script )
1052                 return;
1053
1054         if (!Py_IsInitialized()) {
1055                 printf("\nError: trying to free script data after finalizing Python!");
1056                 printf("\nScript name: %s\n", script->id.name+2);
1057                 return;
1058         }
1059
1060         Py_XDECREF( ( PyObject * ) script->py_draw );
1061         Py_XDECREF( ( PyObject * ) script->py_event );
1062         Py_XDECREF( ( PyObject * ) script->py_button );
1063         Py_XDECREF( ( PyObject * ) script->py_browsercallback );
1064         script->py_draw = NULL;
1065         script->py_event = NULL;
1066         script->py_button = NULL;
1067         script->py_browsercallback = NULL;
1068
1069         dict = script->py_globaldict;
1070
1071         if( dict ) {
1072                 PyDict_Clear( dict );
1073                 Py_DECREF( dict );      /* Release dictionary. */
1074                 script->py_globaldict = NULL;
1075         }
1076
1077         unlink_script( script );
1078 }
1079
1080 /* PyDrivers */
1081
1082 /* PyDrivers are Ipo Drivers governed by expressions written in Python.
1083  * Expressions here are one-liners that evaluate to a float value. */
1084
1085 /* For faster execution we keep a special dictionary for pydrivers, with
1086  * the needed modules and aliases. */
1087 static int bpy_pydriver_create_dict(void)
1088 {
1089         PyObject *d, *mod;
1090
1091         if (bpy_pydriver_Dict) return -1;
1092
1093         d = PyDict_New();
1094         if (!d) return -1;
1095
1096         bpy_pydriver_Dict = d;
1097
1098         /* import some modules: builtins, Blender, math, Blender.noise */
1099
1100         PyDict_SetItemString(d, "__builtins__", PyEval_GetBuiltins());
1101
1102         mod = PyImport_ImportModule("Blender");
1103         if (mod) {
1104                 PyDict_SetItemString(d, "Blender", mod);
1105                 PyDict_SetItemString(d, "b", mod);
1106                 Py_DECREF(mod);
1107         }
1108
1109         mod = PyImport_ImportModule("math");
1110         if (mod) {
1111                 PyDict_Merge(d, PyModule_GetDict(mod), 0); /* 0 - dont overwrite existing values */
1112                 
1113                 /* Only keep for backwards compat! - just import all math into root, they are standard */
1114                 PyDict_SetItemString(d, "math", mod);
1115                 PyDict_SetItemString(d, "m", mod);
1116                 Py_DECREF(mod);
1117         } 
1118
1119         mod = PyImport_ImportModule("Blender.Noise");
1120         if (mod) {
1121                 PyDict_SetItemString(d, "noise", mod);
1122                 PyDict_SetItemString(d, "n", mod);
1123                 Py_DECREF(mod);
1124         }
1125
1126         /* If there's a Blender text called pydrivers.py, import it.
1127          * Users can add their own functions to this module. */
1128         mod = importText("pydrivers"); /* can also use PyImport_Import() */
1129         if (mod) {
1130                 PyDict_SetItemString(d, "pydrivers", mod);
1131                 PyDict_SetItemString(d, "p", mod);
1132                 Py_DECREF(mod);
1133         }
1134         else
1135                 PyErr_Clear();
1136
1137         /* short aliases for some Get() functions: */
1138
1139         /* ob(obname) == Blender.Object.Get(obname) */
1140         mod = PyImport_ImportModule("Blender.Object");
1141         if (mod) {
1142                 PyObject *fcn = PyObject_GetAttrString(mod, "Get");
1143                 Py_DECREF(mod);
1144                 if (fcn) {
1145                         PyDict_SetItemString(d, "ob", fcn);
1146                         Py_DECREF(fcn);
1147                 }
1148         }
1149         
1150         /* TODO - change these */
1151         /* me(meshname) == Blender.Mesh.Get(meshname) */
1152         mod = PyImport_ImportModule("Blender.Mesh");
1153         if (mod) {
1154                 PyObject *fcn = PyObject_GetAttrString(mod, "Get");
1155                 Py_DECREF(mod);
1156                 if (fcn) {
1157                         PyDict_SetItemString(d, "me", fcn);
1158                         Py_DECREF(fcn);
1159                 }
1160         }
1161
1162         /* ma(matname) == Blender.Material.Get(matname) */
1163         mod = PyImport_ImportModule("Blender.Material");
1164         if (mod) {
1165                 PyObject *fcn = PyObject_GetAttrString(mod, "Get");
1166                 Py_DECREF(mod);
1167                 if (fcn) {
1168                         PyDict_SetItemString(d, "ma", fcn);
1169                         Py_DECREF(fcn);
1170                 }
1171         }
1172
1173         return 0;
1174 }
1175
1176 /* error return function for BPY_eval_pydriver */
1177 static float pydriver_error(IpoDriver *driver) {
1178
1179         if (bpy_pydriver_oblist)
1180                 bpy_pydriver_freeList();
1181
1182         if (bpy_pydriver_Dict) { /* free the global dict used by pydrivers */
1183                 PyDict_Clear(bpy_pydriver_Dict);
1184                 Py_DECREF(bpy_pydriver_Dict);
1185                 bpy_pydriver_Dict = NULL;
1186         }
1187
1188         driver->flag |= IPO_DRIVER_FLAG_INVALID; /* py expression failed */
1189         
1190         if (driver->ob)
1191                 fprintf(stderr, "\nError in Ipo Driver: Object %s\nThis is the failed Python expression:\n'%s'\n\n", driver->ob->id.name+2, driver->name);
1192         else
1193                 fprintf(stderr, "\nError in Ipo Driver: No Object\nThis is the failed Python expression:\n'%s'\n\n", driver->name);
1194         
1195         PyErr_Print();
1196
1197         return 0.0f;
1198 }
1199
1200
1201 /********PyConstraints*********/
1202
1203 /* This function checks whether a text-buffer is a PyConstraint candidate.
1204  * It uses simple text parsing that could be easily confused!
1205  */
1206 int BPY_is_pyconstraint(Text *text)
1207 {
1208         TextLine *tline = text->lines.first;
1209
1210         if (tline && (tline->len > 10)) {
1211                 char *line = tline->line;
1212                 
1213                 /* Expected format: #BPYCONSTRAINT
1214                  * The actual checks are forgiving, so slight variations also work. */
1215                 if (line && line[0] == '#' && strstr(line, "BPYCONSTRAINT")) return 1;
1216         }
1217         return 0;
1218 }
1219
1220 /* This function is called to update PyConstraint data so that it is compatible with the script. 
1221  * Some of the allocating/freeing of memory for constraint targets occurs here, espcially
1222  * if the number of targets changes.
1223  */
1224 void BPY_pyconstraint_update(Object *owner, bConstraint *con)
1225 {
1226         bPythonConstraint *data= con->data;
1227         
1228         if (data->text) {       
1229                 /* script does exist. it is assumed that this is a valid pyconstraint script */
1230                 PyObject *globals;
1231                 PyObject *retval, *gval;
1232                 int num, i;
1233                 
1234                 /* clear the relevant flags first */
1235                 data->flag = 0;
1236                                 
1237                 /* populate globals dictionary */
1238                 globals = CreateGlobalDictionary();
1239                 retval = RunPython(data->text, globals);
1240                 
1241                 if (retval == NULL) {
1242                         BPY_Err_Handle(data->text->id.name);
1243                         ReleaseGlobalDictionary(globals);
1244                         data->flag |= PYCON_SCRIPTERROR;
1245                         return;
1246                 }
1247                 
1248                 Py_XDECREF(retval);
1249                 retval = NULL;
1250                 
1251                 /* try to find NUM_TARGETS */
1252                 gval = PyDict_GetItemString(globals, "NUM_TARGETS");
1253                 if ( (gval) && (num= PyInt_AsLong(gval)) ) {
1254                         /* NUM_TARGETS is defined... and non-zero */
1255                         bConstraintTarget *ct;
1256                         
1257                         /* check if it is valid (just make sure it is not negative)
1258                          *      TODO: PyInt_AsLong may return -1 as sign of invalid input... 
1259                          */
1260                         num = abs(num);
1261                         data->flag |= PYCON_USETARGETS;
1262                         
1263                         /* check if the number of targets has changed */
1264                         if (num < data->tarnum) {
1265                                 /* free a few targets */
1266                                 num= data->tarnum - num;
1267                                 for (i = 0; i < num; i++, data->tarnum--) {
1268                                         ct= data->targets.last;
1269                                         BLI_freelinkN(&data->targets, ct);
1270                                 }
1271                         }
1272                         else if (num > data->tarnum) {
1273                                 /* add a few targets */
1274                                 num = num - data->tarnum;
1275                                 for (i = 0; i < num; i++, data->tarnum++) {
1276                                         ct= MEM_callocN(sizeof(bConstraintTarget), "PyConTarget");
1277                                         BLI_addtail(&data->targets, ct);
1278                                 }
1279                         }
1280                         
1281                         /* validate targets */
1282                         con->flag &= ~CONSTRAINT_DISABLE;
1283                         for (ct= data->targets.first; ct; ct= ct->next) {
1284                                 if (!exist_object(ct->tar)) {
1285                                         ct->tar = NULL;
1286                                         con->flag |= CONSTRAINT_DISABLE;
1287                                         break;
1288                                 }
1289                                 
1290                                 if ((ct->tar == owner) && (ct->subtarget[0] != 0)) {
1291                                         if (get_named_bone(get_armature(owner), ct->subtarget) == NULL) {
1292                                                 con->flag |= CONSTRAINT_DISABLE;
1293                                                 break;
1294                                         }
1295                                 }
1296                         }
1297                         
1298                         /* clear globals */
1299                         ReleaseGlobalDictionary(globals);
1300                 }
1301                 else {
1302                         /* NUM_TARGETS is not defined or equals 0 */
1303                         ReleaseGlobalDictionary(globals);
1304                         
1305                         /* free all targets */
1306                         BLI_freelistN(&data->targets);
1307                         data->tarnum = 0;
1308                         data->flag &= ~PYCON_USETARGETS;
1309                         
1310                         return;
1311                 }
1312         }
1313         else {
1314                 /* no script, so clear any settings/data now */
1315                 data->tarnum = 0;
1316                 data->flag = 0;
1317                 con->flag &= ~CONSTRAINT_DISABLE;
1318                 
1319                 BLI_freelistN(&data->targets);
1320                 
1321                 /* supposedly this should still leave the base struct... */
1322                 IDP_FreeProperty(data->prop);
1323         }
1324 }
1325
1326 /* PyConstraints Evaluation Function (only called from evaluate_constraint)
1327  * This function is responsible for modifying the ownermat that it is passed. 
1328  */
1329 void BPY_pyconstraint_eval(bPythonConstraint *con, bConstraintOb *cob, ListBase *targets)
1330 {
1331         PyObject *srcmat, *tarmat, *tarmats, *idprop;
1332         PyObject *globals;
1333         PyObject *gval;
1334         PyObject *pyargs, *retval;
1335         bConstraintTarget *ct;
1336         MatrixObject *retmat;
1337         int row, col, index;
1338         
1339         if (!con->text) return;
1340         if (con->flag & PYCON_SCRIPTERROR) return;
1341         
1342         globals = CreateGlobalDictionary();
1343         
1344         /* wrap blender-data as PyObjects for evaluation 
1345          *      - we expose the owner's matrix as pymatrix
1346          *      - id-properties are wrapped using the id-properties pyapi
1347          *      - targets are presented as a list of matrices
1348          */
1349         srcmat = newMatrixObject((float *)cob->matrix, 4, 4, Py_NEW);
1350         idprop = BPy_Wrap_IDProperty(NULL, con->prop, NULL);
1351         
1352         tarmats= PyList_New(con->tarnum); 
1353         for (ct=targets->first, index=0; ct; ct=ct->next, index++) {
1354                 tarmat = newMatrixObject((float *)ct->matrix, 4, 4, Py_NEW);
1355                 PyList_SET_ITEM(tarmats, index, tarmat);
1356         }
1357         
1358         if (!setup_armature_weakrefs()) {
1359                 fprintf(stderr, "Oops - weakref dict setup\n");
1360                 return;
1361         }
1362         
1363         retval = RunPython(con->text, globals);
1364         
1365         if (retval == NULL) {
1366                 BPY_Err_Handle(con->text->id.name);
1367                 con->flag |= PYCON_SCRIPTERROR;
1368                 
1369                 /* free temp objects */
1370                 Py_XDECREF(idprop);
1371                 Py_XDECREF(srcmat);
1372                 Py_XDECREF(tarmats);
1373                 
1374                 ReleaseGlobalDictionary(globals);
1375                 
1376                 return;
1377         }
1378
1379         if (retval) {Py_XDECREF( retval );}
1380         retval = NULL;
1381         
1382         gval = PyDict_GetItemString(globals, "doConstraint");
1383         if (!gval) {
1384                 printf("ERROR: no doConstraint function in constraint!\n");
1385                 
1386                 /* free temp objects */
1387                 Py_XDECREF(idprop);
1388                 Py_XDECREF(srcmat);
1389                 Py_XDECREF(tarmats);
1390                 
1391                 ReleaseGlobalDictionary(globals);
1392                 
1393                 return;
1394         }
1395         
1396         /* Now for the fun part! Try and find the functions we need. */
1397         if (PyFunction_Check(gval)) {
1398                 pyargs = Py_BuildValue("OOO", srcmat, tarmats, idprop);
1399                 retval = PyObject_CallObject(gval, pyargs);
1400                 Py_XDECREF(pyargs);
1401         } 
1402         else {
1403                 printf("ERROR: doConstraint is supposed to be a function!\n");
1404                 con->flag |= PYCON_SCRIPTERROR;
1405                 
1406                 Py_XDECREF(idprop);
1407                 Py_XDECREF(srcmat);
1408                 Py_XDECREF(tarmats);
1409                 
1410                 ReleaseGlobalDictionary(globals);
1411                 
1412                 return;
1413         }
1414         
1415         if (!retval) {
1416                 BPY_Err_Handle(con->text->id.name);
1417                 con->flag |= PYCON_SCRIPTERROR;
1418                 
1419                 /* free temp objects */
1420                 Py_XDECREF(idprop);
1421                 Py_XDECREF(srcmat);
1422                 Py_XDECREF(tarmats);
1423                 
1424                 ReleaseGlobalDictionary(globals);
1425                 
1426                 return;
1427         }
1428         
1429         
1430         if (!PyObject_TypeCheck(retval, &matrix_Type)) {
1431                 printf("Error in PyConstraint - doConstraint: Function not returning a matrix!\n");
1432                 con->flag |= PYCON_SCRIPTERROR;
1433                 
1434                 Py_XDECREF(idprop);
1435                 Py_XDECREF(srcmat);
1436                 Py_XDECREF(tarmats);
1437                 Py_XDECREF(retval);
1438                 
1439                 ReleaseGlobalDictionary(globals);
1440                 
1441                 return;
1442         }
1443         
1444         retmat = (MatrixObject *)retval;
1445         if (retmat->rowSize != 4 || retmat->colSize != 4) {
1446                 printf("Error in PyConstraint - doConstraint: Matrix returned is the wrong size!\n");
1447                 con->flag |= PYCON_SCRIPTERROR;
1448                 
1449                 Py_XDECREF(idprop);
1450                 Py_XDECREF(srcmat);
1451                 Py_XDECREF(tarmats);
1452                 Py_XDECREF(retval);
1453                 
1454                 ReleaseGlobalDictionary(globals);
1455                 
1456                 return;
1457         }       
1458
1459         /* this is the reverse of code taken from newMatrix() */
1460         for(row = 0; row < 4; row++) {
1461                 for(col = 0; col < 4; col++) {
1462                         cob->matrix[row][col] = retmat->contigPtr[row*4+col];
1463                 }
1464         }
1465         
1466         /* free temp objects */
1467         Py_XDECREF(idprop);
1468         Py_XDECREF(srcmat);
1469         Py_XDECREF(tarmats);
1470         Py_XDECREF(retval);
1471         
1472         /* clear globals */
1473         ReleaseGlobalDictionary(globals);
1474 }
1475
1476 /* This evaluates the target matrix for each target the PyConstraint uses.
1477  * NOTE: it only does one target at a time!
1478  */
1479 void BPY_pyconstraint_target(bPythonConstraint *con, bConstraintTarget *ct)
1480 {
1481         PyObject *tar, *subtar;
1482         PyObject *tarmat, *idprop;
1483         PyObject *globals;
1484         PyObject *gval;
1485         PyObject *pyargs, *retval;
1486         MatrixObject *retmat;
1487         int row, col;
1488         
1489         if (!con->text) return;
1490         if (con->flag & PYCON_SCRIPTERROR) return;
1491         if (!ct) return;
1492         
1493         globals = CreateGlobalDictionary();
1494         
1495         tar = Object_CreatePyObject(ct->tar);
1496         if ((ct->tar) && (ct->tar->type==OB_ARMATURE)) {
1497                 bPoseChannel *pchan;
1498                 pchan = get_pose_channel(ct->tar->pose, ct->subtarget);
1499                 subtar = PyPoseBone_FromPosechannel(pchan);
1500         }
1501         else
1502                 subtar = PyString_FromString(ct->subtarget);
1503         
1504         tarmat = newMatrixObject((float *)ct->matrix, 4, 4, Py_NEW);
1505         idprop = BPy_Wrap_IDProperty( NULL, con->prop, NULL);
1506         
1507         if (!setup_armature_weakrefs()) {
1508                 fprintf(stderr, "Oops - weakref dict setup\n");
1509                 return;
1510         }
1511         
1512         retval = RunPython(con->text, globals);
1513
1514         if (retval == NULL) {
1515                 BPY_Err_Handle(con->text->id.name);
1516                 con->flag |= PYCON_SCRIPTERROR;
1517                 
1518                 /* free temp objects */
1519                 Py_XDECREF(tar);
1520                 Py_XDECREF(subtar);
1521                 Py_XDECREF(idprop);
1522                 Py_XDECREF(tarmat);
1523                 
1524                 ReleaseGlobalDictionary(globals);
1525                 
1526                 return;
1527         }
1528
1529         Py_XDECREF(retval);
1530         retval = NULL;
1531         
1532         /* try to find doTarget function to set the target matrix */
1533         gval = PyDict_GetItemString(globals, "doTarget");
1534         if (!gval) {
1535                 /* free temp objects */
1536                 Py_XDECREF(tar);
1537                 Py_XDECREF(subtar);
1538                 Py_XDECREF(idprop);
1539                 Py_XDECREF(tarmat);
1540                 
1541                 ReleaseGlobalDictionary(globals);
1542                 
1543                 return;
1544         }
1545         
1546         /* Now for the fun part! Try and find the functions we need.*/
1547         if (PyFunction_Check(gval)) {
1548                 pyargs = Py_BuildValue("OOOO", tar, subtar, tarmat, idprop);
1549                 retval = PyObject_CallObject(gval, pyargs);
1550                 Py_XDECREF(pyargs);
1551         } 
1552         else {
1553                 printf("ERROR: doTarget is supposed to be a function!\n");
1554                 con->flag |= PYCON_SCRIPTERROR;
1555                 
1556                 Py_XDECREF(tar);
1557                 Py_XDECREF(subtar);
1558                 Py_XDECREF(idprop);
1559                 Py_XDECREF(tarmat);
1560                 
1561                 ReleaseGlobalDictionary(globals);
1562                 return;
1563         }
1564         
1565         if (!retval) {
1566                 BPY_Err_Handle(con->text->id.name);
1567                 con->flag |= PYCON_SCRIPTERROR;
1568                 
1569                 
1570                 /* free temp objects */
1571                 Py_XDECREF(tar);
1572                 Py_XDECREF(subtar);
1573                 Py_XDECREF(idprop);
1574                 Py_XDECREF(tarmat);
1575                 
1576                 ReleaseGlobalDictionary(globals);
1577                 return;
1578         }
1579         
1580         if (!PyObject_TypeCheck(retval, &matrix_Type)) {
1581                 con->flag |= PYCON_SCRIPTERROR;
1582                 
1583                 Py_XDECREF(tar);
1584                 Py_XDECREF(subtar);
1585                 Py_XDECREF(idprop);
1586                 Py_XDECREF(tarmat);
1587                 Py_XDECREF(retval);
1588                 
1589                 ReleaseGlobalDictionary(globals);
1590                 return;
1591         }
1592         
1593         retmat = (MatrixObject *)retval;
1594         if (retmat->rowSize != 4 || retmat->colSize != 4) {
1595                 printf("Error in PyConstraint - doTarget: Matrix returned is the wrong size!\n");
1596                 con->flag |= PYCON_SCRIPTERROR;
1597                 
1598                 Py_XDECREF(tar);
1599                 Py_XDECREF(subtar);
1600                 Py_XDECREF(idprop);
1601                 Py_XDECREF(tarmat);
1602                 Py_XDECREF(retval);
1603                 
1604                 ReleaseGlobalDictionary(globals);
1605                 return;
1606         }       
1607
1608         /* this is the reverse of code taken from newMatrix() */
1609         for(row = 0; row < 4; row++) {
1610                 for(col = 0; col < 4; col++) {
1611                         ct->matrix[row][col] = retmat->contigPtr[row*4+col];
1612                 }
1613         }
1614         
1615         /* free temp objects */
1616         Py_XDECREF(tar);
1617         Py_XDECREF(subtar);
1618         Py_XDECREF(idprop);
1619         Py_XDECREF(tarmat);
1620         Py_XDECREF(retval);
1621         
1622         /* clear globals */
1623         ReleaseGlobalDictionary(globals);
1624 }
1625
1626 /* This draws+handles the user-defined interface for editing pyconstraints idprops */
1627 void BPY_pyconstraint_settings(void *arg1, void *arg2)
1628 {
1629         bPythonConstraint *con= (bPythonConstraint *)arg1;
1630         PyObject *idprop;
1631         PyObject *globals;
1632         PyObject *gval;
1633         PyObject *retval;
1634         
1635         if (!con->text) return;
1636         if (con->flag & PYCON_SCRIPTERROR) return;
1637         
1638         globals = CreateGlobalDictionary();
1639         
1640         idprop = BPy_Wrap_IDProperty( NULL, con->prop, NULL);
1641         
1642         retval = RunPython(con->text, globals);
1643
1644         if (retval == NULL) {
1645                 BPY_Err_Handle(con->text->id.name);
1646                 ReleaseGlobalDictionary(globals);
1647                 con->flag |= PYCON_SCRIPTERROR;
1648         
1649                 /* free temp objects */
1650                 Py_XDECREF(idprop);
1651                 return;
1652         }
1653
1654         if (retval) {Py_XDECREF( retval );}
1655         retval = NULL;
1656         
1657         gval = PyDict_GetItemString(globals, "getSettings");
1658         if (!gval) {
1659                 printf("ERROR: no getSettings function in constraint!\n");
1660                 
1661                 /* free temp objects */
1662                 ReleaseGlobalDictionary( globals );
1663                 Py_XDECREF(idprop);
1664                 return;
1665         }
1666         
1667         /* Now for the fun part! Try and find the functions we need. */
1668         if (PyFunction_Check(gval)) {
1669                 retval = PyObject_CallFunction(gval, "O", idprop);
1670         } 
1671         else {
1672                 printf("ERROR: getSettings is supposed to be a function!\n");
1673                 ReleaseGlobalDictionary( globals );
1674                 
1675                 Py_XDECREF(idprop);
1676                 return;
1677         }
1678         
1679         if (!retval) {
1680                 BPY_Err_Handle(con->text->id.name);
1681                 con->flag |= PYCON_SCRIPTERROR;
1682                 
1683                 /* free temp objects */
1684                 ReleaseGlobalDictionary(globals);
1685                 Py_XDECREF(idprop);
1686                 return;
1687         }
1688         else {
1689                 /* clear globals */
1690                 ReleaseGlobalDictionary(globals);
1691                 
1692                 /* free temp objects */
1693                 Py_XDECREF(idprop);
1694                 Py_DECREF(retval);
1695                 return;
1696         }
1697 }
1698
1699 /* Update function, it gets rid of pydrivers global dictionary, forcing
1700  * BPY_pydriver_eval to recreate it. This function is used to force
1701  * reloading the Blender text module "pydrivers.py", if available, so
1702  * updates in it reach pydriver evaluation. */
1703 void BPY_pydriver_update(void)
1704 {
1705         if (bpy_pydriver_Dict) { /* free the global dict used by pydrivers */
1706                 PyDict_Clear(bpy_pydriver_Dict);
1707                 Py_DECREF(bpy_pydriver_Dict);
1708                 bpy_pydriver_Dict = NULL;
1709         }
1710
1711         return;
1712 }
1713
1714 /* for depsgraph.c, runs py expr once to collect all refs. made
1715  * to objects (self refs. to the object that owns the py driver
1716  * are not allowed). */
1717 struct Object **BPY_pydriver_get_objects(IpoDriver *driver)
1718 {
1719         /*if (!driver || !driver->ob || driver->name[0] == '\0')
1720                 return NULL;*/
1721
1722         /*PyErr_Clear();*/
1723
1724         /* clear the flag that marks invalid python expressions */
1725         driver->flag &= ~IPO_DRIVER_FLAG_INVALID;
1726
1727         /* tell we're running a pydriver, so Get() functions know they need
1728          * to add the requested obj to our list */
1729         bpy_pydriver_running(1);
1730
1731         /* append driver owner object as the 1st ob in the list;
1732          * we put it there to make sure it is not itself referenced in
1733          * its pydriver expression */
1734         bpy_pydriver_appendToList(driver->ob);
1735
1736         /* this will append any other ob referenced in expr (driver->name)
1737          * or set the driver's error flag if driver's py expression fails */
1738         BPY_pydriver_eval(driver);
1739
1740         bpy_pydriver_running(0); /* ok, we're done */
1741
1742         return bpy_pydriver_obArrayFromList(); /* NULL if eval failed */
1743 }
1744
1745 /* This evals py driver expressions, 'expr' is a Python expression that
1746  * should evaluate to a float number, which is returned. */
1747 float BPY_pydriver_eval(IpoDriver *driver)
1748 {
1749         char *expr = NULL;
1750         PyObject *retval, *bpy_ob = NULL;
1751         float result = 0.0f; /* default return */
1752         int setitem_retval;
1753
1754         if (!driver) return result;
1755
1756         expr = driver->name; /* the py expression to be evaluated */
1757         if (!expr || expr[0]=='\0') return result;
1758
1759         if (!bpy_pydriver_Dict) {
1760                 if (bpy_pydriver_create_dict() != 0) {
1761                         fprintf(stderr, "Pydriver error: couldn't create Python dictionary");
1762                         return result;
1763                 }
1764         }
1765
1766         if (driver->ob)
1767                 bpy_ob = Object_CreatePyObject(driver->ob);
1768
1769         if (!bpy_ob) {
1770                 Py_INCREF(Py_None);
1771                 bpy_ob = Py_None;
1772         }
1773
1774         setitem_retval = EXPP_dict_set_item_str(bpy_pydriver_Dict, "self", bpy_ob);
1775
1776         if( !setup_armature_weakrefs()){
1777                 fprintf( stderr, "Oops - weakref dict setup\n");
1778                 return result;
1779         }
1780
1781         retval = PyRun_String(expr, Py_eval_input, bpy_pydriver_Dict,
1782                 bpy_pydriver_Dict);
1783
1784         if (retval == NULL) {
1785                 return pydriver_error(driver);
1786         }
1787
1788         result = ( float )PyFloat_AsDouble( retval );
1789         
1790         if (result == -1 && PyErr_Occurred()) 
1791                 return pydriver_error(driver);
1792
1793         /* remove 'self', since this dict is also used by py buttons */
1794         if (setitem_retval == 0) PyDict_DelItemString(bpy_pydriver_Dict, "self");
1795
1796         /* all fine, make sure the "invalid expression" flag is cleared */
1797         driver->flag &= ~IPO_DRIVER_FLAG_INVALID;
1798
1799         return result;
1800 }
1801
1802 /* Button Python Evaluation */
1803
1804 /* Python evaluation for gui buttons:
1805  *      users can write any valid Python expression (that evals to an int or float)
1806  *      inside Blender's gui number buttons and have them evaluated to their
1807  *      actual int or float value.
1808  *
1809  *      The global dict used for pydrivers is also used here, so all imported
1810  *      modules for pydrivers (including the pydrivers.py Blender text) are
1811  *      available for button py eval, too. */
1812
1813 static int bpy_button_eval_error(char *expr) {
1814
1815         if (bpy_pydriver_oblist)
1816                 bpy_pydriver_freeList();
1817
1818         if (bpy_pydriver_Dict) { /* free the persistent global dict */
1819                 /* it's the same dict used by pydrivers */
1820                 PyDict_Clear(bpy_pydriver_Dict);
1821                 Py_DECREF(bpy_pydriver_Dict);
1822                 bpy_pydriver_Dict = NULL;
1823         }
1824
1825         fprintf(stderr, "\nError in button evaluation:\nThis is the failed Python expression:\n'%s'\n\n", expr);
1826
1827         PyErr_Print();
1828
1829         return -1;
1830 }
1831
1832 int BPY_button_eval(char *expr, double *value)
1833 {
1834         PyObject *retval, *floatval;
1835
1836         if (!value || !expr || expr[0]=='\0') return -1;
1837
1838         *value = 0.0; /* default value */
1839
1840         if (!bpy_pydriver_Dict) {
1841                 if (bpy_pydriver_create_dict() != 0) {
1842                         fprintf(stderr,
1843                                 "Button Python Eval error: couldn't create Python dictionary");
1844                         return -1;
1845                 }
1846         }
1847
1848
1849         if( !setup_armature_weakrefs()){
1850                 fprintf(stderr, "Oops - weakref dict\n");
1851                 return -1;
1852         }
1853
1854         retval = PyRun_String(expr, Py_eval_input, bpy_pydriver_Dict,
1855                 bpy_pydriver_Dict);
1856
1857         if (retval == NULL) {
1858                 return bpy_button_eval_error(expr);
1859         }
1860         else {
1861                 floatval = PyNumber_Float(retval);
1862                 Py_DECREF(retval);
1863         }
1864
1865         if (floatval == NULL) 
1866                 return bpy_button_eval_error(expr);
1867         else {
1868                 *value = (float)PyFloat_AsDouble(floatval);
1869                 Py_DECREF(floatval);
1870         }
1871
1872         return 0; /* successful exit */
1873 }
1874
1875
1876 /*****************************************************************************/
1877 /* ScriptLinks                                                        */
1878 /*****************************************************************************/
1879
1880 /*****************************************************************************/
1881 /* Description:                                                          */
1882 /* Notes:                               Not implemented yet      */
1883 /*****************************************************************************/
1884 void BPY_clear_bad_scriptlinks( struct Text *byebye )
1885 {
1886 /*
1887         BPY_clear_bad_scriptlist(getObjectList(), byebye);
1888         BPY_clear_bad_scriptlist(getLampList(), byebye);
1889         BPY_clear_bad_scriptlist(getCameraList(), byebye);
1890         BPY_clear_bad_scriptlist(getMaterialList(), byebye);
1891         BPY_clear_bad_scriptlist(getWorldList(),        byebye);
1892         BPY_clear_bad_scriptlink(&scene_getCurrent()->id, byebye);
1893
1894         allqueue(REDRAWBUTSSCRIPT, 0);
1895 */
1896         return;
1897 }
1898
1899 /*****************************************************************************
1900 * Description: Loop through all scripts of a list of object types, and 
1901 *       execute these scripts.  
1902 *       For the scene, only the current active scene the scripts are 
1903 *       executed (if any).
1904 *****************************************************************************/
1905 void BPY_do_all_scripts( short event )
1906 {
1907         DoAllScriptsFromList( &( G.main->object ), event );
1908         DoAllScriptsFromList( &( G.main->lamp ), event );
1909         DoAllScriptsFromList( &( G.main->camera ), event );
1910         DoAllScriptsFromList( &( G.main->mat ), event );
1911         DoAllScriptsFromList( &( G.main->world ), event );
1912
1913         BPY_do_pyscript( &( G.scene->id ), event );
1914
1915         return;
1916 }
1917
1918 /*****************************************************************************
1919 * Description: Execute a Python script when an event occurs. The following  
1920 *               events are possible: frame changed, load script and redraw.  
1921 *               Only events happening to one of the following object types   
1922 *               are handled: Object, Lamp, Camera, Material, World and      
1923 *               Scene.                  
1924 *****************************************************************************/
1925
1926 static ScriptLink *ID_getScriptlink( ID * id )
1927 {
1928         switch ( MAKE_ID2( id->name[0], id->name[1] ) ) {
1929         case ID_OB:
1930                 return &( ( Object * ) id )->scriptlink;
1931         case ID_LA:
1932                 return &( ( Lamp * ) id )->scriptlink;
1933         case ID_CA:
1934                 return &( ( Camera * ) id )->scriptlink;
1935         case ID_MA:
1936                 return &( ( Material * ) id )->scriptlink;
1937         case ID_WO:
1938                 return &( ( World * ) id )->scriptlink;
1939         case ID_SCE:
1940                 return &( ( Scene * ) id )->scriptlink;
1941         default:
1942                 return NULL;
1943         }
1944 }
1945
1946 int BPY_has_onload_script( void )
1947 {
1948         ScriptLink *slink = &G.scene->scriptlink;
1949         int i;
1950
1951         if( !slink || !slink->totscript )
1952                 return 0;
1953
1954         for( i = 0; i < slink->totscript; i++ ) {
1955                 if( ( slink->flag[i] == SCRIPT_ONLOAD )
1956                     && ( slink->scripts[i] != NULL ) )
1957                         return 1;
1958         }
1959
1960         return 0;
1961 }
1962
1963 void BPY_do_pyscript( ID * id, short event )
1964 {
1965         ScriptLink *scriptlink;
1966
1967         if( !id ) return;
1968
1969         scriptlink = ID_getScriptlink( id );
1970
1971         if( scriptlink && scriptlink->totscript ) {
1972                 PyObject *value;
1973                 PyObject *dict;
1974                 PyObject *ret;
1975                 int index, during_slink = during_scriptlink(  );
1976
1977                 /* invalid scriptlinks (new .blend was just loaded), return */
1978                 if( during_slink < 0 )
1979                         return;
1980                 
1981                 if( !setup_armature_weakrefs()){
1982                         printf("Oops - weakref dict, this is a bug\n");
1983                         return;
1984                 }
1985                 
1986                 value = GetPyObjectFromID( id );
1987                 if( !value){
1988                         printf("Oops - could not get a valid python object for Blender.link, this is a bug\n");
1989                         return;
1990                 }
1991                 
1992                 /* tell we're running a scriptlink.  The sum also tells if this script
1993                  * is running nested inside another.  Blender.Load needs this info to
1994                  * avoid trouble with invalid slink pointers. */
1995                 during_slink++;
1996                 disable_where_scriptlink( (short)during_slink );
1997
1998                 /* set globals in Blender module to identify scriptlink */
1999                 PyDict_SetItemString(   g_blenderdict, "bylink", Py_True);
2000                 EXPP_dict_set_item_str( g_blenderdict, "link", value );
2001                 EXPP_dict_set_item_str( g_blenderdict, "event",
2002                                       PyString_FromString( event_to_name
2003                                                            ( event ) ) );
2004                 if (event == SCRIPT_POSTRENDER) event = SCRIPT_RENDER;
2005
2006                 for( index = 0; index < scriptlink->totscript; index++ ) {
2007                         if( ( scriptlink->flag[index] == event ) &&
2008                             ( scriptlink->scripts[index] != NULL ) ) {
2009                                 dict = CreateGlobalDictionary(  );
2010                                 ret = RunPython( ( Text * ) scriptlink->
2011                                                  scripts[index], dict );
2012                                 ReleaseGlobalDictionary( dict );
2013
2014                                 if( !ret ) {
2015                                         /* Failed execution of the script */
2016                                         BPY_Err_Handle( scriptlink->
2017                                                         scripts[index]->name +
2018                                                         2 );
2019                                         //BPY_end_python ();
2020                                         //BPY_start_python ();
2021                                 } else {
2022                                         Py_DECREF( ret );
2023                                 }
2024                                 /* If a scriptlink has just loaded a new .blend file, the
2025                                  * scriptlink pointer became invalid (see api2_2x/Blender.c),
2026                                  * so we stop here. */
2027                                 if( during_scriptlink(  ) == -1 ) {
2028                                         during_slink = 1;
2029                                         break;
2030                                 }
2031                         }
2032                 }
2033
2034                 disable_where_scriptlink( (short)(during_slink - 1) );
2035
2036                 /* cleanup bylink flag and clear link so PyObject
2037                  * can be released 
2038                  */
2039                 PyDict_SetItemString(g_blenderdict, "bylink", Py_False);
2040                 PyDict_SetItemString( g_blenderdict, "link", Py_None );
2041                 EXPP_dict_set_item_str( g_blenderdict, "event", PyString_FromString( "" ) );
2042         }
2043 }
2044
2045
2046 /* SPACE HANDLERS */
2047
2048 /* These are special script links that can be assigned to ScrArea's to
2049  * (EVENT type) receive events sent to a given space (and use or ignore them) or
2050  * (DRAW type) be called after the space is drawn, to draw anything on top of
2051  * the space area. */
2052
2053 /* How to add space handlers to other spaces:
2054  * - add the space event defines to DNA_scriptlink_types.h, as done for
2055  *   3d view: SPACEHANDLER_VIEW3D_EVENT, for example;
2056  * - add the new defines to Blender.SpaceHandler dictionary in Blender.c;
2057  * - check space.c for how to call the event handlers;
2058  * - check drawview.c for how to call the draw handlers;
2059  * - check header_view3d.c for how to add the "Space Handler Scripts" menu.
2060  * Note: DRAW handlers should be called with 'event = 0', chech drawview.c */
2061
2062 int BPY_has_spacehandler(Text *text, ScrArea *sa)
2063 {
2064         ScriptLink *slink;
2065         int index;
2066
2067         if (!sa || !text) return 0;
2068
2069         slink = &sa->scriptlink;
2070
2071         for (index = 0; index < slink->totscript; index++) {
2072                 if (slink->scripts[index] && (slink->scripts[index] == (ID *)text))
2073                         return 1;
2074         }
2075
2076         return 0;       
2077 }
2078
2079 int BPY_is_spacehandler(Text *text, char spacetype)
2080 {
2081         TextLine *tline = text->lines.first;
2082         unsigned short type = 0;
2083
2084         if (tline && (tline->len > 10)) {
2085                 char *line = tline->line;
2086
2087                 /* Expected format: # SPACEHANDLER.SPACE.TYPE
2088                  * Ex: # SPACEHANDLER.VIEW3D.DRAW
2089                  * The actual checks are forgiving, so slight variations also work. */
2090                 if (line && line[0] == '#' && strstr(line, "HANDLER")) {
2091                         line++; /* skip '#' */
2092
2093                         /* only done for 3D View right now, trivial to add for others: */
2094                         switch (spacetype) {
2095                                 case SPACE_VIEW3D:
2096                                         if (strstr(line, "3D")) { /* VIEW3D, 3DVIEW */
2097                                                 if (strstr(line, "DRAW")) type = SPACEHANDLER_VIEW3D_DRAW;
2098                                                 else if (strstr(line, "EVENT")) type = SPACEHANDLER_VIEW3D_EVENT;
2099                                         }
2100                                         break;
2101                         }
2102                 }
2103         }
2104         return type; /* 0 if not a space handler */
2105 }
2106
2107 int BPY_del_spacehandler(Text *text, ScrArea *sa)
2108 {
2109         ScriptLink *slink;
2110         int i, j;
2111
2112         if (!sa || !text) return -1;
2113
2114         slink = &sa->scriptlink;
2115         if (slink->totscript < 1) return -1;
2116
2117         for (i = 0; i < slink->totscript; i++) {
2118                 if (text == (Text *)slink->scripts[i]) {
2119
2120                         for (j = i; j < slink->totscript - 1; j++) {
2121                                 slink->flag[j] = slink->flag[j+1];
2122                                 slink->scripts[j] = slink->scripts[j+1];
2123                         }
2124                         slink->totscript--;
2125                         /* like done in buttons_script.c we just free memory
2126                          * if all slinks have been removed -- less fragmentation,
2127                          * these should be quite small arrays */
2128                         if (slink->totscript == 0) {
2129                                 if (slink->scripts) MEM_freeN(slink->scripts);
2130                                 if (slink->flag) MEM_freeN(slink->flag);
2131                                 break;
2132                         }
2133                 }
2134         }
2135         return 0;
2136 }
2137
2138 int BPY_add_spacehandler(Text *text, ScrArea *sa, char spacetype)
2139 {
2140         unsigned short handlertype;
2141
2142         if (!sa || !text) return -1;
2143
2144         handlertype = (unsigned short)BPY_is_spacehandler(text, spacetype);
2145
2146         if (handlertype) {
2147                 ScriptLink *slink = &sa->scriptlink;
2148                 void *stmp, *ftmp;
2149                 unsigned short space_event = SPACEHANDLER_VIEW3D_EVENT;
2150
2151                 /* extend slink */
2152
2153                 stmp= slink->scripts;           
2154                 slink->scripts= MEM_mallocN(sizeof(ID*)*(slink->totscript+1),
2155                         "spacehandlerscripts");
2156         
2157                 ftmp= slink->flag;              
2158                 slink->flag= MEM_mallocN(sizeof(short*)*(slink->totscript+1),
2159                         "spacehandlerflags");
2160         
2161                 if (slink->totscript) {
2162                         memcpy(slink->scripts, stmp, sizeof(ID*)*(slink->totscript));
2163                         MEM_freeN(stmp);
2164
2165                         memcpy(slink->flag, ftmp, sizeof(short)*(slink->totscript));
2166                         MEM_freeN(ftmp);
2167                 }
2168
2169                 switch (spacetype) {
2170                         case SPACE_VIEW3D:
2171                                 if (handlertype == 1) space_event = SPACEHANDLER_VIEW3D_EVENT;
2172                                 else space_event = SPACEHANDLER_VIEW3D_DRAW;
2173                                 break;
2174                         default:
2175                                 break;
2176                 }
2177
2178                 slink->scripts[slink->totscript] = (ID *)text;
2179                 slink->flag[slink->totscript]= space_event;
2180
2181                 slink->totscript++;
2182                 slink->actscript = slink->totscript;
2183
2184         }
2185         return 0;
2186 }
2187
2188 int BPY_do_spacehandlers( ScrArea *sa, unsigned short event,
2189         unsigned short space_event )
2190 {
2191         ScriptLink *scriptlink;
2192         int retval = 0;
2193         
2194         if (!sa || !(G.f & G_DOSCRIPTLINKS)) return 0;
2195         
2196         scriptlink = &sa->scriptlink;
2197
2198         if (scriptlink->totscript > 0) {
2199                 PyObject *dict;
2200                 PyObject *ret;
2201                 int index, during_slink = during_scriptlink();
2202
2203                 /* invalid scriptlinks (new .blend was just loaded), return */
2204                 if (during_slink < 0) return 0;
2205
2206                 /* tell we're running a scriptlink.  The sum also tells if this script
2207                  * is running nested inside another.  Blender.Load needs this info to
2208                  * avoid trouble with invalid slink pointers.
2209                  * Update (test): allow EVENT space handlers to call file/image selectors,
2210                  * still disabled for DRAW space handlers: */
2211                 if (event == 0) { /* event = 0: DRAW space handler */
2212                         during_slink++;
2213                         disable_where_scriptlink( (short)during_slink );
2214                 }
2215
2216                 if( !setup_armature_weakrefs()){
2217                         printf("Oops - weakref dict, this is a bug\n");
2218                         return 0;
2219                 }
2220                 
2221                 /* set globals in Blender module to identify space handler scriptlink */
2222                 PyDict_SetItemString(g_blenderdict, "bylink", Py_True);
2223                 /* unlike normal scriptlinks, here Blender.link is int (space event type) */
2224                 EXPP_dict_set_item_str(g_blenderdict, "link", PyInt_FromLong(space_event));
2225                 /* note: DRAW space_events set event to 0 */
2226                 EXPP_dict_set_item_str(g_blenderdict, "event", PyInt_FromLong(event));
2227                 /* now run all assigned space handlers for this space and space_event */
2228                 for( index = 0; index < scriptlink->totscript; index++ ) {
2229
2230                         /* for DRAW handlers: */
2231                         if (event == 0) {
2232                                 glPushAttrib(GL_ALL_ATTRIB_BITS);
2233                                 glMatrixMode(GL_PROJECTION);
2234                                 glPushMatrix();
2235                                 glMatrixMode(GL_MODELVIEW);
2236                                 glPushMatrix();
2237                         }
2238
2239                         if( ( scriptlink->flag[index] == space_event ) &&
2240                             ( scriptlink->scripts[index] != NULL ) ) {
2241                                 dict = CreateGlobalDictionary();
2242                                 ret = RunPython( ( Text * ) scriptlink->scripts[index], dict );
2243                                 ReleaseGlobalDictionary( dict );
2244
2245                                 if (!ret) { /* Failed execution of the script */
2246                                         BPY_Err_Handle( scriptlink->scripts[index]->name+2 );
2247                                 } else {
2248                                         Py_DECREF(ret);
2249
2250                                         /* an EVENT type (event != 0) script can either accept an event or
2251                                          * ignore it:
2252                                          * if the script sets Blender.event to None it accepted it;
2253                                          * otherwise the space's event handling callback that called us
2254                                          * can go on processing the event */
2255                                         if (event && (PyDict_GetItemString(g_blenderdict,"event") == Py_None))
2256                                                 retval = 1; /* event was swallowed */
2257                                 }
2258
2259                                 /* If a scriptlink has just loaded a new .blend file, the
2260                                  * scriptlink pointer became invalid (see api2_2x/Blender.c),
2261                                  * so we stop here. */
2262                                 if( during_scriptlink(  ) == -1 ) {
2263                                         during_slink = 1;
2264                                         if (event == 0) glPopAttrib();
2265                                         break;
2266                                 }
2267                         }
2268
2269                         /* for DRAW handlers: */
2270                         if (event == 0) {
2271                                 glMatrixMode(GL_PROJECTION);
2272                                 glPopMatrix();
2273                                 glMatrixMode(GL_MODELVIEW);
2274                                 glPopMatrix();
2275                                 glPopAttrib();
2276                                 disable_where_scriptlink( (short)(during_slink - 1) );
2277                         }
2278
2279                 }
2280
2281                 PyDict_SetItemString(g_blenderdict, "bylink", Py_False);
2282                 PyDict_SetItemString(g_blenderdict, "link", Py_None );
2283                 EXPP_dict_set_item_str(g_blenderdict, "event", PyString_FromString(""));
2284         }
2285         
2286         /* retval:
2287          * space_event is of type EVENT:
2288          * 0 - event was returned,
2289          * 1 - event was processed;
2290          * space_event is of type DRAW:
2291          * 0 always */
2292
2293         return retval;
2294 }
2295
2296 /*****************************************************************************
2297 * Description:  
2298 * Notes:
2299 *****************************************************************************/
2300 void BPY_free_scriptlink( struct ScriptLink *slink )
2301 {
2302         if( slink->totscript ) {
2303                 if( slink->flag ) {
2304                         MEM_freeN( slink->flag );
2305                         slink->flag= NULL;
2306                 }
2307                 if( slink->scripts ) {
2308                         MEM_freeN( slink->scripts );
2309                         slink->scripts= NULL;
2310                 }
2311         }
2312
2313         return;
2314 }
2315
2316 static int CheckAllSpaceHandlers(Text *text)
2317 {
2318         bScreen *screen;
2319         ScrArea *sa;
2320         ScriptLink *slink;
2321         int fixed = 0;
2322
2323         for (screen = G.main->screen.first; screen; screen = screen->id.next) {
2324                 for (sa = screen->areabase.first; sa; sa = sa->next) {
2325                         slink = &sa->scriptlink;
2326                         if (!slink->totscript) continue;
2327                         if (BPY_del_spacehandler(text, sa) == 0) fixed++;
2328                 }
2329         }
2330         return fixed;
2331 }
2332
2333 static int CheckAllScriptsFromList( ListBase * list, Text * text )
2334 {
2335         ID *id;
2336         ScriptLink *scriptlink;
2337         int index;
2338         int fixed = 0;
2339
2340         id = list->first;
2341
2342         while( id != NULL ) {
2343                 scriptlink = ID_getScriptlink( id );
2344                 if( scriptlink && scriptlink->totscript ) {
2345                         for( index = 0; index < scriptlink->totscript; index++) {
2346                                 if ((Text *)scriptlink->scripts[index] == text) {
2347                                         scriptlink->scripts[index] = NULL;
2348                                         fixed++;
2349                                 }
2350                         }
2351                 }
2352                 id = id->next;
2353         }
2354
2355         return fixed;
2356 }
2357
2358 /* When a Text is deleted, we need to unlink it from eventual scriptlinks */
2359 int BPY_check_all_scriptlinks( Text * text )
2360 {
2361         int fixed = 0;
2362         fixed += CheckAllScriptsFromList( &( G.main->object ), text );
2363         fixed += CheckAllScriptsFromList( &( G.main->lamp ), text );
2364         fixed += CheckAllScriptsFromList( &( G.main->camera ), text );
2365         fixed += CheckAllScriptsFromList( &( G.main->mat ), text );
2366         fixed += CheckAllScriptsFromList( &( G.main->world ), text );
2367         fixed += CheckAllScriptsFromList( &( G.main->scene ), text );
2368         fixed += CheckAllSpaceHandlers(text);
2369
2370         return fixed;
2371 }
2372
2373 /*****************************************************************************
2374 * Description: 
2375 * Notes:
2376 *****************************************************************************/
2377 void BPY_copy_scriptlink( struct ScriptLink *scriptlink )
2378 {
2379         void *tmp;
2380
2381         if( scriptlink->totscript ) {
2382
2383                 tmp = scriptlink->scripts;
2384                 scriptlink->scripts =
2385                         MEM_mallocN( sizeof( ID * ) * scriptlink->totscript,
2386                                      "scriptlistL" );
2387                 memcpy( scriptlink->scripts, tmp,
2388                         sizeof( ID * ) * scriptlink->totscript );
2389
2390                 tmp = scriptlink->flag;
2391                 scriptlink->flag =
2392                         MEM_mallocN( sizeof( short ) * scriptlink->totscript,
2393                                      "scriptlistF" );
2394                 memcpy( scriptlink->flag, tmp,
2395                         sizeof( short ) * scriptlink->totscript );
2396         }
2397
2398         return;
2399 }
2400
2401 /****************************************************************************
2402 * Description:
2403 * Notes:                Not implemented yet
2404 *****************************************************************************/
2405 int BPY_call_importloader( char *name )
2406 {                       /* XXX Should this function go away from Blender? */
2407         printf( "In BPY_call_importloader(name=%s)\n", name );
2408         return ( 0 );
2409 }
2410
2411 /*****************************************************************************
2412 * Private functions
2413 *****************************************************************************/
2414
2415 /*****************************************************************************
2416 * Description: This function executes the python script passed by text. 
2417 *               The Python dictionary containing global variables needs to
2418 *               be passed in globaldict.
2419 *****************************************************************************/
2420 PyObject *RunPython( Text * text, PyObject * globaldict )
2421 {
2422         char *buf = NULL;
2423
2424 /* The script text is compiled to Python bytecode and saved at text->compiled
2425  * to speed-up execution if the user executes the script multiple times */
2426
2427         if( !text->compiled ) { /* if it wasn't already compiled, do it now */
2428                 buf = txt_to_buf( text );
2429
2430                 text->compiled =
2431                         Py_CompileString( buf, GetName( text ),
2432                                           Py_file_input );
2433
2434                 MEM_freeN( buf );
2435
2436                 if( PyErr_Occurred(  ) ) {
2437                         BPY_free_compiled_text( text );
2438                         return NULL;
2439                 }
2440
2441         }
2442
2443         return PyEval_EvalCode( text->compiled, globaldict, globaldict );
2444 }
2445
2446 /*****************************************************************************
2447 * Description: This function returns the value of the name field of the 
2448 *       given Text struct.
2449 *****************************************************************************/
2450 char *GetName( Text * text )
2451 {
2452         return ( text->id.name + 2 );
2453 }
2454
2455 /*****************************************************************************
2456 * Description: This function creates a new Python dictionary object.
2457 *****************************************************************************/
2458 PyObject *CreateGlobalDictionary( void )
2459 {
2460         PyObject *dict = PyDict_New(  );
2461
2462         PyDict_SetItemString( dict, "__builtins__", PyEval_GetBuiltins(  ) );
2463         EXPP_dict_set_item_str( dict, "__name__",
2464                               PyString_FromString( "__main__" ) );
2465
2466         return dict;
2467 }
2468
2469 /*****************************************************************************
2470 * Description: This function deletes a given Python dictionary object.
2471 *****************************************************************************/
2472 void ReleaseGlobalDictionary( PyObject * dict )
2473 {
2474         PyDict_Clear( dict );
2475         Py_DECREF( dict );      /* Release dictionary. */
2476
2477         return;
2478 }
2479
2480 /***************************************************************************
2481 * Description: This function runs all scripts (if any) present in the
2482 *               list argument. The event by which the function has been 
2483 *               called, is passed in the event argument.
2484 *****************************************************************************/
2485 void DoAllScriptsFromList( ListBase * list, short event )
2486 {
2487         ID *id;
2488
2489         id = list->first;
2490
2491         while( id != NULL ) {
2492                 BPY_do_pyscript( id, event );
2493                 id = id->next;
2494         }
2495
2496         return;
2497 }
2498
2499 PyObject *importText( char *name )
2500 {
2501         Text *text;
2502         char *txtname;
2503         char *buf = NULL;
2504         int namelen = strlen( name );
2505
2506         txtname = malloc( namelen + 3 + 1 );
2507         if( !txtname )
2508                 return NULL;
2509
2510         memcpy( txtname, name, namelen );
2511         memcpy( &txtname[namelen], ".py", 4 );
2512
2513         text = ( Text * ) & ( G.main->text.first );
2514
2515         while( text ) {
2516                 if( !strcmp( txtname, GetName( text ) ) )
2517                         break;
2518                 text = text->id.next;
2519         }
2520
2521         if( !text ) {
2522                 free( txtname );
2523                 return NULL;
2524         }
2525
2526         if( !text->compiled ) {
2527                 buf = txt_to_buf( text );
2528                 text->compiled =
2529                         Py_CompileString( buf, GetName( text ),
2530                                           Py_file_input );
2531                 MEM_freeN( buf );
2532
2533                 if( PyErr_Occurred(  ) ) {
2534                         PyErr_Print(  );
2535                         BPY_free_compiled_text( text );
2536                         free( txtname );
2537                         return NULL;
2538                 }
2539         }
2540
2541         free( txtname );
2542         return PyImport_ExecCodeModule( name, text->compiled );
2543 }
2544
2545 static PyMethodDef bimport[] = {
2546         {"blimport", blender_import, METH_VARARGS, "our own import"}
2547 };
2548
2549 PyObject *blender_import( PyObject * self, PyObject * args )
2550 {
2551         PyObject *exception, *err, *tb;
2552         char *name;
2553         PyObject *globals = NULL, *locals = NULL, *fromlist = NULL;
2554         PyObject *m;
2555
2556         if( !PyArg_ParseTuple( args, "s|OOO:bimport",
2557                                &name, &globals, &locals, &fromlist ) )
2558                 return NULL;
2559
2560         m = PyImport_ImportModuleEx( name, globals, locals, fromlist );
2561
2562         if( m )
2563                 return m;
2564         else
2565                 PyErr_Fetch( &exception, &err, &tb );   /*restore for probable later use */
2566
2567         m = importText( name );
2568         if( m ) {               /* found module, ignore above exception */
2569                 PyErr_Clear(  );
2570                 Py_XDECREF( exception );
2571                 Py_XDECREF( err );
2572                 Py_XDECREF( tb );
2573                 printf( "imported from text buffer...\n" );
2574         } else {
2575                 PyErr_Restore( exception, err, tb );
2576         }
2577         return m;
2578 }
2579
2580 void init_ourImport( void )
2581 {
2582         PyObject *m, *d;
2583         PyObject *import = PyCFunction_New( bimport, NULL );
2584
2585         m = PyImport_AddModule( "__builtin__" );
2586         d = PyModule_GetDict( m );
2587         
2588         EXPP_dict_set_item_str( d, "__import__", import );
2589 }
2590
2591 /*
2592  * find in-memory module and recompile
2593  */
2594
2595 static PyObject *reimportText( PyObject *module )
2596 {
2597         Text *text;
2598         char *txtname;
2599         char *name;
2600         char *buf = NULL;
2601
2602         /* get name, filename from the module itself */
2603
2604         txtname = PyModule_GetFilename( module );
2605         name = PyModule_GetName( module );
2606         if( !txtname || !name)
2607                 return NULL;
2608
2609         /* look up the text object */
2610         text = ( Text * ) & ( G.main->text.first );
2611         while( text ) {
2612                 if( !strcmp( txtname, GetName( text ) ) )
2613                         break;
2614                 text = text->id.next;
2615         }
2616
2617         /* uh-oh.... didn't find it */
2618         if( !text )
2619                 return NULL;
2620
2621         /* if previously compiled, free the object */
2622         /* (can't see how could be NULL, but check just in case) */ 
2623         if( text->compiled ){
2624                 Py_DECREF( (PyObject *)text->compiled );
2625         }
2626
2627         /* compile the buffer */
2628         buf = txt_to_buf( text );
2629         text->compiled = Py_CompileString( buf, GetName( text ),
2630                         Py_file_input );
2631         MEM_freeN( buf );
2632
2633         /* if compile failed.... return this error */
2634         if( PyErr_Occurred(  ) ) {
2635                 PyErr_Print(  );
2636                 BPY_free_compiled_text( text );
2637                 return NULL;
2638         }
2639
2640         /* make into a module */
2641         return PyImport_ExecCodeModule( name, text->compiled );
2642 }
2643
2644 /*
2645  * our reload() module, to handle reloading in-memory scripts
2646  */
2647
2648 static PyObject *blender_reload( PyObject * self, PyObject * args )
2649 {
2650         PyObject *exception, *err, *tb;
2651         PyObject *module = NULL;
2652         PyObject *newmodule = NULL;
2653
2654         /* check for a module arg */
2655         if( !PyArg_ParseTuple( args, "O:breload", &module ) )
2656                 return NULL;
2657
2658         /* try reimporting from file */
2659         newmodule = PyImport_ReloadModule( module );
2660         if( newmodule )
2661                 return newmodule;
2662
2663         /* no file, try importing from memory */
2664         PyErr_Fetch( &exception, &err, &tb );   /*restore for probable later use */
2665
2666         newmodule = reimportText( module );
2667         if( newmodule ) {               /* found module, ignore above exception */
2668                 PyErr_Clear(  );
2669                 Py_XDECREF( exception );
2670                 Py_XDECREF( err );
2671                 Py_XDECREF( tb );
2672         } else
2673                 PyErr_Restore( exception, err, tb );
2674
2675         return newmodule;
2676 }
2677
2678 static PyMethodDef breload[] = {
2679         {"blreload", blender_reload, METH_VARARGS, "our own reload"}
2680 };
2681
2682 void init_ourReload( void )
2683 {
2684         PyObject *m, *d;
2685         PyObject *reload = PyCFunction_New( breload, NULL );
2686
2687         m = PyImport_AddModule( "__builtin__" );
2688         d = PyModule_GetDict( m );
2689         EXPP_dict_set_item_str( d, "reload", reload );
2690 }