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