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