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