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