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