Python API
[blender.git] / source / blender / python / api2_2x / Blender.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, Joseph Gilbert,
29  * Campbell Barton
30  *
31  * ***** END GPL/BL DUAL LICENSE BLOCK *****
32 */
33 struct ID; /*keep me up here */
34
35 #include "Blender.h" /*This must come first */
36
37 /* for open, close in Blender_Load */
38 #include <fcntl.h>
39 #include "BDR_editobject.h"     /* exit_editmode() */
40 #include "BDR_drawmesh.h"       /* set_mipmap() */
41 #include "BIF_usiblender.h"
42 #include "BLI_blenlib.h"
43 #include "BLO_writefile.h"
44 #include "BKE_blender.h"
45 #include "BKE_exotic.h"
46 #include "BKE_global.h"
47 #include "BKE_packedFile.h"
48 #include "BKE_utildefines.h"
49 #include "BKE_object.h"
50 #include "BKE_scene.h"
51 #include "BKE_text.h"
52 #include "BKE_ipo.h"
53 #include "BKE_library.h"
54 #include "BKE_main.h"
55 #include "BPI_script.h"
56 #include "BSE_headerbuttons.h"
57 #include "DNA_screen_types.h"   /* for SPACE_VIEW3D */
58 #include "DNA_userdef_types.h"
59 #include "DNA_packedFile_types.h"
60 #include "EXPP_interface.h" /* for bpy_gethome() */
61 #include "gen_utils.h"
62 #include "modules.h"
63 #include "constant.h"
64 #include "../BPY_extern.h" /* BPY_txt_do_python_Text */
65 #include "../BPY_menus.h"       /* to update menus */
66 #include "Armature.h"
67 #include "BezTriple.h"
68 #include "Camera.h"
69 #include "Constraint.h"
70 #include "Curve.h"
71 #include "CurNurb.h"
72 #include "Draw.h"
73 #include "Effect.h"
74 #include "Ipo.h"
75 #include "Ipocurve.h"
76 #include "IDProp.h"
77 #include "Key.h"
78 #include "Lamp.h"
79 #include "Lattice.h"
80 #include "Library.h"
81 #include "Mathutils.h"
82 #include "Geometry.h"
83 #include "Mesh.h"
84 #include "Metaball.h"
85 #include "Modifier.h"
86 #include "NMesh.h"
87 #include "Object.h"
88 #include "Group.h"
89 #include "Registry.h"
90 #include "Scene.h"
91 #include "Sound.h"
92 #include "SurfNurb.h"
93 #include "Sys.h"
94 #include "Text.h"
95 #include "Texture.h"
96 #include "Window.h"
97 #include "World.h"
98 #include "Types.h"
99
100 /**********************************************************/
101 /* Python API function prototypes for the Blender module.       */
102 /**********************************************************/
103 static PyObject *Blender_Set( PyObject * self, PyObject * args );
104 static PyObject *Blender_Get( PyObject * self, PyObject * value );
105 static PyObject *Blender_Redraw( PyObject * self, PyObject * args );
106 static PyObject *Blender_Quit( PyObject * self );
107 static PyObject *Blender_Load( PyObject * self, PyObject * args );
108 static PyObject *Blender_Save( PyObject * self, PyObject * args );
109 static PyObject *Blender_Run( PyObject * self, PyObject * value );
110 static PyObject *Blender_ShowHelp( PyObject * self, PyObject * script );
111 static PyObject *Blender_UpdateMenus( PyObject * self);
112 static PyObject *Blender_PackAll( PyObject * self);
113 static PyObject *Blender_UnpackAll( PyObject * self, PyObject * value);
114 static PyObject *Blender_CountPackedFiles( PyObject * self );
115
116 extern PyObject *Text3d_Init( void ); /* missing in some include */
117
118 /*****************************************************************************/
119 /* The following string definitions are used for documentation strings.  */
120 /* In Python these will be written to the console when doing a           */
121 /* Blender.__doc__       */
122 /*****************************************************************************/
123 static char Blender_Set_doc[] =
124         "(request, data) - Update settings in Blender\n\
125 \n\
126 (request) A string identifying the setting to change\n\
127         'curframe'      - Sets the current frame using the number in data";
128
129 static char Blender_Get_doc[] = "(request) - Retrieve settings from Blender\n\
130 \n\
131 (request) A string indentifying the data to be returned\n\
132         'curframe'      - Returns the current animation frame\n\
133         'curtime'       - Returns the current animation time\n\
134         'staframe'      - Returns the start frame of the animation\n\
135         'endframe'      - Returns the end frame of the animation\n\
136         'filename'      - Returns the name of the last file read or written\n\
137         'homedir' - Returns Blender's home dir\n\
138         'datadir' - Returns the dir where scripts can save their data, if available\n\
139         'scriptsdir' - Returns the main dir where scripts are kept, if available\n\
140         'uscriptsdir' - Returns the user defined dir for scripts, if available\n\
141         'version'       - Returns the Blender version number";
142
143 static char Blender_Redraw_doc[] = "() - Redraw all 3D windows";
144
145 static char Blender_Quit_doc[] =
146         "() - Quit Blender.  The current data is saved as 'quit.blend' before leaving.";
147
148 static char Blender_Load_doc[] = "(filename) - Load the given file.\n\
149 Supported formats:\n\
150 Blender, DXF, Inventor 1.0 ASCII, VRML 1.0 asc, STL, Videoscape, radiogour.\n\
151 \n\
152 Notes:\n\
153 1 - () - an empty argument loads the default .B.blend file;\n\
154 2 - if the substring '.B.blend' occurs inside 'filename', the default\n\
155 .B.blend file is loaded;\n\
156 3 - If a Blender file is loaded the script ends immediately.\n\
157 4 - The current data is always preserved as an autosave file, for safety;\n\
158 5 - This function only works if the script where it's executed is the\n\
159 only one running at the moment.";
160
161 static char Blender_Save_doc[] =
162         "(filename) - Save data to a file based on the filename's extension.\n\
163 Supported are: Blender's .blend and the builtin exporters:\n\
164 VRML 1.0 (.wrl), Videoscape (.obj), DXF (.dxf) and STL (.stl)\n\
165 (filename) - A filename with one of the supported extensions.\n\
166 Note 1: 'filename' should not contain the substring \".B.blend\" in it.\n\
167 Note 2: only .blend raises an error if file wasn't saved.\n\
168 \tYou can use Blender.sys.exists(filename) to make sure the file was saved\n\
169 \twhen writing to one of the other formats.";
170
171 static char Blender_Run_doc[] =
172         "(script) - Run the given Python script.\n\
173 (script) - the path to a file or the name of an available Blender Text.";
174
175 static char Blender_ShowHelp_doc[] =
176 "(script) - Show help for the given Python script.\n\
177   This will try to open the 'Scripts Help Browser' script, so to have\n\
178 any help displayed the passed 'script' must be properly documented\n\
179 with the expected strings (check API ref docs or any bundled script\n\
180 for examples).\n\n\
181 (script) - the filename of a script in the default or user defined\n\
182            scripts dir (no need to supply the full path name)."; 
183
184 static char Blender_UpdateMenus_doc[] =
185         "() - Update the menus where scripts are registered.  Only needed for\n\
186 scripts that save other new scripts in the default or user defined folders.";
187
188 static char Blender_PackAll_doc[] =
189 "() - Pack all files.\n\
190 All files will packed into the blend file.";
191 static char Blender_UnpackAll_doc[] =
192 "(mode) - Unpack files.\n\
193 All files will be unpacked using specified mode.\n\n\
194 (mode) - the unpack mode.";
195
196 static char Blender_CountPackedFiles_doc[] =
197 "() - Returns the number of packed files.";
198
199 /*****************************************************************************/
200 /* Python method structure definition.           */
201 /*****************************************************************************/
202 static struct PyMethodDef Blender_methods[] = {
203         {"Set", Blender_Set, METH_VARARGS, Blender_Set_doc},
204         {"Get", Blender_Get, METH_O, Blender_Get_doc},
205         {"Redraw", Blender_Redraw, METH_VARARGS, Blender_Redraw_doc},
206         {"Quit", ( PyCFunction ) Blender_Quit, METH_NOARGS, Blender_Quit_doc},
207         {"Load", Blender_Load, METH_VARARGS, Blender_Load_doc},
208         {"Save", Blender_Save, METH_VARARGS, Blender_Save_doc},
209         {"Run", Blender_Run, METH_O, Blender_Run_doc},
210         {"ShowHelp", Blender_ShowHelp, METH_O, Blender_ShowHelp_doc},
211         {"CountPackedFiles", ( PyCFunction ) Blender_CountPackedFiles, METH_NOARGS, Blender_CountPackedFiles_doc},
212         {"PackAll", ( PyCFunction ) Blender_PackAll, METH_NOARGS, Blender_PackAll_doc},
213         {"UnpackAll", Blender_UnpackAll, METH_O, Blender_UnpackAll_doc},
214         {"UpdateMenus", ( PyCFunction ) Blender_UpdateMenus, METH_NOARGS,
215          Blender_UpdateMenus_doc},
216         {NULL, NULL, 0, NULL}
217 };
218
219 /*****************************************************************************/
220 /* Global variables      */
221 /*****************************************************************************/
222 PyObject *g_blenderdict;
223
224 /*****************************************************************************/
225 /* Function:    Blender_Set              */
226 /* Python equivalent:   Blender.Set              */
227 /*****************************************************************************/
228 static PyObject *Blender_Set( PyObject * self, PyObject * args )
229 {
230         char *name, *dir = NULL;
231         PyObject *arg;
232
233         if( !PyArg_ParseTuple( args, "sO", &name, &arg ) )
234                 return EXPP_ReturnPyObjError( PyExc_ValueError, "expected 2 args, where the first is always a string" );
235
236         if( StringEqual( name, "curframe" ) ) {
237                 if( !PyInt_Check( arg ) )
238                         return EXPP_ReturnPyObjError( PyExc_ValueError,
239                                         "expected an integer" );
240
241                 G.scene->r.cfra = (short)PyInt_AsLong( arg ) ;
242
243                 /*      update all objects, so python scripts can export all objects
244                  in a scene without worrying about the view layers */
245                 scene_update_for_newframe(G.scene, (1<<20) - 1);
246                 
247         } else if (StringEqual( name , "uscriptsdir" ) ) {
248                 if ( !PyArg_Parse( arg , "s" , &dir ))
249                         return EXPP_ReturnPyObjError( PyExc_ValueError, "expected a string" );
250                 BLI_strncpy(U.pythondir, dir, FILE_MAXDIR);
251         } else if (StringEqual( name , "yfexportdir" ) ) {
252                 if ( !PyArg_Parse( arg , "s" , &dir ))
253                         return EXPP_ReturnPyObjError( PyExc_ValueError, "expected a string" );
254                 BLI_strncpy(U.yfexportdir, dir, FILE_MAXDIR);           
255         } else if (StringEqual( name , "fontsdir" ) ) {
256                 if ( !PyArg_Parse( arg , "s" , &dir ))
257                         return EXPP_ReturnPyObjError( PyExc_ValueError, "expected a string" );
258                 BLI_strncpy(U.fontdir, dir, FILE_MAXDIR);
259         } else if (StringEqual( name , "texturesdir" ) ) {
260                 if ( !PyArg_Parse( arg , "s" , &dir ))
261                         return EXPP_ReturnPyObjError( PyExc_ValueError, "expected a string" );
262                 BLI_strncpy(U.textudir, dir, FILE_MAXDIR);
263         } else if (StringEqual( name , "texpluginsdir" ) ) {
264                 if ( !PyArg_Parse( arg , "s" , &dir ))
265                         return EXPP_ReturnPyObjError( PyExc_ValueError, "expected a string" );
266                 BLI_strncpy(U.plugtexdir, dir, FILE_MAXDIR);
267         } else if (StringEqual( name , "seqpluginsdir" ) ) {
268                 if ( !PyArg_Parse( arg , "s" , &dir ))
269                         return EXPP_ReturnPyObjError( PyExc_ValueError, "expected a string" );
270                 BLI_strncpy(U.plugseqdir, dir, FILE_MAXDIR);
271         } else if (StringEqual( name , "renderdir" ) ) {
272                 if ( !PyArg_Parse( arg , "s" , &dir ))
273                         return EXPP_ReturnPyObjError( PyExc_ValueError, "expected a string" );
274                 BLI_strncpy(U.renderdir, dir, FILE_MAXDIR);
275         } else if (StringEqual( name , "soundsdir" ) ) {
276                 if ( !PyArg_Parse( arg , "s" , &dir ))
277                         return EXPP_ReturnPyObjError( PyExc_ValueError, "expected a string" );
278                 BLI_strncpy(U.sounddir, dir, FILE_MAXDIR);
279         } else if (StringEqual( name , "tempdir" ) ) {
280                 if ( !PyArg_Parse( arg , "s" , &dir ))
281                         return EXPP_ReturnPyObjError( PyExc_ValueError, "expected a string" );
282                 BLI_strncpy(U.tempdir, dir, FILE_MAXDIR);
283         } else if (StringEqual( name , "compressfile" ) ) {
284                 int value = PyObject_IsTrue( arg );
285                 
286                 if (value==-1)
287                         return EXPP_ReturnPyObjError( PyExc_ValueError,
288                                         "expected an integer" );
289                 
290                 if (value)
291                         U.flag |= USER_FILECOMPRESS;
292                 else
293                         U.flag &= ~USER_FILECOMPRESS;
294         } else if (StringEqual( name , "mipmap" ) ) {
295                 int value = PyObject_IsTrue( arg );
296                 
297                 if (value==-1)
298                         return EXPP_ReturnPyObjError( PyExc_ValueError,
299                                         "expected an integer" );
300                 
301                 if (value)
302                         U.gameflags &= ~USER_DISABLE_MIPMAP;
303                 else
304                         U.gameflags |= USER_DISABLE_MIPMAP;
305                 
306                 set_mipmap(!(U.gameflags & USER_DISABLE_MIPMAP));
307         }else
308                 return ( EXPP_ReturnPyObjError( PyExc_AttributeError,
309                                                 "value given is not a blender setting" ) );
310         Py_RETURN_NONE;
311 }
312
313 /*****************************************************************************/
314 /* Function:            Blender_Get      */
315 /* Python equivalent:   Blender.Get              */
316 /*****************************************************************************/
317 static PyObject *Blender_Get( PyObject * self, PyObject * value )
318 {
319         PyObject *ret = NULL;
320         char *str = PyString_AsString(value);
321
322         if( !str )
323                 return EXPP_ReturnPyObjError (PyExc_TypeError,
324                         "expected string argument");
325
326         if( StringEqual( str, "curframe" ) )
327                 ret = PyInt_FromLong( G.scene->r.cfra );
328         else if( StringEqual( str, "curtime" ) )
329                 ret = PyFloat_FromDouble( frame_to_float( G.scene->r.cfra ) );
330         else if( StringEqual( str, "rt" ) )
331                 ret = PyInt_FromLong( (long)frame_to_float( G.rt ) );
332         else if( StringEqual( str, "staframe" ) )
333                 ret = PyInt_FromLong( G.scene->r.sfra );
334         else if( StringEqual( str, "endframe" ) )
335                 ret = PyInt_FromLong( G.scene->r.efra );
336         else if( StringEqual( str, "filename" ) ) {
337                 if ( strstr(G.main->name, ".B.blend") != 0)
338                         ret = PyString_FromString("");
339                 else
340                         ret = PyString_FromString(G.main->name);
341         }
342         else if( StringEqual( str, "homedir" ) ) {
343                 char *hdir = bpy_gethome(0);
344                 if( hdir && BLI_exists( hdir ))
345                         ret = PyString_FromString( hdir );
346                 else
347                         ret = EXPP_incr_ret( Py_None );
348         }
349         else if( StringEqual( str, "datadir" ) ) {
350                 char datadir[FILE_MAXDIR];
351                 char *sdir = bpy_gethome(1);
352
353                 if (sdir) {
354                         BLI_make_file_string( "/", datadir, sdir, "bpydata" );
355                         if( BLI_exists( datadir ) )
356                                 ret = PyString_FromString( datadir );
357                 }
358                 if (!ret) ret = EXPP_incr_ret( Py_None );
359         }
360         else if(StringEqual(str, "udatadir")) {
361                 if (U.pythondir[0] != '\0') {
362                         char upydir[FILE_MAXDIR];
363
364                         BLI_strncpy(upydir, U.pythondir, FILE_MAXDIR);
365                         BLI_convertstringcode(upydir, G.sce, 0);
366
367                         if (BLI_exists(upydir)) {
368                                 char udatadir[FILE_MAXDIR];
369
370                                 BLI_make_file_string("/", udatadir, upydir, "bpydata");
371
372                                 if (BLI_exists(udatadir))
373                                         ret = PyString_FromString(udatadir);
374                         }
375                 }
376                 if (!ret) ret = EXPP_incr_ret(Py_None);
377         }
378         else if( StringEqual( str, "scriptsdir" ) ) {
379                 char *sdir = bpy_gethome(1);
380
381                 if (sdir)
382                         ret = PyString_FromString(sdir);
383                 else
384                         ret = EXPP_incr_ret( Py_None );
385         }
386         else if( StringEqual( str, "uscriptsdir" ) ) {
387                 if (U.pythondir[0] != '\0') {
388                         char upydir[FILE_MAXDIR];
389
390                         BLI_strncpy(upydir, U.pythondir, FILE_MAXDIR);
391                         BLI_convertstringcode(upydir, G.sce, 0);
392
393                         if( BLI_exists( upydir ) )
394                                 ret = PyString_FromString( upydir );
395                 }
396                 if (!ret) ret = EXPP_incr_ret(Py_None);
397         }
398         /* USER PREFS: */
399         else if( StringEqual( str, "yfexportdir" ) ) {
400                 if (U.yfexportdir[0] != '\0') {
401                         char yfexportdir[FILE_MAXDIR];
402
403                         BLI_strncpy(yfexportdir, U.yfexportdir, FILE_MAXDIR);
404                         BLI_convertstringcode(yfexportdir, G.sce, 0);
405
406                         if( BLI_exists( yfexportdir ) )
407                                 ret = PyString_FromString( yfexportdir );
408                 }
409                 if (!ret) ret = EXPP_incr_ret(Py_None);
410         }
411         /* fontsdir */
412         else if( StringEqual( str, "fontsdir" ) ) {
413                 if (U.fontdir[0] != '\0') {
414                         char fontdir[FILE_MAXDIR];
415
416                         BLI_strncpy(fontdir, U.fontdir, FILE_MAXDIR);
417                         BLI_convertstringcode(fontdir, G.sce, 0);
418
419                         if( BLI_exists( fontdir ) )
420                                 ret = PyString_FromString( fontdir );
421                 }
422                 if (!ret) ret = EXPP_incr_ret(Py_None);
423         }       
424         /* texturesdir */
425         else if( StringEqual( str, "texturesdir" ) ) {
426                 if (U.textudir[0] != '\0') {
427                         char textudir[FILE_MAXDIR];
428
429                         BLI_strncpy(textudir, U.textudir, FILE_MAXDIR);
430                         BLI_convertstringcode(textudir, G.sce, 0);
431
432                         if( BLI_exists( textudir ) )
433                                 ret = PyString_FromString( textudir );
434                 }
435                 if (!ret) ret = EXPP_incr_ret(Py_None);
436         }               
437         /* texpluginsdir */
438         else if( StringEqual( str, "texpluginsdir" ) ) {
439                 if (U.plugtexdir[0] != '\0') {
440                         char plugtexdir[FILE_MAXDIR];
441
442                         BLI_strncpy(plugtexdir, U.plugtexdir, FILE_MAXDIR);
443                         BLI_convertstringcode(plugtexdir, G.sce, 0);
444
445                         if( BLI_exists( plugtexdir ) )
446                                 ret = PyString_FromString( plugtexdir );
447                 }
448                 if (!ret) ret = EXPP_incr_ret(Py_None);
449         }                       
450         /* seqpluginsdir */
451         else if( StringEqual( str, "seqpluginsdir" ) ) {
452                 if (U.plugseqdir[0] != '\0') {
453                         char plugseqdir[FILE_MAXDIR];
454
455                         BLI_strncpy(plugseqdir, U.plugseqdir, FILE_MAXDIR);
456                         BLI_convertstringcode(plugseqdir, G.sce, 0);
457
458                         if( BLI_exists( plugseqdir ) )
459                                 ret = PyString_FromString( plugseqdir );
460                 }
461                 if (!ret) ret = EXPP_incr_ret(Py_None);
462         }                       
463         /* renderdir */
464         else if( StringEqual( str, "renderdir" ) ) {
465                 if (U.renderdir[0] != '\0') {
466                         char renderdir[FILE_MAXDIR];
467
468                         BLI_strncpy(renderdir, U.renderdir, FILE_MAXDIR);
469                         BLI_convertstringcode(renderdir, G.sce, 0);
470
471                         if( BLI_exists( renderdir ) )
472                                 ret = PyString_FromString( renderdir );
473                 }
474                 if (!ret) ret = EXPP_incr_ret(Py_None);
475         }               
476         /* soundsdir */
477         else if( StringEqual( str, "soundsdir" ) ) {
478                 if (U.sounddir[0] != '\0') {
479                         char sounddir[FILE_MAXDIR];
480
481                         BLI_strncpy(sounddir, U.sounddir, FILE_MAXDIR);
482                         BLI_convertstringcode(sounddir, G.sce, 0);
483
484                         if( BLI_exists( sounddir ) )
485                                 ret = PyString_FromString( sounddir );
486                 }
487                 if (!ret) ret = EXPP_incr_ret(Py_None);
488         }               
489         /* tempdir */
490         else if( StringEqual( str, "tempdir" ) ) {
491                 if (U.tempdir[0] != '\0') {
492                         char tempdir[FILE_MAXDIR];
493
494                         BLI_strncpy(tempdir, U.tempdir, FILE_MAXDIR);
495                         BLI_convertstringcode(tempdir, G.sce, 0);
496
497                         if( BLI_exists( tempdir ) )
498                                 ret = PyString_FromString( tempdir );
499                 }
500                 if (!ret) ret = EXPP_incr_ret(Py_None);
501         }
502         /* icondir */
503         else if( StringEqual( str, "icondir" ) ) {
504                 
505                 char icondirstr[FILE_MAXDIR];
506
507                 #ifdef WIN32
508                         BLI_make_file_string("/", icondirstr, BLI_gethome(), "icons");
509                 #else
510                         BLI_make_file_string("/", icondirstr, BLI_gethome(), ".blender/icons");
511                 #endif
512
513                 if( BLI_exists( icondirstr ) )
514                         ret = PyString_FromString( icondirstr );
515                 
516                 if (!ret) ret = EXPP_incr_ret(Py_None);
517         }
518         /* According to the old file (opy_blender.c), the following if
519            statement is a quick hack and needs some clean up. */
520         else if( StringEqual( str, "vrmloptions" ) ) {
521                 ret = PyDict_New(  );
522
523                 EXPP_dict_set_item_str( ret, "twoside",
524                         PyInt_FromLong( U.vrmlflag & USER_VRML_TWOSIDED ) );
525
526                 EXPP_dict_set_item_str( ret, "layers",
527                         PyInt_FromLong( U.vrmlflag & USER_VRML_LAYERS ) );
528
529                 EXPP_dict_set_item_str( ret, "autoscale",
530                         PyInt_FromLong( U.vrmlflag & USER_VRML_AUTOSCALE ) );
531
532         } /* End 'quick hack' part. */
533         else if(StringEqual( str, "version" ))
534                 ret = PyInt_FromLong( G.version );
535                 
536         else if(StringEqual( str, "compressfile" ))
537                 ret = PyInt_FromLong( (U.flag & USER_FILECOMPRESS) >> 15  );
538         else if(StringEqual( str, "mipmap" ))
539                 ret = PyInt_FromLong( (U.gameflags & USER_DISABLE_MIPMAP) == 0  );
540         else
541                 return EXPP_ReturnPyObjError( PyExc_AttributeError, "unknown attribute" );
542
543         if (ret) return ret;
544         else
545                 return EXPP_ReturnPyObjError (PyExc_MemoryError,
546                         "could not create the PyObject!");
547 }
548
549 /*****************************************************************************/
550 /* Function:            Blender_Redraw           */
551 /* Python equivalent:   Blender.Redraw                   */
552 /*****************************************************************************/
553 static PyObject *Blender_Redraw( PyObject * self, PyObject * args )
554 {
555         return M_Window_Redraw( self, args );
556 }
557
558 /*****************************************************************************/
559 /* Function:            Blender_Quit             */
560 /* Python equivalent:   Blender.Quit                     */
561 /*****************************************************************************/
562 static PyObject *Blender_Quit( PyObject * self )
563 {
564         BIF_write_autosave(  ); /* save the current data first */
565
566         exit_usiblender(  );    /* renames last autosave to quit.blend */
567
568         Py_RETURN_NONE;
569 }
570
571 /**
572  * Blender.Load
573  * loads Blender's .blend, DXF, radiogour(?), STL, Videoscape,
574  * Inventor 1.0 ASCII, VRML 1.0 asc.
575  */
576 static PyObject *Blender_Load( PyObject * self, PyObject * args )
577 {
578         char *fname = NULL;
579         int keep_oldfname = 0;
580         Script *script = NULL;
581         char str[32], name[FILE_MAXDIR];
582         int file, is_blend_file = 0;
583
584         if( !PyArg_ParseTuple( args, "|si", &fname, &keep_oldfname ) )
585                 return EXPP_ReturnPyObjError( PyExc_TypeError,
586                         "expected filename and optional int or nothing as arguments" );
587
588         if( fname ) {
589                 if( strlen( fname ) > FILE_MAXDIR )     /* G.main->name's max length */
590                         return EXPP_ReturnPyObjError( PyExc_AttributeError,
591                                                       "filename too long!" );
592                 else if( !BLI_exists( fname ) )
593                         return EXPP_ReturnPyObjError( PyExc_AttributeError,
594                                                       "requested file doesn't exist!" );
595
596                 if( keep_oldfname )
597                         BLI_strncpy( name, G.sce, FILE_MAXDIR );
598         }
599
600         /* We won't let a new .blend file be loaded if there are still other
601          * scripts running, since loading a new file will close and remove them. */
602
603         if( G.main->script.first != G.main->script.last )
604                 return EXPP_ReturnPyObjError( PyExc_RuntimeError,
605                                               "there are other scripts running at the Scripts win, close them first!" );
606
607         if( fname ) {
608                 file = open( fname, O_BINARY | O_RDONLY );
609
610                 if( file <= 0 ) {
611                         return EXPP_ReturnPyObjError( PyExc_RuntimeError,
612                                                       "cannot open file!" );
613                 } else {
614                         read( file, str, 31 );
615                         close( file );
616
617                         if( strncmp( str, "BLEN", 4 ) == 0 )
618                                 is_blend_file = 1;
619                 }
620         } else
621                 is_blend_file = 1;      /* no arg given means default: .B.blend */
622
623         if( is_blend_file ) {
624
625                 int during_slink = during_scriptlink(  );
626
627                 /* when loading a .blend file from a scriptlink, the scriptlink pointer
628                  * in BPY_do_pyscript becomes invalid during a loop.  Inform it here.
629                  * Also do not allow a nested scriptlink (called from inside another)
630                  * to load .blend files, to avoid nasty problems. */
631                 if( during_slink >= 1 ) {
632                         if( during_slink == 1 )
633                                 disable_where_scriptlink( -1 );
634                         else {
635                                 return EXPP_ReturnPyObjError
636                                         ( PyExc_EnvironmentError,
637                                           "Blender.Load: cannot load .blend files from a nested scriptlink." );
638                         }
639                 }
640
641                 /* trick: mark the script so that its script struct won't be freed after
642                  * the script is executed (to avoid a double free warning on exit): */
643                 script = G.main->script.first;
644                 if( script )
645                         script->flags |= SCRIPT_GUI;
646
647                 BIF_write_autosave(  ); /* for safety let's preserve the current data */
648         }
649
650         if( G.obedit )
651                 exit_editmode(EM_FREEDATA);
652
653         if (G.background) { /* background mode */
654                 if (is_blend_file)
655                         BKE_read_file(fname, NULL);
656                 else {
657                         return EXPP_ReturnPyObjError(PyExc_AttributeError,
658                                 "only .blend files can be loaded from command line,\n\
659         other file types require interactive mode.");
660                 }
661         }
662         else { /* interactive mode */
663                 /* for safety, any filename with .B.blend is considered the default one.
664                  * It doesn't seem necessary to compare file attributes (like st_ino and
665                  * st_dev, according to the glibc info pages) to find out if the given
666                  * filename, that may have been given with a twisted misgiving path, is the
667                  * default one for sure.  Taking any .B.blend file as the default is good
668                  * enough here.  Note: the default file requires extra clean-up done by
669                  * BIF_read_homefile: freeing the user theme data. */
670                 if( !fname || ( strstr( fname, ".B.blend" ) && is_blend_file ) )
671                         BIF_read_homefile(0);
672                 else
673                         BIF_read_file( fname );
674
675                 if( fname && keep_oldfname ) {
676                         /*BLI_strncpy(G.main->name, name, FILE_MAXDIR); */
677                         BLI_strncpy( G.sce, name, FILE_MAXDIR );
678                 }
679         }
680
681         Py_RETURN_NONE;
682 }
683
684 static PyObject *Blender_Save( PyObject * self, PyObject * args )
685 {
686         char *fname = NULL;
687         int overwrite = 0, len = 0;
688         char *error = NULL;
689         Library *li;
690
691         if( !PyArg_ParseTuple( args, "s|i", &fname, &overwrite ) )
692                 return EXPP_ReturnPyObjError( PyExc_TypeError,
693                                               "expected filename and optional int (overwrite flag) as arguments" );
694
695         for( li = G.main->library.first; li; li = li->id.next ) {
696                 if( BLI_streq( li->name, fname ) ) {
697                         return EXPP_ReturnPyObjError( PyExc_AttributeError,
698                                                       "cannot overwrite used library" );
699                 }
700         }
701
702         /* for safety, any filename with .B.blend is considered the default one
703          * and not accepted here. */
704         if( strstr( fname, ".B.blend" ) )
705                 return EXPP_ReturnPyObjError( PyExc_AttributeError,
706                                               "filename can't contain the substring \".B.blend\" in it." );
707
708         len = strlen( fname );
709
710         if( len > FILE_MAXDIR + FILE_MAXFILE )
711                 return EXPP_ReturnPyObjError( PyExc_AttributeError,
712                                               "filename is too long!" );
713         else if( BLI_exists( fname ) && !overwrite )
714                 return EXPP_ReturnPyObjError( PyExc_AttributeError,
715                                               "file already exists and overwrite flag was not given." );
716
717         disable_where_script( 1 );      /* to avoid error popups in the write_* functions */
718
719         if( BLI_testextensie( fname, ".blend" ) ) {
720                 int writeflags;
721                 if( G.fileflags & G_AUTOPACK )
722                         packAll(  );
723                 
724                 writeflags= G.fileflags & ~G_FILE_COMPRESS;
725                 if(U.flag & USER_FILECOMPRESS)
726                 writeflags |= G_FILE_COMPRESS;
727                 
728                 if( !BLO_write_file( fname, writeflags, &error ) ) {
729                         disable_where_script( 0 );
730                         return EXPP_ReturnPyObjError( PyExc_SystemError,
731                                                       error );
732                 }
733         } else if( BLI_testextensie( fname, ".dxf" ) )
734                 write_dxf( fname );
735         else if( BLI_testextensie( fname, ".stl" ) )
736                 write_stl( fname );
737         else if( BLI_testextensie( fname, ".wrl" ) )
738                 write_vrml( fname );
739         else if( BLI_testextensie( fname, ".obj" ) )
740                 write_videoscape( fname );
741         else {
742                 disable_where_script( 0 );
743                 return EXPP_ReturnPyObjError( PyExc_AttributeError,
744                                               "unknown file extension." );
745         }
746
747         disable_where_script( 0 );
748
749         Py_RETURN_NONE;
750 }
751
752 static PyObject *Blender_ShowHelp(PyObject *self, PyObject *script)
753 {
754         char hspath[FILE_MAXDIR + FILE_MAXFILE]; /* path to help_browser.py */
755         char *sdir = bpy_gethome(1);
756         PyObject *rkeyd = NULL, *arglist = NULL;
757
758         if (!PyString_Check(script))
759                 return EXPP_ReturnPyObjError(PyExc_TypeError,
760                         "expected a script filename as argument");
761
762         /* first we try to find the help_browser script */
763
764         if (sdir) BLI_make_file_string("/", hspath, sdir, "help_browser.py");
765
766         if (!sdir || (!BLI_exists(hspath) && (U.pythondir[0] != '\0'))) {
767                         char upydir[FILE_MAXDIR];
768
769                         BLI_strncpy(upydir, U.pythondir, FILE_MAXDIR);
770                         BLI_convertstringcode(upydir, G.sce, 0);
771                         BLI_make_file_string("/", hspath, upydir, "help_browser.py");
772
773                         if (!BLI_exists(hspath))
774                                 return EXPP_ReturnPyObjError(PyExc_RuntimeError,
775                                         "can't find script help_browser.py");
776         }
777
778         /* now we store the passed script in the registry dict and call the
779          * help_browser to show help info for it */
780         rkeyd = PyDict_New();
781         if (!rkeyd)
782                 return EXPP_ReturnPyObjError(PyExc_MemoryError,
783                         "can't create py dictionary!");
784
785         /* note: don't use EXPP_dict_set_item_str for 'script', which is an
786          * argument to the function we're in and so shouldn't be decref'ed: */
787         PyDict_SetItemString(rkeyd, "script", script);
788
789         EXPP_dict_set_item_str(bpy_registryDict, "__help_browser", rkeyd);
790
791         arglist = Py_BuildValue("(s)", hspath);
792         Blender_Run(self, arglist);
793         Py_DECREF(arglist);
794
795         Py_RETURN_NONE;
796 }
797
798 static PyObject *Blender_Run(PyObject *self, PyObject *value)
799 {
800         char *fname = PyString_AsString(value);
801         Text *text = NULL;
802         int is_blender_text = 0;
803         Script *script = NULL;
804
805         if (!fname)
806                 return EXPP_ReturnPyObjError(PyExc_TypeError,
807                         "expected a filename or a Blender Text name as argument");
808
809         if (!BLI_exists(fname)) {       /* if there's no such filename ... */
810                 text = G.main->text.first;      /* try an already existing Blender Text */
811
812                 while (text) {
813                         if (!strcmp(fname, text->id.name + 2)) break;
814                         text = text->id.next;
815                 }
816
817                 if (!text) {
818                         return EXPP_ReturnPyObjError(PyExc_AttributeError,
819                                 "no such file or Blender text");
820                 }
821                 else is_blender_text = 1;       /* fn is already a Blender Text */
822         }
823
824         else {
825                 text = add_text(fname);
826
827                 if (!text) {
828                         return EXPP_ReturnPyObjError(PyExc_RuntimeError,
829                                 "couldn't create Blender Text from given file");
830                 }
831         }
832
833         /* (this is messy, check Draw.c's Method_Register and Window.c's file
834          * selector for more info)
835          * - caller script is the one that called this Blender_Run function;
836          * - called script is the argument to this function: fname;
837          * To mark scripts whose global dicts can't be freed right after
838          * the script execution (or better, 'first pass', since these scripts
839          * leave callbacks for gui or file/image selectors) we flag them.  But to
840          * get a pointer to them we need to check which one is currently
841          * running (if none we're already at a spacescript).  To make sure only
842          * the called script will have the SCRIPT_RUNNING flag on, we unset it
843          * for the caller script here: */
844         script = G.main->script.first;
845         while (script) {
846                 if (script->flags & SCRIPT_RUNNING) break;
847                 script = script->id.next;
848         }
849
850         if (script) script->flags &= ~SCRIPT_RUNNING; /* unset */
851
852         BPY_txt_do_python_Text(text); /* call new script */
853
854         if (script) script->flags |= SCRIPT_RUNNING; /* set */
855
856         if (!is_blender_text) free_libblock(&G.main->text, text);
857
858         Py_RETURN_NONE;
859 }
860
861 static PyObject * Blender_UpdateMenus( PyObject * self )
862 {
863
864         BPyMenu_RemoveAllEntries();
865
866         if (BPyMenu_Init(1) == -1)
867                 return EXPP_ReturnPyObjError( PyExc_RuntimeError,
868                         "invalid scripts dir");
869
870         Py_RETURN_NONE;
871 }
872
873 /*****************************************************************************/
874 /* Function:            Blender_PackAll          */
875 /* Python equivalent:   Blender.PackAll                  */
876 /*****************************************************************************/
877 static PyObject *Blender_PackAll( PyObject * self)
878 {
879         packAll();
880         Py_RETURN_NONE;
881 }
882
883 /*****************************************************************************/
884 /* Function:            Blender_UnpackAll                */
885 /* Python equivalent:   Blender.UnpackAll                        */
886 /*****************************************************************************/
887 static PyObject *Blender_UnpackAll( PyObject * self, PyObject *value)
888 {
889         int mode = PyInt_AsLong(value);
890         
891         if (mode==-1)
892                 return EXPP_ReturnPyObjError( PyExc_ValueError, "expected an int Blender.UnpackModes");
893         unpackAll(mode);
894         Py_RETURN_NONE;
895 }
896  
897 /*****************************************************************************/
898 /* Function:            Blender_CountPackedFiles                 */
899 /* Python equivalent:   Blender.CountPackedFiles                         */
900 /*****************************************************************************/
901 static PyObject *Blender_CountPackedFiles( PyObject * self )
902 {
903         int nfiles = countPackedFiles();
904         return PyInt_FromLong( nfiles );
905 }
906 static PyObject *Blender_UnpackModesDict( void )
907 {
908         PyObject *UnpackModes = PyConstant_New(  );
909         if( UnpackModes ) {
910                 BPy_constant *d = ( BPy_constant * ) UnpackModes;
911                 PyConstant_Insert( d, "EQUAL", PyInt_FromLong((long)PF_EQUAL) );
912                 PyConstant_Insert( d, "DIFFERS",PyInt_FromLong((long)PF_DIFFERS) );
913                 PyConstant_Insert( d, "NOFILE", PyInt_FromLong((long)PF_NOFILE) );
914                 PyConstant_Insert( d, "WRITE_ORIGINAL", PyInt_FromLong((long)PF_WRITE_ORIGINAL) );
915                 PyConstant_Insert( d, "WRITE_LOCAL", PyInt_FromLong((long)PF_WRITE_LOCAL) );
916                 PyConstant_Insert( d, "USE_LOCAL", PyInt_FromLong((long)PF_USE_LOCAL) );
917                 PyConstant_Insert( d, "USE_ORIGINAL", PyInt_FromLong((long)PF_USE_ORIGINAL) );
918                 PyConstant_Insert( d, "KEEP", PyInt_FromLong((long)PF_KEEP) );
919                 PyConstant_Insert( d, "NOOP", PyInt_FromLong((long)PF_NOOP) );
920                 PyConstant_Insert( d, "ASK", PyInt_FromLong((long)PF_EQUAL) );
921         }
922         return UnpackModes;
923 }
924
925 /*****************************************************************************/
926 /* Function:            initBlender              */
927 /*****************************************************************************/
928
929 void M_Blender_Init(void)
930 {
931         PyObject *module;
932         PyObject *dict, *smode, *SpaceHandlers, *UnpackModes;
933         
934         /* G.scene should only aver be NULL if blender is executed in 
935         background mode, not loading a blend file and executing a python script eg.
936         blender -P somescript.py -b
937         The if below solves the segfaults that happen when python runs and
938         G.scene is NULL */
939         if(G.background && G.main->scene.first==NULL) {
940                 Scene *sce= add_scene("1");
941                 /*set_scene(sce);*/ /* causes a crash */
942                 G.scene= sce;
943         }
944         
945         module = Py_InitModule3("Blender", Blender_methods,
946                 "The main Blender module");
947
948         types_InitAll();        /* set all our pytypes to &PyType_Type */
949
950         /* constants for packed files*/
951         UnpackModes = Blender_UnpackModesDict(  );
952         if( UnpackModes )
953                 PyModule_AddObject( module, "UnpackModes", UnpackModes );
954  
955         SpaceHandlers = PyConstant_New();
956         if (SpaceHandlers) {
957                 BPy_constant *d = (BPy_constant *)SpaceHandlers;
958
959                 PyConstant_Insert(d,"VIEW3D_EVENT",PyInt_FromLong(SPACEHANDLER_VIEW3D_EVENT));
960                 PyConstant_Insert(d,"VIEW3D_DRAW", PyInt_FromLong(SPACEHANDLER_VIEW3D_DRAW));
961
962                 PyModule_AddObject(module, "SpaceHandlers", SpaceHandlers);
963         }
964
965         if (G.background)
966                 smode = PyString_FromString("background");
967         else
968                 smode = PyString_FromString("interactive");
969
970         dict = PyModule_GetDict(module);
971         g_blenderdict = dict;
972
973         PyModule_AddIntConstant(module, "TRUE", 1);
974         PyModule_AddIntConstant( module, "FALSE", 0 );
975
976         EXPP_dict_set_item_str(dict, "bylink", EXPP_incr_ret_False());
977         PyDict_SetItemString(dict, "link", Py_None);
978         EXPP_dict_set_item_str(dict, "event", PyString_FromString(""));
979         EXPP_dict_set_item_str(dict, "mode", smode);
980
981         PyDict_SetItemString(dict, "Armature", Armature_Init());
982         PyDict_SetItemString(dict, "BezTriple", BezTriple_Init());
983         PyDict_SetItemString(dict, "BGL", BGL_Init());
984         PyDict_SetItemString(dict, "CurNurb", CurNurb_Init());
985         PyDict_SetItemString(dict, "Constraint", Constraint_Init());
986         PyDict_SetItemString(dict, "Curve", Curve_Init());
987         PyDict_SetItemString(dict, "Camera", Camera_Init());
988         PyDict_SetItemString(dict, "Draw", Draw_Init());
989         PyDict_SetItemString(dict, "Effect", Effect_Init());
990         PyDict_SetItemString(dict, "Ipo", Ipo_Init());
991         PyDict_SetItemString(dict, "IpoCurve", IpoCurve_Init());
992         PyDict_SetItemString(dict, "Image", Image_Init());
993         PyDict_SetItemString(dict, "Key", Key_Init());
994         PyDict_SetItemString(dict, "Lamp", Lamp_Init());
995         PyDict_SetItemString(dict, "Lattice", Lattice_Init());
996         PyDict_SetItemString(dict, "Library", oldLibrary_Init());
997         PyDict_SetItemString(dict, "Material", Material_Init());
998         PyDict_SetItemString(dict, "Mesh", Mesh_Init()); 
999         PyDict_SetItemString(dict, "Metaball", Metaball_Init());
1000         PyDict_SetItemString(dict, "Mathutils", Mathutils_Init());
1001         PyDict_SetItemString(dict, "Geometry", Geometry_Init());
1002         PyDict_SetItemString(dict, "Modifier", Modifier_Init());
1003         PyDict_SetItemString(dict, "NMesh", NMesh_Init());
1004         PyDict_SetItemString(dict, "Noise", Noise_Init());
1005         PyDict_SetItemString(dict, "Object", Object_Init());
1006         PyDict_SetItemString(dict, "Group", Group_Init());
1007         PyDict_SetItemString(dict, "Registry", Registry_Init());
1008         PyDict_SetItemString(dict, "Scene", Scene_Init());
1009         PyDict_SetItemString(dict, "Sound", Sound_Init());
1010         PyDict_SetItemString(dict, "SurfNurb", SurfNurb_Init());
1011         PyDict_SetItemString(dict, "sys", sys_Init());
1012         PyDict_SetItemString(dict, "Types", Types_Init());
1013         PyDict_SetItemString(dict, "Text", Text_Init());
1014         PyDict_SetItemString(dict, "Text3d", Text3d_Init());
1015         PyDict_SetItemString(dict, "Texture", Texture_Init());
1016         PyDict_SetItemString(dict, "Window", Window_Init());
1017         PyDict_SetItemString(dict, "World", World_Init());
1018
1019 }