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