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