py/rna remove functions now all work in a similar way.
[blender.git] / source / creator / creator.c
1 /*
2  * $Id$
3  *
4  * ***** BEGIN GPL LICENSE BLOCK *****
5  *
6  * This program is free software; you can redistribute it and/or
7  * modify it under the terms of the GNU General Public License
8  * as published by the Free Software Foundation; either version 2
9  * of the License, or (at your option) any later version.
10  *
11  * This program is distributed in the hope that it will be useful,
12  * but WITHOUT ANY WARRANTY; without even the implied warranty of
13  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14  * GNU General Public License for more details.
15  *
16  * You should have received a copy of the GNU General Public License
17  * along with this program; if not, write to the Free Software Foundation,
18  * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
19  *
20  * The Original Code is Copyright (C) 2001-2002 by NaN Holding BV.
21  * All rights reserved.
22  *
23  * The Original Code is: all of this file.
24  *
25  * Contributor(s): none yet.
26  *
27  * ***** END GPL LICENSE BLOCK *****
28  */
29
30 #if defined(__linux__) && defined(__GNUC__)
31 #define _GNU_SOURCE
32 #include <fenv.h>
33 #endif
34
35 #define OSX_SSE_FPE (defined(__APPLE__) && (defined(__i386__) || defined(__x86_64__)))
36
37 #if OSX_SSE_FPE
38 #include <xmmintrin.h>
39 #endif
40
41 #include <stdlib.h>
42 #include <string.h>
43
44 /* for setuid / getuid */
45 #ifdef __sgi
46 #include <sys/types.h>
47 #include <unistd.h>
48 #endif
49
50 /* This little block needed for linking to Blender... */
51
52 #include "MEM_guardedalloc.h"
53
54 #ifdef WIN32
55 #include "BLI_winstuff.h"
56 #endif
57
58 #include "BLI_args.h"
59 #include "BLI_threads.h"
60
61 #include "GEN_messaging.h"
62
63 #include "DNA_ID.h"
64 #include "DNA_scene_types.h"
65
66 #include "BLI_blenlib.h"
67
68 #include "BKE_utildefines.h"
69 #include "BKE_blender.h"
70 #include "BKE_context.h"
71 #include "BKE_font.h"
72 #include "BKE_global.h"
73 #include "BKE_main.h"
74 #include "BKE_material.h"
75 #include "BKE_packedFile.h"
76 #include "BKE_scene.h"
77 #include "BKE_node.h"
78 #include "BKE_report.h"
79 #include "BKE_sound.h"
80
81 #include "IMB_imbuf.h"  // for IMB_init
82
83 #ifndef DISABLE_PYTHON
84 #include "BPY_extern.h"
85 #endif
86
87 #include "RE_pipeline.h"
88
89 //XXX #include "playanim_ext.h"
90 #include "ED_datafiles.h"
91
92 #include "WM_api.h"
93
94 #include "RNA_define.h"
95
96 #include "GPU_draw.h"
97 #include "GPU_extensions.h"
98
99 /* for passing information between creator and gameengine */
100 #include "SYS_System.h"
101
102 #include <signal.h>
103
104 #ifdef __FreeBSD__
105 # include <sys/types.h>
106 # include <floatingpoint.h>
107 # include <sys/rtprio.h>
108 #endif
109
110 #ifdef WITH_BINRELOC
111 #include "binreloc.h"
112 #endif
113
114 // from buildinfo.c
115 #ifdef BUILD_DATE
116 extern char build_date[];
117 extern char build_time[];
118 extern char build_rev[];
119 extern char build_platform[];
120 extern char build_type[];
121 #endif
122
123 /*      Local Function prototypes */
124 static int print_help(int argc, char **argv, void *data);
125 static int print_version(int argc, char **argv, void *data);
126
127 /* for the callbacks: */
128
129 extern int pluginapi_force_ref(void);  /* from blenpluginapi:pluginapi.c */
130
131 char bprogname[FILE_MAXDIR+FILE_MAXFILE]; /* from blenpluginapi:pluginapi.c */
132 char btempdir[FILE_MAXDIR+FILE_MAXFILE];
133
134 /* Initialise callbacks for the modules that need them */
135 static void setCallbacks(void); 
136
137 /* set breakpoints here when running in debug mode, useful to catch floating point errors */
138 #if defined(__sgi) || defined(__linux__) || defined(_WIN32) || OSX_SSE_FPE
139 static void fpe_handler(int sig)
140 {
141         // printf("SIGFPE trapped\n");
142 }
143 #endif
144
145 /* handling ctrl-c event in console */
146 static void blender_esc(int sig)
147 {
148         static int count = 0;
149         
150         G.afbreek = 1;  /* forces render loop to read queue, not sure if its needed */
151         
152         if (sig == 2) {
153                 if (count) {
154                         printf("\nBlender killed\n");
155                         exit(2);
156                 }
157                 printf("\nSent an internal break event. Press ^C again to kill Blender\n");
158                 count++;
159         }
160 }
161
162 /* buildinfo can have quotes */
163 #ifdef BUILD_DATE
164 static void strip_quotes(char *str)
165 {
166     if(str[0] == '"') {
167         int len= strlen(str) - 1;
168         memmove(str, str+1, len);
169         if(str[len-1] == '"') {
170             str[len-1]= '\0';
171         }
172     }
173 }
174 #endif
175
176 static int print_version(int argc, char **argv, void *data)
177 {
178 #ifdef BUILD_DATE
179         printf ("Blender %d.%02d (sub %d) Build\n", BLENDER_VERSION/100, BLENDER_VERSION%100, BLENDER_SUBVERSION);
180         printf ("\tbuild date: %s\n", build_date);
181         printf ("\tbuild time: %s\n", build_time);
182         printf ("\tbuild revision: %s\n", build_rev);
183         printf ("\tbuild platform: %s\n", build_platform);
184         printf ("\tbuild type: %s\n", build_type);
185 #else
186         printf ("Blender %d.%02d (sub %d) Build\n", BLENDER_VERSION/100, BLENDER_VERSION%100, BLENDER_SUBVERSION);
187 #endif
188
189         exit(0);
190
191         return 0;
192 }
193
194 static int print_help(int argc, char **argv, void *data)
195 {
196         bArgs *ba = (bArgs*)data;
197
198         printf ("Blender %d.%02d (sub %d) Build\n", BLENDER_VERSION/100, BLENDER_VERSION%100, BLENDER_SUBVERSION);
199         printf ("Usage: blender [args ...] [file] [args ...]\n\n");
200
201         printf ("Render Options:\n");
202         BLI_argsPrintArgDoc(ba, "--background");
203         BLI_argsPrintArgDoc(ba, "--render-anim");
204         BLI_argsPrintArgDoc(ba, "--scene");
205         BLI_argsPrintArgDoc(ba, "--render-frame");
206         BLI_argsPrintArgDoc(ba, "--frame-start");
207         BLI_argsPrintArgDoc(ba, "--frame-end");
208         BLI_argsPrintArgDoc(ba, "--frame-jump");
209         BLI_argsPrintArgDoc(ba, "--render-output");
210         BLI_argsPrintArgDoc(ba, "--engine");
211         
212         printf("\n");
213         printf ("Format Options:\n");
214         BLI_argsPrintArgDoc(ba, "--render-format");
215         BLI_argsPrintArgDoc(ba, "--use-extension");
216         BLI_argsPrintArgDoc(ba, "--threads");
217
218         printf("\n");
219         printf ("Animation Playback Options:\n");
220         BLI_argsPrintArgDoc(ba, "-a");
221                                 
222         printf("\n");
223         printf ("Window Options:\n");
224         BLI_argsPrintArgDoc(ba, "--window-border");
225         BLI_argsPrintArgDoc(ba, "--window-borderless");
226         BLI_argsPrintArgDoc(ba, "--window-geometry");
227
228         printf("\n");
229         printf ("Game Engine Specific Options:\n");
230         BLI_argsPrintArgDoc(ba, "-g");
231
232         printf("\n");
233         printf ("Misc Options:\n");
234         BLI_argsPrintArgDoc(ba, "--debug");
235         BLI_argsPrintArgDoc(ba, "--debug-fpe");
236
237         printf("\n");
238
239         BLI_argsPrintArgDoc(ba, "-nojoystick");
240         BLI_argsPrintArgDoc(ba, "-noglsl");
241         BLI_argsPrintArgDoc(ba, "-noaudio");
242         BLI_argsPrintArgDoc(ba, "-setaudio");
243
244         printf("\n");
245
246         BLI_argsPrintArgDoc(ba, "--help");
247
248         printf("\n");
249
250         BLI_argsPrintArgDoc(ba, "--enable-autoexec");
251         BLI_argsPrintArgDoc(ba, "--disable-autoexec");
252
253         printf("\n");
254
255         BLI_argsPrintArgDoc(ba, "--python");
256         BLI_argsPrintArgDoc(ba, "--python-console");
257
258 #ifdef WIN32
259         BLI_argsPrintArgDoc(ba, "-R");
260 #endif
261         BLI_argsPrintArgDoc(ba, "--version");
262
263         BLI_argsPrintArgDoc(ba, "--");
264
265         printf ("Other Options:\n");
266         BLI_argsPrintOtherDoc(ba);
267
268         printf ("Argument Parsing:\n");
269         printf ("\targuments must be separated by white space. eg\n");
270         printf ("\t\t\"blender -ba test.blend\"\n");
271         printf ("\t...will ignore the 'a'\n");
272         printf ("\t\t\"blender -b test.blend -f8\"\n");
273         printf ("\t...will ignore 8 because there is no space between the -f and the frame value\n\n");
274
275         printf ("Argument Order:\n");
276         printf ("Arguments are executed in the order they are given. eg\n");
277         printf ("\t\t\"blender --background test.blend --render-frame 1 --render-output /tmp\"\n");
278         printf ("\t...will not render to /tmp because '--render-frame 1' renders before the output path is set\n");
279         printf ("\t\t\"blender --background --render-output /tmp test.blend --render-frame 1\"\n");
280         printf ("\t...will not render to /tmp because loading the blend file overwrites the render output that was set\n");
281         printf ("\t\t\"blender --background test.blend --render-output /tmp --render-frame 1\" works as expected.\n\n");
282
283         printf ("\nEnvironment Variables:\n");
284         printf ("  $BLENDER_USER_CONFIG      Directory for user configuration files.\n");
285         printf ("  $BLENDER_SYSTEM_CONFIG    Directory for system wide configuration files.\n");
286         printf ("  $BLENDER_USER_SCRIPTS     Directory for user scripts.\n");
287         printf ("  $BLENDER_SYSTEM_SCRIPTS   Directory for system wide scripts.\n");
288         printf ("  $BLENDER_USER_DATAFILES   Directory for user data files (icons, translations, ..).\n");
289         printf ("  $BLENDER_SYSTEM_DATAFILES Directory for system wide data files.\n");
290         printf ("  $BLENDER_SYSTEM_PYTHON    Directory for system python libraries.\n");
291 #ifdef WIN32
292         printf ("  $TEMP                     Store temporary files here.\n");
293 #else
294         printf ("  $TMP or $TMPDIR           Store temporary files here.\n");
295 #endif
296 #ifndef DISABLE_SDL
297         printf ("  $SDL_AUDIODRIVER          LibSDL audio driver - alsa, esd, dma.\n");
298 #endif
299         printf ("  $PYTHONHOME               Path to the python directory, eg. /usr/lib/python.\n\n");
300
301         exit(0);
302
303         return 0;
304 }
305
306
307 double PIL_check_seconds_timer(void);
308
309 /* XXX This was here to fix a crash when running python scripts
310  * with -P that used the screen.
311  *
312  * static void main_init_screen( void )
313 {
314         setscreen(G.curscreen);
315         
316         if(G.main->scene.first==0) {
317                 set_scene( add_scene("1") );
318         }
319 }*/
320
321 static int end_arguments(int argc, char **argv, void *data)
322 {
323         return -1;
324 }
325
326 static int enable_python(int argc, char **argv, void *data)
327 {
328         G.f |= G_SCRIPT_AUTOEXEC;
329         return 0;
330 }
331
332 static int disable_python(int argc, char **argv, void *data)
333 {
334         G.f &= ~G_SCRIPT_AUTOEXEC;
335         return 0;
336 }
337
338 static int background_mode(int argc, char **argv, void *data)
339 {
340         G.background = 1;
341         return 0;
342 }
343
344 static int debug_mode(int argc, char **argv, void *data)
345 {
346         G.f |= G_DEBUG;         /* std output printf's */
347         printf ("Blender %d.%02d (sub %d) Build\n", BLENDER_VERSION/100, BLENDER_VERSION%100, BLENDER_SUBVERSION);
348         MEM_set_memory_debug();
349
350 #ifdef NAN_BUILDINFO
351         printf("Build: %s %s %s %s\n", build_date, build_time, build_platform, build_type);
352 #endif // NAN_BUILDINFO
353
354         BLI_argsPrint(data);
355         return 0;
356 }
357
358 static int set_fpe(int argc, char **argv, void *data)
359 {
360 #if defined(__sgi) || defined(__linux__) || defined(_WIN32) || OSX_SSE_FPE
361         /* zealous but makes float issues a heck of a lot easier to find!
362          * set breakpoints on fpe_handler */
363         signal(SIGFPE, fpe_handler);
364
365 # if defined(__linux__) && defined(__GNUC__)
366         feenableexcept(FE_DIVBYZERO | FE_INVALID | FE_OVERFLOW );
367 # endif /* defined(__linux__) && defined(__GNUC__) */
368 # if OSX_SSE_FPE
369         /* OSX uses SSE for floating point by default, so here 
370          * use SSE instructions to throw floating point exceptions */
371         _MM_SET_EXCEPTION_MASK(_MM_MASK_MASK &~
372                                                    (_MM_MASK_OVERFLOW|_MM_MASK_INVALID|_MM_MASK_DIV_ZERO));
373 # endif /* OSX_SSE_FPE */
374 # if defined(_WIN32) && defined(_MSC_VER)
375         _controlfp_s(NULL, 0, _MCW_EM); /* enables all fp exceptions */
376         _controlfp_s(NULL, _EM_DENORMAL | _EM_UNDERFLOW | _EM_INEXACT, _MCW_EM); /* hide the ones we don't care about */
377 # endif /* _WIN32 && _MSC_VER */
378 #endif
379
380         return 0;
381 }
382
383 static int playback_mode(int argc, char **argv, void *data)
384 {
385         /* not if -b was given first */
386         if (G.background == 0) {
387
388 // XXX                          playanim(argc, argv); /* not the same argc and argv as before */
389                 exit(0);
390         }
391
392         return -2;
393 }
394
395 static int prefsize(int argc, char **argv, void *data)
396 {
397         int stax, stay, sizx, sizy;
398
399         if (argc < 5) {
400                 printf ("-p requires four arguments\n");
401                 exit(1);
402         }
403
404         stax= atoi(argv[1]);
405         stay= atoi(argv[2]);
406         sizx= atoi(argv[3]);
407         sizy= atoi(argv[4]);
408
409         WM_setprefsize(stax, stay, sizx, sizy);
410
411         return 4;
412 }
413
414 static int with_borders(int argc, char **argv, void *data)
415 {
416         /* with borders XXX OLD CRUFT!*/
417
418         return 0;
419 }
420
421 static int without_borders(int argc, char **argv, void *data)
422 {
423         /* borderless, win + linux XXX OLD CRUFT */
424         /* XXX, fixme mein, borderless on OSX */
425
426         return 0;
427 }
428
429 static int register_extension(int argc, char **argv, void *data)
430 {
431 #ifdef WIN32
432         char *path = BLI_argsArgv(data)[0];
433         RegisterBlendExtension(path);
434 #endif
435
436         return 0;
437 }
438
439 static int no_joystick(int argc, char **argv, void *data)
440 {
441         SYS_SystemHandle *syshandle = data;
442
443         /**
444                 don't initialize joysticks if user doesn't want to use joysticks
445                 failed joystick initialization delays over 5 seconds, before game engine start
446         */
447         SYS_WriteCommandLineInt(*syshandle, "nojoystick",1);
448         if (G.f & G_DEBUG) printf("disabling nojoystick\n");
449
450         return 0;
451 }
452
453 static int no_glsl(int argc, char **argv, void *data)
454 {
455         GPU_extensions_disable();
456         return 0;
457 }
458
459 static int no_audio(int argc, char **argv, void *data)
460 {
461         sound_force_device(0);
462         return 0;
463 }
464
465 static int set_audio(int argc, char **argv, void *data)
466 {
467         if (argc < 1) {
468                 printf("-setaudio require one argument\n");
469                 exit(1);
470         }
471
472         sound_force_device(sound_define_from_str(argv[1]));
473         return 1;
474 }
475
476 static int set_output(int argc, char **argv, void *data)
477 {
478         bContext *C = data;
479         if (argc >= 1){
480                 if (CTX_data_scene(C)) {
481                         Scene *scene= CTX_data_scene(C);
482                         BLI_strncpy(scene->r.pic, argv[1], FILE_MAXDIR);
483                 } else {
484                         printf("\nError: no blend loaded. cannot use '-o / --render-output'.\n");
485                 }
486                 return 1;
487         } else {
488                 printf("\nError: you must specify a path after '-o  / --render-output'.\n");
489                 return 0;
490         }
491 }
492
493 static int set_engine(int argc, char **argv, void *data)
494 {
495         bContext *C = data;
496         if (argc >= 1)
497         {
498                 if (!strcmp(argv[1],"help"))
499                 {
500                         RenderEngineType *type = NULL;
501
502                         for( type = R_engines.first; type; type = type->next )
503                         {
504                                 printf("\t%s\n", type->idname);
505                         }
506                         exit(0);
507                 }
508                 else
509                 {
510                         if (CTX_data_scene(C)==NULL)
511                         {
512                                 printf("\nError: no blend loaded. order the arguments so '-E  / --engine ' is after a blend is loaded.\n");
513                         }
514                         else
515                         {
516                                 Scene *scene= CTX_data_scene(C);
517                                 RenderData *rd = &scene->r;
518                                 RenderEngineType *type = NULL;
519
520                                 for( type = R_engines.first; type; type = type->next )
521                                 {
522                                         if (!strcmp(argv[1],type->idname))
523                                         {
524                                                 BLI_strncpy(rd->engine, type->idname, sizeof(rd->engine));
525                                         }
526                                 }
527                         }
528                 }
529
530                 return 1;
531         }
532         else
533         {
534                 printf("\nEngine not specified.\n");
535                 return 0;
536         }
537 }
538
539 static int set_image_type(int argc, char **argv, void *data)
540 {
541         bContext *C = data;
542         if (argc >= 1){
543                 char *imtype = argv[1];
544                 if (CTX_data_scene(C)==NULL) {
545                         printf("\nError: no blend loaded. order the arguments so '-F  / --render-format' is after the blend is loaded.\n");
546                 } else {
547                         Scene *scene= CTX_data_scene(C);
548                         if      (!strcmp(imtype,"TGA")) scene->r.imtype = R_TARGA;
549                         else if (!strcmp(imtype,"IRIS")) scene->r.imtype = R_IRIS;
550 #ifdef WITH_DDS
551                         else if (!strcmp(imtype,"DDS")) scene->r.imtype = R_DDS;
552 #endif
553                         else if (!strcmp(imtype,"JPEG")) scene->r.imtype = R_JPEG90;
554                         else if (!strcmp(imtype,"IRIZ")) scene->r.imtype = R_IRIZ;
555                         else if (!strcmp(imtype,"RAWTGA")) scene->r.imtype = R_RAWTGA;
556                         else if (!strcmp(imtype,"AVIRAW")) scene->r.imtype = R_AVIRAW;
557                         else if (!strcmp(imtype,"AVIJPEG")) scene->r.imtype = R_AVIJPEG;
558                         else if (!strcmp(imtype,"PNG")) scene->r.imtype = R_PNG;
559                         else if (!strcmp(imtype,"AVICODEC")) scene->r.imtype = R_AVICODEC;
560                         else if (!strcmp(imtype,"QUICKTIME")) scene->r.imtype = R_QUICKTIME;
561                         else if (!strcmp(imtype,"BMP")) scene->r.imtype = R_BMP;
562 #ifdef WITH_HDR
563                         else if (!strcmp(imtype,"HDR")) scene->r.imtype = R_RADHDR;
564 #endif
565 #ifdef WITH_TIFF
566                         else if (!strcmp(imtype,"TIFF")) scene->r.imtype = R_TIFF;
567 #endif
568 #ifdef WITH_OPENEXR
569                         else if (!strcmp(imtype,"EXR")) scene->r.imtype = R_OPENEXR;
570                         else if (!strcmp(imtype,"MULTILAYER")) scene->r.imtype = R_MULTILAYER;
571 #endif
572                         else if (!strcmp(imtype,"MPEG")) scene->r.imtype = R_FFMPEG;
573                         else if (!strcmp(imtype,"FRAMESERVER")) scene->r.imtype = R_FRAMESERVER;
574 #ifdef WITH_CINEON
575                         else if (!strcmp(imtype,"CINEON")) scene->r.imtype = R_CINEON;
576                         else if (!strcmp(imtype,"DPX")) scene->r.imtype = R_DPX;
577 #endif
578 #if WITH_OPENJPEG
579                         else if (!strcmp(imtype,"JP2")) scene->r.imtype = R_JP2;
580 #endif
581                         else printf("\nError: Format from '-F / --render-format' not known or not compiled in this release.\n");
582                 }
583                 return 1;
584         } else {
585                 printf("\nError: you must specify a format after '-F  / --render-foramt'.\n");
586                 return 0;
587         }
588 }
589
590 static int set_threads(int argc, char **argv, void *data)
591 {
592         if (argc >= 1) {
593                 if(G.background) {
594                         RE_set_max_threads(atoi(argv[1]));
595                 } else {
596                         printf("Warning: threads can only be set in background mode\n");
597                 }
598                 return 1;
599         } else {
600                 printf("\nError: you must specify a number of threads between 0 and 8 '-t  / --threads'.\n");
601                 return 0;
602         }
603 }
604
605 static int set_extension(int argc, char **argv, void *data)
606 {
607         bContext *C = data;
608         if (argc >= 1) {
609                 if (CTX_data_scene(C)) {
610                         Scene *scene= CTX_data_scene(C);
611                         if (argv[1][0] == '0') {
612                                 scene->r.scemode &= ~R_EXTENSION;
613                         } else if (argv[1][0] == '1') {
614                                 scene->r.scemode |= R_EXTENSION;
615                         } else {
616                                 printf("\nError: Use '-x 1 / -x 0' To set the extension option or '--use-extension'\n");
617                         }
618                 } else {
619                         printf("\nError: no blend loaded. order the arguments so '-o ' is after '-x '.\n");
620                 }
621                 return 1;
622         } else {
623                 printf("\nError: you must specify a path after '- '.\n");
624                 return 0;
625         }
626 }
627
628 static int set_ge_parameters(int argc, char **argv, void *data)
629 {
630         SYS_SystemHandle syshandle = *(SYS_SystemHandle*)data;
631         int a = 0;
632 /**
633 gameengine parameters are automaticly put into system
634 -g [paramname = value]
635 -g [boolparamname]
636 example:
637 -g novertexarrays
638 -g maxvertexarraysize = 512
639 */
640
641         if(argc >= 1)
642         {
643                 char* paramname = argv[a];
644                 /* check for single value versus assignment */
645                 if (a+1 < argc && (*(argv[a+1]) == '='))
646                 {
647                         a++;
648                         if (a+1 < argc)
649                         {
650                                 a++;
651                                 /* assignment */
652                                 SYS_WriteCommandLineString(syshandle,paramname,argv[a]);
653                         }  else
654                         {
655                                 printf("error: argument assignment (%s) without value.\n",paramname);
656                                 return 0;
657                         }
658                         /* name arg eaten */
659
660                 } else {
661                         SYS_WriteCommandLineInt(syshandle,argv[a],1);
662
663                         /* doMipMap */
664                         if (!strcmp(argv[a],"nomipmap"))
665                         {
666                                 GPU_set_mipmap(0); //doMipMap = 0;
667                         }
668                         /* linearMipMap */
669                         if (!strcmp(argv[a],"linearmipmap"))
670                         {
671                                 GPU_set_linear_mipmap(1); //linearMipMap = 1;
672                         }
673
674
675                 } /* if (*(argv[a+1]) == '=') */
676         }
677
678         return a;
679 }
680
681 static int render_frame(int argc, char **argv, void *data)
682 {
683         bContext *C = data;
684         if (CTX_data_scene(C)) {
685                 Main *bmain= CTX_data_main(C);
686                 Scene *scene= CTX_data_scene(C);
687
688                 if (argc > 1) {
689                         Render *re = RE_NewRender(scene->id.name);
690                         int frame;
691                         ReportList reports;
692
693                         switch(*argv[1]) {
694                         case '+':
695                                 frame= scene->r.sfra + atoi(argv[1]+1);
696                                 break;
697                         case '-':
698                                 frame= (scene->r.efra - atoi(argv[1]+1)) + 1;
699                                 break;
700                         default:
701                                 frame= atoi(argv[1]);
702                                 break;
703                         }
704
705                         BKE_reports_init(&reports, RPT_PRINT);
706
707                         frame = MIN2(MAXFRAME, MAX2(MINAFRAME, frame));
708
709                         RE_BlenderAnim(re, bmain, scene, scene->lay, frame, frame, scene->r.frame_step, &reports);
710                         return 1;
711                 } else {
712                         printf("\nError: frame number must follow '-f / --render-frame'.\n");
713                         return 0;
714                 }
715         } else {
716                 printf("\nError: no blend loaded. cannot use '-f / --render-frame'.\n");
717                 return 0;
718         }
719 }
720
721 static int render_animation(int argc, char **argv, void *data)
722 {
723         bContext *C = data;
724         if (CTX_data_scene(C)) {
725                 Main *bmain= CTX_data_main(C);
726                 Scene *scene= CTX_data_scene(C);
727                 Render *re= RE_NewRender(scene->id.name);
728                 ReportList reports;
729                 BKE_reports_init(&reports, RPT_PRINT);
730                 RE_BlenderAnim(re, bmain, scene, scene->lay, scene->r.sfra, scene->r.efra, scene->r.frame_step, &reports);
731         } else {
732                 printf("\nError: no blend loaded. cannot use '-a'.\n");
733         }
734         return 0;
735 }
736
737 static int set_scene(int argc, char **argv, void *data)
738 {
739         if(argc > 1) {
740                 bContext *C= data;
741                 Scene *sce= set_scene_name(CTX_data_main(C), argv[1]);
742                 if(sce) {
743                         CTX_data_scene_set(C, sce);
744                 }
745                 return 1;
746         } else {
747                 printf("\nError: Scene name must follow '-S / --scene'.\n");
748                 return 0;
749         }
750 }
751
752 static int set_start_frame(int argc, char **argv, void *data)
753 {
754         bContext *C = data;
755         if (CTX_data_scene(C)) {
756                 Scene *scene= CTX_data_scene(C);
757                 if (argc > 1) {
758                         int frame = atoi(argv[1]);
759                         (scene->r.sfra) = CLAMPIS(frame, MINFRAME, MAXFRAME);
760                         return 1;
761                 } else {
762                         printf("\nError: frame number must follow '-s / --frame-start'.\n");
763                         return 0;
764                 }
765         } else {
766                 printf("\nError: no blend loaded. cannot use '-s / --frame-start'.\n");
767                 return 0;
768         }
769 }
770
771 static int set_end_frame(int argc, char **argv, void *data)
772 {
773         bContext *C = data;
774         if (CTX_data_scene(C)) {
775                 Scene *scene= CTX_data_scene(C);
776                 if (argc > 1) {
777                         int frame = atoi(argv[1]);
778                         (scene->r.efra) = CLAMPIS(frame, MINFRAME, MAXFRAME);
779                         return 1;
780                 } else {
781                         printf("\nError: frame number must follow '-e / --frame-end'.\n");
782                         return 0;
783                 }
784         } else {
785                 printf("\nError: no blend loaded. cannot use '-e / --frame-end'.\n");
786                 return 0;
787         }
788 }
789
790 static int set_skip_frame(int argc, char **argv, void *data)
791 {
792         bContext *C = data;
793         if (CTX_data_scene(C)) {
794                 Scene *scene= CTX_data_scene(C);
795                 if (argc > 1) {
796                         int frame = atoi(argv[1]);
797                         (scene->r.frame_step) = CLAMPIS(frame, 1, MAXFRAME);
798                         return 1;
799                 } else {
800                         printf("\nError: number of frames to step must follow '-j / --frame-jump'.\n");
801                         return 0;
802                 }
803         } else {
804                 printf("\nError: no blend loaded. cannot use '-j / --frame-jump'.\n");
805                 return 0;
806         }
807 }
808
809 /* macro for ugly context setup/reset */
810 #ifndef DISABLE_PYTHON
811 #define BPY_CTX_SETUP(_cmd) \
812 { \
813         wmWindowManager *wm= CTX_wm_manager(C); \
814         wmWindow *prevwin= CTX_wm_window(C); \
815         Scene *prevscene= CTX_data_scene(C); \
816         if(wm->windows.first) { \
817                 CTX_wm_window_set(C, wm->windows.first); \
818                 _cmd; \
819                 CTX_wm_window_set(C, prevwin); \
820         } \
821         else { \
822                 fprintf(stderr, "Python script \"%s\" running with missing context data.\n", argv[1]); \
823                 _cmd; \
824         } \
825         CTX_data_scene_set(C, prevscene); \
826 } \
827
828 #endif /* DISABLE_PYTHON */
829
830 static int run_python(int argc, char **argv, void *data)
831 {
832 #ifndef DISABLE_PYTHON
833         bContext *C = data;
834
835         /* workaround for scripts not getting a bpy.context.scene, causes internal errors elsewhere */
836         if (argc > 1) {
837                 /* Make the path absolute because its needed for relative linked blends to be found */
838                 char filename[FILE_MAXDIR + FILE_MAXFILE];
839                 BLI_strncpy(filename, argv[1], sizeof(filename));
840                 BLI_path_cwd(filename);
841
842                 BPY_CTX_SETUP( BPY_run_python_script(C, filename, NULL, NULL) )
843
844                 return 1;
845         } else {
846                 printf("\nError: you must specify a Python script after '-P / --python'.\n");
847                 return 0;
848         }
849 #else
850         printf("This blender was built without python support\n");
851         return 0;
852 #endif /* DISABLE_PYTHON */
853 }
854
855 static int run_python_console(int argc, char **argv, void *data)
856 {
857 #ifndef DISABLE_PYTHON
858         bContext *C = data;     
859         const char *expr= "__import__('code').interact()";
860
861         BPY_CTX_SETUP( BPY_eval_string(C, expr) )
862
863         return 0;
864 #else
865         printf("This blender was built without python support\n");
866         return 0;
867 #endif /* DISABLE_PYTHON */
868 }
869
870 static int load_file(int argc, char **argv, void *data)
871 {
872         bContext *C = data;
873
874         /* Make the path absolute because its needed for relative linked blends to be found */
875         char filename[FILE_MAXDIR + FILE_MAXFILE];
876         BLI_strncpy(filename, argv[0], sizeof(filename));
877         BLI_path_cwd(filename);
878
879         if (G.background) {
880                 int retval = BKE_read_file(C, filename, NULL, NULL);
881
882                 /*we successfully loaded a blend file, get sure that
883                 pointcache works */
884                 if (retval!=0) {
885                         wmWindowManager *wm= CTX_wm_manager(C);
886                         CTX_wm_manager_set(C, NULL); /* remove wm to force check */
887                         WM_check(C);
888                         G.relbase_valid = 1;
889                         if (CTX_wm_manager(C) == NULL) CTX_wm_manager_set(C, wm); /* reset wm */
890                 }
891
892                 /* WM_read_file() runs normally but since we're in background mode do here */
893 #ifndef DISABLE_PYTHON
894                 /* run any texts that were loaded in and flagged as modules */
895                 BPY_load_user_modules(C);
896 #endif
897
898                 /* happens for the UI on file reading too (huh? (ton))*/
899         // XXX                  BKE_reset_undo();
900         //                              BKE_write_undo("original");     /* save current state */
901         } else {
902                 /* we are not running in background mode here, but start blender in UI mode with
903                    a file - this should do everything a 'load file' does */
904                 WM_read_file(C, filename, NULL);
905         }
906
907         G.file_loaded = 1;
908
909         return 0;
910 }
911
912 void setupArguments(bContext *C, bArgs *ba, SYS_SystemHandle *syshandle)
913 {
914         static char output_doc[] = "<path>"
915                 "\n\tSet the render path and file name."
916                 "\n\tUse // at the start of the path to"
917                 "\n\t\trender relative to the blend file."
918                 "\n\tThe # characters are replaced by the frame number, and used to define zero padding."
919                 "\n\t\tani_##_test.png becomes ani_01_test.png"
920                 "\n\t\ttest-######.png becomes test-000001.png"
921                 "\n\t\tWhen the filename does not contain #, The suffix #### is added to the filename"
922                 "\n\tThe frame number will be added at the end of the filename."
923                 "\n\t\teg: blender -b foobar.blend -o //render_ -F PNG -x 1 -a"
924                 "\n\t\t//render_ becomes //render_####, writing frames as //render_0001.png//";
925
926         static char format_doc[] = "<format>"
927                 "\n\tSet the render format, Valid options are..."
928                 "\n\t\tTGA IRIS JPEG MOVIE IRIZ RAWTGA"
929                 "\n\t\tAVIRAW AVIJPEG PNG BMP FRAMESERVER"
930                 "\n\t(formats that can be compiled into blender, not available on all systems)"
931                 "\n\t\tHDR TIFF EXR MULTILAYER MPEG AVICODEC QUICKTIME CINEON DPX DDS";
932
933         static char playback_doc[] = "<options> <file(s)>"
934                 "\n\tPlayback <file(s)>, only operates this way when not running in background."
935                 "\n\t\t-p <sx> <sy>\tOpen with lower left corner at <sx>, <sy>"
936                 "\n\t\t-m\t\tRead from disk (Don't buffer)"
937                 "\n\t\t-f <fps> <fps-base>\t\tSpecify FPS to start with"
938                 "\n\t\t-j <frame>\tSet frame step to <frame>";
939
940         static char game_doc[] = "Game Engine specific options"
941                 "\n\t-g fixedtime\t\tRun on 50 hertz without dropping frames"
942                 "\n\t-g vertexarrays\tUse Vertex Arrays for rendering (usually faster)"
943                 "\n\t-g nomipmap\t\tNo Texture Mipmapping"
944                 "\n\t-g linearmipmap\tLinear Texture Mipmapping instead of Nearest (default)";
945
946         static char debug_doc[] = "\n\tTurn debugging on\n"
947                 "\n\t* Prints every operator call and their arguments"
948                 "\n\t* Disables mouse grab (to interact with a debugger in some cases)"
949                 "\n\t* Keeps python sys.stdin rather then setting it to None";
950
951         //BLI_argsAdd(ba, pass, short_arg, long_arg, doc, cb, C);
952
953         /* end argument processing after -- */
954         BLI_argsAdd(ba, -1, "--", NULL, "\n\tEnds option processing, following arguments passed unchanged. Access via python's sys.argv", end_arguments, NULL);
955
956         /* first pass: background mode, disable python and commands that exit after usage */
957         BLI_argsAdd(ba, 1, "-h", "--help", "\n\tPrint this help text and exit", print_help, ba);
958         /* Windows only */
959         BLI_argsAdd(ba, 1, "/?", NULL, "\n\tPrint this help text and exit (windows only)", print_help, ba);
960
961         BLI_argsAdd(ba, 1, "-v", "--version", "\n\tPrint Blender version and exit", print_version, NULL);
962
963         BLI_argsAdd(ba, 1, "-y", "--enable-autoexec", "\n\tEnable automatic python script execution (default)", enable_python, NULL);
964         BLI_argsAdd(ba, 1, "-Y", "--disable-autoexec", "\n\tDisable automatic python script execution (pydrivers, pyconstraints, pynodes)", disable_python, NULL);
965
966         BLI_argsAdd(ba, 1, "-b", "--background", "<file>\n\tLoad <file> in background (often used for UI-less rendering)", background_mode, NULL);
967
968         BLI_argsAdd(ba, 1, "-a", NULL, playback_doc, playback_mode, NULL);
969
970         BLI_argsAdd(ba, 1, "-d", "--debug", debug_doc, debug_mode, ba);
971     BLI_argsAdd(ba, 1, NULL, "--debug-fpe", "\n\tEnable floating point exceptions", set_fpe, NULL);
972
973         /* second pass: custom window stuff */
974         BLI_argsAdd(ba, 2, "-p", "--window-geometry", "<sx> <sy> <w> <h>\n\tOpen with lower left corner at <sx>, <sy> and width and height as <w>, <h>", prefsize, NULL);
975         BLI_argsAdd(ba, 2, "-w", "--window-border", "\n\tForce opening with borders (default)", with_borders, NULL);
976         BLI_argsAdd(ba, 2, "-W", "--window-borderless", "\n\tForce opening with without borders", without_borders, NULL);
977         BLI_argsAdd(ba, 2, "-R", NULL, "\n\tRegister .blend extension (windows only)", register_extension, ba);
978
979         /* third pass: disabling things and forcing settings */
980         BLI_argsAddCase(ba, 3, "-nojoystick", 1, NULL, 0, "\n\tDisable joystick support", no_joystick, syshandle);
981         BLI_argsAddCase(ba, 3, "-noglsl", 1, NULL, 0, "\n\tDisable GLSL shading", no_glsl, NULL);
982         BLI_argsAddCase(ba, 3, "-noaudio", 1, NULL, 0, "\n\tForce sound system to None", no_audio, NULL);
983         BLI_argsAddCase(ba, 3, "-setaudio", 1, NULL, 0, "\n\tForce sound system to a specific device\n\tNULL SDL OPENAL JACK", set_audio, NULL);
984
985         /* fourth pass: processing arguments */
986         BLI_argsAdd(ba, 4, "-g", NULL, game_doc, set_ge_parameters, syshandle);
987         BLI_argsAdd(ba, 4, "-f", "--render-frame", "<frame>\n\tRender frame <frame> and save it.\n\t+<frame> start frame relative, -<frame> end frame relative.", render_frame, C);
988         BLI_argsAdd(ba, 4, "-a", "--render-anim", "\n\tRender frames from start to end (inclusive)", render_animation, C);
989         BLI_argsAdd(ba, 4, "-S", "--scene", "<name>\n\tSet the active scene <name> for rendering", set_scene, C);
990         BLI_argsAdd(ba, 4, "-s", "--frame-start", "<frame>\n\tSet start to frame <frame> (use before the -a argument)", set_start_frame, C);
991         BLI_argsAdd(ba, 4, "-e", "--frame-end", "<frame>\n\tSet end to frame <frame> (use before the -a argument)", set_end_frame, C);
992         BLI_argsAdd(ba, 4, "-j", "--frame-jump", "<frames>\n\tSet number of frames to step forward after each rendered frame", set_skip_frame, C);
993         BLI_argsAdd(ba, 4, "-P", "--python", "<filename>\n\tRun the given Python script (filename or Blender Text)", run_python, C);
994         BLI_argsAdd(ba, 4, NULL, "--python-console", "\n\tRun blender with an interactive console", run_python_console, C);
995
996         BLI_argsAdd(ba, 4, "-o", "--render-output", output_doc, set_output, C);
997         BLI_argsAdd(ba, 4, "-E", "--engine", "<engine>\n\tSpecify the render engine\n\tuse -E help to list available engines", set_engine, C);
998
999         BLI_argsAdd(ba, 4, "-F", "--render-format", format_doc, set_image_type, C);
1000         BLI_argsAdd(ba, 4, "-t", "--threads", "<threads>\n\tUse amount of <threads> for rendering in background\n\t[1-" QUOTE(BLENDER_MAX_THREADS) "], 0 for systems processor count.", set_threads, NULL);
1001         BLI_argsAdd(ba, 4, "-x", "--use-extension", "<bool>\n\tSet option to add the file extension to the end of the file", set_extension, C);
1002
1003 }
1004
1005 int main(int argc, char **argv)
1006 {
1007         SYS_SystemHandle syshandle;
1008         bContext *C= CTX_create();
1009         bArgs *ba;
1010
1011 #ifdef WITH_BINRELOC
1012         br_init( NULL );
1013 #endif
1014
1015         setCallbacks();
1016 #ifdef __APPLE__
1017                 /* patch to ignore argument finder gives us (pid?) */
1018         if (argc==2 && strncmp(argv[1], "-psn_", 5)==0) {
1019                 extern int GHOST_HACK_getFirstFile(char buf[]);
1020                 static char firstfilebuf[512];
1021
1022                 argc= 1;
1023
1024                 if (GHOST_HACK_getFirstFile(firstfilebuf)) {
1025                         argc= 2;
1026                         argv[1]= firstfilebuf;
1027                 }
1028         }
1029
1030 #endif
1031
1032 #ifdef __FreeBSD__
1033         fpsetmask(0);
1034 #endif
1035
1036         // copy path to executable in bprogname. playanim and creting runtimes
1037         // need this.
1038
1039         BLI_where_am_i(bprogname, argv[0]);
1040         
1041 #ifdef BUILD_DATE       
1042     strip_quotes(build_date);
1043     strip_quotes(build_time);
1044     strip_quotes(build_rev);
1045     strip_quotes(build_platform);
1046     strip_quotes(build_type);
1047 #endif
1048
1049         BLI_threadapi_init();
1050
1051         RNA_init();
1052         RE_engines_init();
1053
1054                 /* Hack - force inclusion of the plugin api functions,
1055                  * see blenpluginapi:pluginapi.c
1056                  */
1057         pluginapi_force_ref();
1058
1059         init_nodesystem();
1060         
1061         initglobals();  /* blender.c */
1062
1063         IMB_init();
1064
1065         syshandle = SYS_GetSystem();
1066         GEN_init_messaging_system();
1067
1068         /* first test for background */
1069         ba = BLI_argsInit(argc, argv); /* skip binary path */
1070         setupArguments(C, ba, &syshandle);
1071
1072         BLI_argsParse(ba, 1, NULL, NULL);
1073
1074 #ifdef __sgi
1075         setuid(getuid()); /* end superuser */
1076 #endif
1077
1078
1079         /* for all platforms, even windos has it! */
1080         if(G.background) signal(SIGINT, blender_esc);   /* ctrl c out bg render */
1081         
1082         /* background render uses this font too */
1083         BKE_font_register_builtin(datatoc_Bfont, datatoc_Bfont_size);
1084
1085         /* Initialiaze ffmpeg if built in, also needed for bg mode if videos are
1086            rendered via ffmpeg */
1087         sound_init_once();
1088         
1089         init_def_material();
1090
1091         if(G.background==0) {
1092                 BLI_argsParse(ba, 2, NULL, NULL);
1093                 BLI_argsParse(ba, 3, NULL, NULL);
1094
1095                 WM_init(C, argc, argv);
1096                 
1097                 /* this is properly initialized with user defs, but this is default */
1098                 BLI_where_is_temp( btempdir, 1 ); /* call after loading the startup.blend so we can read U.tempdir */
1099
1100 #ifndef DISABLE_SDL
1101         BLI_setenv("SDL_VIDEODRIVER", "dummy");
1102 /* I think this is not necessary anymore (04-24-2010 neXyon)
1103 #ifdef __linux__
1104         // On linux the default SDL driver dma often would not play
1105         // use alsa if none is set
1106         setenv("SDL_AUDIODRIVER", "alsa", 0);
1107 #endif
1108 */
1109 #endif
1110         }
1111         else {
1112                 BLI_argsParse(ba, 3, NULL, NULL);
1113
1114                 WM_init(C, argc, argv);
1115
1116                 BLI_where_is_temp( btempdir, 0 ); /* call after loading the startup.blend so we can read U.tempdir */
1117         }
1118 #ifndef DISABLE_PYTHON
1119         /**
1120          * NOTE: the U.pythondir string is NULL until WM_init() is executed,
1121          * so we provide the BPY_ function below to append the user defined
1122          * pythondir to Python's sys.path at this point.  Simply putting
1123          * WM_init() before BPY_start_python() crashes Blender at startup.
1124          * Update: now this function also inits the bpymenus, which also depend
1125          * on U.pythondir.
1126          */
1127
1128         // TODO - U.pythondir
1129
1130 #endif
1131         
1132         CTX_py_init_set(C, 1);
1133         WM_keymap_init(C);
1134
1135         /* OK we are ready for it */
1136         BLI_argsParse(ba, 4, load_file, C);
1137
1138         BLI_argsFree(ba);
1139
1140         if(G.background) {
1141                 /* actually incorrect, but works for now (ton) */
1142                 WM_exit(C);
1143         }
1144
1145         else {
1146                 if((G.fileflags & G_FILE_AUTOPLAY) && (G.f & G_SCRIPT_AUTOEXEC))
1147                 {
1148                         if(WM_init_game(C))
1149                                 return 0;
1150                 }
1151                 else if(!G.file_loaded)
1152                         WM_init_splash(C);
1153         }
1154
1155         WM_main(C);
1156
1157
1158         /*XXX if (scr_init==0) {
1159                 main_init_screen();
1160         }
1161         
1162         screenmain();*/ /* main display loop */
1163
1164         return 0;
1165 } /* end of int main(argc,argv) */
1166
1167 static void error_cb(char *err)
1168 {
1169         
1170         printf("%s\n", err);    /* XXX do this in WM too */
1171 }
1172
1173 static void mem_error_cb(const char *errorStr)
1174 {
1175         fputs(errorStr, stderr);
1176         fflush(stderr);
1177 }
1178
1179 static void setCallbacks(void)
1180 {
1181         /* Error output from the alloc routines: */
1182         MEM_set_error_callback(mem_error_cb);
1183
1184
1185         /* BLI_blenlib: */
1186
1187         BLI_setErrorCallBack(error_cb); /* */
1188 // XXX  BLI_setInterruptCallBack(blender_test_break);
1189
1190 }