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