415f1064dbb6a040e968158af615c6940b0eaacb
[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                         else if (!strcmp(imtype,"HDR")) scene->r.imtype = R_RADHDR;
563 #ifdef WITH_TIFF
564                         else if (!strcmp(imtype,"TIFF")) scene->r.imtype = R_TIFF;
565 #endif
566 #ifdef WITH_OPENEXR
567                         else if (!strcmp(imtype,"EXR")) scene->r.imtype = R_OPENEXR;
568                         else if (!strcmp(imtype,"MULTILAYER")) scene->r.imtype = R_MULTILAYER;
569 #endif
570                         else if (!strcmp(imtype,"MPEG")) scene->r.imtype = R_FFMPEG;
571                         else if (!strcmp(imtype,"FRAMESERVER")) scene->r.imtype = R_FRAMESERVER;
572                         else if (!strcmp(imtype,"CINEON")) scene->r.imtype = R_CINEON;
573                         else if (!strcmp(imtype,"DPX")) scene->r.imtype = R_DPX;
574 #if WITH_OPENJPEG
575                         else if (!strcmp(imtype,"JP2")) scene->r.imtype = R_JP2;
576 #endif
577                         else printf("\nError: Format from '-F / --render-format' not known or not compiled in this release.\n");
578                 }
579                 return 1;
580         } else {
581                 printf("\nError: you must specify a format after '-F  / --render-foramt'.\n");
582                 return 0;
583         }
584 }
585
586 static int set_threads(int argc, char **argv, void *data)
587 {
588         if (argc >= 1) {
589                 if(G.background) {
590                         RE_set_max_threads(atoi(argv[1]));
591                 } else {
592                         printf("Warning: threads can only be set in background mode\n");
593                 }
594                 return 1;
595         } else {
596                 printf("\nError: you must specify a number of threads between 0 and 8 '-t  / --threads'.\n");
597                 return 0;
598         }
599 }
600
601 static int set_extension(int argc, char **argv, void *data)
602 {
603         bContext *C = data;
604         if (argc >= 1) {
605                 if (CTX_data_scene(C)) {
606                         Scene *scene= CTX_data_scene(C);
607                         if (argv[1][0] == '0') {
608                                 scene->r.scemode &= ~R_EXTENSION;
609                         } else if (argv[1][0] == '1') {
610                                 scene->r.scemode |= R_EXTENSION;
611                         } else {
612                                 printf("\nError: Use '-x 1 / -x 0' To set the extension option or '--use-extension'\n");
613                         }
614                 } else {
615                         printf("\nError: no blend loaded. order the arguments so '-o ' is after '-x '.\n");
616                 }
617                 return 1;
618         } else {
619                 printf("\nError: you must specify a path after '- '.\n");
620                 return 0;
621         }
622 }
623
624 static int set_ge_parameters(int argc, char **argv, void *data)
625 {
626         SYS_SystemHandle syshandle = *(SYS_SystemHandle*)data;
627         int a = 0;
628 /**
629 gameengine parameters are automaticly put into system
630 -g [paramname = value]
631 -g [boolparamname]
632 example:
633 -g novertexarrays
634 -g maxvertexarraysize = 512
635 */
636
637         if(argc >= 1)
638         {
639                 char* paramname = argv[a];
640                 /* check for single value versus assignment */
641                 if (a+1 < argc && (*(argv[a+1]) == '='))
642                 {
643                         a++;
644                         if (a+1 < argc)
645                         {
646                                 a++;
647                                 /* assignment */
648                                 SYS_WriteCommandLineString(syshandle,paramname,argv[a]);
649                         }  else
650                         {
651                                 printf("error: argument assignment (%s) without value.\n",paramname);
652                                 return 0;
653                         }
654                         /* name arg eaten */
655
656                 } else {
657                         SYS_WriteCommandLineInt(syshandle,argv[a],1);
658
659                         /* doMipMap */
660                         if (!strcmp(argv[a],"nomipmap"))
661                         {
662                                 GPU_set_mipmap(0); //doMipMap = 0;
663                         }
664                         /* linearMipMap */
665                         if (!strcmp(argv[a],"linearmipmap"))
666                         {
667                                 GPU_set_linear_mipmap(1); //linearMipMap = 1;
668                         }
669
670
671                 } /* if (*(argv[a+1]) == '=') */
672         }
673
674         return a;
675 }
676
677 static int render_frame(int argc, char **argv, void *data)
678 {
679         bContext *C = data;
680         if (CTX_data_scene(C)) {
681                 Main *bmain= CTX_data_main(C);
682                 Scene *scene= CTX_data_scene(C);
683
684                 if (argc > 1) {
685                         Render *re = RE_NewRender(scene->id.name);
686                         int frame;
687                         ReportList reports;
688
689                         switch(*argv[1]) {
690                         case '+':
691                                 frame= scene->r.sfra + atoi(argv[1]+1);
692                                 break;
693                         case '-':
694                                 frame= (scene->r.efra - atoi(argv[1]+1)) + 1;
695                                 break;
696                         default:
697                                 frame= atoi(argv[1]);
698                                 break;
699                         }
700
701                         BKE_reports_init(&reports, RPT_PRINT);
702
703                         frame = MIN2(MAXFRAME, MAX2(MINAFRAME, frame));
704
705                         RE_BlenderAnim(re, bmain, scene, scene->lay, frame, frame, scene->r.frame_step, &reports);
706                         return 1;
707                 } else {
708                         printf("\nError: frame number must follow '-f / --render-frame'.\n");
709                         return 0;
710                 }
711         } else {
712                 printf("\nError: no blend loaded. cannot use '-f / --render-frame'.\n");
713                 return 0;
714         }
715 }
716
717 static int render_animation(int argc, char **argv, void *data)
718 {
719         bContext *C = data;
720         if (CTX_data_scene(C)) {
721                 Main *bmain= CTX_data_main(C);
722                 Scene *scene= CTX_data_scene(C);
723                 Render *re= RE_NewRender(scene->id.name);
724                 ReportList reports;
725                 BKE_reports_init(&reports, RPT_PRINT);
726                 RE_BlenderAnim(re, bmain, scene, scene->lay, scene->r.sfra, scene->r.efra, scene->r.frame_step, &reports);
727         } else {
728                 printf("\nError: no blend loaded. cannot use '-a'.\n");
729         }
730         return 0;
731 }
732
733 static int set_scene(int argc, char **argv, void *data)
734 {
735         if(argc > 1) {
736                 bContext *C= data;
737                 Scene *sce= set_scene_name(CTX_data_main(C), argv[1]);
738                 if(sce) {
739                         CTX_data_scene_set(C, sce);
740                 }
741                 return 1;
742         } else {
743                 printf("\nError: Scene name must follow '-S / --scene'.\n");
744                 return 0;
745         }
746 }
747
748 static int set_start_frame(int argc, char **argv, void *data)
749 {
750         bContext *C = data;
751         if (CTX_data_scene(C)) {
752                 Scene *scene= CTX_data_scene(C);
753                 if (argc > 1) {
754                         int frame = atoi(argv[1]);
755                         (scene->r.sfra) = CLAMPIS(frame, MINFRAME, MAXFRAME);
756                         return 1;
757                 } else {
758                         printf("\nError: frame number must follow '-s / --frame-start'.\n");
759                         return 0;
760                 }
761         } else {
762                 printf("\nError: no blend loaded. cannot use '-s / --frame-start'.\n");
763                 return 0;
764         }
765 }
766
767 static int set_end_frame(int argc, char **argv, void *data)
768 {
769         bContext *C = data;
770         if (CTX_data_scene(C)) {
771                 Scene *scene= CTX_data_scene(C);
772                 if (argc > 1) {
773                         int frame = atoi(argv[1]);
774                         (scene->r.efra) = CLAMPIS(frame, MINFRAME, MAXFRAME);
775                         return 1;
776                 } else {
777                         printf("\nError: frame number must follow '-e / --frame-end'.\n");
778                         return 0;
779                 }
780         } else {
781                 printf("\nError: no blend loaded. cannot use '-e / --frame-end'.\n");
782                 return 0;
783         }
784 }
785
786 static int set_skip_frame(int argc, char **argv, void *data)
787 {
788         bContext *C = data;
789         if (CTX_data_scene(C)) {
790                 Scene *scene= CTX_data_scene(C);
791                 if (argc > 1) {
792                         int frame = atoi(argv[1]);
793                         (scene->r.frame_step) = CLAMPIS(frame, 1, MAXFRAME);
794                         return 1;
795                 } else {
796                         printf("\nError: number of frames to step must follow '-j / --frame-jump'.\n");
797                         return 0;
798                 }
799         } else {
800                 printf("\nError: no blend loaded. cannot use '-j / --frame-jump'.\n");
801                 return 0;
802         }
803 }
804
805 /* macro for ugly context setup/reset */
806 #ifndef DISABLE_PYTHON
807 #define BPY_CTX_SETUP(_cmd) \
808 { \
809         wmWindowManager *wm= CTX_wm_manager(C); \
810         wmWindow *prevwin= CTX_wm_window(C); \
811         Scene *prevscene= CTX_data_scene(C); \
812         if(wm->windows.first) { \
813                 CTX_wm_window_set(C, wm->windows.first); \
814                 _cmd; \
815                 CTX_wm_window_set(C, prevwin); \
816         } \
817         else { \
818                 fprintf(stderr, "Python script \"%s\" running with missing context data.\n", argv[1]); \
819                 _cmd; \
820         } \
821         CTX_data_scene_set(C, prevscene); \
822 } \
823
824 #endif /* DISABLE_PYTHON */
825
826 static int run_python(int argc, char **argv, void *data)
827 {
828 #ifndef DISABLE_PYTHON
829         bContext *C = data;
830
831         /* workaround for scripts not getting a bpy.context.scene, causes internal errors elsewhere */
832         if (argc > 1) {
833                 /* Make the path absolute because its needed for relative linked blends to be found */
834                 char filename[FILE_MAXDIR + FILE_MAXFILE];
835                 BLI_strncpy(filename, argv[1], sizeof(filename));
836                 BLI_path_cwd(filename);
837
838                 BPY_CTX_SETUP( BPY_run_python_script(C, filename, NULL, NULL) )
839
840                 return 1;
841         } else {
842                 printf("\nError: you must specify a Python script after '-P / --python'.\n");
843                 return 0;
844         }
845 #else
846         printf("This blender was built without python support\n");
847         return 0;
848 #endif /* DISABLE_PYTHON */
849 }
850
851 static int run_python_console(int argc, char **argv, void *data)
852 {
853 #ifndef DISABLE_PYTHON
854         bContext *C = data;     
855         const char *expr= "__import__('code').interact()";
856
857         BPY_CTX_SETUP( BPY_eval_string(C, expr) )
858
859         return 0;
860 #else
861         printf("This blender was built without python support\n");
862         return 0;
863 #endif /* DISABLE_PYTHON */
864 }
865
866 static int load_file(int argc, char **argv, void *data)
867 {
868         bContext *C = data;
869
870         /* Make the path absolute because its needed for relative linked blends to be found */
871         char filename[FILE_MAXDIR + FILE_MAXFILE];
872         BLI_strncpy(filename, argv[0], sizeof(filename));
873         BLI_path_cwd(filename);
874
875         if (G.background) {
876                 int retval = BKE_read_file(C, filename, NULL, NULL);
877
878                 /*we successfully loaded a blend file, get sure that
879                 pointcache works */
880                 if (retval!=0) {
881                         wmWindowManager *wm= CTX_wm_manager(C);
882                         CTX_wm_manager_set(C, NULL); /* remove wm to force check */
883                         WM_check(C);
884                         G.relbase_valid = 1;
885                         if (CTX_wm_manager(C) == NULL) CTX_wm_manager_set(C, wm); /* reset wm */
886                 }
887
888                 /* WM_read_file() runs normally but since we're in background mode do here */
889 #ifndef DISABLE_PYTHON
890                 /* run any texts that were loaded in and flagged as modules */
891                 BPY_load_user_modules(C);
892 #endif
893
894                 /* happens for the UI on file reading too (huh? (ton))*/
895         // XXX                  BKE_reset_undo();
896         //                              BKE_write_undo("original");     /* save current state */
897         } else {
898                 /* we are not running in background mode here, but start blender in UI mode with
899                    a file - this should do everything a 'load file' does */
900                 WM_read_file(C, filename, NULL);
901         }
902
903         G.file_loaded = 1;
904
905         return 0;
906 }
907
908 void setupArguments(bContext *C, bArgs *ba, SYS_SystemHandle *syshandle)
909 {
910         static char output_doc[] = "<path>"
911                 "\n\tSet the render path and file name."
912                 "\n\tUse // at the start of the path to"
913                 "\n\t\trender relative to the blend file."
914                 "\n\tThe # characters are replaced by the frame number, and used to define zero padding."
915                 "\n\t\tani_##_test.png becomes ani_01_test.png"
916                 "\n\t\ttest-######.png becomes test-000001.png"
917                 "\n\t\tWhen the filename does not contain #, The suffix #### is added to the filename"
918                 "\n\tThe frame number will be added at the end of the filename."
919                 "\n\t\teg: blender -b foobar.blend -o //render_ -F PNG -x 1 -a"
920                 "\n\t\t//render_ becomes //render_####, writing frames as //render_0001.png//";
921
922         static char format_doc[] = "<format>"
923                 "\n\tSet the render format, Valid options are..."
924                 "\n\t\tTGA IRIS JPEG MOVIE IRIZ RAWTGA"
925                 "\n\t\tAVIRAW AVIJPEG PNG BMP FRAMESERVER"
926                 "\n\t(formats that can be compiled into blender, not available on all systems)"
927                 "\n\t\tHDR TIFF EXR MULTILAYER MPEG AVICODEC QUICKTIME CINEON DPX DDS";
928
929         static char playback_doc[] = "<options> <file(s)>"
930                 "\n\tPlayback <file(s)>, only operates this way when not running in background."
931                 "\n\t\t-p <sx> <sy>\tOpen with lower left corner at <sx>, <sy>"
932                 "\n\t\t-m\t\tRead from disk (Don't buffer)"
933                 "\n\t\t-f <fps> <fps-base>\t\tSpecify FPS to start with"
934                 "\n\t\t-j <frame>\tSet frame step to <frame>";
935
936         static char game_doc[] = "Game Engine specific options"
937                 "\n\t-g fixedtime\t\tRun on 50 hertz without dropping frames"
938                 "\n\t-g vertexarrays\tUse Vertex Arrays for rendering (usually faster)"
939                 "\n\t-g nomipmap\t\tNo Texture Mipmapping"
940                 "\n\t-g linearmipmap\tLinear Texture Mipmapping instead of Nearest (default)";
941
942         static char debug_doc[] = "\n\tTurn debugging on\n"
943                 "\n\t* Prints every operator call and their arguments"
944                 "\n\t* Disables mouse grab (to interact with a debugger in some cases)"
945                 "\n\t* Keeps python sys.stdin rather then setting it to None";
946
947         //BLI_argsAdd(ba, pass, short_arg, long_arg, doc, cb, C);
948
949         /* end argument processing after -- */
950         BLI_argsAdd(ba, -1, "--", NULL, "\n\tEnds option processing, following arguments passed unchanged. Access via python's sys.argv", end_arguments, NULL);
951
952         /* first pass: background mode, disable python and commands that exit after usage */
953         BLI_argsAdd(ba, 1, "-h", "--help", "\n\tPrint this help text and exit", print_help, ba);
954         /* Windows only */
955         BLI_argsAdd(ba, 1, "/?", NULL, "\n\tPrint this help text and exit (windows only)", print_help, ba);
956
957         BLI_argsAdd(ba, 1, "-v", "--version", "\n\tPrint Blender version and exit", print_version, NULL);
958
959         BLI_argsAdd(ba, 1, "-y", "--enable-autoexec", "\n\tEnable automatic python script execution (default)", enable_python, NULL);
960         BLI_argsAdd(ba, 1, "-Y", "--disable-autoexec", "\n\tDisable automatic python script execution (pydrivers, pyconstraints, pynodes)", disable_python, NULL);
961
962         BLI_argsAdd(ba, 1, "-b", "--background", "<file>\n\tLoad <file> in background (often used for UI-less rendering)", background_mode, NULL);
963
964         BLI_argsAdd(ba, 1, "-a", NULL, playback_doc, playback_mode, NULL);
965
966         BLI_argsAdd(ba, 1, "-d", "--debug", debug_doc, debug_mode, ba);
967     BLI_argsAdd(ba, 1, NULL, "--debug-fpe", "\n\tEnable floating point exceptions", set_fpe, NULL);
968
969         /* second pass: custom window stuff */
970         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);
971         BLI_argsAdd(ba, 2, "-w", "--window-border", "\n\tForce opening with borders (default)", with_borders, NULL);
972         BLI_argsAdd(ba, 2, "-W", "--window-borderless", "\n\tForce opening with without borders", without_borders, NULL);
973         BLI_argsAdd(ba, 2, "-R", NULL, "\n\tRegister .blend extension (windows only)", register_extension, ba);
974
975         /* third pass: disabling things and forcing settings */
976         BLI_argsAddCase(ba, 3, "-nojoystick", 1, NULL, 0, "\n\tDisable joystick support", no_joystick, syshandle);
977         BLI_argsAddCase(ba, 3, "-noglsl", 1, NULL, 0, "\n\tDisable GLSL shading", no_glsl, NULL);
978         BLI_argsAddCase(ba, 3, "-noaudio", 1, NULL, 0, "\n\tForce sound system to None", no_audio, NULL);
979         BLI_argsAddCase(ba, 3, "-setaudio", 1, NULL, 0, "\n\tForce sound system to a specific device\n\tNULL SDL OPENAL JACK", set_audio, NULL);
980
981         /* fourth pass: processing arguments */
982         BLI_argsAdd(ba, 4, "-g", NULL, game_doc, set_ge_parameters, syshandle);
983         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);
984         BLI_argsAdd(ba, 4, "-a", "--render-anim", "\n\tRender frames from start to end (inclusive)", render_animation, C);
985         BLI_argsAdd(ba, 4, "-S", "--scene", "<name>\n\tSet the active scene <name> for rendering", set_scene, C);
986         BLI_argsAdd(ba, 4, "-s", "--frame-start", "<frame>\n\tSet start to frame <frame> (use before the -a argument)", set_start_frame, C);
987         BLI_argsAdd(ba, 4, "-e", "--frame-end", "<frame>\n\tSet end to frame <frame> (use before the -a argument)", set_end_frame, C);
988         BLI_argsAdd(ba, 4, "-j", "--frame-jump", "<frames>\n\tSet number of frames to step forward after each rendered frame", set_skip_frame, C);
989         BLI_argsAdd(ba, 4, "-P", "--python", "<filename>\n\tRun the given Python script (filename or Blender Text)", run_python, C);
990         BLI_argsAdd(ba, 4, NULL, "--python-console", "\n\tRun blender with an interactive console", run_python_console, C);
991
992         BLI_argsAdd(ba, 4, "-o", "--render-output", output_doc, set_output, C);
993         BLI_argsAdd(ba, 4, "-E", "--engine", "<engine>\n\tSpecify the render engine\n\tuse -E help to list available engines", set_engine, C);
994
995         BLI_argsAdd(ba, 4, "-F", "--render-format", format_doc, set_image_type, C);
996         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);
997         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);
998
999 }
1000
1001 int main(int argc, char **argv)
1002 {
1003         SYS_SystemHandle syshandle;
1004         bContext *C= CTX_create();
1005         bArgs *ba;
1006
1007 #ifdef WITH_BINRELOC
1008         br_init( NULL );
1009 #endif
1010
1011         setCallbacks();
1012 #ifdef __APPLE__
1013                 /* patch to ignore argument finder gives us (pid?) */
1014         if (argc==2 && strncmp(argv[1], "-psn_", 5)==0) {
1015                 extern int GHOST_HACK_getFirstFile(char buf[]);
1016                 static char firstfilebuf[512];
1017
1018                 argc= 1;
1019
1020                 if (GHOST_HACK_getFirstFile(firstfilebuf)) {
1021                         argc= 2;
1022                         argv[1]= firstfilebuf;
1023                 }
1024         }
1025
1026 #endif
1027
1028 #ifdef __FreeBSD__
1029         fpsetmask(0);
1030 #endif
1031
1032         // copy path to executable in bprogname. playanim and creting runtimes
1033         // need this.
1034
1035         BLI_where_am_i(bprogname, argv[0]);
1036         
1037 #ifdef BUILD_DATE       
1038     strip_quotes(build_date);
1039     strip_quotes(build_time);
1040     strip_quotes(build_rev);
1041     strip_quotes(build_platform);
1042     strip_quotes(build_type);
1043 #endif
1044
1045         BLI_threadapi_init();
1046
1047         RNA_init();
1048         RE_engines_init();
1049
1050                 /* Hack - force inclusion of the plugin api functions,
1051                  * see blenpluginapi:pluginapi.c
1052                  */
1053         pluginapi_force_ref();
1054
1055         init_nodesystem();
1056         
1057         initglobals();  /* blender.c */
1058
1059         IMB_init();
1060
1061         syshandle = SYS_GetSystem();
1062         GEN_init_messaging_system();
1063
1064         /* first test for background */
1065         ba = BLI_argsInit(argc, argv); /* skip binary path */
1066         setupArguments(C, ba, &syshandle);
1067
1068         BLI_argsParse(ba, 1, NULL, NULL);
1069
1070 #ifdef __sgi
1071         setuid(getuid()); /* end superuser */
1072 #endif
1073
1074
1075         /* for all platforms, even windos has it! */
1076         if(G.background) signal(SIGINT, blender_esc);   /* ctrl c out bg render */
1077         
1078         /* background render uses this font too */
1079         BKE_font_register_builtin(datatoc_Bfont, datatoc_Bfont_size);
1080
1081         /* Initialiaze ffmpeg if built in, also needed for bg mode if videos are
1082            rendered via ffmpeg */
1083         sound_init_once();
1084         
1085         init_def_material();
1086
1087         if(G.background==0) {
1088                 BLI_argsParse(ba, 2, NULL, NULL);
1089                 BLI_argsParse(ba, 3, NULL, NULL);
1090
1091                 WM_init(C, argc, argv);
1092                 
1093                 /* this is properly initialized with user defs, but this is default */
1094                 BLI_where_is_temp( btempdir, 1 ); /* call after loading the startup.blend so we can read U.tempdir */
1095
1096 #ifndef DISABLE_SDL
1097         BLI_setenv("SDL_VIDEODRIVER", "dummy");
1098 /* I think this is not necessary anymore (04-24-2010 neXyon)
1099 #ifdef __linux__
1100         // On linux the default SDL driver dma often would not play
1101         // use alsa if none is set
1102         setenv("SDL_AUDIODRIVER", "alsa", 0);
1103 #endif
1104 */
1105 #endif
1106         }
1107         else {
1108                 BLI_argsParse(ba, 3, NULL, NULL);
1109
1110                 WM_init(C, argc, argv);
1111
1112                 BLI_where_is_temp( btempdir, 0 ); /* call after loading the startup.blend so we can read U.tempdir */
1113         }
1114 #ifndef DISABLE_PYTHON
1115         /**
1116          * NOTE: the U.pythondir string is NULL until WM_init() is executed,
1117          * so we provide the BPY_ function below to append the user defined
1118          * pythondir to Python's sys.path at this point.  Simply putting
1119          * WM_init() before BPY_start_python() crashes Blender at startup.
1120          * Update: now this function also inits the bpymenus, which also depend
1121          * on U.pythondir.
1122          */
1123
1124         // TODO - U.pythondir
1125
1126 #endif
1127         
1128         CTX_py_init_set(C, 1);
1129         WM_keymap_init(C);
1130
1131         /* OK we are ready for it */
1132         BLI_argsParse(ba, 4, load_file, C);
1133
1134         BLI_argsFree(ba);
1135
1136         if(G.background) {
1137                 /* actually incorrect, but works for now (ton) */
1138                 WM_exit(C);
1139         }
1140
1141         else {
1142                 if((G.fileflags & G_FILE_AUTOPLAY) && (G.f & G_SCRIPT_AUTOEXEC))
1143                         WM_init_game(C);
1144
1145                 else if(!G.file_loaded)
1146                         WM_init_splash(C);
1147         }
1148
1149         WM_main(C);
1150
1151
1152         /*XXX if (scr_init==0) {
1153                 main_init_screen();
1154         }
1155         
1156         screenmain();*/ /* main display loop */
1157
1158         return 0;
1159 } /* end of int main(argc,argv) */
1160
1161 static void error_cb(char *err)
1162 {
1163         
1164         printf("%s\n", err);    /* XXX do this in WM too */
1165 }
1166
1167 static void mem_error_cb(const char *errorStr)
1168 {
1169         fputs(errorStr, stderr);
1170         fflush(stderr);
1171 }
1172
1173 static void setCallbacks(void)
1174 {
1175         /* Error output from the alloc routines: */
1176         MEM_set_error_callback(mem_error_cb);
1177
1178
1179         /* BLI_blenlib: */
1180
1181         BLI_setErrorCallBack(error_cb); /* */
1182 // XXX  BLI_setInterruptCallBack(blender_test_break);
1183
1184 }