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