| 
									
										
										
										
											2002-10-12 11:37:38 +00:00
										 |  |  | /**
 | 
					
						
							|  |  |  |  * blenkernel/py_main.c | 
					
						
							|  |  |  |  * (cleaned up somewhat nzc apr-2001) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |  * $Id$ | 
					
						
							|  |  |  |  * | 
					
						
							|  |  |  |  * ***** BEGIN GPL/BL DUAL LICENSE BLOCK ***** | 
					
						
							|  |  |  |  * | 
					
						
							|  |  |  |  * This program is free software; you can redistribute it and/or | 
					
						
							|  |  |  |  * modify it under the terms of the GNU General Public License | 
					
						
							|  |  |  |  * as published by the Free Software Foundation; either version 2 | 
					
						
							|  |  |  |  * of the License, or (at your option) any later version. The Blender | 
					
						
							|  |  |  |  * Foundation also sells licenses for use in proprietary software under | 
					
						
							|  |  |  |  * the Blender License.  See http://www.blender.org/BL/ for information
 | 
					
						
							|  |  |  |  * about this. | 
					
						
							|  |  |  |  * | 
					
						
							|  |  |  |  * This program is distributed in the hope that it will be useful, | 
					
						
							|  |  |  |  * but WITHOUT ANY WARRANTY; without even the implied warranty of | 
					
						
							|  |  |  |  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the | 
					
						
							|  |  |  |  * GNU General Public License for more details. | 
					
						
							|  |  |  |  * | 
					
						
							|  |  |  |  * You should have received a copy of the GNU General Public License | 
					
						
							|  |  |  |  * along with this program; if not, write to the Free Software Foundation, | 
					
						
							|  |  |  |  * Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA. | 
					
						
							|  |  |  |  * | 
					
						
							|  |  |  |  * The Original Code is Copyright (C) 2001-2002 by NaN Holding BV. | 
					
						
							|  |  |  |  * All rights reserved. | 
					
						
							|  |  |  |  * | 
					
						
							|  |  |  |  * The Original Code is: all of this file. | 
					
						
							|  |  |  |  * | 
					
						
							|  |  |  |  * Contributor(s): none yet. | 
					
						
							|  |  |  |  * | 
					
						
							|  |  |  |  * ***** END GPL/BL DUAL LICENSE BLOCK ***** | 
					
						
							|  |  |  |  * | 
					
						
							|  |  |  |  */ | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | /* NOTE: all externally callable routines have the prefix BPY_
 | 
					
						
							|  |  |  |  -- see also ../include/BPY_extern.h */ | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | #include "BPY_main.h"
 | 
					
						
							|  |  |  | #include "BPY_modules.h"
 | 
					
						
							|  |  |  | #include "BPY_macros.h"
 | 
					
						
							|  |  |  | #include "DNA_space_types.h"
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | #include "b_interface.h"
 | 
					
						
							|  |  |  | #include "mydevice.h"
 | 
					
						
							|  |  |  | #include "import.h"
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2002-11-25 12:02:15 +00:00
										 |  |  | #ifdef HAVE_CONFIG_H
 | 
					
						
							|  |  |  | #include <config.h>
 | 
					
						
							|  |  |  | #endif
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2002-10-12 11:37:38 +00:00
										 |  |  | /* PROTOS */ | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | extern void init_frozenmodules(void);  // frozen module library
 | 
					
						
							|  |  |  | extern void initmxTextTools(void); | 
					
						
							|  |  |  | extern void inittess(void);            // tesselator module
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | void init_ourImport(void); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | /* GLOBALS */ | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | PyObject* ErrorObject     = NULL; | 
					
						
							|  |  |  | PyObject* callback        = NULL; | 
					
						
							|  |  |  | PyObject* callbackArgs    = NULL; | 
					
						
							|  |  |  | PyObject* blenderprogname = NULL; | 
					
						
							|  |  |  | ID*       script_link_id  = NULL; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | /*------------------------------------------------------------------------*/  | 
					
						
							|  |  |  | /* START PYTHON (from creator.c)                                          */ | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | void INITMODULE(BLENDERMODULE)(void); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | struct _inittab blendermodules[] = { | 
					
						
							|  |  |  | #ifndef SHAREDMODULE         // Blender module can alternatively be compiled shared
 | 
					
						
							|  |  |  | 	#ifdef STATIC_TEXTTOOLS  // see api.h
 | 
					
						
							|  |  |  | 	{ "mxTextTools" , initmxTextTools }, | 
					
						
							|  |  |  | 	#endif
 | 
					
						
							|  |  |  | 	{ MODNAME(BLENDERMODULE) , INITMODULE(BLENDERMODULE) }, | 
					
						
							|  |  |  | #endif
 | 
					
						
							|  |  |  | #ifdef NO_RELEASE
 | 
					
						
							|  |  |  | 	{ "tess" , inittess }, // GLU tesselator wrapper module
 | 
					
						
							|  |  |  | #endif
 | 
					
						
							|  |  |  | 	{ 0, 0} | 
					
						
							|  |  |  | }; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | /* hack to make sure, inittab is extended only first time */ | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | static short g_is_extended = 0; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | /** (Re)initializes the Python Interpreter.
 | 
					
						
							|  |  |  |   * This function should be only called if the Python interpreter | 
					
						
							|  |  |  |   * was not yet initialized (check Py_IsInitialized() ) | 
					
						
							|  |  |  |   */ | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | static void initBPythonInterpreter(void) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  | 	Py_Initialize(); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	init_ourImport(); /* our own import, later: security */ | 
					
						
							|  |  |  | 	if (!BPY_CHECKFLAG(G_NOFROZEN)) { | 
					
						
							|  |  |  | 		init_frozenmodules(); /* initialize frozen modules unless disabled */ | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 	init_syspath(); | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | /** This function initializes Blender Python. It should be called only
 | 
					
						
							|  |  |  |   * once at start, which is currently not the case (GameEngine Python). | 
					
						
							|  |  |  |   * Therefore, it contains some dirty workarounds. They will be thrown | 
					
						
							|  |  |  |   * into the grachten once the different APIs are merged into something | 
					
						
							|  |  |  |   * more consistent. | 
					
						
							|  |  |  |   * | 
					
						
							|  |  |  |   */ | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | void BPY_start_python(void) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  | 	Py_SetProgramName("blender"); | 
					
						
							|  |  |  | 	if (BPY_DEBUGFLAG) { | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 		Py_VerboseFlag = 1; | 
					
						
							|  |  |  | 		Py_DebugFlag = 1; | 
					
						
							|  |  |  | 	} else { | 
					
						
							|  |  |  | #ifndef EXPERIMENTAL 		
 | 
					
						
							|  |  |  | 		Py_FrozenFlag = 1; /* no warnings about non set PYTHONHOME */ | 
					
						
							|  |  |  | 		Py_NoSiteFlag = 1; /* disable auto site module import */ | 
					
						
							|  |  |  | #endif		
 | 
					
						
							|  |  |  | 	}	 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	if (!g_is_extended) { | 
					
						
							|  |  |  | 		g_is_extended = 1; | 
					
						
							|  |  |  | 		PyImport_ExtendInittab(blendermodules); /* extend builtin module table */ | 
					
						
							|  |  |  | 	}	 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	initBPythonInterpreter(); | 
					
						
							|  |  |  | #ifdef NO_RELEASE
 | 
					
						
							|  |  |  | 	if (PyRun_SimpleString("import startup")) | 
					
						
							|  |  |  | 	{ | 
					
						
							|  |  |  | 		BPY_warn(("init script not found, continuing anyway\n")); | 
					
						
							|  |  |  | 		PyErr_Clear(); | 
					
						
							|  |  |  | 		return; | 
					
						
							|  |  |  | 	}	 | 
					
						
							|  |  |  | #endif	
 | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | /** Ends the Python interpreter. This cleans up all global variables
 | 
					
						
							|  |  |  |   * Blender-Python descriptor objects will (MUST!) decref on their | 
					
						
							|  |  |  |   * raw blender objects, so this function should be called more or less | 
					
						
							|  |  |  |   * immediately before garbage collection actions. | 
					
						
							|  |  |  |   */ | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | void BPY_end_python(void) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  | 	Py_Finalize(); | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | void BPY_free_compiled_text(Text* text) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  | 	if (!text->compiled) return; | 
					
						
							|  |  |  | 	Py_DECREF((PyObject*) text->compiled); | 
					
						
							|  |  |  | 	text->compiled = NULL; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | void syspath_append(PyObject *dir) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  | 	PyObject *m, *d; | 
					
						
							|  |  |  | 	PyObject *o; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	PyErr_Clear(); | 
					
						
							|  |  |  | 	m = PyImport_ImportModule("sys"); | 
					
						
							|  |  |  | 	d = PyModule_GetDict(m); | 
					
						
							|  |  |  | 	o = PyDict_GetItemString(d, "path"); | 
					
						
							|  |  |  | 	if (!PyList_Check(o)) { | 
					
						
							|  |  |  | 		return; | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 	PyList_Append(o, dir); | 
					
						
							|  |  |  | 	if (PyErr_Occurred()) { | 
					
						
							|  |  |  | 		Py_FatalError("could not build sys.path"); | 
					
						
							|  |  |  | 	}	 | 
					
						
							|  |  |  | 	Py_DECREF(m); | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | /* build blender specific system path for external modules */ | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | void init_syspath(void) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  | 	PyObject *path; | 
					
						
							|  |  |  | 	PyObject *m, *d; | 
					
						
							|  |  |  | 	PyObject *p; | 
					
						
							|  |  |  | 	char *c; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	char execdir[PATH_MAXCHAR], *progname; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	int n; | 
					
						
							|  |  |  | 	 | 
					
						
							|  |  |  | 	path = Py_BuildValue("s", bprogname); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	m = PyImport_ImportModule(MODNAME(BLENDERMODULE) ".sys"); | 
					
						
							|  |  |  | 	if (m) { | 
					
						
							|  |  |  | 		d = PyModule_GetDict(m); | 
					
						
							|  |  |  | 		PyDict_SetItemString(d, "progname", path); | 
					
						
							|  |  |  | 		Py_DECREF(m); | 
					
						
							|  |  |  | 	} else { | 
					
						
							|  |  |  | 		BPY_debug(("Warning: could not set Blender.sys.progname\n")); | 
					
						
							|  |  |  | 	}	 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	progname = BLI_last_slash(bprogname); /* looks for the last dir separator */ | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	c = Py_GetPath(); /* get python system path */ | 
					
						
							|  |  |  | 	PySys_SetPath(c); /* initialize */ | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	n = progname - bprogname;  | 
					
						
							|  |  |  | 	if (n > 0) { | 
					
						
							|  |  |  | 		strncpy(execdir, bprogname, n); | 
					
						
							|  |  |  | 		execdir[n] = '\0'; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 		p = Py_BuildValue("s", execdir); | 
					
						
							|  |  |  | 		syspath_append(p);  /* append to module search path */ | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 		/* set Blender.sys.progname */ | 
					
						
							|  |  |  | 	} else {	 | 
					
						
							|  |  |  | 		BPY_debug(("Warning: could not determine argv[0] path\n")); | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 	/* TODO look for the blender executable in the search path */ | 
					
						
							|  |  |  | 	BPY_debug(("append to syspath: %s\n", U.pythondir)); | 
					
						
							|  |  |  | 	if (U.pythondir) { | 
					
						
							|  |  |  | 		p = Py_BuildValue("s", U.pythondir); | 
					
						
							|  |  |  | 		syspath_append(p);  /* append to module search path */ | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 	BPY_debug(("append done\n")); | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | #define FILENAME_LENGTH 24
 | 
					
						
							|  |  |  | typedef struct _ScriptError { | 
					
						
							|  |  |  | 	char filename[FILENAME_LENGTH]; | 
					
						
							|  |  |  | 	int lineno; | 
					
						
							|  |  |  | } ScriptError; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | ScriptError g_script_error; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | int BPY_Err_getLinenumber() | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  | 	return g_script_error.lineno; | 
					
						
							|  |  |  | }	 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | const char *BPY_Err_getFilename() | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  | 	return g_script_error.filename; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | /** Returns (PyString) filename from a traceback object */ | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | PyObject *traceback_getFilename(PyObject *tb) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  | 	PyObject *v; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	v = PyObject_GetAttrString(tb, "tb_frame"); Py_DECREF(v); | 
					
						
							|  |  |  | 	v = PyObject_GetAttrString(v, "f_code"); Py_DECREF(v); | 
					
						
							|  |  |  | 	v = PyObject_GetAttrString(v, "co_filename");  | 
					
						
							|  |  |  | 	return v; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | /** Blender Python error handler. This catches the error and stores
 | 
					
						
							|  |  |  |   * filename and line number in a global | 
					
						
							|  |  |  |   */ | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | void BPY_Err_Handle(Text *text) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  | 	PyObject *exception, *err, *tb, *v; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	PyErr_Fetch(&exception, &err, &tb); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	if (!exception && !tb) { | 
					
						
							|  |  |  | 		printf("FATAL: spurious exception\n"); | 
					
						
							|  |  |  | 		return; | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	strcpy(g_script_error.filename, getName(text)); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	if (exception && PyErr_GivenExceptionMatches(exception, PyExc_SyntaxError)) { | 
					
						
							|  |  |  | 		// no traceback available when SyntaxError
 | 
					
						
							|  |  |  | 		PyErr_Restore(exception, err, tb); // takes away reference!
 | 
					
						
							|  |  |  | 		PyErr_Print(); | 
					
						
							|  |  |  | 		v = PyObject_GetAttrString(err, "lineno"); | 
					
						
							|  |  |  | 		g_script_error.lineno = PyInt_AsLong(v); | 
					
						
							|  |  |  | 		Py_XDECREF(v); | 
					
						
							|  |  |  | 		return;  | 
					
						
							|  |  |  | 	} else { | 
					
						
							|  |  |  | 		PyErr_NormalizeException(&exception, &err, &tb); | 
					
						
							|  |  |  | 		PyErr_Restore(exception, err, tb); // takes away reference!
 | 
					
						
							|  |  |  | 		PyErr_Print(); | 
					
						
							|  |  |  | 		tb = PySys_GetObject("last_traceback"); | 
					
						
							|  |  |  | 		Py_INCREF(tb); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | // check traceback objects and look for last traceback in the
 | 
					
						
							|  |  |  | // same text file. This is used to jump to the line of where the
 | 
					
						
							|  |  |  | // error occured. If the error occured in another text file or module,
 | 
					
						
							|  |  |  | // the last frame in the current file is adressed
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 		while (1) {	 | 
					
						
							|  |  |  | 			v = PyObject_GetAttrString(tb, "tb_next"); | 
					
						
							|  |  |  | 			if (v == Py_None ||  | 
					
						
							|  |  |  | 			  strcmp(PyString_AsString(traceback_getFilename(v)), getName(text))) | 
					
						
							|  |  |  | 				break; | 
					
						
							|  |  |  | 			Py_DECREF(tb); | 
					
						
							|  |  |  | 			tb = v; | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 		v = PyObject_GetAttrString(tb, "tb_lineno"); | 
					
						
							|  |  |  | 		g_script_error.lineno = PyInt_AsLong(v); | 
					
						
							|  |  |  | 		Py_XDECREF(v); | 
					
						
							|  |  |  | 		v = traceback_getFilename(tb); | 
					
						
							|  |  |  | 		strncpy(g_script_error.filename, PyString_AsString(v), FILENAME_LENGTH); | 
					
						
							|  |  |  | 		Py_XDECREF(v); | 
					
						
							|  |  |  | 		Py_DECREF(tb); | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | /** Runs a Python string in the global name space of the given dictionary
 | 
					
						
							|  |  |  |     'globaldict' */ | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | static PyObject *newGlobalDictionary(void) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  | 	PyObject *d = PyDict_New(); | 
					
						
							|  |  |  | 	PyDict_SetItemString(d, "__builtins__", PyEval_GetBuiltins()); | 
					
						
							|  |  |  | 	PyDict_SetItemString(d, "__name__", PyString_FromString("__main__")); | 
					
						
							|  |  |  | 	return d; | 
					
						
							|  |  |  | }	 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | static void releaseGlobalDictionary(PyObject *d) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  | 	BPY_debug(("--- CLEAR namespace\n")); | 
					
						
							|  |  |  | 	PyDict_Clear(d); | 
					
						
							|  |  |  | 	Py_DECREF(d); // release dictionary
 | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | PyObject *BPY_runPython(Text *text, PyObject *globaldict) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  | 	PyObject *ret; | 
					
						
							|  |  |  | 	char* buf = NULL; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	if (!text->compiled) | 
					
						
							|  |  |  | 	{ | 
					
						
							|  |  |  | 		buf = txt_to_buf(text); | 
					
						
							|  |  |  | 		/* bah, what a filthy hack -- removed */ | 
					
						
							|  |  |  | 		/*      strcat(buf, "\n"); */ | 
					
						
							|  |  |  | 		text->compiled = Py_CompileString(buf, getName(text), Py_file_input); | 
					
						
							|  |  |  | 		MEM_freeN(buf); | 
					
						
							|  |  |  | 		if (PyErr_Occurred()) | 
					
						
							|  |  |  | 		{ | 
					
						
							|  |  |  | 			BPY_free_compiled_text(text); | 
					
						
							|  |  |  | 			return 0; | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 	BPY_debug(("Run Python script \"%s\" ...\n", getName(text))); | 
					
						
							|  |  |  | 	ret = PyEval_EvalCode(text->compiled, globaldict, globaldict); | 
					
						
							|  |  |  | 	return ret; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | /** This function is executed whenever ALT+PKEY is pressed -> drawtext.c 
 | 
					
						
							|  |  |  |     It returns the global namespace dictionary of the script context | 
					
						
							|  |  |  | 	(which is created newly when CLEAR_NAMESPACE is defined). | 
					
						
							|  |  |  | 	This may be stored in the SpaceText instance to give control over | 
					
						
							|  |  |  | 	namespace persistence. Remember that the same script may be executed | 
					
						
							|  |  |  | 	in several windows.. | 
					
						
							|  |  |  | 	Namespace persistence is desired for scripts that use the GUI and | 
					
						
							|  |  |  | 	store callbacks to the current script. | 
					
						
							|  |  |  | */ | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | PyObject  *BPY_txt_do_python(SpaceText *st) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  | 	PyObject* d = NULL; | 
					
						
							|  |  |  | 	PyObject *ret; | 
					
						
							|  |  |  | 	Text *text = st->text; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	if (!text) | 
					
						
							|  |  |  | 	{ | 
					
						
							|  |  |  | 	  return NULL; | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	/* TODO: make this an option: */ | 
					
						
							|  |  |  | #ifdef CLEAR_NAMESPACE	
 | 
					
						
							|  |  |  | 	BPY_debug(("--- enable clear namespace\n")); | 
					
						
							|  |  |  | 	st->flags |= ST_CLEAR_NAMESPACE; | 
					
						
							|  |  |  | #endif
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | #ifdef CLEAR_NAMESPACE
 | 
					
						
							|  |  |  | 	d = newGlobalDictionary(); | 
					
						
							|  |  |  | #else
 | 
					
						
							|  |  |  | 	d = PyModule_GetDict(PyImport_AddModule("__main__")); | 
					
						
							|  |  |  | #endif	
 | 
					
						
							|  |  |  | 	 | 
					
						
							|  |  |  | 	ret = BPY_runPython(text, d); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	if (!ret) { | 
					
						
							|  |  |  | #ifdef CLEAR_NAMESPACE			
 | 
					
						
							|  |  |  | 		releaseGlobalDictionary(d); | 
					
						
							|  |  |  | #endif
 | 
					
						
							|  |  |  | 		BPY_Err_Handle(text); | 
					
						
							|  |  |  | 		Py_Finalize(); | 
					
						
							|  |  |  | 		initBPythonInterpreter(); | 
					
						
							|  |  |  | 		return NULL; | 
					
						
							|  |  |  | 	}	 | 
					
						
							|  |  |  | 	else | 
					
						
							|  |  |  | 		Py_DECREF(ret); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	/* The following lines clear the global name space of the python
 | 
					
						
							|  |  |  | 	 * interpreter. This is desired to release objects after execution | 
					
						
							|  |  |  | 	 * of a script (remember that each wrapper object increments the refcount | 
					
						
							|  |  |  | 	 * of the Blender Object.  | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	 * Exception: scripts that use the GUI rely on the | 
					
						
							|  |  |  | 	 * persistent global namespace, so they need a workaround: The namespace | 
					
						
							|  |  |  | 	 * is released when the GUI is exit. | 
					
						
							|  |  |  | 	 * See opy_draw.c:Method_Register() | 
					
						
							|  |  |  | 	 * | 
					
						
							|  |  |  | 	 */ | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | #ifdef CLEAR_NAMESPACE	
 | 
					
						
							|  |  |  | 	if (st->flags & ST_CLEAR_NAMESPACE) { | 
					
						
							|  |  |  | 		releaseGlobalDictionary(d); | 
					
						
							|  |  |  | 		garbage_collect(getGlobal()->main);  | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | #endif	
 | 
					
						
							|  |  |  | 	 | 
					
						
							|  |  |  | 	return d; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | /****************************************/ | 
					
						
							|  |  |  | /* SCRIPTLINKS                          */ | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | static void do_all_scriptlist(ListBase* list, short event) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  | 	ID *id; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	id = list->first; | 
					
						
							|  |  |  | 	while (id) | 
					
						
							|  |  |  | 	{ | 
					
						
							|  |  |  | 		BPY_do_pyscript (id, event); | 
					
						
							|  |  |  | 		id = id->next; | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | void BPY_do_all_scripts(short event) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  | 	do_all_scriptlist(getObjectList(), event); | 
					
						
							|  |  |  | 	do_all_scriptlist(getLampList(),   event); | 
					
						
							|  |  |  | 	do_all_scriptlist(getCameraList(), event); | 
					
						
							|  |  |  | 	do_all_scriptlist(getMaterialList(), event); | 
					
						
							|  |  |  | 	do_all_scriptlist(getWorldList(),  event); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	BPY_do_pyscript(&scene_getCurrent()->id, event); | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | char *event_to_name(short event) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  | 	switch (event) { | 
					
						
							|  |  |  | 	case SCRIPT_FRAMECHANGED: | 
					
						
							|  |  |  | 		return "FrameChanged"; | 
					
						
							|  |  |  | 	case SCRIPT_ONLOAD: | 
					
						
							|  |  |  | 		return "OnLoad"; | 
					
						
							|  |  |  | 	case SCRIPT_REDRAW: | 
					
						
							|  |  |  | 		return "Redraw"; | 
					
						
							|  |  |  | 	default: | 
					
						
							|  |  |  | 		return "Unknown"; | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | }	 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | void BPY_do_pyscript(ID *id, short event) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  | 	int         i, offset; | 
					
						
							|  |  |  | 	char        evName[24] = ""; | 
					
						
							|  |  |  | 	char*       structname = NULL; | 
					
						
							|  |  |  | 	ScriptLink* scriptlink; | 
					
						
							|  |  |  | 	PyObject *globaldict; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	switch(GET_ID_TYPE(id)) { | 
					
						
							|  |  |  | 	case ID_OB: structname= "Object"; break; | 
					
						
							|  |  |  | 	case ID_LA:  structname= "Lamp"; break; | 
					
						
							|  |  |  | 	case ID_CA:  structname= "Camera"; break; | 
					
						
							|  |  |  | 	case ID_MA:  structname= "Material"; break; | 
					
						
							|  |  |  | 	case ID_WO:  structname= "World"; break; | 
					
						
							|  |  |  | 	case ID_SCE: structname= "Scene"; break; | 
					
						
							|  |  |  | 	default: return; | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	offset = BLO_findstruct_offset(structname, "scriptlink"); | 
					
						
							|  |  |  | 	if (offset < 0) | 
					
						
							|  |  |  | 	{ | 
					
						
							|  |  |  | 		BPY_warn(("Internal error, unable to find script link\n")); | 
					
						
							|  |  |  | 		return; | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 	scriptlink = (ScriptLink*) (((char*)id) + offset); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	/* no script provided */ | 
					
						
							|  |  |  | 	if (!scriptlink->totscript) return; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | /* Debugging output */ | 
					
						
							|  |  |  | 	switch (event) | 
					
						
							|  |  |  | 	{ | 
					
						
							|  |  |  | 	case SCRIPT_FRAMECHANGED: | 
					
						
							|  |  |  | 		strcpy(evName, "SCRIPT_FRAMECHANGED"); | 
					
						
							|  |  |  | 		BPY_debug(("do_pyscript(%s, %s)\n", getIDName(id), evName));  | 
					
						
							|  |  |  | 		break; | 
					
						
							|  |  |  | 	case SCRIPT_ONLOAD: | 
					
						
							|  |  |  | 		strcpy(evName, "SCRIPT_ONLOAD"); | 
					
						
							|  |  |  | 		BPY_debug(("do_pyscript(%s, %s)\n", getIDName(id), evName));  | 
					
						
							|  |  |  | 		break; | 
					
						
							|  |  |  | 	case SCRIPT_REDRAW: | 
					
						
							|  |  |  | 		strcpy(evName, "SCRIPT_REDRAW"); | 
					
						
							|  |  |  | 		BPY_debug(("do_pyscript(%s, %s)\n", getIDName(id), evName)); | 
					
						
							|  |  |  | 		break; | 
					
						
							|  |  |  | 	default: | 
					
						
							|  |  |  | 		BPY_debug(("do_pyscript(): This should not happen !!!"));  | 
					
						
							|  |  |  | 		break; | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | /* END DEBUGGING */ | 
					
						
							|  |  |  | #ifndef SHAREDMODULE
 | 
					
						
							|  |  |  | 	set_scriptlinks(id, event); | 
					
						
							|  |  |  | #endif
 | 
					
						
							|  |  |  | 	disable_where_script(1); | 
					
						
							|  |  |  | 	for (i = 0; i < scriptlink->totscript; i++) | 
					
						
							|  |  |  | 	{ | 
					
						
							|  |  |  | 		if (scriptlink->flag[i] == event && scriptlink->scripts[i]) | 
					
						
							|  |  |  | 		{ | 
					
						
							|  |  |  | 			BPY_debug(("Evaluate script \"%s\" ...\n", | 
					
						
							|  |  |  | 				getIDName(scriptlink->scripts[i]))); | 
					
						
							|  |  |  | 			script_link_id = id; | 
					
						
							|  |  |  | #ifdef CLEAR_NAMESPACE
 | 
					
						
							|  |  |  | 			globaldict = newGlobalDictionary(); | 
					
						
							|  |  |  | #else
 | 
					
						
							|  |  |  | 			globaldict = PyModule_GetDict(PyImport_AddModule("__main__")); | 
					
						
							|  |  |  | #endif			
 | 
					
						
							|  |  |  | 			BPY_runPython((Text*) scriptlink->scripts[i], globaldict); | 
					
						
							|  |  |  | #ifdef CLEAR_NAMESPACE
 | 
					
						
							|  |  |  | 			releaseGlobalDictionary(globaldict); | 
					
						
							|  |  |  | #endif			
 | 
					
						
							|  |  |  | 			 | 
					
						
							|  |  |  | 			script_link_id = NULL; | 
					
						
							|  |  |  | 			BPY_debug(("... done\n")); | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | #ifndef SHAREDMODULE
 | 
					
						
							|  |  |  | 	release_scriptlinks(id); | 
					
						
							|  |  |  | #endif
 | 
					
						
							|  |  |  | 	disable_where_script(0); | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | void BPY_clear_bad_scriptlink(ID *id, Text *byebye) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  | 	ScriptLink* scriptlink; | 
					
						
							|  |  |  | 	int         offset = -1; | 
					
						
							|  |  |  | 	char*       structname = NULL; | 
					
						
							|  |  |  | 	int         i; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	switch (GET_ID_TYPE(id)) { | 
					
						
							|  |  |  | 	case ID_OB:  structname = "Object"; break; | 
					
						
							|  |  |  | 	case ID_LA:  structname = "Lamp"; break; | 
					
						
							|  |  |  | 	case ID_CA:  structname = "Camera"; break; | 
					
						
							|  |  |  | 	case ID_MA:  structname = "Material"; break; | 
					
						
							|  |  |  | 	case ID_WO:  structname = "World"; break; | 
					
						
							|  |  |  | 	case ID_SCE: structname = "Scene"; break; | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	if (!structname) return; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	offset= BLO_findstruct_offset(structname, "scriptlink"); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	if (offset<0) return; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	scriptlink= (ScriptLink *) (((char *)id) + offset); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	for(i=0; i<scriptlink->totscript; i++) | 
					
						
							|  |  |  | 	if ((Text*)scriptlink->scripts[i] == byebye) | 
					
						
							|  |  |  | 		scriptlink->scripts[i] = NULL; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | void BPY_clear_bad_scriptlist(ListBase *list, Text *byebye) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  | 	ID *id; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	id= list->first; | 
					
						
							|  |  |  | 	while (id) | 
					
						
							|  |  |  | 	{ | 
					
						
							|  |  |  | 		BPY_clear_bad_scriptlink(id, byebye); | 
					
						
							|  |  |  | 		id= id->next; | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | void BPY_clear_bad_scriptlinks(Text *byebye) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  | 	BPY_clear_bad_scriptlist(getObjectList(),	byebye); | 
					
						
							|  |  |  | 	BPY_clear_bad_scriptlist(getLampList(),	byebye); | 
					
						
							|  |  |  | 	BPY_clear_bad_scriptlist(getCameraList(),	byebye); | 
					
						
							|  |  |  | 	BPY_clear_bad_scriptlist(getMaterialList(),	byebye); | 
					
						
							|  |  |  | 	BPY_clear_bad_scriptlist(getWorldList(),	byebye); | 
					
						
							|  |  |  | 	BPY_clear_bad_scriptlink(&scene_getCurrent()->id,    byebye); | 
					
						
							|  |  |  | 	allqueue(REDRAWBUTSSCRIPT, 0); | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | void BPY_free_scriptlink(ScriptLink *slink) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  | 	if (slink->totscript) | 
					
						
							|  |  |  | 	{ | 
					
						
							|  |  |  | 		if(slink->flag) MEM_freeN(slink->flag); | 
					
						
							|  |  |  | 		if(slink->scripts) MEM_freeN(slink->scripts); | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | void BPY_copy_scriptlink(ScriptLink *scriptlink) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  | 	void *tmp; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	if (scriptlink->totscript) | 
					
						
							|  |  |  | 	{ | 
					
						
							|  |  |  | 		tmp = scriptlink->scripts; | 
					
						
							|  |  |  | 		scriptlink->scripts = MEM_mallocN(sizeof(ID*)*scriptlink->totscript, "scriptlistL"); | 
					
						
							|  |  |  | 		memcpy(scriptlink->scripts, tmp, sizeof(ID*)*scriptlink->totscript); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 		tmp = scriptlink->flag; | 
					
						
							|  |  |  | 		scriptlink->flag = MEM_mallocN(sizeof(short)*scriptlink->totscript, "scriptlistF"); | 
					
						
							|  |  |  | 		memcpy(scriptlink->flag, tmp, sizeof(short)*scriptlink->totscript); | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | /*
 | 
					
						
							|  |  |  |  *  Python alien graphics format conversion framework | 
					
						
							|  |  |  |  * | 
					
						
							|  |  |  |  *  $Id$ | 
					
						
							|  |  |  |  * | 
					
						
							|  |  |  |  *	 | 
					
						
							|  |  |  |  * | 
					
						
							|  |  |  |  */ | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | /* import importloader module with registered importers */ | 
					
						
							|  |  |  | #include "BPY_extern.h"
 | 
					
						
							|  |  |  | #include "Python.h"
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | int BPY_call_importloader(char *name) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  | 	PyObject *mod, *tmp, *meth, *args; | 
					
						
							|  |  |  | 	int i, success = 0; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	init_syspath(); | 
					
						
							|  |  |  | 	mod = PyImport_ImportModule("Converter.importloader"); | 
					
						
							|  |  |  | 	if (mod) { | 
					
						
							|  |  |  | 		meth = PyObject_GetAttrString(mod, "process"); // new ref
 | 
					
						
							|  |  |  | 		args = Py_BuildValue("(s)", name); | 
					
						
							|  |  |  | 		tmp = PyEval_CallObject(meth, args); | 
					
						
							|  |  |  | 		Py_DECREF(meth); | 
					
						
							|  |  |  | 		if (PyErr_Occurred()) { | 
					
						
							|  |  |  | 			PyErr_Print(); | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 		if (tmp) {  | 
					
						
							|  |  |  | 			i = PyInt_AsLong(tmp); | 
					
						
							|  |  |  | 			if (i)  | 
					
						
							|  |  |  | 				success = 1; | 
					
						
							|  |  |  | 			Py_DECREF(tmp); | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 		Py_DECREF(mod); | 
					
						
							|  |  |  | 	} else { | 
					
						
							|  |  |  | 		PyErr_Print(); | 
					
						
							|  |  |  | 		BPY_warn(("couldn't import 'importloader' \n")); | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 	return success; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | // more to come...
 |