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