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